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-2014 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"
29 #include "stringpool.h"
30 #include "stor-layout.h"
32 #include "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
61 #include "tree-pass.h"
63 #include "splay-tree.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "pretty-print.h"
72 #include "tree-nested.h"
76 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
77 phases. The first phase scans the function looking for OMP statements
78 and then for variables that must be replaced to satisfy data sharing
79 clauses. The second phase expands code for the constructs, as well as
80 re-gimplifying things when variables have been replaced with complex
83 Final code generation is done by pass_expand_omp. The flowgraph is
84 scanned for parallel regions which are then moved to a new
85 function, to be invoked by the thread library. */
87 /* Parallel region information. Every parallel and workshare
88 directive is enclosed between two markers, the OMP_* directive
89 and a corresponding OMP_RETURN statement. */
93 /* The enclosing region. */
94 struct omp_region
*outer
;
96 /* First child region. */
97 struct omp_region
*inner
;
99 /* Next peer region. */
100 struct omp_region
*next
;
102 /* Block containing the omp directive as its last stmt. */
105 /* Block containing the OMP_RETURN as its last stmt. */
108 /* Block containing the OMP_CONTINUE as its last stmt. */
111 /* If this is a combined parallel+workshare region, this is a list
112 of additional arguments needed by the combined parallel+workshare
114 vec
<tree
, va_gc
> *ws_args
;
116 /* The code for the omp directive of this region. */
117 enum gimple_code type
;
119 /* Schedule kind, only used for OMP_FOR type regions. */
120 enum omp_clause_schedule_kind sched_kind
;
122 /* True if this is a combined parallel+workshare region. */
123 bool is_combined_parallel
;
126 /* Context structure. Used to store information about each parallel
127 directive in the code. */
129 typedef struct omp_context
131 /* This field must be at the beginning, as we do "inheritance": Some
132 callback functions for tree-inline.c (e.g., omp_copy_decl)
133 receive a copy_body_data pointer that is up-casted to an
134 omp_context pointer. */
137 /* The tree of contexts corresponding to the encountered constructs. */
138 struct omp_context
*outer
;
141 /* Map variables to fields in a structure that allows communication
142 between sending and receiving threads. */
143 splay_tree field_map
;
148 /* These are used just by task contexts, if task firstprivate fn is
149 needed. srecord_type is used to communicate from the thread
150 that encountered the task construct to task firstprivate fn,
151 record_type is allocated by GOMP_task, initialized by task firstprivate
152 fn and passed to the task body fn. */
153 splay_tree sfield_map
;
156 /* A chain of variables to add to the top-level block surrounding the
157 construct. In the case of a parallel, this is in the child function. */
160 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
161 barriers should jump to during omplower pass. */
164 /* What to do with variables with implicitly determined sharing
166 enum omp_clause_default_kind default_kind
;
168 /* Nesting depth of this context. Used to beautify error messages re
169 invalid gotos. The outermost ctx is depth 1, with depth 0 being
170 reserved for the main body of the function. */
173 /* True if this parallel directive is nested within another. */
176 /* True if this construct can be cancelled. */
181 struct omp_for_data_loop
183 tree v
, n1
, n2
, step
;
184 enum tree_code cond_code
;
187 /* A structure describing the main elements of a parallel loop. */
191 struct omp_for_data_loop loop
;
196 bool have_nowait
, have_ordered
;
197 enum omp_clause_schedule_kind sched_kind
;
198 struct omp_for_data_loop
*loops
;
202 static splay_tree all_contexts
;
203 static int taskreg_nesting_level
;
204 static int target_nesting_level
;
205 static struct omp_region
*root_omp_region
;
206 static bitmap task_shared_vars
;
208 static void scan_omp (gimple_seq
*, omp_context
*);
209 static tree
scan_omp_1_op (tree
*, int *, void *);
211 #define WALK_SUBSTMTS \
215 case GIMPLE_EH_FILTER: \
216 case GIMPLE_TRANSACTION: \
217 /* The sub-statements for these should be walked. */ \
218 *handled_ops_p = false; \
221 /* Convenience function for calling scan_omp_1_op on tree operands. */
224 scan_omp_op (tree
*tp
, omp_context
*ctx
)
226 struct walk_stmt_info wi
;
228 memset (&wi
, 0, sizeof (wi
));
230 wi
.want_locations
= true;
232 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
235 static void lower_omp (gimple_seq
*, omp_context
*);
236 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
237 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
239 /* Find an OpenMP clause of type KIND within CLAUSES. */
242 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
244 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
245 if (OMP_CLAUSE_CODE (clauses
) == kind
)
251 /* Return true if CTX is for an omp parallel. */
254 is_parallel_ctx (omp_context
*ctx
)
256 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
260 /* Return true if CTX is for an omp task. */
263 is_task_ctx (omp_context
*ctx
)
265 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
269 /* Return true if CTX is for an omp parallel or omp task. */
272 is_taskreg_ctx (omp_context
*ctx
)
274 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
275 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
279 /* Return true if REGION is a combined parallel+workshare region. */
282 is_combined_parallel (struct omp_region
*region
)
284 return region
->is_combined_parallel
;
288 /* Extract the header elements of parallel loop FOR_STMT and store
292 extract_omp_for_data (gimple for_stmt
, struct omp_for_data
*fd
,
293 struct omp_for_data_loop
*loops
)
295 tree t
, var
, *collapse_iter
, *collapse_count
;
296 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
297 struct omp_for_data_loop
*loop
;
299 struct omp_for_data_loop dummy_loop
;
300 location_t loc
= gimple_location (for_stmt
);
301 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
302 bool distribute
= gimple_omp_for_kind (for_stmt
)
303 == GF_OMP_FOR_KIND_DISTRIBUTE
;
305 fd
->for_stmt
= for_stmt
;
307 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
308 if (fd
->collapse
> 1)
311 fd
->loops
= &fd
->loop
;
313 fd
->have_nowait
= distribute
|| simd
;
314 fd
->have_ordered
= false;
315 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
316 fd
->chunk_size
= NULL_TREE
;
317 collapse_iter
= NULL
;
318 collapse_count
= NULL
;
320 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
321 switch (OMP_CLAUSE_CODE (t
))
323 case OMP_CLAUSE_NOWAIT
:
324 fd
->have_nowait
= true;
326 case OMP_CLAUSE_ORDERED
:
327 fd
->have_ordered
= true;
329 case OMP_CLAUSE_SCHEDULE
:
330 gcc_assert (!distribute
);
331 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
332 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
334 case OMP_CLAUSE_DIST_SCHEDULE
:
335 gcc_assert (distribute
);
336 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
338 case OMP_CLAUSE_COLLAPSE
:
339 if (fd
->collapse
> 1)
341 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
342 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
348 /* FIXME: for now map schedule(auto) to schedule(static).
349 There should be analysis to determine whether all iterations
350 are approximately the same amount of work (then schedule(static)
351 is best) or if it varies (then schedule(dynamic,N) is better). */
352 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
354 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
355 gcc_assert (fd
->chunk_size
== NULL
);
357 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
358 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
359 gcc_assert (fd
->chunk_size
== NULL
);
360 else if (fd
->chunk_size
== NULL
)
362 /* We only need to compute a default chunk size for ordered
363 static loops and dynamic loops. */
364 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
366 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
367 ? integer_zero_node
: integer_one_node
;
370 for (i
= 0; i
< fd
->collapse
; i
++)
372 if (fd
->collapse
== 1)
374 else if (loops
!= NULL
)
379 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
380 gcc_assert (SSA_VAR_P (loop
->v
));
381 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
382 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
383 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
384 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
386 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
387 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
388 switch (loop
->cond_code
)
394 gcc_assert (gimple_omp_for_kind (for_stmt
)
395 == GF_OMP_FOR_KIND_CILKSIMD
);
398 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
399 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
401 loop
->n2
= fold_build2_loc (loc
,
402 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
403 build_int_cst (TREE_TYPE (loop
->n2
), 1));
404 loop
->cond_code
= LT_EXPR
;
407 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
408 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
410 loop
->n2
= fold_build2_loc (loc
,
411 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
412 build_int_cst (TREE_TYPE (loop
->n2
), 1));
413 loop
->cond_code
= GT_EXPR
;
419 t
= gimple_omp_for_incr (for_stmt
, i
);
420 gcc_assert (TREE_OPERAND (t
, 0) == var
);
421 switch (TREE_CODE (t
))
424 loop
->step
= TREE_OPERAND (t
, 1);
426 case POINTER_PLUS_EXPR
:
427 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
430 loop
->step
= TREE_OPERAND (t
, 1);
431 loop
->step
= fold_build1_loc (loc
,
432 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
440 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
441 && !fd
->have_ordered
))
443 if (fd
->collapse
== 1)
444 iter_type
= TREE_TYPE (loop
->v
);
446 || TYPE_PRECISION (iter_type
)
447 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
449 = build_nonstandard_integer_type
450 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
452 else if (iter_type
!= long_long_unsigned_type_node
)
454 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
455 iter_type
= long_long_unsigned_type_node
;
456 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
457 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
458 >= TYPE_PRECISION (iter_type
))
462 if (loop
->cond_code
== LT_EXPR
)
463 n
= fold_build2_loc (loc
,
464 PLUS_EXPR
, TREE_TYPE (loop
->v
),
465 loop
->n2
, loop
->step
);
468 if (TREE_CODE (n
) != INTEGER_CST
469 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
470 iter_type
= long_long_unsigned_type_node
;
472 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
473 > TYPE_PRECISION (iter_type
))
477 if (loop
->cond_code
== LT_EXPR
)
480 n2
= fold_build2_loc (loc
,
481 PLUS_EXPR
, TREE_TYPE (loop
->v
),
482 loop
->n2
, loop
->step
);
486 n1
= fold_build2_loc (loc
,
487 MINUS_EXPR
, TREE_TYPE (loop
->v
),
488 loop
->n2
, loop
->step
);
491 if (TREE_CODE (n1
) != INTEGER_CST
492 || TREE_CODE (n2
) != INTEGER_CST
493 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
494 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
495 iter_type
= long_long_unsigned_type_node
;
499 if (collapse_count
&& *collapse_count
== NULL
)
501 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
502 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
503 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
504 if (t
&& integer_zerop (t
))
505 count
= build_zero_cst (long_long_unsigned_type_node
);
506 else if ((i
== 0 || count
!= NULL_TREE
)
507 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
508 && TREE_CONSTANT (loop
->n1
)
509 && TREE_CONSTANT (loop
->n2
)
510 && TREE_CODE (loop
->step
) == INTEGER_CST
)
512 tree itype
= TREE_TYPE (loop
->v
);
514 if (POINTER_TYPE_P (itype
))
515 itype
= signed_type_for (itype
);
516 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
517 t
= fold_build2_loc (loc
,
519 fold_convert_loc (loc
, itype
, loop
->step
), t
);
520 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
521 fold_convert_loc (loc
, itype
, loop
->n2
));
522 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
523 fold_convert_loc (loc
, itype
, loop
->n1
));
524 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
525 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
526 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
527 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
528 fold_convert_loc (loc
, itype
,
531 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
532 fold_convert_loc (loc
, itype
, loop
->step
));
533 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
534 if (count
!= NULL_TREE
)
535 count
= fold_build2_loc (loc
,
536 MULT_EXPR
, long_long_unsigned_type_node
,
540 if (TREE_CODE (count
) != INTEGER_CST
)
543 else if (count
&& !integer_zerop (count
))
550 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
551 || fd
->have_ordered
))
553 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
554 iter_type
= long_long_unsigned_type_node
;
556 iter_type
= long_integer_type_node
;
558 else if (collapse_iter
&& *collapse_iter
!= NULL
)
559 iter_type
= TREE_TYPE (*collapse_iter
);
560 fd
->iter_type
= iter_type
;
561 if (collapse_iter
&& *collapse_iter
== NULL
)
562 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
563 if (collapse_count
&& *collapse_count
== NULL
)
566 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
568 *collapse_count
= create_tmp_var (iter_type
, ".count");
571 if (fd
->collapse
> 1)
573 fd
->loop
.v
= *collapse_iter
;
574 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
575 fd
->loop
.n2
= *collapse_count
;
576 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
577 fd
->loop
.cond_code
= LT_EXPR
;
582 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
583 is the immediate dominator of PAR_ENTRY_BB, return true if there
584 are no data dependencies that would prevent expanding the parallel
585 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
587 When expanding a combined parallel+workshare region, the call to
588 the child function may need additional arguments in the case of
589 GIMPLE_OMP_FOR regions. In some cases, these arguments are
590 computed out of variables passed in from the parent to the child
591 via 'struct .omp_data_s'. For instance:
593 #pragma omp parallel for schedule (guided, i * 4)
598 # BLOCK 2 (PAR_ENTRY_BB)
600 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
602 # BLOCK 3 (WS_ENTRY_BB)
603 .omp_data_i = &.omp_data_o;
604 D.1667 = .omp_data_i->i;
606 #pragma omp for schedule (guided, D.1598)
608 When we outline the parallel region, the call to the child function
609 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
610 that value is computed *after* the call site. So, in principle we
611 cannot do the transformation.
613 To see whether the code in WS_ENTRY_BB blocks the combined
614 parallel+workshare call, we collect all the variables used in the
615 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
616 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
619 FIXME. If we had the SSA form built at this point, we could merely
620 hoist the code in block 3 into block 2 and be done with it. But at
621 this point we don't have dataflow information and though we could
622 hack something up here, it is really not worth the aggravation. */
625 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
627 struct omp_for_data fd
;
628 gimple ws_stmt
= last_stmt (ws_entry_bb
);
630 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
633 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
635 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
637 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
639 if (fd
.iter_type
!= long_integer_type_node
)
642 /* FIXME. We give up too easily here. If any of these arguments
643 are not constants, they will likely involve variables that have
644 been mapped into fields of .omp_data_s for sharing with the child
645 function. With appropriate data flow, it would be possible to
647 if (!is_gimple_min_invariant (fd
.loop
.n1
)
648 || !is_gimple_min_invariant (fd
.loop
.n2
)
649 || !is_gimple_min_invariant (fd
.loop
.step
)
650 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
657 /* Collect additional arguments needed to emit a combined
658 parallel+workshare call. WS_STMT is the workshare directive being
661 static vec
<tree
, va_gc
> *
662 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
665 location_t loc
= gimple_location (ws_stmt
);
666 vec
<tree
, va_gc
> *ws_args
;
668 if (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
)
670 struct omp_for_data fd
;
673 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
677 if (gimple_omp_for_combined_into_p (ws_stmt
))
680 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
681 OMP_CLAUSE__LOOPTEMP_
);
683 n1
= OMP_CLAUSE_DECL (innerc
);
684 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
685 OMP_CLAUSE__LOOPTEMP_
);
687 n2
= OMP_CLAUSE_DECL (innerc
);
690 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
692 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
693 ws_args
->quick_push (t
);
695 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
696 ws_args
->quick_push (t
);
698 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
699 ws_args
->quick_push (t
);
703 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
704 ws_args
->quick_push (t
);
709 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
711 /* Number of sections is equal to the number of edges from the
712 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
713 the exit of the sections region. */
714 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
715 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
716 vec_alloc (ws_args
, 1);
717 ws_args
->quick_push (t
);
725 /* Discover whether REGION is a combined parallel+workshare region. */
728 determine_parallel_type (struct omp_region
*region
)
730 basic_block par_entry_bb
, par_exit_bb
;
731 basic_block ws_entry_bb
, ws_exit_bb
;
733 if (region
== NULL
|| region
->inner
== NULL
734 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
735 || region
->inner
->cont
== NULL
)
738 /* We only support parallel+for and parallel+sections. */
739 if (region
->type
!= GIMPLE_OMP_PARALLEL
740 || (region
->inner
->type
!= GIMPLE_OMP_FOR
741 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
744 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
745 WS_EXIT_BB -> PAR_EXIT_BB. */
746 par_entry_bb
= region
->entry
;
747 par_exit_bb
= region
->exit
;
748 ws_entry_bb
= region
->inner
->entry
;
749 ws_exit_bb
= region
->inner
->exit
;
751 if (single_succ (par_entry_bb
) == ws_entry_bb
752 && single_succ (ws_exit_bb
) == par_exit_bb
753 && workshare_safe_to_combine_p (ws_entry_bb
)
754 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
755 || (last_and_only_stmt (ws_entry_bb
)
756 && last_and_only_stmt (par_exit_bb
))))
758 gimple par_stmt
= last_stmt (par_entry_bb
);
759 gimple ws_stmt
= last_stmt (ws_entry_bb
);
761 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
763 /* If this is a combined parallel loop, we need to determine
764 whether or not to use the combined library calls. There
765 are two cases where we do not apply the transformation:
766 static loops and any kind of ordered loop. In the first
767 case, we already open code the loop so there is no need
768 to do anything else. In the latter case, the combined
769 parallel loop call would still need extra synchronization
770 to implement ordered semantics, so there would not be any
771 gain in using the combined call. */
772 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
773 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
775 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
776 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
778 region
->is_combined_parallel
= false;
779 region
->inner
->is_combined_parallel
= false;
784 region
->is_combined_parallel
= true;
785 region
->inner
->is_combined_parallel
= true;
786 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
791 /* Return true if EXPR is variable sized. */
794 is_variable_sized (const_tree expr
)
796 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
799 /* Return true if DECL is a reference type. */
802 is_reference (tree decl
)
804 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
807 /* Lookup variables in the decl or field splay trees. The "maybe" form
808 allows for the variable form to not have been entered, otherwise we
809 assert that the variable must have been entered. */
812 lookup_decl (tree var
, omp_context
*ctx
)
815 n
= (tree
*) pointer_map_contains (ctx
->cb
.decl_map
, var
);
820 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
823 n
= (tree
*) pointer_map_contains (ctx
->cb
.decl_map
, var
);
824 return n
? *n
: NULL_TREE
;
828 lookup_field (tree var
, omp_context
*ctx
)
831 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
832 return (tree
) n
->value
;
836 lookup_sfield (tree var
, omp_context
*ctx
)
839 n
= splay_tree_lookup (ctx
->sfield_map
840 ? ctx
->sfield_map
: ctx
->field_map
,
841 (splay_tree_key
) var
);
842 return (tree
) n
->value
;
846 maybe_lookup_field (tree var
, omp_context
*ctx
)
849 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
850 return n
? (tree
) n
->value
: NULL_TREE
;
853 /* Return true if DECL should be copied by pointer. SHARED_CTX is
854 the parallel context if DECL is to be shared. */
857 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
859 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
862 /* We can only use copy-in/copy-out semantics for shared variables
863 when we know the value is not accessible from an outer scope. */
866 /* ??? Trivially accessible from anywhere. But why would we even
867 be passing an address in this case? Should we simply assert
868 this to be false, or should we have a cleanup pass that removes
869 these from the list of mappings? */
870 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
873 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
874 without analyzing the expression whether or not its location
875 is accessible to anyone else. In the case of nested parallel
876 regions it certainly may be. */
877 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
880 /* Do not use copy-in/copy-out for variables that have their
882 if (TREE_ADDRESSABLE (decl
))
885 /* lower_send_shared_vars only uses copy-in, but not copy-out
887 if (TREE_READONLY (decl
)
888 || ((TREE_CODE (decl
) == RESULT_DECL
889 || TREE_CODE (decl
) == PARM_DECL
)
890 && DECL_BY_REFERENCE (decl
)))
893 /* Disallow copy-in/out in nested parallel if
894 decl is shared in outer parallel, otherwise
895 each thread could store the shared variable
896 in its own copy-in location, making the
897 variable no longer really shared. */
898 if (shared_ctx
->is_nested
)
902 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
903 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
910 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
911 c
; c
= OMP_CLAUSE_CHAIN (c
))
912 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
913 && OMP_CLAUSE_DECL (c
) == decl
)
917 goto maybe_mark_addressable_and_ret
;
921 /* For tasks avoid using copy-in/out. As tasks can be
922 deferred or executed in different thread, when GOMP_task
923 returns, the task hasn't necessarily terminated. */
924 if (is_task_ctx (shared_ctx
))
927 maybe_mark_addressable_and_ret
:
928 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
929 if (is_gimple_reg (outer
))
931 /* Taking address of OUTER in lower_send_shared_vars
932 might need regimplification of everything that uses the
934 if (!task_shared_vars
)
935 task_shared_vars
= BITMAP_ALLOC (NULL
);
936 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
937 TREE_ADDRESSABLE (outer
) = 1;
946 /* Construct a new automatic decl similar to VAR. */
949 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
951 tree copy
= copy_var_decl (var
, name
, type
);
953 DECL_CONTEXT (copy
) = current_function_decl
;
954 DECL_CHAIN (copy
) = ctx
->block_vars
;
955 ctx
->block_vars
= copy
;
961 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
963 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
966 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
969 omp_build_component_ref (tree obj
, tree field
)
971 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
972 if (TREE_THIS_VOLATILE (field
))
973 TREE_THIS_VOLATILE (ret
) |= 1;
974 if (TREE_READONLY (field
))
975 TREE_READONLY (ret
) |= 1;
979 /* Build tree nodes to access the field for VAR on the receiver side. */
982 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
984 tree x
, field
= lookup_field (var
, ctx
);
986 /* If the receiver record type was remapped in the child function,
987 remap the field into the new record type. */
988 x
= maybe_lookup_field (field
, ctx
);
992 x
= build_simple_mem_ref (ctx
->receiver_decl
);
993 x
= omp_build_component_ref (x
, field
);
995 x
= build_simple_mem_ref (x
);
1000 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1001 of a parallel, this is a component reference; for workshare constructs
1002 this is some variable. */
1005 build_outer_var_ref (tree var
, omp_context
*ctx
)
1009 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1011 else if (is_variable_sized (var
))
1013 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1014 x
= build_outer_var_ref (x
, ctx
);
1015 x
= build_simple_mem_ref (x
);
1017 else if (is_taskreg_ctx (ctx
))
1019 bool by_ref
= use_pointer_for_field (var
, NULL
);
1020 x
= build_receiver_ref (var
, by_ref
, ctx
);
1022 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1023 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1025 /* #pragma omp simd isn't a worksharing construct, and can reference even
1026 private vars in its linear etc. clauses. */
1028 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1029 x
= lookup_decl (var
, ctx
->outer
);
1030 else if (ctx
->outer
)
1031 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1035 else if (ctx
->outer
)
1036 x
= lookup_decl (var
, ctx
->outer
);
1037 else if (is_reference (var
))
1038 /* This can happen with orphaned constructs. If var is reference, it is
1039 possible it is shared and as such valid. */
1044 if (is_reference (var
))
1045 x
= build_simple_mem_ref (x
);
1050 /* Build tree nodes to access the field for VAR on the sender side. */
1053 build_sender_ref (tree var
, omp_context
*ctx
)
1055 tree field
= lookup_sfield (var
, ctx
);
1056 return omp_build_component_ref (ctx
->sender_decl
, field
);
1059 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1062 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1064 tree field
, type
, sfield
= NULL_TREE
;
1066 gcc_assert ((mask
& 1) == 0
1067 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1068 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1069 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1071 type
= TREE_TYPE (var
);
1074 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1075 type
= build_pointer_type (build_pointer_type (type
));
1078 type
= build_pointer_type (type
);
1079 else if ((mask
& 3) == 1 && is_reference (var
))
1080 type
= TREE_TYPE (type
);
1082 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1083 FIELD_DECL
, DECL_NAME (var
), type
);
1085 /* Remember what variable this field was created for. This does have a
1086 side effect of making dwarf2out ignore this member, so for helpful
1087 debugging we clear it later in delete_omp_context. */
1088 DECL_ABSTRACT_ORIGIN (field
) = var
;
1089 if (type
== TREE_TYPE (var
))
1091 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1092 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1093 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1096 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1098 if ((mask
& 3) == 3)
1100 insert_field_into_struct (ctx
->record_type
, field
);
1101 if (ctx
->srecord_type
)
1103 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1104 FIELD_DECL
, DECL_NAME (var
), type
);
1105 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1106 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1107 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1108 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1109 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1114 if (ctx
->srecord_type
== NULL_TREE
)
1118 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1119 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1120 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1122 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1123 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1124 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1125 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1126 splay_tree_insert (ctx
->sfield_map
,
1127 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1128 (splay_tree_value
) sfield
);
1132 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1133 : ctx
->srecord_type
, field
);
1137 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1138 (splay_tree_value
) field
);
1139 if ((mask
& 2) && ctx
->sfield_map
)
1140 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1141 (splay_tree_value
) sfield
);
1145 install_var_local (tree var
, omp_context
*ctx
)
1147 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1148 insert_decl_map (&ctx
->cb
, var
, new_var
);
1152 /* Adjust the replacement for DECL in CTX for the new context. This means
1153 copying the DECL_VALUE_EXPR, and fixing up the type. */
1156 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1158 tree new_decl
, size
;
1160 new_decl
= lookup_decl (decl
, ctx
);
1162 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1164 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1165 && DECL_HAS_VALUE_EXPR_P (decl
))
1167 tree ve
= DECL_VALUE_EXPR (decl
);
1168 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1169 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1170 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1173 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1175 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1176 if (size
== error_mark_node
)
1177 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1178 DECL_SIZE (new_decl
) = size
;
1180 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1181 if (size
== error_mark_node
)
1182 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1183 DECL_SIZE_UNIT (new_decl
) = size
;
1187 /* The callback for remap_decl. Search all containing contexts for a
1188 mapping of the variable; this avoids having to duplicate the splay
1189 tree ahead of time. We know a mapping doesn't already exist in the
1190 given context. Create new mappings to implement default semantics. */
1193 omp_copy_decl (tree var
, copy_body_data
*cb
)
1195 omp_context
*ctx
= (omp_context
*) cb
;
1198 if (TREE_CODE (var
) == LABEL_DECL
)
1200 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1201 DECL_CONTEXT (new_var
) = current_function_decl
;
1202 insert_decl_map (&ctx
->cb
, var
, new_var
);
1206 while (!is_taskreg_ctx (ctx
))
1211 new_var
= maybe_lookup_decl (var
, ctx
);
1216 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1219 return error_mark_node
;
1223 /* Debugging dumps for parallel regions. */
1224 void dump_omp_region (FILE *, struct omp_region
*, int);
1225 void debug_omp_region (struct omp_region
*);
1226 void debug_all_omp_regions (void);
1228 /* Dump the parallel region tree rooted at REGION. */
1231 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1233 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1234 gimple_code_name
[region
->type
]);
1237 dump_omp_region (file
, region
->inner
, indent
+ 4);
1241 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1242 region
->cont
->index
);
1246 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1247 region
->exit
->index
);
1249 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1252 dump_omp_region (file
, region
->next
, indent
);
1256 debug_omp_region (struct omp_region
*region
)
1258 dump_omp_region (stderr
, region
, 0);
1262 debug_all_omp_regions (void)
1264 dump_omp_region (stderr
, root_omp_region
, 0);
1268 /* Create a new parallel region starting at STMT inside region PARENT. */
1270 static struct omp_region
*
1271 new_omp_region (basic_block bb
, enum gimple_code type
,
1272 struct omp_region
*parent
)
1274 struct omp_region
*region
= XCNEW (struct omp_region
);
1276 region
->outer
= parent
;
1278 region
->type
= type
;
1282 /* This is a nested region. Add it to the list of inner
1283 regions in PARENT. */
1284 region
->next
= parent
->inner
;
1285 parent
->inner
= region
;
1289 /* This is a toplevel region. Add it to the list of toplevel
1290 regions in ROOT_OMP_REGION. */
1291 region
->next
= root_omp_region
;
1292 root_omp_region
= region
;
1298 /* Release the memory associated with the region tree rooted at REGION. */
1301 free_omp_region_1 (struct omp_region
*region
)
1303 struct omp_region
*i
, *n
;
1305 for (i
= region
->inner
; i
; i
= n
)
1308 free_omp_region_1 (i
);
1314 /* Release the memory for the entire omp region tree. */
1317 free_omp_regions (void)
1319 struct omp_region
*r
, *n
;
1320 for (r
= root_omp_region
; r
; r
= n
)
1323 free_omp_region_1 (r
);
1325 root_omp_region
= NULL
;
1329 /* Create a new context, with OUTER_CTX being the surrounding context. */
1331 static omp_context
*
1332 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1334 omp_context
*ctx
= XCNEW (omp_context
);
1336 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1337 (splay_tree_value
) ctx
);
1342 ctx
->outer
= outer_ctx
;
1343 ctx
->cb
= outer_ctx
->cb
;
1344 ctx
->cb
.block
= NULL
;
1345 ctx
->depth
= outer_ctx
->depth
+ 1;
1349 ctx
->cb
.src_fn
= current_function_decl
;
1350 ctx
->cb
.dst_fn
= current_function_decl
;
1351 ctx
->cb
.src_node
= cgraph_get_node (current_function_decl
);
1352 gcc_checking_assert (ctx
->cb
.src_node
);
1353 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1354 ctx
->cb
.src_cfun
= cfun
;
1355 ctx
->cb
.copy_decl
= omp_copy_decl
;
1356 ctx
->cb
.eh_lp_nr
= 0;
1357 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1361 ctx
->cb
.decl_map
= pointer_map_create ();
1366 static gimple_seq
maybe_catch_exception (gimple_seq
);
1368 /* Finalize task copyfn. */
1371 finalize_task_copyfn (gimple task_stmt
)
1373 struct function
*child_cfun
;
1375 gimple_seq seq
= NULL
, new_seq
;
1378 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1379 if (child_fn
== NULL_TREE
)
1382 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1383 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1385 push_cfun (child_cfun
);
1386 bind
= gimplify_body (child_fn
, false);
1387 gimple_seq_add_stmt (&seq
, bind
);
1388 new_seq
= maybe_catch_exception (seq
);
1391 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1393 gimple_seq_add_stmt (&seq
, bind
);
1395 gimple_set_body (child_fn
, seq
);
1398 /* Inform the callgraph about the new function. */
1399 cgraph_add_new_function (child_fn
, false);
1402 /* Destroy a omp_context data structures. Called through the splay tree
1403 value delete callback. */
1406 delete_omp_context (splay_tree_value value
)
1408 omp_context
*ctx
= (omp_context
*) value
;
1410 pointer_map_destroy (ctx
->cb
.decl_map
);
1413 splay_tree_delete (ctx
->field_map
);
1414 if (ctx
->sfield_map
)
1415 splay_tree_delete (ctx
->sfield_map
);
1417 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1418 it produces corrupt debug information. */
1419 if (ctx
->record_type
)
1422 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1423 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1425 if (ctx
->srecord_type
)
1428 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1429 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1432 if (is_task_ctx (ctx
))
1433 finalize_task_copyfn (ctx
->stmt
);
1438 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1442 fixup_child_record_type (omp_context
*ctx
)
1444 tree f
, type
= ctx
->record_type
;
1446 /* ??? It isn't sufficient to just call remap_type here, because
1447 variably_modified_type_p doesn't work the way we expect for
1448 record types. Testing each field for whether it needs remapping
1449 and creating a new record by hand works, however. */
1450 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1451 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1455 tree name
, new_fields
= NULL
;
1457 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1458 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1459 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1460 TYPE_DECL
, name
, type
);
1461 TYPE_NAME (type
) = name
;
1463 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1465 tree new_f
= copy_node (f
);
1466 DECL_CONTEXT (new_f
) = type
;
1467 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1468 DECL_CHAIN (new_f
) = new_fields
;
1469 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1470 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1472 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1476 /* Arrange to be able to look up the receiver field
1477 given the sender field. */
1478 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1479 (splay_tree_value
) new_f
);
1481 TYPE_FIELDS (type
) = nreverse (new_fields
);
1485 TREE_TYPE (ctx
->receiver_decl
) = build_pointer_type (type
);
1488 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1489 specified by CLAUSES. */
1492 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1495 bool scan_array_reductions
= false;
1497 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1501 switch (OMP_CLAUSE_CODE (c
))
1503 case OMP_CLAUSE_PRIVATE
:
1504 decl
= OMP_CLAUSE_DECL (c
);
1505 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1507 else if (!is_variable_sized (decl
))
1508 install_var_local (decl
, ctx
);
1511 case OMP_CLAUSE_SHARED
:
1512 decl
= OMP_CLAUSE_DECL (c
);
1513 /* Ignore shared directives in teams construct. */
1514 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1516 /* Global variables don't need to be copied,
1517 the receiver side will use them directly. */
1518 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1519 if (is_global_var (odecl
))
1521 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1524 gcc_assert (is_taskreg_ctx (ctx
));
1525 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1526 || !is_variable_sized (decl
));
1527 /* Global variables don't need to be copied,
1528 the receiver side will use them directly. */
1529 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1531 by_ref
= use_pointer_for_field (decl
, ctx
);
1532 if (! TREE_READONLY (decl
)
1533 || TREE_ADDRESSABLE (decl
)
1535 || is_reference (decl
))
1537 install_var_field (decl
, by_ref
, 3, ctx
);
1538 install_var_local (decl
, ctx
);
1541 /* We don't need to copy const scalar vars back. */
1542 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1545 case OMP_CLAUSE_LASTPRIVATE
:
1546 /* Let the corresponding firstprivate clause create
1548 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1552 case OMP_CLAUSE_FIRSTPRIVATE
:
1553 case OMP_CLAUSE_REDUCTION
:
1554 case OMP_CLAUSE_LINEAR
:
1555 decl
= OMP_CLAUSE_DECL (c
);
1557 if (is_variable_sized (decl
))
1559 if (is_task_ctx (ctx
))
1560 install_var_field (decl
, false, 1, ctx
);
1563 else if (is_taskreg_ctx (ctx
))
1566 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1567 by_ref
= use_pointer_for_field (decl
, NULL
);
1569 if (is_task_ctx (ctx
)
1570 && (global
|| by_ref
|| is_reference (decl
)))
1572 install_var_field (decl
, false, 1, ctx
);
1574 install_var_field (decl
, by_ref
, 2, ctx
);
1577 install_var_field (decl
, by_ref
, 3, ctx
);
1579 install_var_local (decl
, ctx
);
1582 case OMP_CLAUSE__LOOPTEMP_
:
1583 gcc_assert (is_parallel_ctx (ctx
));
1584 decl
= OMP_CLAUSE_DECL (c
);
1585 install_var_field (decl
, false, 3, ctx
);
1586 install_var_local (decl
, ctx
);
1589 case OMP_CLAUSE_COPYPRIVATE
:
1590 case OMP_CLAUSE_COPYIN
:
1591 decl
= OMP_CLAUSE_DECL (c
);
1592 by_ref
= use_pointer_for_field (decl
, NULL
);
1593 install_var_field (decl
, by_ref
, 3, ctx
);
1596 case OMP_CLAUSE_DEFAULT
:
1597 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1600 case OMP_CLAUSE_FINAL
:
1602 case OMP_CLAUSE_NUM_THREADS
:
1603 case OMP_CLAUSE_NUM_TEAMS
:
1604 case OMP_CLAUSE_THREAD_LIMIT
:
1605 case OMP_CLAUSE_DEVICE
:
1606 case OMP_CLAUSE_SCHEDULE
:
1607 case OMP_CLAUSE_DIST_SCHEDULE
:
1608 case OMP_CLAUSE_DEPEND
:
1610 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1614 case OMP_CLAUSE_FROM
:
1615 case OMP_CLAUSE_MAP
:
1617 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1618 decl
= OMP_CLAUSE_DECL (c
);
1619 /* Global variables with "omp declare target" attribute
1620 don't need to be copied, the receiver side will use them
1622 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1624 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1625 && lookup_attribute ("omp declare target",
1626 DECL_ATTRIBUTES (decl
)))
1628 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1629 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
)
1631 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1632 #pragma omp target data, there is nothing to map for
1634 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
1635 && !POINTER_TYPE_P (TREE_TYPE (decl
)))
1640 if (DECL_SIZE (decl
)
1641 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1643 tree decl2
= DECL_VALUE_EXPR (decl
);
1644 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1645 decl2
= TREE_OPERAND (decl2
, 0);
1646 gcc_assert (DECL_P (decl2
));
1647 install_var_field (decl2
, true, 3, ctx
);
1648 install_var_local (decl2
, ctx
);
1649 install_var_local (decl
, ctx
);
1653 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1654 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1655 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1656 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1657 install_var_field (decl
, true, 7, ctx
);
1659 install_var_field (decl
, true, 3, ctx
);
1660 if (gimple_omp_target_kind (ctx
->stmt
)
1661 == GF_OMP_TARGET_KIND_REGION
)
1662 install_var_local (decl
, ctx
);
1667 tree base
= get_base_address (decl
);
1668 tree nc
= OMP_CLAUSE_CHAIN (c
);
1671 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1672 && OMP_CLAUSE_DECL (nc
) == base
1673 && OMP_CLAUSE_MAP_KIND (nc
) == OMP_CLAUSE_MAP_POINTER
1674 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1676 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1677 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1681 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1682 (splay_tree_key
) decl
));
1684 = build_decl (OMP_CLAUSE_LOCATION (c
),
1685 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1686 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1687 insert_field_into_struct (ctx
->record_type
, field
);
1688 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1689 (splay_tree_value
) field
);
1694 case OMP_CLAUSE_NOWAIT
:
1695 case OMP_CLAUSE_ORDERED
:
1696 case OMP_CLAUSE_COLLAPSE
:
1697 case OMP_CLAUSE_UNTIED
:
1698 case OMP_CLAUSE_MERGEABLE
:
1699 case OMP_CLAUSE_PROC_BIND
:
1700 case OMP_CLAUSE_SAFELEN
:
1703 case OMP_CLAUSE_ALIGNED
:
1704 decl
= OMP_CLAUSE_DECL (c
);
1705 if (is_global_var (decl
)
1706 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1707 install_var_local (decl
, ctx
);
1715 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1717 switch (OMP_CLAUSE_CODE (c
))
1719 case OMP_CLAUSE_LASTPRIVATE
:
1720 /* Let the corresponding firstprivate clause create
1722 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1723 scan_array_reductions
= true;
1724 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1728 case OMP_CLAUSE_PRIVATE
:
1729 case OMP_CLAUSE_FIRSTPRIVATE
:
1730 case OMP_CLAUSE_REDUCTION
:
1731 case OMP_CLAUSE_LINEAR
:
1732 decl
= OMP_CLAUSE_DECL (c
);
1733 if (is_variable_sized (decl
))
1734 install_var_local (decl
, ctx
);
1735 fixup_remapped_decl (decl
, ctx
,
1736 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1737 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1738 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1739 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1740 scan_array_reductions
= true;
1741 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1742 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1743 scan_array_reductions
= true;
1746 case OMP_CLAUSE_SHARED
:
1747 /* Ignore shared directives in teams construct. */
1748 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1750 decl
= OMP_CLAUSE_DECL (c
);
1751 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1752 fixup_remapped_decl (decl
, ctx
, false);
1755 case OMP_CLAUSE_MAP
:
1756 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
)
1758 decl
= OMP_CLAUSE_DECL (c
);
1760 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1761 && lookup_attribute ("omp declare target",
1762 DECL_ATTRIBUTES (decl
)))
1766 if (OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1767 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1768 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1770 tree new_decl
= lookup_decl (decl
, ctx
);
1771 TREE_TYPE (new_decl
)
1772 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1774 else if (DECL_SIZE (decl
)
1775 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1777 tree decl2
= DECL_VALUE_EXPR (decl
);
1778 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1779 decl2
= TREE_OPERAND (decl2
, 0);
1780 gcc_assert (DECL_P (decl2
));
1781 fixup_remapped_decl (decl2
, ctx
, false);
1782 fixup_remapped_decl (decl
, ctx
, true);
1785 fixup_remapped_decl (decl
, ctx
, false);
1789 case OMP_CLAUSE_COPYPRIVATE
:
1790 case OMP_CLAUSE_COPYIN
:
1791 case OMP_CLAUSE_DEFAULT
:
1793 case OMP_CLAUSE_NUM_THREADS
:
1794 case OMP_CLAUSE_NUM_TEAMS
:
1795 case OMP_CLAUSE_THREAD_LIMIT
:
1796 case OMP_CLAUSE_DEVICE
:
1797 case OMP_CLAUSE_SCHEDULE
:
1798 case OMP_CLAUSE_DIST_SCHEDULE
:
1799 case OMP_CLAUSE_NOWAIT
:
1800 case OMP_CLAUSE_ORDERED
:
1801 case OMP_CLAUSE_COLLAPSE
:
1802 case OMP_CLAUSE_UNTIED
:
1803 case OMP_CLAUSE_FINAL
:
1804 case OMP_CLAUSE_MERGEABLE
:
1805 case OMP_CLAUSE_PROC_BIND
:
1806 case OMP_CLAUSE_SAFELEN
:
1807 case OMP_CLAUSE_ALIGNED
:
1808 case OMP_CLAUSE_DEPEND
:
1809 case OMP_CLAUSE__LOOPTEMP_
:
1811 case OMP_CLAUSE_FROM
:
1819 if (scan_array_reductions
)
1820 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1821 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1822 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1824 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
1825 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
1827 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
1828 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1829 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
1830 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1831 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1832 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
1835 /* Create a new name for omp child function. Returns an identifier. */
1838 create_omp_child_function_name (bool task_copy
)
1840 return (clone_function_name (current_function_decl
,
1841 task_copy
? "_omp_cpyfn" : "_omp_fn"));
1844 /* Build a decl for the omp child function. It'll not contain a body
1845 yet, just the bare decl. */
1848 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
1850 tree decl
, type
, name
, t
;
1852 name
= create_omp_child_function_name (task_copy
);
1854 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1855 ptr_type_node
, NULL_TREE
);
1857 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
1859 decl
= build_decl (gimple_location (ctx
->stmt
),
1860 FUNCTION_DECL
, name
, type
);
1863 ctx
->cb
.dst_fn
= decl
;
1865 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
1867 TREE_STATIC (decl
) = 1;
1868 TREE_USED (decl
) = 1;
1869 DECL_ARTIFICIAL (decl
) = 1;
1870 DECL_NAMELESS (decl
) = 1;
1871 DECL_IGNORED_P (decl
) = 0;
1872 TREE_PUBLIC (decl
) = 0;
1873 DECL_UNINLINABLE (decl
) = 1;
1874 DECL_EXTERNAL (decl
) = 0;
1875 DECL_CONTEXT (decl
) = NULL_TREE
;
1876 DECL_INITIAL (decl
) = make_node (BLOCK
);
1877 bool target_p
= false;
1878 if (lookup_attribute ("omp declare target",
1879 DECL_ATTRIBUTES (current_function_decl
)))
1884 for (octx
= ctx
; octx
; octx
= octx
->outer
)
1885 if (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
1886 && gimple_omp_target_kind (octx
->stmt
)
1887 == GF_OMP_TARGET_KIND_REGION
)
1894 DECL_ATTRIBUTES (decl
)
1895 = tree_cons (get_identifier ("omp declare target"),
1896 NULL_TREE
, DECL_ATTRIBUTES (decl
));
1898 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1899 RESULT_DECL
, NULL_TREE
, void_type_node
);
1900 DECL_ARTIFICIAL (t
) = 1;
1901 DECL_IGNORED_P (t
) = 1;
1902 DECL_CONTEXT (t
) = decl
;
1903 DECL_RESULT (decl
) = t
;
1905 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1906 PARM_DECL
, get_identifier (".omp_data_i"), ptr_type_node
);
1907 DECL_ARTIFICIAL (t
) = 1;
1908 DECL_NAMELESS (t
) = 1;
1909 DECL_ARG_TYPE (t
) = ptr_type_node
;
1910 DECL_CONTEXT (t
) = current_function_decl
;
1912 DECL_ARGUMENTS (decl
) = t
;
1914 ctx
->receiver_decl
= t
;
1917 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1918 PARM_DECL
, get_identifier (".omp_data_o"),
1920 DECL_ARTIFICIAL (t
) = 1;
1921 DECL_NAMELESS (t
) = 1;
1922 DECL_ARG_TYPE (t
) = ptr_type_node
;
1923 DECL_CONTEXT (t
) = current_function_decl
;
1925 TREE_ADDRESSABLE (t
) = 1;
1926 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1927 DECL_ARGUMENTS (decl
) = t
;
1930 /* Allocate memory for the function structure. The call to
1931 allocate_struct_function clobbers CFUN, so we need to restore
1933 push_struct_function (decl
);
1934 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
1938 /* Callback for walk_gimple_seq. Check if combined parallel
1939 contains gimple_omp_for_combined_into_p OMP_FOR. */
1942 find_combined_for (gimple_stmt_iterator
*gsi_p
,
1943 bool *handled_ops_p
,
1944 struct walk_stmt_info
*wi
)
1946 gimple stmt
= gsi_stmt (*gsi_p
);
1948 *handled_ops_p
= true;
1949 switch (gimple_code (stmt
))
1953 case GIMPLE_OMP_FOR
:
1954 if (gimple_omp_for_combined_into_p (stmt
)
1955 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
1958 return integer_zero_node
;
1967 /* Scan an OpenMP parallel directive. */
1970 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
1974 gimple stmt
= gsi_stmt (*gsi
);
1976 /* Ignore parallel directives with empty bodies, unless there
1977 are copyin clauses. */
1979 && empty_body_p (gimple_omp_body (stmt
))
1980 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
1981 OMP_CLAUSE_COPYIN
) == NULL
)
1983 gsi_replace (gsi
, gimple_build_nop (), false);
1987 if (gimple_omp_parallel_combined_p (stmt
))
1990 struct walk_stmt_info wi
;
1992 memset (&wi
, 0, sizeof (wi
));
1994 walk_gimple_seq (gimple_omp_body (stmt
),
1995 find_combined_for
, NULL
, &wi
);
1996 for_stmt
= (gimple
) wi
.info
;
1999 struct omp_for_data fd
;
2000 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2001 /* We need two temporaries with fd.loop.v type (istart/iend)
2002 and then (fd.collapse - 1) temporaries with the same
2003 type for count2 ... countN-1 vars if not constant. */
2004 size_t count
= 2, i
;
2005 tree type
= fd
.iter_type
;
2007 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2008 count
+= fd
.collapse
- 1;
2009 for (i
= 0; i
< count
; i
++)
2011 tree temp
= create_tmp_var (type
, NULL
);
2012 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2013 OMP_CLAUSE__LOOPTEMP_
);
2014 OMP_CLAUSE_DECL (c
) = temp
;
2015 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2016 gimple_omp_parallel_set_clauses (stmt
, c
);
2021 ctx
= new_omp_context (stmt
, outer_ctx
);
2022 if (taskreg_nesting_level
> 1)
2023 ctx
->is_nested
= true;
2024 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2025 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2026 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2027 name
= create_tmp_var_name (".omp_data_s");
2028 name
= build_decl (gimple_location (stmt
),
2029 TYPE_DECL
, name
, ctx
->record_type
);
2030 DECL_ARTIFICIAL (name
) = 1;
2031 DECL_NAMELESS (name
) = 1;
2032 TYPE_NAME (ctx
->record_type
) = name
;
2033 create_omp_child_function (ctx
, false);
2034 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2036 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2037 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2039 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2040 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2043 layout_type (ctx
->record_type
);
2044 fixup_child_record_type (ctx
);
2048 /* Scan an OpenMP task directive. */
2051 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2055 gimple stmt
= gsi_stmt (*gsi
);
2056 location_t loc
= gimple_location (stmt
);
2058 /* Ignore task directives with empty bodies. */
2060 && empty_body_p (gimple_omp_body (stmt
)))
2062 gsi_replace (gsi
, gimple_build_nop (), false);
2066 ctx
= new_omp_context (stmt
, outer_ctx
);
2067 if (taskreg_nesting_level
> 1)
2068 ctx
->is_nested
= true;
2069 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2070 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2071 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2072 name
= create_tmp_var_name (".omp_data_s");
2073 name
= build_decl (gimple_location (stmt
),
2074 TYPE_DECL
, name
, ctx
->record_type
);
2075 DECL_ARTIFICIAL (name
) = 1;
2076 DECL_NAMELESS (name
) = 1;
2077 TYPE_NAME (ctx
->record_type
) = name
;
2078 create_omp_child_function (ctx
, false);
2079 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2081 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2083 if (ctx
->srecord_type
)
2085 name
= create_tmp_var_name (".omp_data_a");
2086 name
= build_decl (gimple_location (stmt
),
2087 TYPE_DECL
, name
, ctx
->srecord_type
);
2088 DECL_ARTIFICIAL (name
) = 1;
2089 DECL_NAMELESS (name
) = 1;
2090 TYPE_NAME (ctx
->srecord_type
) = name
;
2091 create_omp_child_function (ctx
, true);
2094 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2096 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2098 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2099 t
= build_int_cst (long_integer_type_node
, 0);
2100 gimple_omp_task_set_arg_size (stmt
, t
);
2101 t
= build_int_cst (long_integer_type_node
, 1);
2102 gimple_omp_task_set_arg_align (stmt
, t
);
2106 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2107 /* Move VLA fields to the end. */
2108 p
= &TYPE_FIELDS (ctx
->record_type
);
2110 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2111 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2114 *p
= TREE_CHAIN (*p
);
2115 TREE_CHAIN (*q
) = NULL_TREE
;
2116 q
= &TREE_CHAIN (*q
);
2119 p
= &DECL_CHAIN (*p
);
2121 layout_type (ctx
->record_type
);
2122 fixup_child_record_type (ctx
);
2123 if (ctx
->srecord_type
)
2124 layout_type (ctx
->srecord_type
);
2125 t
= fold_convert_loc (loc
, long_integer_type_node
,
2126 TYPE_SIZE_UNIT (ctx
->record_type
));
2127 gimple_omp_task_set_arg_size (stmt
, t
);
2128 t
= build_int_cst (long_integer_type_node
,
2129 TYPE_ALIGN_UNIT (ctx
->record_type
));
2130 gimple_omp_task_set_arg_align (stmt
, t
);
2135 /* Scan an OpenMP loop directive. */
2138 scan_omp_for (gimple stmt
, omp_context
*outer_ctx
)
2143 ctx
= new_omp_context (stmt
, outer_ctx
);
2145 scan_sharing_clauses (gimple_omp_for_clauses (stmt
), ctx
);
2147 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2148 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2150 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2151 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2152 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2153 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2155 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2158 /* Scan an OpenMP sections directive. */
2161 scan_omp_sections (gimple stmt
, omp_context
*outer_ctx
)
2165 ctx
= new_omp_context (stmt
, outer_ctx
);
2166 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2167 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2170 /* Scan an OpenMP single directive. */
2173 scan_omp_single (gimple stmt
, omp_context
*outer_ctx
)
2178 ctx
= new_omp_context (stmt
, outer_ctx
);
2179 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2180 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2181 name
= create_tmp_var_name (".omp_copy_s");
2182 name
= build_decl (gimple_location (stmt
),
2183 TYPE_DECL
, name
, ctx
->record_type
);
2184 TYPE_NAME (ctx
->record_type
) = name
;
2186 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2187 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2189 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2190 ctx
->record_type
= NULL
;
2192 layout_type (ctx
->record_type
);
2195 /* Scan an OpenMP target{, data, update} directive. */
2198 scan_omp_target (gimple stmt
, omp_context
*outer_ctx
)
2202 int kind
= gimple_omp_target_kind (stmt
);
2204 ctx
= new_omp_context (stmt
, outer_ctx
);
2205 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2206 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2207 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2208 name
= create_tmp_var_name (".omp_data_t");
2209 name
= build_decl (gimple_location (stmt
),
2210 TYPE_DECL
, name
, ctx
->record_type
);
2211 DECL_ARTIFICIAL (name
) = 1;
2212 DECL_NAMELESS (name
) = 1;
2213 TYPE_NAME (ctx
->record_type
) = name
;
2214 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2216 create_omp_child_function (ctx
, false);
2217 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2220 scan_sharing_clauses (gimple_omp_target_clauses (stmt
), ctx
);
2221 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2223 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2224 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2227 TYPE_FIELDS (ctx
->record_type
)
2228 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2229 #ifdef ENABLE_CHECKING
2231 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2232 for (field
= TYPE_FIELDS (ctx
->record_type
);
2234 field
= DECL_CHAIN (field
))
2235 gcc_assert (DECL_ALIGN (field
) == align
);
2237 layout_type (ctx
->record_type
);
2238 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2239 fixup_child_record_type (ctx
);
2243 /* Scan an OpenMP teams directive. */
2246 scan_omp_teams (gimple stmt
, omp_context
*outer_ctx
)
2248 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2249 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2250 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2253 /* Check OpenMP nesting restrictions. */
2255 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2259 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2260 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2262 error_at (gimple_location (stmt
),
2263 "OpenMP constructs may not be nested inside simd region");
2266 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2268 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2269 || (gimple_omp_for_kind (stmt
)
2270 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2271 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2273 error_at (gimple_location (stmt
),
2274 "only distribute or parallel constructs are allowed to "
2275 "be closely nested inside teams construct");
2280 switch (gimple_code (stmt
))
2282 case GIMPLE_OMP_FOR
:
2283 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2285 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2287 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2289 error_at (gimple_location (stmt
),
2290 "distribute construct must be closely nested inside "
2298 if (is_gimple_call (stmt
)
2299 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2300 == BUILT_IN_GOMP_CANCEL
2301 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2302 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2304 const char *bad
= NULL
;
2305 const char *kind
= NULL
;
2308 error_at (gimple_location (stmt
), "orphaned %qs construct",
2309 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2310 == BUILT_IN_GOMP_CANCEL
2311 ? "#pragma omp cancel"
2312 : "#pragma omp cancellation point");
2315 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2316 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2320 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2321 bad
= "#pragma omp parallel";
2322 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2323 == BUILT_IN_GOMP_CANCEL
2324 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2325 ctx
->cancellable
= true;
2329 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2330 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2331 bad
= "#pragma omp for";
2332 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2333 == BUILT_IN_GOMP_CANCEL
2334 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2336 ctx
->cancellable
= true;
2337 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2339 warning_at (gimple_location (stmt
), 0,
2340 "%<#pragma omp cancel for%> inside "
2341 "%<nowait%> for construct");
2342 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2343 OMP_CLAUSE_ORDERED
))
2344 warning_at (gimple_location (stmt
), 0,
2345 "%<#pragma omp cancel for%> inside "
2346 "%<ordered%> for construct");
2351 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2352 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2353 bad
= "#pragma omp sections";
2354 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2355 == BUILT_IN_GOMP_CANCEL
2356 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2358 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2360 ctx
->cancellable
= true;
2361 if (find_omp_clause (gimple_omp_sections_clauses
2364 warning_at (gimple_location (stmt
), 0,
2365 "%<#pragma omp cancel sections%> inside "
2366 "%<nowait%> sections construct");
2370 gcc_assert (ctx
->outer
2371 && gimple_code (ctx
->outer
->stmt
)
2372 == GIMPLE_OMP_SECTIONS
);
2373 ctx
->outer
->cancellable
= true;
2374 if (find_omp_clause (gimple_omp_sections_clauses
2377 warning_at (gimple_location (stmt
), 0,
2378 "%<#pragma omp cancel sections%> inside "
2379 "%<nowait%> sections construct");
2385 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2386 bad
= "#pragma omp task";
2388 ctx
->cancellable
= true;
2392 error_at (gimple_location (stmt
), "invalid arguments");
2397 error_at (gimple_location (stmt
),
2398 "%<%s %s%> construct not closely nested inside of %qs",
2399 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2400 == BUILT_IN_GOMP_CANCEL
2401 ? "#pragma omp cancel"
2402 : "#pragma omp cancellation point", kind
, bad
);
2407 case GIMPLE_OMP_SECTIONS
:
2408 case GIMPLE_OMP_SINGLE
:
2409 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2410 switch (gimple_code (ctx
->stmt
))
2412 case GIMPLE_OMP_FOR
:
2413 case GIMPLE_OMP_SECTIONS
:
2414 case GIMPLE_OMP_SINGLE
:
2415 case GIMPLE_OMP_ORDERED
:
2416 case GIMPLE_OMP_MASTER
:
2417 case GIMPLE_OMP_TASK
:
2418 case GIMPLE_OMP_CRITICAL
:
2419 if (is_gimple_call (stmt
))
2421 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2422 != BUILT_IN_GOMP_BARRIER
)
2424 error_at (gimple_location (stmt
),
2425 "barrier region may not be closely nested inside "
2426 "of work-sharing, critical, ordered, master or "
2427 "explicit task region");
2430 error_at (gimple_location (stmt
),
2431 "work-sharing region may not be closely nested inside "
2432 "of work-sharing, critical, ordered, master or explicit "
2435 case GIMPLE_OMP_PARALLEL
:
2441 case GIMPLE_OMP_MASTER
:
2442 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2443 switch (gimple_code (ctx
->stmt
))
2445 case GIMPLE_OMP_FOR
:
2446 case GIMPLE_OMP_SECTIONS
:
2447 case GIMPLE_OMP_SINGLE
:
2448 case GIMPLE_OMP_TASK
:
2449 error_at (gimple_location (stmt
),
2450 "master region may not be closely nested inside "
2451 "of work-sharing or explicit task region");
2453 case GIMPLE_OMP_PARALLEL
:
2459 case GIMPLE_OMP_ORDERED
:
2460 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2461 switch (gimple_code (ctx
->stmt
))
2463 case GIMPLE_OMP_CRITICAL
:
2464 case GIMPLE_OMP_TASK
:
2465 error_at (gimple_location (stmt
),
2466 "ordered region may not be closely nested inside "
2467 "of critical or explicit task region");
2469 case GIMPLE_OMP_FOR
:
2470 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2471 OMP_CLAUSE_ORDERED
) == NULL
)
2473 error_at (gimple_location (stmt
),
2474 "ordered region must be closely nested inside "
2475 "a loop region with an ordered clause");
2479 case GIMPLE_OMP_PARALLEL
:
2480 error_at (gimple_location (stmt
),
2481 "ordered region must be closely nested inside "
2482 "a loop region with an ordered clause");
2488 case GIMPLE_OMP_CRITICAL
:
2489 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2490 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_CRITICAL
2491 && (gimple_omp_critical_name (stmt
)
2492 == gimple_omp_critical_name (ctx
->stmt
)))
2494 error_at (gimple_location (stmt
),
2495 "critical region may not be nested inside a critical "
2496 "region with the same name");
2500 case GIMPLE_OMP_TEAMS
:
2502 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2503 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2505 error_at (gimple_location (stmt
),
2506 "teams construct not closely nested inside of target "
2518 /* Helper function scan_omp.
2520 Callback for walk_tree or operators in walk_gimple_stmt used to
2521 scan for OpenMP directives in TP. */
2524 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
2526 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
2527 omp_context
*ctx
= (omp_context
*) wi
->info
;
2530 switch (TREE_CODE (t
))
2537 *tp
= remap_decl (t
, &ctx
->cb
);
2541 if (ctx
&& TYPE_P (t
))
2542 *tp
= remap_type (t
, &ctx
->cb
);
2543 else if (!DECL_P (t
))
2548 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
2549 if (tem
!= TREE_TYPE (t
))
2551 if (TREE_CODE (t
) == INTEGER_CST
)
2552 *tp
= wide_int_to_tree (tem
, t
);
2554 TREE_TYPE (t
) = tem
;
2564 /* Return true if FNDECL is a setjmp or a longjmp. */
2567 setjmp_or_longjmp_p (const_tree fndecl
)
2569 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
2570 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
2571 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
2574 tree declname
= DECL_NAME (fndecl
);
2577 const char *name
= IDENTIFIER_POINTER (declname
);
2578 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
2582 /* Helper function for scan_omp.
2584 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2585 the current statement in GSI. */
2588 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
2589 struct walk_stmt_info
*wi
)
2591 gimple stmt
= gsi_stmt (*gsi
);
2592 omp_context
*ctx
= (omp_context
*) wi
->info
;
2594 if (gimple_has_location (stmt
))
2595 input_location
= gimple_location (stmt
);
2597 /* Check the OpenMP nesting restrictions. */
2598 bool remove
= false;
2599 if (is_gimple_omp (stmt
))
2600 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2601 else if (is_gimple_call (stmt
))
2603 tree fndecl
= gimple_call_fndecl (stmt
);
2606 if (setjmp_or_longjmp_p (fndecl
)
2608 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2609 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2612 error_at (gimple_location (stmt
),
2613 "setjmp/longjmp inside simd construct");
2615 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
2616 switch (DECL_FUNCTION_CODE (fndecl
))
2618 case BUILT_IN_GOMP_BARRIER
:
2619 case BUILT_IN_GOMP_CANCEL
:
2620 case BUILT_IN_GOMP_CANCELLATION_POINT
:
2621 case BUILT_IN_GOMP_TASKYIELD
:
2622 case BUILT_IN_GOMP_TASKWAIT
:
2623 case BUILT_IN_GOMP_TASKGROUP_START
:
2624 case BUILT_IN_GOMP_TASKGROUP_END
:
2625 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2634 stmt
= gimple_build_nop ();
2635 gsi_replace (gsi
, stmt
, false);
2638 *handled_ops_p
= true;
2640 switch (gimple_code (stmt
))
2642 case GIMPLE_OMP_PARALLEL
:
2643 taskreg_nesting_level
++;
2644 scan_omp_parallel (gsi
, ctx
);
2645 taskreg_nesting_level
--;
2648 case GIMPLE_OMP_TASK
:
2649 taskreg_nesting_level
++;
2650 scan_omp_task (gsi
, ctx
);
2651 taskreg_nesting_level
--;
2654 case GIMPLE_OMP_FOR
:
2655 scan_omp_for (stmt
, ctx
);
2658 case GIMPLE_OMP_SECTIONS
:
2659 scan_omp_sections (stmt
, ctx
);
2662 case GIMPLE_OMP_SINGLE
:
2663 scan_omp_single (stmt
, ctx
);
2666 case GIMPLE_OMP_SECTION
:
2667 case GIMPLE_OMP_MASTER
:
2668 case GIMPLE_OMP_TASKGROUP
:
2669 case GIMPLE_OMP_ORDERED
:
2670 case GIMPLE_OMP_CRITICAL
:
2671 ctx
= new_omp_context (stmt
, ctx
);
2672 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2675 case GIMPLE_OMP_TARGET
:
2676 scan_omp_target (stmt
, ctx
);
2679 case GIMPLE_OMP_TEAMS
:
2680 scan_omp_teams (stmt
, ctx
);
2687 *handled_ops_p
= false;
2689 for (var
= gimple_bind_vars (stmt
); var
; var
= DECL_CHAIN (var
))
2690 insert_decl_map (&ctx
->cb
, var
, var
);
2694 *handled_ops_p
= false;
2702 /* Scan all the statements starting at the current statement. CTX
2703 contains context information about the OpenMP directives and
2704 clauses found during the scan. */
2707 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
2709 location_t saved_location
;
2710 struct walk_stmt_info wi
;
2712 memset (&wi
, 0, sizeof (wi
));
2714 wi
.want_locations
= true;
2716 saved_location
= input_location
;
2717 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
2718 input_location
= saved_location
;
2721 /* Re-gimplification and code generation routines. */
2723 /* Build a call to GOMP_barrier. */
2726 build_omp_barrier (tree lhs
)
2728 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
2729 : BUILT_IN_GOMP_BARRIER
);
2730 gimple g
= gimple_build_call (fndecl
, 0);
2732 gimple_call_set_lhs (g
, lhs
);
2736 /* If a context was created for STMT when it was scanned, return it. */
2738 static omp_context
*
2739 maybe_lookup_ctx (gimple stmt
)
2742 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
2743 return n
? (omp_context
*) n
->value
: NULL
;
2747 /* Find the mapping for DECL in CTX or the immediately enclosing
2748 context that has a mapping for DECL.
2750 If CTX is a nested parallel directive, we may have to use the decl
2751 mappings created in CTX's parent context. Suppose that we have the
2752 following parallel nesting (variable UIDs showed for clarity):
2755 #omp parallel shared(iD.1562) -> outer parallel
2756 iD.1562 = iD.1562 + 1;
2758 #omp parallel shared (iD.1562) -> inner parallel
2759 iD.1562 = iD.1562 - 1;
2761 Each parallel structure will create a distinct .omp_data_s structure
2762 for copying iD.1562 in/out of the directive:
2764 outer parallel .omp_data_s.1.i -> iD.1562
2765 inner parallel .omp_data_s.2.i -> iD.1562
2767 A shared variable mapping will produce a copy-out operation before
2768 the parallel directive and a copy-in operation after it. So, in
2769 this case we would have:
2772 .omp_data_o.1.i = iD.1562;
2773 #omp parallel shared(iD.1562) -> outer parallel
2774 .omp_data_i.1 = &.omp_data_o.1
2775 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2777 .omp_data_o.2.i = iD.1562; -> **
2778 #omp parallel shared(iD.1562) -> inner parallel
2779 .omp_data_i.2 = &.omp_data_o.2
2780 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2783 ** This is a problem. The symbol iD.1562 cannot be referenced
2784 inside the body of the outer parallel region. But since we are
2785 emitting this copy operation while expanding the inner parallel
2786 directive, we need to access the CTX structure of the outer
2787 parallel directive to get the correct mapping:
2789 .omp_data_o.2.i = .omp_data_i.1->i
2791 Since there may be other workshare or parallel directives enclosing
2792 the parallel directive, it may be necessary to walk up the context
2793 parent chain. This is not a problem in general because nested
2794 parallelism happens only rarely. */
2797 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2802 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2803 t
= maybe_lookup_decl (decl
, up
);
2805 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
2807 return t
? t
: decl
;
2811 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2812 in outer contexts. */
2815 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2820 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2821 t
= maybe_lookup_decl (decl
, up
);
2823 return t
? t
: decl
;
2827 /* Construct the initialization value for reduction CLAUSE. */
2830 omp_reduction_init (tree clause
, tree type
)
2832 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
2833 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
2840 case TRUTH_ORIF_EXPR
:
2841 case TRUTH_XOR_EXPR
:
2843 return build_zero_cst (type
);
2846 case TRUTH_AND_EXPR
:
2847 case TRUTH_ANDIF_EXPR
:
2849 return fold_convert_loc (loc
, type
, integer_one_node
);
2852 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
2855 if (SCALAR_FLOAT_TYPE_P (type
))
2857 REAL_VALUE_TYPE max
, min
;
2858 if (HONOR_INFINITIES (TYPE_MODE (type
)))
2861 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
2864 real_maxval (&min
, 1, TYPE_MODE (type
));
2865 return build_real (type
, min
);
2869 gcc_assert (INTEGRAL_TYPE_P (type
));
2870 return TYPE_MIN_VALUE (type
);
2874 if (SCALAR_FLOAT_TYPE_P (type
))
2876 REAL_VALUE_TYPE max
;
2877 if (HONOR_INFINITIES (TYPE_MODE (type
)))
2880 real_maxval (&max
, 0, TYPE_MODE (type
));
2881 return build_real (type
, max
);
2885 gcc_assert (INTEGRAL_TYPE_P (type
));
2886 return TYPE_MAX_VALUE (type
);
2894 /* Return alignment to be assumed for var in CLAUSE, which should be
2895 OMP_CLAUSE_ALIGNED. */
2898 omp_clause_aligned_alignment (tree clause
)
2900 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
2901 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
2903 /* Otherwise return implementation defined alignment. */
2904 unsigned int al
= 1;
2905 enum machine_mode mode
, vmode
;
2906 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
2908 vs
= 1 << floor_log2 (vs
);
2909 static enum mode_class classes
[]
2910 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
2911 for (int i
= 0; i
< 4; i
+= 2)
2912 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
2914 mode
= GET_MODE_WIDER_MODE (mode
))
2916 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
2917 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
2920 && GET_MODE_SIZE (vmode
) < vs
2921 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
2922 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
2924 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
2925 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
2927 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
2928 / GET_MODE_SIZE (mode
));
2929 if (TYPE_MODE (type
) != vmode
)
2931 if (TYPE_ALIGN_UNIT (type
) > al
)
2932 al
= TYPE_ALIGN_UNIT (type
);
2934 return build_int_cst (integer_type_node
, al
);
2937 /* Return maximum possible vectorization factor for the target. */
2944 || !flag_tree_loop_optimize
2945 || (!flag_tree_loop_vectorize
2946 && (global_options_set
.x_flag_tree_loop_vectorize
2947 || global_options_set
.x_flag_tree_vectorize
)))
2950 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
2953 vs
= 1 << floor_log2 (vs
);
2956 enum machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
2957 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
2958 return GET_MODE_NUNITS (vqimode
);
2962 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2966 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
2967 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
2971 max_vf
= omp_max_vf ();
2974 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2975 OMP_CLAUSE_SAFELEN
);
2977 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
), max_vf
) == -1)
2978 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
2982 idx
= create_tmp_var (unsigned_type_node
, NULL
);
2983 lane
= create_tmp_var (unsigned_type_node
, NULL
);
2989 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
2990 tree avar
= create_tmp_var_raw (atype
, NULL
);
2991 if (TREE_ADDRESSABLE (new_var
))
2992 TREE_ADDRESSABLE (avar
) = 1;
2993 DECL_ATTRIBUTES (avar
)
2994 = tree_cons (get_identifier ("omp simd array"), NULL
,
2995 DECL_ATTRIBUTES (avar
));
2996 gimple_add_tmp_var (avar
);
2997 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
2998 NULL_TREE
, NULL_TREE
);
2999 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3000 NULL_TREE
, NULL_TREE
);
3001 if (DECL_P (new_var
))
3003 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3004 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3009 /* Helper function of lower_rec_input_clauses. For a reference
3010 in simd reduction, add an underlying variable it will reference. */
3013 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3015 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3016 if (TREE_CONSTANT (z
))
3018 const char *name
= NULL
;
3019 if (DECL_NAME (new_vard
))
3020 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3022 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3023 gimple_add_tmp_var (z
);
3024 TREE_ADDRESSABLE (z
) = 1;
3025 z
= build_fold_addr_expr_loc (loc
, z
);
3026 gimplify_assign (new_vard
, z
, ilist
);
3030 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3031 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3032 private variables. Initialization statements go in ILIST, while calls
3033 to destructors go in DLIST. */
3036 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3037 omp_context
*ctx
, struct omp_for_data
*fd
)
3039 tree c
, dtor
, copyin_seq
, x
, ptr
;
3040 bool copyin_by_ref
= false;
3041 bool lastprivate_firstprivate
= false;
3042 bool reduction_omp_orig_ref
= false;
3044 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3045 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3047 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3048 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3049 gimple_seq llist
[2] = { NULL
, NULL
};
3053 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3054 with data sharing clauses referencing variable sized vars. That
3055 is unnecessarily hard to support and very unlikely to result in
3056 vectorized code anyway. */
3058 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3059 switch (OMP_CLAUSE_CODE (c
))
3061 case OMP_CLAUSE_REDUCTION
:
3062 case OMP_CLAUSE_PRIVATE
:
3063 case OMP_CLAUSE_FIRSTPRIVATE
:
3064 case OMP_CLAUSE_LASTPRIVATE
:
3065 case OMP_CLAUSE_LINEAR
:
3066 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3073 /* Do all the fixed sized types in the first pass, and the variable sized
3074 types in the second pass. This makes sure that the scalar arguments to
3075 the variable sized types are processed before we use them in the
3076 variable sized operations. */
3077 for (pass
= 0; pass
< 2; ++pass
)
3079 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3081 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3084 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3088 case OMP_CLAUSE_PRIVATE
:
3089 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3092 case OMP_CLAUSE_SHARED
:
3093 /* Ignore shared directives in teams construct. */
3094 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3096 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3098 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3101 case OMP_CLAUSE_FIRSTPRIVATE
:
3102 case OMP_CLAUSE_COPYIN
:
3103 case OMP_CLAUSE_LINEAR
:
3105 case OMP_CLAUSE_REDUCTION
:
3106 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3107 reduction_omp_orig_ref
= true;
3109 case OMP_CLAUSE__LOOPTEMP_
:
3110 /* Handle _looptemp_ clauses only on parallel. */
3114 case OMP_CLAUSE_LASTPRIVATE
:
3115 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3117 lastprivate_firstprivate
= true;
3121 /* Even without corresponding firstprivate, if
3122 decl is Fortran allocatable, it needs outer var
3125 && lang_hooks
.decls
.omp_private_outer_ref
3126 (OMP_CLAUSE_DECL (c
)))
3127 lastprivate_firstprivate
= true;
3129 case OMP_CLAUSE_ALIGNED
:
3132 var
= OMP_CLAUSE_DECL (c
);
3133 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3134 && !is_global_var (var
))
3136 new_var
= maybe_lookup_decl (var
, ctx
);
3137 if (new_var
== NULL_TREE
)
3138 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3139 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3140 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3141 omp_clause_aligned_alignment (c
));
3142 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3143 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3144 gimplify_and_add (x
, ilist
);
3146 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3147 && is_global_var (var
))
3149 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3150 new_var
= lookup_decl (var
, ctx
);
3151 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3152 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3153 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3154 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3155 omp_clause_aligned_alignment (c
));
3156 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3157 x
= create_tmp_var (ptype
, NULL
);
3158 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3159 gimplify_and_add (t
, ilist
);
3160 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3161 SET_DECL_VALUE_EXPR (new_var
, t
);
3162 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3169 new_var
= var
= OMP_CLAUSE_DECL (c
);
3170 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3171 new_var
= lookup_decl (var
, ctx
);
3173 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3178 else if (is_variable_sized (var
))
3180 /* For variable sized types, we need to allocate the
3181 actual storage here. Call alloca and store the
3182 result in the pointer decl that we created elsewhere. */
3186 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3191 ptr
= DECL_VALUE_EXPR (new_var
);
3192 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3193 ptr
= TREE_OPERAND (ptr
, 0);
3194 gcc_assert (DECL_P (ptr
));
3195 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3197 /* void *tmp = __builtin_alloca */
3198 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3199 stmt
= gimple_build_call (atmp
, 1, x
);
3200 tmp
= create_tmp_var_raw (ptr_type_node
, NULL
);
3201 gimple_add_tmp_var (tmp
);
3202 gimple_call_set_lhs (stmt
, tmp
);
3204 gimple_seq_add_stmt (ilist
, stmt
);
3206 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3207 gimplify_assign (ptr
, x
, ilist
);
3210 else if (is_reference (var
))
3212 /* For references that are being privatized for Fortran,
3213 allocate new backing storage for the new pointer
3214 variable. This allows us to avoid changing all the
3215 code that expects a pointer to something that expects
3216 a direct variable. */
3220 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3221 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3223 x
= build_receiver_ref (var
, false, ctx
);
3224 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3226 else if (TREE_CONSTANT (x
))
3228 /* For reduction in SIMD loop, defer adding the
3229 initialization of the reference, because if we decide
3230 to use SIMD array for it, the initilization could cause
3232 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3236 const char *name
= NULL
;
3237 if (DECL_NAME (var
))
3238 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3240 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3242 gimple_add_tmp_var (x
);
3243 TREE_ADDRESSABLE (x
) = 1;
3244 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3249 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3250 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3255 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3256 gimplify_assign (new_var
, x
, ilist
);
3259 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3261 else if (c_kind
== OMP_CLAUSE_REDUCTION
3262 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3270 switch (OMP_CLAUSE_CODE (c
))
3272 case OMP_CLAUSE_SHARED
:
3273 /* Ignore shared directives in teams construct. */
3274 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3276 /* Shared global vars are just accessed directly. */
3277 if (is_global_var (new_var
))
3279 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3280 needs to be delayed until after fixup_child_record_type so
3281 that we get the correct type during the dereference. */
3282 by_ref
= use_pointer_for_field (var
, ctx
);
3283 x
= build_receiver_ref (var
, by_ref
, ctx
);
3284 SET_DECL_VALUE_EXPR (new_var
, x
);
3285 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3287 /* ??? If VAR is not passed by reference, and the variable
3288 hasn't been initialized yet, then we'll get a warning for
3289 the store into the omp_data_s structure. Ideally, we'd be
3290 able to notice this and not store anything at all, but
3291 we're generating code too early. Suppress the warning. */
3293 TREE_NO_WARNING (var
) = 1;
3296 case OMP_CLAUSE_LASTPRIVATE
:
3297 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3301 case OMP_CLAUSE_PRIVATE
:
3302 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3303 x
= build_outer_var_ref (var
, ctx
);
3304 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3306 if (is_task_ctx (ctx
))
3307 x
= build_receiver_ref (var
, false, ctx
);
3309 x
= build_outer_var_ref (var
, ctx
);
3315 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3318 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3319 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3320 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3321 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3322 idx
, lane
, ivar
, lvar
))
3325 x
= lang_hooks
.decls
.omp_clause_default_ctor
3326 (c
, unshare_expr (ivar
), x
);
3328 gimplify_and_add (x
, &llist
[0]);
3331 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3334 gimple_seq tseq
= NULL
;
3337 gimplify_stmt (&dtor
, &tseq
);
3338 gimple_seq_add_seq (&llist
[1], tseq
);
3345 gimplify_and_add (nx
, ilist
);
3349 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3352 gimple_seq tseq
= NULL
;
3355 gimplify_stmt (&dtor
, &tseq
);
3356 gimple_seq_add_seq (dlist
, tseq
);
3360 case OMP_CLAUSE_LINEAR
:
3361 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3362 goto do_firstprivate
;
3363 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3366 x
= build_outer_var_ref (var
, ctx
);
3369 case OMP_CLAUSE_FIRSTPRIVATE
:
3370 if (is_task_ctx (ctx
))
3372 if (is_reference (var
) || is_variable_sized (var
))
3374 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3376 || use_pointer_for_field (var
, NULL
))
3378 x
= build_receiver_ref (var
, false, ctx
);
3379 SET_DECL_VALUE_EXPR (new_var
, x
);
3380 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3385 x
= build_outer_var_ref (var
, ctx
);
3388 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3389 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3391 tree stept
= POINTER_TYPE_P (TREE_TYPE (x
))
3392 ? sizetype
: TREE_TYPE (x
);
3393 tree t
= fold_convert (stept
,
3394 OMP_CLAUSE_LINEAR_STEP (c
));
3395 tree c
= find_omp_clause (clauses
,
3396 OMP_CLAUSE__LOOPTEMP_
);
3398 tree l
= OMP_CLAUSE_DECL (c
);
3399 if (fd
->collapse
== 1)
3401 tree n1
= fd
->loop
.n1
;
3402 tree step
= fd
->loop
.step
;
3403 tree itype
= TREE_TYPE (l
);
3404 if (POINTER_TYPE_P (itype
))
3405 itype
= signed_type_for (itype
);
3406 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3407 if (TYPE_UNSIGNED (itype
)
3408 && fd
->loop
.cond_code
== GT_EXPR
)
3409 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3410 fold_build1 (NEGATE_EXPR
,
3412 fold_build1 (NEGATE_EXPR
,
3415 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3417 t
= fold_build2 (MULT_EXPR
, stept
,
3418 fold_convert (stept
, l
), t
);
3419 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3420 x
= fold_build2 (POINTER_PLUS_EXPR
,
3421 TREE_TYPE (x
), x
, t
);
3423 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3426 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3427 || TREE_ADDRESSABLE (new_var
))
3428 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3429 idx
, lane
, ivar
, lvar
))
3431 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
3433 tree iv
= create_tmp_var (TREE_TYPE (new_var
), NULL
);
3434 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
3435 gimplify_and_add (x
, ilist
);
3436 gimple_stmt_iterator gsi
3437 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3439 = gimple_build_assign (unshare_expr (lvar
), iv
);
3440 gsi_insert_before_without_update (&gsi
, g
,
3442 tree stept
= POINTER_TYPE_P (TREE_TYPE (iv
))
3443 ? sizetype
: TREE_TYPE (iv
);
3444 tree t
= fold_convert (stept
,
3445 OMP_CLAUSE_LINEAR_STEP (c
));
3446 enum tree_code code
= PLUS_EXPR
;
3447 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
3448 code
= POINTER_PLUS_EXPR
;
3449 g
= gimple_build_assign_with_ops (code
, iv
, iv
, t
);
3450 gsi_insert_before_without_update (&gsi
, g
,
3454 x
= lang_hooks
.decls
.omp_clause_copy_ctor
3455 (c
, unshare_expr (ivar
), x
);
3456 gimplify_and_add (x
, &llist
[0]);
3457 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3460 gimple_seq tseq
= NULL
;
3463 gimplify_stmt (&dtor
, &tseq
);
3464 gimple_seq_add_seq (&llist
[1], tseq
);
3469 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
3470 gimplify_and_add (x
, ilist
);
3473 case OMP_CLAUSE__LOOPTEMP_
:
3474 gcc_assert (is_parallel_ctx (ctx
));
3475 x
= build_outer_var_ref (var
, ctx
);
3476 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3477 gimplify_and_add (x
, ilist
);
3480 case OMP_CLAUSE_COPYIN
:
3481 by_ref
= use_pointer_for_field (var
, NULL
);
3482 x
= build_receiver_ref (var
, by_ref
, ctx
);
3483 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
3484 append_to_statement_list (x
, ©in_seq
);
3485 copyin_by_ref
|= by_ref
;
3488 case OMP_CLAUSE_REDUCTION
:
3489 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3491 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3493 x
= build_outer_var_ref (var
, ctx
);
3495 if (is_reference (var
)
3496 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
3498 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3499 SET_DECL_VALUE_EXPR (placeholder
, x
);
3500 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3501 tree new_vard
= new_var
;
3502 if (is_reference (var
))
3504 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3505 new_vard
= TREE_OPERAND (new_var
, 0);
3506 gcc_assert (DECL_P (new_vard
));
3509 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3510 idx
, lane
, ivar
, lvar
))
3512 if (new_vard
== new_var
)
3514 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
3515 SET_DECL_VALUE_EXPR (new_var
, ivar
);
3519 SET_DECL_VALUE_EXPR (new_vard
,
3520 build_fold_addr_expr (ivar
));
3521 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3523 x
= lang_hooks
.decls
.omp_clause_default_ctor
3524 (c
, unshare_expr (ivar
),
3525 build_outer_var_ref (var
, ctx
));
3527 gimplify_and_add (x
, &llist
[0]);
3528 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3530 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3531 lower_omp (&tseq
, ctx
);
3532 gimple_seq_add_seq (&llist
[0], tseq
);
3534 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3535 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3536 lower_omp (&tseq
, ctx
);
3537 gimple_seq_add_seq (&llist
[1], tseq
);
3538 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3539 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3540 if (new_vard
== new_var
)
3541 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3543 SET_DECL_VALUE_EXPR (new_vard
,
3544 build_fold_addr_expr (lvar
));
3545 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3550 gimplify_stmt (&dtor
, &tseq
);
3551 gimple_seq_add_seq (&llist
[1], tseq
);
3555 /* If this is a reference to constant size reduction var
3556 with placeholder, we haven't emitted the initializer
3557 for it because it is undesirable if SIMD arrays are used.
3558 But if they aren't used, we need to emit the deferred
3559 initialization now. */
3560 else if (is_reference (var
) && is_simd
)
3561 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3562 x
= lang_hooks
.decls
.omp_clause_default_ctor
3563 (c
, unshare_expr (new_var
),
3564 build_outer_var_ref (var
, ctx
));
3566 gimplify_and_add (x
, ilist
);
3567 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3569 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3570 lower_omp (&tseq
, ctx
);
3571 gimple_seq_add_seq (ilist
, tseq
);
3573 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3576 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3577 lower_omp (&tseq
, ctx
);
3578 gimple_seq_add_seq (dlist
, tseq
);
3579 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3581 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3586 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
3587 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
3588 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3590 /* reduction(-:var) sums up the partial results, so it
3591 acts identically to reduction(+:var). */
3592 if (code
== MINUS_EXPR
)
3595 tree new_vard
= new_var
;
3596 if (is_simd
&& is_reference (var
))
3598 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3599 new_vard
= TREE_OPERAND (new_var
, 0);
3600 gcc_assert (DECL_P (new_vard
));
3603 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3604 idx
, lane
, ivar
, lvar
))
3606 tree ref
= build_outer_var_ref (var
, ctx
);
3608 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
3610 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
3611 ref
= build_outer_var_ref (var
, ctx
);
3612 gimplify_assign (ref
, x
, &llist
[1]);
3614 if (new_vard
!= new_var
)
3616 SET_DECL_VALUE_EXPR (new_vard
,
3617 build_fold_addr_expr (lvar
));
3618 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3623 if (is_reference (var
) && is_simd
)
3624 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3625 gimplify_assign (new_var
, x
, ilist
);
3628 tree ref
= build_outer_var_ref (var
, ctx
);
3630 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3631 ref
= build_outer_var_ref (var
, ctx
);
3632 gimplify_assign (ref
, x
, dlist
);
3646 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
3647 /* Don't want uninit warnings on simduid, it is always uninitialized,
3648 but we use it not for the value, but for the DECL_UID only. */
3649 TREE_NO_WARNING (uid
) = 1;
3651 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
3652 gimple_call_set_lhs (g
, lane
);
3653 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3654 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
3655 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
3656 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
3657 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3658 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3659 g
= gimple_build_assign_with_ops (INTEGER_CST
, lane
,
3660 build_int_cst (unsigned_type_node
, 0),
3662 gimple_seq_add_stmt (ilist
, g
);
3663 for (int i
= 0; i
< 2; i
++)
3666 tree vf
= create_tmp_var (unsigned_type_node
, NULL
);
3667 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
3668 gimple_call_set_lhs (g
, vf
);
3669 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
3670 gimple_seq_add_stmt (seq
, g
);
3671 tree t
= build_int_cst (unsigned_type_node
, 0);
3672 g
= gimple_build_assign_with_ops (INTEGER_CST
, idx
, t
, NULL_TREE
);
3673 gimple_seq_add_stmt (seq
, g
);
3674 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
3675 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
3676 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
3677 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
3678 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
3679 gimple_seq_add_seq (seq
, llist
[i
]);
3680 t
= build_int_cst (unsigned_type_node
, 1);
3681 g
= gimple_build_assign_with_ops (PLUS_EXPR
, idx
, idx
, t
);
3682 gimple_seq_add_stmt (seq
, g
);
3683 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
3684 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
3685 gimple_seq_add_stmt (seq
, g
);
3686 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
3690 /* The copyin sequence is not to be executed by the main thread, since
3691 that would result in self-copies. Perhaps not visible to scalars,
3692 but it certainly is to C++ operator=. */
3695 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
3697 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
3698 build_int_cst (TREE_TYPE (x
), 0));
3699 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
3700 gimplify_and_add (x
, ilist
);
3703 /* If any copyin variable is passed by reference, we must ensure the
3704 master thread doesn't modify it before it is copied over in all
3705 threads. Similarly for variables in both firstprivate and
3706 lastprivate clauses we need to ensure the lastprivate copying
3707 happens after firstprivate copying in all threads. And similarly
3708 for UDRs if initializer expression refers to omp_orig. */
3709 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
3711 /* Don't add any barrier for #pragma omp simd or
3712 #pragma omp distribute. */
3713 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3714 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
3715 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
3718 /* If max_vf is non-zero, then we can use only a vectorization factor
3719 up to the max_vf we chose. So stick it into the safelen clause. */
3722 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3723 OMP_CLAUSE_SAFELEN
);
3725 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3728 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
3729 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
3731 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3732 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3738 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3739 both parallel and workshare constructs. PREDICATE may be NULL if it's
3743 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
3746 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
3747 bool par_clauses
= false;
3748 tree simduid
= NULL
, lastlane
= NULL
;
3750 /* Early exit if there are no lastprivate or linear clauses. */
3751 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
3752 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
3753 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
3754 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
3756 if (clauses
== NULL
)
3758 /* If this was a workshare clause, see if it had been combined
3759 with its parallel. In that case, look for the clauses on the
3760 parallel statement itself. */
3761 if (is_parallel_ctx (ctx
))
3765 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
3768 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
3769 OMP_CLAUSE_LASTPRIVATE
);
3770 if (clauses
== NULL
)
3778 tree label_true
, arm1
, arm2
;
3780 label
= create_artificial_label (UNKNOWN_LOCATION
);
3781 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
3782 arm1
= TREE_OPERAND (predicate
, 0);
3783 arm2
= TREE_OPERAND (predicate
, 1);
3784 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3785 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3786 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
3788 gimple_seq_add_stmt (stmt_list
, stmt
);
3789 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
3792 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3793 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3795 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
3797 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
3800 for (c
= clauses
; c
;)
3803 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3805 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
3806 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3807 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
3809 var
= OMP_CLAUSE_DECL (c
);
3810 new_var
= lookup_decl (var
, ctx
);
3812 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
3814 tree val
= DECL_VALUE_EXPR (new_var
);
3815 if (TREE_CODE (val
) == ARRAY_REF
3816 && VAR_P (TREE_OPERAND (val
, 0))
3817 && lookup_attribute ("omp simd array",
3818 DECL_ATTRIBUTES (TREE_OPERAND (val
,
3821 if (lastlane
== NULL
)
3823 lastlane
= create_tmp_var (unsigned_type_node
, NULL
);
3825 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
3827 TREE_OPERAND (val
, 1));
3828 gimple_call_set_lhs (g
, lastlane
);
3829 gimple_seq_add_stmt (stmt_list
, g
);
3831 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
3832 TREE_OPERAND (val
, 0), lastlane
,
3833 NULL_TREE
, NULL_TREE
);
3837 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
3838 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
3840 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
3841 gimple_seq_add_seq (stmt_list
,
3842 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
3843 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
3845 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3846 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
3848 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
3849 gimple_seq_add_seq (stmt_list
,
3850 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
3851 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
3854 x
= build_outer_var_ref (var
, ctx
);
3855 if (is_reference (var
))
3856 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3857 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
3858 gimplify_and_add (x
, stmt_list
);
3860 c
= OMP_CLAUSE_CHAIN (c
);
3861 if (c
== NULL
&& !par_clauses
)
3863 /* If this was a workshare clause, see if it had been combined
3864 with its parallel. In that case, continue looking for the
3865 clauses also on the parallel statement itself. */
3866 if (is_parallel_ctx (ctx
))
3870 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
3873 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
3874 OMP_CLAUSE_LASTPRIVATE
);
3880 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
3884 /* Generate code to implement the REDUCTION clauses. */
3887 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
3889 gimple_seq sub_seq
= NULL
;
3894 /* SIMD reductions are handled in lower_rec_input_clauses. */
3895 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3896 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3899 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3900 update in that case, otherwise use a lock. */
3901 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
3902 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
3904 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3906 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3916 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3918 tree var
, ref
, new_var
;
3919 enum tree_code code
;
3920 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3922 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
3925 var
= OMP_CLAUSE_DECL (c
);
3926 new_var
= lookup_decl (var
, ctx
);
3927 if (is_reference (var
))
3928 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3929 ref
= build_outer_var_ref (var
, ctx
);
3930 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3932 /* reduction(-:var) sums up the partial results, so it acts
3933 identically to reduction(+:var). */
3934 if (code
== MINUS_EXPR
)
3939 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
3941 addr
= save_expr (addr
);
3942 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
3943 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
3944 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
3945 gimplify_and_add (x
, stmt_seqp
);
3949 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3951 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3953 if (is_reference (var
)
3954 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
3956 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
3957 SET_DECL_VALUE_EXPR (placeholder
, ref
);
3958 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3959 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
3960 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
3961 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3962 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
3966 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3967 ref
= build_outer_var_ref (var
, ctx
);
3968 gimplify_assign (ref
, x
, &sub_seq
);
3972 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
3974 gimple_seq_add_stmt (stmt_seqp
, stmt
);
3976 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
3978 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
3980 gimple_seq_add_stmt (stmt_seqp
, stmt
);
3984 /* Generate code to implement the COPYPRIVATE clauses. */
3987 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
3992 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3994 tree var
, new_var
, ref
, x
;
3996 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3998 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4001 var
= OMP_CLAUSE_DECL (c
);
4002 by_ref
= use_pointer_for_field (var
, NULL
);
4004 ref
= build_sender_ref (var
, ctx
);
4005 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4008 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4009 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4011 gimplify_assign (ref
, x
, slist
);
4013 ref
= build_receiver_ref (var
, false, ctx
);
4016 ref
= fold_convert_loc (clause_loc
,
4017 build_pointer_type (TREE_TYPE (new_var
)),
4019 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4021 if (is_reference (var
))
4023 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4024 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4025 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4027 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4028 gimplify_and_add (x
, rlist
);
4033 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4034 and REDUCTION from the sender (aka parent) side. */
4037 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4042 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4044 tree val
, ref
, x
, var
;
4045 bool by_ref
, do_in
= false, do_out
= false;
4046 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4048 switch (OMP_CLAUSE_CODE (c
))
4050 case OMP_CLAUSE_PRIVATE
:
4051 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4054 case OMP_CLAUSE_FIRSTPRIVATE
:
4055 case OMP_CLAUSE_COPYIN
:
4056 case OMP_CLAUSE_LASTPRIVATE
:
4057 case OMP_CLAUSE_REDUCTION
:
4058 case OMP_CLAUSE__LOOPTEMP_
:
4064 val
= OMP_CLAUSE_DECL (c
);
4065 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4067 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4068 && is_global_var (var
))
4070 if (is_variable_sized (val
))
4072 by_ref
= use_pointer_for_field (val
, NULL
);
4074 switch (OMP_CLAUSE_CODE (c
))
4076 case OMP_CLAUSE_PRIVATE
:
4077 case OMP_CLAUSE_FIRSTPRIVATE
:
4078 case OMP_CLAUSE_COPYIN
:
4079 case OMP_CLAUSE__LOOPTEMP_
:
4083 case OMP_CLAUSE_LASTPRIVATE
:
4084 if (by_ref
|| is_reference (val
))
4086 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4093 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4098 case OMP_CLAUSE_REDUCTION
:
4100 do_out
= !(by_ref
|| is_reference (val
));
4109 ref
= build_sender_ref (val
, ctx
);
4110 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4111 gimplify_assign (ref
, x
, ilist
);
4112 if (is_task_ctx (ctx
))
4113 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4118 ref
= build_sender_ref (val
, ctx
);
4119 gimplify_assign (var
, ref
, olist
);
4124 /* Generate code to implement SHARED from the sender (aka parent)
4125 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4126 list things that got automatically shared. */
4129 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4131 tree var
, ovar
, nvar
, f
, x
, record_type
;
4133 if (ctx
->record_type
== NULL
)
4136 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4137 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4139 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4140 nvar
= maybe_lookup_decl (ovar
, ctx
);
4141 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4144 /* If CTX is a nested parallel directive. Find the immediately
4145 enclosing parallel or workshare construct that contains a
4146 mapping for OVAR. */
4147 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4149 if (use_pointer_for_field (ovar
, ctx
))
4151 x
= build_sender_ref (ovar
, ctx
);
4152 var
= build_fold_addr_expr (var
);
4153 gimplify_assign (x
, var
, ilist
);
4157 x
= build_sender_ref (ovar
, ctx
);
4158 gimplify_assign (x
, var
, ilist
);
4160 if (!TREE_READONLY (var
)
4161 /* We don't need to receive a new reference to a result
4162 or parm decl. In fact we may not store to it as we will
4163 invalidate any pending RSO and generate wrong gimple
4165 && !((TREE_CODE (var
) == RESULT_DECL
4166 || TREE_CODE (var
) == PARM_DECL
)
4167 && DECL_BY_REFERENCE (var
)))
4169 x
= build_sender_ref (ovar
, ctx
);
4170 gimplify_assign (var
, x
, olist
);
4177 /* A convenience function to build an empty GIMPLE_COND with just the
4181 gimple_build_cond_empty (tree cond
)
4183 enum tree_code pred_code
;
4186 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4187 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4191 /* Build the function calls to GOMP_parallel_start etc to actually
4192 generate the parallel operation. REGION is the parallel region
4193 being expanded. BB is the block where to insert the code. WS_ARGS
4194 will be set if this is a call to a combined parallel+workshare
4195 construct, it contains the list of additional arguments needed by
4196 the workshare construct. */
4199 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4200 gimple entry_stmt
, vec
<tree
, va_gc
> *ws_args
)
4202 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4203 gimple_stmt_iterator gsi
;
4205 enum built_in_function start_ix
;
4207 location_t clause_loc
;
4208 vec
<tree
, va_gc
> *args
;
4210 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4212 /* Determine what flavor of GOMP_parallel we will be
4214 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4215 if (is_combined_parallel (region
))
4217 switch (region
->inner
->type
)
4219 case GIMPLE_OMP_FOR
:
4220 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4221 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4222 + (region
->inner
->sched_kind
4223 == OMP_CLAUSE_SCHEDULE_RUNTIME
4224 ? 3 : region
->inner
->sched_kind
));
4225 start_ix
= (enum built_in_function
)start_ix2
;
4227 case GIMPLE_OMP_SECTIONS
:
4228 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4235 /* By default, the value of NUM_THREADS is zero (selected at run time)
4236 and there is no conditional. */
4238 val
= build_int_cst (unsigned_type_node
, 0);
4239 flags
= build_int_cst (unsigned_type_node
, 0);
4241 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4243 cond
= OMP_CLAUSE_IF_EXPR (c
);
4245 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4248 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4249 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4252 clause_loc
= gimple_location (entry_stmt
);
4254 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4256 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4258 /* Ensure 'val' is of the correct type. */
4259 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4261 /* If we found the clause 'if (cond)', build either
4262 (cond != 0) or (cond ? val : 1u). */
4265 cond
= gimple_boolify (cond
);
4267 if (integer_zerop (val
))
4268 val
= fold_build2_loc (clause_loc
,
4269 EQ_EXPR
, unsigned_type_node
, cond
,
4270 build_int_cst (TREE_TYPE (cond
), 0));
4273 basic_block cond_bb
, then_bb
, else_bb
;
4274 edge e
, e_then
, e_else
;
4275 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4277 tmp_var
= create_tmp_var (TREE_TYPE (val
), NULL
);
4278 if (gimple_in_ssa_p (cfun
))
4280 tmp_then
= make_ssa_name (tmp_var
, NULL
);
4281 tmp_else
= make_ssa_name (tmp_var
, NULL
);
4282 tmp_join
= make_ssa_name (tmp_var
, NULL
);
4291 e
= split_block (bb
, NULL
);
4296 then_bb
= create_empty_bb (cond_bb
);
4297 else_bb
= create_empty_bb (then_bb
);
4298 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4299 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4301 stmt
= gimple_build_cond_empty (cond
);
4302 gsi
= gsi_start_bb (cond_bb
);
4303 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4305 gsi
= gsi_start_bb (then_bb
);
4306 stmt
= gimple_build_assign (tmp_then
, val
);
4307 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4309 gsi
= gsi_start_bb (else_bb
);
4310 stmt
= gimple_build_assign
4311 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4312 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4314 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4315 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4316 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4317 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4318 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4319 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4321 if (gimple_in_ssa_p (cfun
))
4323 gimple phi
= create_phi_node (tmp_join
, bb
);
4324 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4325 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4331 gsi
= gsi_start_bb (bb
);
4332 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4333 false, GSI_CONTINUE_LINKING
);
4336 gsi
= gsi_last_bb (bb
);
4337 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4339 t1
= null_pointer_node
;
4341 t1
= build_fold_addr_expr (t
);
4342 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4344 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4345 args
->quick_push (t2
);
4346 args
->quick_push (t1
);
4347 args
->quick_push (val
);
4349 args
->splice (*ws_args
);
4350 args
->quick_push (flags
);
4352 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4353 builtin_decl_explicit (start_ix
), args
);
4355 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4356 false, GSI_CONTINUE_LINKING
);
4360 /* Build the function call to GOMP_task to actually
4361 generate the task operation. BB is the block where to insert the code. */
4364 expand_task_call (basic_block bb
, gimple entry_stmt
)
4366 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
4367 gimple_stmt_iterator gsi
;
4368 location_t loc
= gimple_location (entry_stmt
);
4370 clauses
= gimple_omp_task_clauses (entry_stmt
);
4372 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4374 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
4376 cond
= boolean_true_node
;
4378 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
4379 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
4380 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
4381 flags
= build_int_cst (unsigned_type_node
,
4382 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
4384 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
4387 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
4388 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
4389 build_int_cst (unsigned_type_node
, 2),
4390 build_int_cst (unsigned_type_node
, 0));
4391 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
4394 depend
= OMP_CLAUSE_DECL (depend
);
4396 depend
= build_int_cst (ptr_type_node
, 0);
4398 gsi
= gsi_last_bb (bb
);
4399 t
= gimple_omp_task_data_arg (entry_stmt
);
4401 t2
= null_pointer_node
;
4403 t2
= build_fold_addr_expr_loc (loc
, t
);
4404 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
4405 t
= gimple_omp_task_copy_fn (entry_stmt
);
4407 t3
= null_pointer_node
;
4409 t3
= build_fold_addr_expr_loc (loc
, t
);
4411 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
4413 gimple_omp_task_arg_size (entry_stmt
),
4414 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
4417 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4418 false, GSI_CONTINUE_LINKING
);
4422 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4423 catch handler and return it. This prevents programs from violating the
4424 structured block semantics with throws. */
4427 maybe_catch_exception (gimple_seq body
)
4432 if (!flag_exceptions
)
4435 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
4436 decl
= lang_hooks
.eh_protect_cleanup_actions ();
4438 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
4440 g
= gimple_build_eh_must_not_throw (decl
);
4441 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
4444 return gimple_seq_alloc_with_stmt (g
);
4447 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4450 vec2chain (vec
<tree
, va_gc
> *v
)
4452 tree chain
= NULL_TREE
, t
;
4455 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
4457 DECL_CHAIN (t
) = chain
;
4465 /* Remove barriers in REGION->EXIT's block. Note that this is only
4466 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4467 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4468 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4472 remove_exit_barrier (struct omp_region
*region
)
4474 gimple_stmt_iterator gsi
;
4475 basic_block exit_bb
;
4479 int any_addressable_vars
= -1;
4481 exit_bb
= region
->exit
;
4483 /* If the parallel region doesn't return, we don't have REGION->EXIT
4488 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4489 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4490 statements that can appear in between are extremely limited -- no
4491 memory operations at all. Here, we allow nothing at all, so the
4492 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4493 gsi
= gsi_last_bb (exit_bb
);
4494 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
4496 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
4499 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
4501 gsi
= gsi_last_bb (e
->src
);
4502 if (gsi_end_p (gsi
))
4504 stmt
= gsi_stmt (gsi
);
4505 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
4506 && !gimple_omp_return_nowait_p (stmt
))
4508 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4509 in many cases. If there could be tasks queued, the barrier
4510 might be needed to let the tasks run before some local
4511 variable of the parallel that the task uses as shared
4512 runs out of scope. The task can be spawned either
4513 from within current function (this would be easy to check)
4514 or from some function it calls and gets passed an address
4515 of such a variable. */
4516 if (any_addressable_vars
< 0)
4518 gimple parallel_stmt
= last_stmt (region
->entry
);
4519 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
4520 tree local_decls
, block
, decl
;
4523 any_addressable_vars
= 0;
4524 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
4525 if (TREE_ADDRESSABLE (decl
))
4527 any_addressable_vars
= 1;
4530 for (block
= gimple_block (stmt
);
4531 !any_addressable_vars
4533 && TREE_CODE (block
) == BLOCK
;
4534 block
= BLOCK_SUPERCONTEXT (block
))
4536 for (local_decls
= BLOCK_VARS (block
);
4538 local_decls
= DECL_CHAIN (local_decls
))
4539 if (TREE_ADDRESSABLE (local_decls
))
4541 any_addressable_vars
= 1;
4544 if (block
== gimple_block (parallel_stmt
))
4548 if (!any_addressable_vars
)
4549 gimple_omp_return_set_nowait (stmt
);
4555 remove_exit_barriers (struct omp_region
*region
)
4557 if (region
->type
== GIMPLE_OMP_PARALLEL
)
4558 remove_exit_barrier (region
);
4562 region
= region
->inner
;
4563 remove_exit_barriers (region
);
4564 while (region
->next
)
4566 region
= region
->next
;
4567 remove_exit_barriers (region
);
4572 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4573 calls. These can't be declared as const functions, but
4574 within one parallel body they are constant, so they can be
4575 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4576 which are declared const. Similarly for task body, except
4577 that in untied task omp_get_thread_num () can change at any task
4578 scheduling point. */
4581 optimize_omp_library_calls (gimple entry_stmt
)
4584 gimple_stmt_iterator gsi
;
4585 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4586 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
4587 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4588 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
4589 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
4590 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
4591 OMP_CLAUSE_UNTIED
) != NULL
);
4593 FOR_EACH_BB_FN (bb
, cfun
)
4594 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4596 gimple call
= gsi_stmt (gsi
);
4599 if (is_gimple_call (call
)
4600 && (decl
= gimple_call_fndecl (call
))
4601 && DECL_EXTERNAL (decl
)
4602 && TREE_PUBLIC (decl
)
4603 && DECL_INITIAL (decl
) == NULL
)
4607 if (DECL_NAME (decl
) == thr_num_id
)
4609 /* In #pragma omp task untied omp_get_thread_num () can change
4610 during the execution of the task region. */
4613 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4615 else if (DECL_NAME (decl
) == num_thr_id
)
4616 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4620 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
4621 || gimple_call_num_args (call
) != 0)
4624 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
4627 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
4628 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
4629 TREE_TYPE (TREE_TYPE (built_in
))))
4632 gimple_call_set_fndecl (call
, built_in
);
4637 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4641 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
4645 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4646 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
4649 if (TREE_CODE (t
) == ADDR_EXPR
)
4650 recompute_tree_invariant_for_addr_expr (t
);
4652 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
4656 /* Prepend TO = FROM assignment before *GSI_P. */
4659 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
4661 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
4662 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
4663 true, GSI_SAME_STMT
);
4664 gimple stmt
= gimple_build_assign (to
, from
);
4665 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
4666 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
4667 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
4669 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
4670 gimple_regimplify_operands (stmt
, &gsi
);
4674 /* Expand the OpenMP parallel or task directive starting at REGION. */
4677 expand_omp_taskreg (struct omp_region
*region
)
4679 basic_block entry_bb
, exit_bb
, new_bb
;
4680 struct function
*child_cfun
;
4681 tree child_fn
, block
, t
;
4682 gimple_stmt_iterator gsi
;
4683 gimple entry_stmt
, stmt
;
4685 vec
<tree
, va_gc
> *ws_args
;
4687 entry_stmt
= last_stmt (region
->entry
);
4688 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
4689 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
4691 entry_bb
= region
->entry
;
4692 exit_bb
= region
->exit
;
4694 if (is_combined_parallel (region
))
4695 ws_args
= region
->ws_args
;
4699 if (child_cfun
->cfg
)
4701 /* Due to inlining, it may happen that we have already outlined
4702 the region, in which case all we need to do is make the
4703 sub-graph unreachable and emit the parallel call. */
4704 edge entry_succ_e
, exit_succ_e
;
4706 entry_succ_e
= single_succ_edge (entry_bb
);
4708 gsi
= gsi_last_bb (entry_bb
);
4709 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
4710 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
4711 gsi_remove (&gsi
, true);
4716 exit_succ_e
= single_succ_edge (exit_bb
);
4717 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
4719 remove_edge_and_dominated_blocks (entry_succ_e
);
4723 unsigned srcidx
, dstidx
, num
;
4725 /* If the parallel region needs data sent from the parent
4726 function, then the very first statement (except possible
4727 tree profile counter updates) of the parallel body
4728 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4729 &.OMP_DATA_O is passed as an argument to the child function,
4730 we need to replace it with the argument as seen by the child
4733 In most cases, this will end up being the identity assignment
4734 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4735 a function call that has been inlined, the original PARM_DECL
4736 .OMP_DATA_I may have been converted into a different local
4737 variable. In which case, we need to keep the assignment. */
4738 if (gimple_omp_taskreg_data_arg (entry_stmt
))
4740 basic_block entry_succ_bb
= single_succ (entry_bb
);
4742 gimple parcopy_stmt
= NULL
;
4744 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
4748 gcc_assert (!gsi_end_p (gsi
));
4749 stmt
= gsi_stmt (gsi
);
4750 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
4753 if (gimple_num_ops (stmt
) == 2)
4755 tree arg
= gimple_assign_rhs1 (stmt
);
4757 /* We're ignore the subcode because we're
4758 effectively doing a STRIP_NOPS. */
4760 if (TREE_CODE (arg
) == ADDR_EXPR
4761 && TREE_OPERAND (arg
, 0)
4762 == gimple_omp_taskreg_data_arg (entry_stmt
))
4764 parcopy_stmt
= stmt
;
4770 gcc_assert (parcopy_stmt
!= NULL
);
4771 arg
= DECL_ARGUMENTS (child_fn
);
4773 if (!gimple_in_ssa_p (cfun
))
4775 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
4776 gsi_remove (&gsi
, true);
4779 /* ?? Is setting the subcode really necessary ?? */
4780 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
4781 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
4786 /* If we are in ssa form, we must load the value from the default
4787 definition of the argument. That should not be defined now,
4788 since the argument is not used uninitialized. */
4789 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
4790 narg
= make_ssa_name (arg
, gimple_build_nop ());
4791 set_ssa_default_def (cfun
, arg
, narg
);
4792 /* ?? Is setting the subcode really necessary ?? */
4793 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
4794 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
4795 update_stmt (parcopy_stmt
);
4799 /* Declare local variables needed in CHILD_CFUN. */
4800 block
= DECL_INITIAL (child_fn
);
4801 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
4802 /* The gimplifier could record temporaries in parallel/task block
4803 rather than in containing function's local_decls chain,
4804 which would mean cgraph missed finalizing them. Do it now. */
4805 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
4806 if (TREE_CODE (t
) == VAR_DECL
4808 && !DECL_EXTERNAL (t
))
4809 varpool_finalize_decl (t
);
4810 DECL_SAVED_TREE (child_fn
) = NULL
;
4811 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4812 gimple_set_body (child_fn
, NULL
);
4813 TREE_USED (block
) = 1;
4815 /* Reset DECL_CONTEXT on function arguments. */
4816 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
4817 DECL_CONTEXT (t
) = child_fn
;
4819 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4820 so that it can be moved to the child function. */
4821 gsi
= gsi_last_bb (entry_bb
);
4822 stmt
= gsi_stmt (gsi
);
4823 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
4824 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
4825 gsi_remove (&gsi
, true);
4826 e
= split_block (entry_bb
, stmt
);
4828 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
4830 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4833 gsi
= gsi_last_bb (exit_bb
);
4834 gcc_assert (!gsi_end_p (gsi
)
4835 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
4836 stmt
= gimple_build_return (NULL
);
4837 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
4838 gsi_remove (&gsi
, true);
4841 /* Move the parallel region into CHILD_CFUN. */
4843 if (gimple_in_ssa_p (cfun
))
4845 init_tree_ssa (child_cfun
);
4846 init_ssa_operands (child_cfun
);
4847 child_cfun
->gimple_df
->in_ssa_p
= true;
4851 block
= gimple_block (entry_stmt
);
4853 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
4855 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
4856 /* When the OMP expansion process cannot guarantee an up-to-date
4857 loop tree arrange for the child function to fixup loops. */
4858 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
4859 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
4861 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4862 num
= vec_safe_length (child_cfun
->local_decls
);
4863 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
4865 t
= (*child_cfun
->local_decls
)[srcidx
];
4866 if (DECL_CONTEXT (t
) == cfun
->decl
)
4868 if (srcidx
!= dstidx
)
4869 (*child_cfun
->local_decls
)[dstidx
] = t
;
4873 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
4875 /* Inform the callgraph about the new function. */
4876 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
4877 cgraph_add_new_function (child_fn
, true);
4879 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4880 fixed in a following pass. */
4881 push_cfun (child_cfun
);
4883 optimize_omp_library_calls (entry_stmt
);
4884 rebuild_cgraph_edges ();
4886 /* Some EH regions might become dead, see PR34608. If
4887 pass_cleanup_cfg isn't the first pass to happen with the
4888 new child, these dead EH edges might cause problems.
4889 Clean them up now. */
4890 if (flag_exceptions
)
4893 bool changed
= false;
4895 FOR_EACH_BB_FN (bb
, cfun
)
4896 changed
|= gimple_purge_dead_eh_edges (bb
);
4898 cleanup_tree_cfg ();
4900 if (gimple_in_ssa_p (cfun
))
4901 update_ssa (TODO_update_ssa
);
4905 /* Emit a library call to launch the children threads. */
4906 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
4907 expand_parallel_call (region
, new_bb
, entry_stmt
, ws_args
);
4909 expand_task_call (new_bb
, entry_stmt
);
4910 if (gimple_in_ssa_p (cfun
))
4911 update_ssa (TODO_update_ssa_only_virtuals
);
4915 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4916 of the combined collapse > 1 loop constructs, generate code like:
4917 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4922 count3 = (adj + N32 - N31) / STEP3;
4923 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4928 count2 = (adj + N22 - N21) / STEP2;
4929 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4934 count1 = (adj + N12 - N11) / STEP1;
4935 count = count1 * count2 * count3;
4936 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4938 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4939 of the combined loop constructs, just initialize COUNTS array
4940 from the _looptemp_ clauses. */
4942 /* NOTE: It *could* be better to moosh all of the BBs together,
4943 creating one larger BB with all the computation and the unexpected
4944 jump at the end. I.e.
4946 bool zero3, zero2, zero1, zero;
4949 count3 = (N32 - N31) /[cl] STEP3;
4951 count2 = (N22 - N21) /[cl] STEP2;
4953 count1 = (N12 - N11) /[cl] STEP1;
4954 zero = zero3 || zero2 || zero1;
4955 count = count1 * count2 * count3;
4956 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4958 After all, we expect the zero=false, and thus we expect to have to
4959 evaluate all of the comparison expressions, so short-circuiting
4960 oughtn't be a win. Since the condition isn't protecting a
4961 denominator, we're not concerned about divide-by-zero, so we can
4962 fully evaluate count even if a numerator turned out to be wrong.
4964 It seems like putting this all together would create much better
4965 scheduling opportunities, and less pressure on the chip's branch
4969 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
4970 basic_block
&entry_bb
, tree
*counts
,
4971 basic_block
&zero_iter_bb
, int &first_zero_iter
,
4972 basic_block
&l2_dom_bb
)
4974 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
4979 /* Collapsed loops need work for expansion into SSA form. */
4980 gcc_assert (!gimple_in_ssa_p (cfun
));
4982 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
4983 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
4985 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4986 isn't supposed to be handled, as the inner loop doesn't
4988 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
4989 OMP_CLAUSE__LOOPTEMP_
);
4990 gcc_assert (innerc
);
4991 for (i
= 0; i
< fd
->collapse
; i
++)
4993 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
4994 OMP_CLAUSE__LOOPTEMP_
);
4995 gcc_assert (innerc
);
4997 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
4999 counts
[0] = NULL_TREE
;
5004 for (i
= 0; i
< fd
->collapse
; i
++)
5006 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5008 if (SSA_VAR_P (fd
->loop
.n2
)
5009 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5010 fold_convert (itype
, fd
->loops
[i
].n1
),
5011 fold_convert (itype
, fd
->loops
[i
].n2
)))
5012 == NULL_TREE
|| !integer_onep (t
)))
5015 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5016 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5017 true, GSI_SAME_STMT
);
5018 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5019 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5020 true, GSI_SAME_STMT
);
5021 stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5022 NULL_TREE
, NULL_TREE
);
5023 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5024 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
5025 expand_omp_regimplify_p
, NULL
, NULL
)
5026 || walk_tree (gimple_cond_rhs_ptr (stmt
),
5027 expand_omp_regimplify_p
, NULL
, NULL
))
5029 *gsi
= gsi_for_stmt (stmt
);
5030 gimple_regimplify_operands (stmt
, gsi
);
5032 e
= split_block (entry_bb
, stmt
);
5033 if (zero_iter_bb
== NULL
)
5035 first_zero_iter
= i
;
5036 zero_iter_bb
= create_empty_bb (entry_bb
);
5037 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5038 *gsi
= gsi_after_labels (zero_iter_bb
);
5039 stmt
= gimple_build_assign (fd
->loop
.n2
,
5040 build_zero_cst (type
));
5041 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5042 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5045 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5046 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5047 e
->flags
= EDGE_TRUE_VALUE
;
5048 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5049 if (l2_dom_bb
== NULL
)
5050 l2_dom_bb
= entry_bb
;
5052 *gsi
= gsi_last_bb (entry_bb
);
5055 if (POINTER_TYPE_P (itype
))
5056 itype
= signed_type_for (itype
);
5057 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5059 t
= fold_build2 (PLUS_EXPR
, itype
,
5060 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5061 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5062 fold_convert (itype
, fd
->loops
[i
].n2
));
5063 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5064 fold_convert (itype
, fd
->loops
[i
].n1
));
5065 /* ?? We could probably use CEIL_DIV_EXPR instead of
5066 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5067 generate the same code in the end because generically we
5068 don't know that the values involved must be negative for
5070 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5071 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5072 fold_build1 (NEGATE_EXPR
, itype
, t
),
5073 fold_build1 (NEGATE_EXPR
, itype
,
5074 fold_convert (itype
,
5075 fd
->loops
[i
].step
)));
5077 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5078 fold_convert (itype
, fd
->loops
[i
].step
));
5079 t
= fold_convert (type
, t
);
5080 if (TREE_CODE (t
) == INTEGER_CST
)
5084 counts
[i
] = create_tmp_reg (type
, ".count");
5085 expand_omp_build_assign (gsi
, counts
[i
], t
);
5087 if (SSA_VAR_P (fd
->loop
.n2
))
5092 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5093 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5099 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5101 V3 = N31 + (T % count3) * STEP3;
5103 V2 = N21 + (T % count2) * STEP2;
5105 V1 = N11 + T * STEP1;
5106 if this loop doesn't have an inner loop construct combined with it.
5107 If it does have an inner loop construct combined with it and the
5108 iteration count isn't known constant, store values from counts array
5109 into its _looptemp_ temporaries instead. */
5112 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5113 tree
*counts
, gimple inner_stmt
, tree startvar
)
5116 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5118 /* If fd->loop.n2 is constant, then no propagation of the counts
5119 is needed, they are constant. */
5120 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5123 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5124 ? gimple_omp_parallel_clauses (inner_stmt
)
5125 : gimple_omp_for_clauses (inner_stmt
);
5126 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5127 isn't supposed to be handled, as the inner loop doesn't
5129 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5130 gcc_assert (innerc
);
5131 for (i
= 0; i
< fd
->collapse
; i
++)
5133 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5134 OMP_CLAUSE__LOOPTEMP_
);
5135 gcc_assert (innerc
);
5138 tree tem
= OMP_CLAUSE_DECL (innerc
);
5139 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5140 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5141 false, GSI_CONTINUE_LINKING
);
5142 gimple stmt
= gimple_build_assign (tem
, t
);
5143 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5149 tree type
= TREE_TYPE (fd
->loop
.v
);
5150 tree tem
= create_tmp_reg (type
, ".tem");
5151 gimple stmt
= gimple_build_assign (tem
, startvar
);
5152 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5154 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5156 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5158 if (POINTER_TYPE_P (vtype
))
5159 itype
= signed_type_for (vtype
);
5161 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5164 t
= fold_convert (itype
, t
);
5165 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5166 fold_convert (itype
, fd
->loops
[i
].step
));
5167 if (POINTER_TYPE_P (vtype
))
5168 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5170 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5171 t
= force_gimple_operand_gsi (gsi
, t
,
5172 DECL_P (fd
->loops
[i
].v
)
5173 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5175 GSI_CONTINUE_LINKING
);
5176 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5177 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5180 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5181 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5182 false, GSI_CONTINUE_LINKING
);
5183 stmt
= gimple_build_assign (tem
, t
);
5184 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5190 /* Helper function for expand_omp_for_*. Generate code like:
5193 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5197 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5204 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5205 basic_block body_bb
)
5207 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5209 gimple_stmt_iterator gsi
;
5215 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5217 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5219 bb
= create_empty_bb (last_bb
);
5220 add_bb_to_loop (bb
, last_bb
->loop_father
);
5221 gsi
= gsi_start_bb (bb
);
5223 if (i
< fd
->collapse
- 1)
5225 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5226 e
->probability
= REG_BR_PROB_BASE
/ 8;
5228 t
= fd
->loops
[i
+ 1].n1
;
5229 t
= force_gimple_operand_gsi (&gsi
, t
,
5230 DECL_P (fd
->loops
[i
+ 1].v
)
5231 && TREE_ADDRESSABLE (fd
->loops
[i
5234 GSI_CONTINUE_LINKING
);
5235 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5236 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5241 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5243 if (POINTER_TYPE_P (vtype
))
5244 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5246 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5247 t
= force_gimple_operand_gsi (&gsi
, t
,
5248 DECL_P (fd
->loops
[i
].v
)
5249 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5250 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5251 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5252 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5256 t
= fd
->loops
[i
].n2
;
5257 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5258 false, GSI_CONTINUE_LINKING
);
5259 tree v
= fd
->loops
[i
].v
;
5260 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5261 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5262 false, GSI_CONTINUE_LINKING
);
5263 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5264 stmt
= gimple_build_cond_empty (t
);
5265 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5266 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5267 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5270 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5278 /* A subroutine of expand_omp_for. Generate code for a parallel
5279 loop with any schedule. Given parameters:
5281 for (V = N1; V cond N2; V += STEP) BODY;
5283 where COND is "<" or ">", we generate pseudocode
5285 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5286 if (more) goto L0; else goto L3;
5293 if (V cond iend) goto L1; else goto L2;
5295 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5298 If this is a combined omp parallel loop, instead of the call to
5299 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5300 If this is gimple_omp_for_combined_p loop, then instead of assigning
5301 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5302 inner GIMPLE_OMP_FOR and V += STEP; and
5303 if (V cond iend) goto L1; else goto L2; are removed.
5305 For collapsed loops, given parameters:
5307 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5308 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5309 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5312 we generate pseudocode
5314 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5319 count3 = (adj + N32 - N31) / STEP3;
5320 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5325 count2 = (adj + N22 - N21) / STEP2;
5326 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5331 count1 = (adj + N12 - N11) / STEP1;
5332 count = count1 * count2 * count3;
5337 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5338 if (more) goto L0; else goto L3;
5342 V3 = N31 + (T % count3) * STEP3;
5344 V2 = N21 + (T % count2) * STEP2;
5346 V1 = N11 + T * STEP1;
5351 if (V < iend) goto L10; else goto L2;
5354 if (V3 cond3 N32) goto L1; else goto L11;
5358 if (V2 cond2 N22) goto L1; else goto L12;
5364 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5370 expand_omp_for_generic (struct omp_region
*region
,
5371 struct omp_for_data
*fd
,
5372 enum built_in_function start_fn
,
5373 enum built_in_function next_fn
,
5376 tree type
, istart0
, iend0
, iend
;
5377 tree t
, vmain
, vback
, bias
= NULL_TREE
;
5378 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
5379 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
5380 gimple_stmt_iterator gsi
;
5382 bool in_combined_parallel
= is_combined_parallel (region
);
5383 bool broken_loop
= region
->cont
== NULL
;
5385 tree
*counts
= NULL
;
5388 gcc_assert (!broken_loop
|| !in_combined_parallel
);
5389 gcc_assert (fd
->iter_type
== long_integer_type_node
5390 || !in_combined_parallel
);
5392 type
= TREE_TYPE (fd
->loop
.v
);
5393 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
5394 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
5395 TREE_ADDRESSABLE (istart0
) = 1;
5396 TREE_ADDRESSABLE (iend0
) = 1;
5398 /* See if we need to bias by LLONG_MIN. */
5399 if (fd
->iter_type
== long_long_unsigned_type_node
5400 && TREE_CODE (type
) == INTEGER_TYPE
5401 && !TYPE_UNSIGNED (type
))
5405 if (fd
->loop
.cond_code
== LT_EXPR
)
5408 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5412 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5415 if (TREE_CODE (n1
) != INTEGER_CST
5416 || TREE_CODE (n2
) != INTEGER_CST
5417 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
5418 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
5421 entry_bb
= region
->entry
;
5422 cont_bb
= region
->cont
;
5424 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5425 gcc_assert (broken_loop
5426 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
5427 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
5428 l1_bb
= single_succ (l0_bb
);
5431 l2_bb
= create_empty_bb (cont_bb
);
5432 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
5433 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5437 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5438 exit_bb
= region
->exit
;
5440 gsi
= gsi_last_bb (entry_bb
);
5442 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5443 if (fd
->collapse
> 1)
5445 int first_zero_iter
= -1;
5446 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
5448 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5449 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5450 zero_iter_bb
, first_zero_iter
,
5455 /* Some counts[i] vars might be uninitialized if
5456 some loop has zero iterations. But the body shouldn't
5457 be executed in that case, so just avoid uninit warnings. */
5458 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
5459 if (SSA_VAR_P (counts
[i
]))
5460 TREE_NO_WARNING (counts
[i
]) = 1;
5462 e
= split_block (entry_bb
, gsi_stmt (gsi
));
5464 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
5465 gsi
= gsi_last_bb (entry_bb
);
5466 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
5467 get_immediate_dominator (CDI_DOMINATORS
,
5471 if (in_combined_parallel
)
5473 /* In a combined parallel loop, emit a call to
5474 GOMP_loop_foo_next. */
5475 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5476 build_fold_addr_expr (istart0
),
5477 build_fold_addr_expr (iend0
));
5481 tree t0
, t1
, t2
, t3
, t4
;
5482 /* If this is not a combined parallel loop, emit a call to
5483 GOMP_loop_foo_start in ENTRY_BB. */
5484 t4
= build_fold_addr_expr (iend0
);
5485 t3
= build_fold_addr_expr (istart0
);
5486 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
5489 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5491 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5492 OMP_CLAUSE__LOOPTEMP_
);
5493 gcc_assert (innerc
);
5494 t0
= OMP_CLAUSE_DECL (innerc
);
5495 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5496 OMP_CLAUSE__LOOPTEMP_
);
5497 gcc_assert (innerc
);
5498 t1
= OMP_CLAUSE_DECL (innerc
);
5500 if (POINTER_TYPE_P (TREE_TYPE (t0
))
5501 && TYPE_PRECISION (TREE_TYPE (t0
))
5502 != TYPE_PRECISION (fd
->iter_type
))
5504 /* Avoid casting pointers to integer of a different size. */
5505 tree itype
= signed_type_for (type
);
5506 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
5507 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
5511 t1
= fold_convert (fd
->iter_type
, t1
);
5512 t0
= fold_convert (fd
->iter_type
, t0
);
5516 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
5517 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
5519 if (fd
->iter_type
== long_integer_type_node
)
5523 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5524 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5525 6, t0
, t1
, t2
, t
, t3
, t4
);
5528 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5529 5, t0
, t1
, t2
, t3
, t4
);
5537 /* The GOMP_loop_ull_*start functions have additional boolean
5538 argument, true for < loops and false for > loops.
5539 In Fortran, the C bool type can be different from
5540 boolean_type_node. */
5541 bfn_decl
= builtin_decl_explicit (start_fn
);
5542 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
5543 t5
= build_int_cst (c_bool_type
,
5544 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
5547 tree bfn_decl
= builtin_decl_explicit (start_fn
);
5548 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5549 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
5552 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5553 6, t5
, t0
, t1
, t2
, t3
, t4
);
5556 if (TREE_TYPE (t
) != boolean_type_node
)
5557 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5558 t
, build_int_cst (TREE_TYPE (t
), 0));
5559 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5560 true, GSI_SAME_STMT
);
5561 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5563 /* Remove the GIMPLE_OMP_FOR statement. */
5564 gsi_remove (&gsi
, true);
5566 /* Iteration setup for sequential loop goes in L0_BB. */
5567 tree startvar
= fd
->loop
.v
;
5568 tree endvar
= NULL_TREE
;
5570 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5572 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
5573 && gimple_omp_for_kind (inner_stmt
)
5574 == GF_OMP_FOR_KIND_SIMD
);
5575 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
5576 OMP_CLAUSE__LOOPTEMP_
);
5577 gcc_assert (innerc
);
5578 startvar
= OMP_CLAUSE_DECL (innerc
);
5579 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5580 OMP_CLAUSE__LOOPTEMP_
);
5581 gcc_assert (innerc
);
5582 endvar
= OMP_CLAUSE_DECL (innerc
);
5585 gsi
= gsi_start_bb (l0_bb
);
5588 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5589 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5590 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5591 t
= fold_convert (TREE_TYPE (startvar
), t
);
5592 t
= force_gimple_operand_gsi (&gsi
, t
,
5594 && TREE_ADDRESSABLE (startvar
),
5595 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5596 stmt
= gimple_build_assign (startvar
, t
);
5597 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5601 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5602 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5603 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5604 t
= fold_convert (TREE_TYPE (startvar
), t
);
5605 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5606 false, GSI_CONTINUE_LINKING
);
5609 stmt
= gimple_build_assign (endvar
, iend
);
5610 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5611 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
5612 stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
5614 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, iend
,
5616 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5618 if (fd
->collapse
> 1)
5619 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
5623 /* Code to control the increment and predicate for the sequential
5624 loop goes in the CONT_BB. */
5625 gsi
= gsi_last_bb (cont_bb
);
5626 stmt
= gsi_stmt (gsi
);
5627 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
5628 vmain
= gimple_omp_continue_control_use (stmt
);
5629 vback
= gimple_omp_continue_control_def (stmt
);
5631 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5633 if (POINTER_TYPE_P (type
))
5634 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
5636 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
5637 t
= force_gimple_operand_gsi (&gsi
, t
,
5639 && TREE_ADDRESSABLE (vback
),
5640 NULL_TREE
, true, GSI_SAME_STMT
);
5641 stmt
= gimple_build_assign (vback
, t
);
5642 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5644 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
5645 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
5647 stmt
= gimple_build_cond_empty (t
);
5648 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5651 /* Remove GIMPLE_OMP_CONTINUE. */
5652 gsi_remove (&gsi
, true);
5654 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
5655 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
5657 /* Emit code to get the next parallel iteration in L2_BB. */
5658 gsi
= gsi_start_bb (l2_bb
);
5660 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5661 build_fold_addr_expr (istart0
),
5662 build_fold_addr_expr (iend0
));
5663 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5664 false, GSI_CONTINUE_LINKING
);
5665 if (TREE_TYPE (t
) != boolean_type_node
)
5666 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5667 t
, build_int_cst (TREE_TYPE (t
), 0));
5668 stmt
= gimple_build_cond_empty (t
);
5669 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5672 /* Add the loop cleanup function. */
5673 gsi
= gsi_last_bb (exit_bb
);
5674 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
5675 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
5676 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5677 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
5679 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
5680 stmt
= gimple_build_call (t
, 0);
5681 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5682 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
5683 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5684 gsi_remove (&gsi
, true);
5686 /* Connect the new blocks. */
5687 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
5688 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
5694 e
= find_edge (cont_bb
, l3_bb
);
5695 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
5697 phis
= phi_nodes (l3_bb
);
5698 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5700 gimple phi
= gsi_stmt (gsi
);
5701 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
5702 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
5706 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
5707 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
5708 e
= find_edge (cont_bb
, l1_bb
);
5709 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5714 else if (fd
->collapse
> 1)
5717 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
5720 e
->flags
= EDGE_TRUE_VALUE
;
5723 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5724 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
5728 e
= find_edge (cont_bb
, l2_bb
);
5729 e
->flags
= EDGE_FALLTHRU
;
5731 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
5733 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
5734 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
5735 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
5736 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
5737 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
5738 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
5739 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
5740 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
5742 struct loop
*outer_loop
= alloc_loop ();
5743 outer_loop
->header
= l0_bb
;
5744 outer_loop
->latch
= l2_bb
;
5745 add_loop (outer_loop
, l0_bb
->loop_father
);
5747 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5749 struct loop
*loop
= alloc_loop ();
5750 loop
->header
= l1_bb
;
5751 /* The loop may have multiple latches. */
5752 add_loop (loop
, outer_loop
);
5758 /* A subroutine of expand_omp_for. Generate code for a parallel
5759 loop with static schedule and no specified chunk size. Given
5762 for (V = N1; V cond N2; V += STEP) BODY;
5764 where COND is "<" or ">", we generate pseudocode
5766 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5771 if ((__typeof (V)) -1 > 0 && cond is >)
5772 n = -(adj + N2 - N1) / -STEP;
5774 n = (adj + N2 - N1) / STEP;
5777 if (threadid < tt) goto L3; else goto L4;
5782 s0 = q * threadid + tt;
5785 if (s0 >= e0) goto L2; else goto L0;
5791 if (V cond e) goto L1;
5796 expand_omp_for_static_nochunk (struct omp_region
*region
,
5797 struct omp_for_data
*fd
,
5800 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
5801 tree type
, itype
, vmain
, vback
;
5802 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
5803 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
5805 gimple_stmt_iterator gsi
;
5808 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
5809 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
5810 bool broken_loop
= region
->cont
== NULL
;
5811 tree
*counts
= NULL
;
5814 itype
= type
= TREE_TYPE (fd
->loop
.v
);
5815 if (POINTER_TYPE_P (type
))
5816 itype
= signed_type_for (type
);
5818 entry_bb
= region
->entry
;
5819 cont_bb
= region
->cont
;
5820 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5821 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5822 gcc_assert (broken_loop
5823 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
5824 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
5825 body_bb
= single_succ (seq_start_bb
);
5828 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
5829 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5831 exit_bb
= region
->exit
;
5833 /* Iteration space partitioning goes in ENTRY_BB. */
5834 gsi
= gsi_last_bb (entry_bb
);
5835 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5837 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
5839 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
5840 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
5843 if (fd
->collapse
> 1)
5845 int first_zero_iter
= -1;
5846 basic_block l2_dom_bb
= NULL
;
5848 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5849 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5850 fin_bb
, first_zero_iter
,
5854 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5855 t
= integer_one_node
;
5857 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
5858 fold_convert (type
, fd
->loop
.n1
),
5859 fold_convert (type
, fd
->loop
.n2
));
5860 if (fd
->collapse
== 1
5861 && TYPE_UNSIGNED (type
)
5862 && (t
== NULL_TREE
|| !integer_onep (t
)))
5864 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
5865 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
5866 true, GSI_SAME_STMT
);
5867 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
5868 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
5869 true, GSI_SAME_STMT
);
5870 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
5871 NULL_TREE
, NULL_TREE
);
5872 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5873 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
5874 expand_omp_regimplify_p
, NULL
, NULL
)
5875 || walk_tree (gimple_cond_rhs_ptr (stmt
),
5876 expand_omp_regimplify_p
, NULL
, NULL
))
5878 gsi
= gsi_for_stmt (stmt
);
5879 gimple_regimplify_operands (stmt
, &gsi
);
5881 ep
= split_block (entry_bb
, stmt
);
5882 ep
->flags
= EDGE_TRUE_VALUE
;
5883 entry_bb
= ep
->dest
;
5884 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
5885 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
5886 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5887 if (gimple_in_ssa_p (cfun
))
5889 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
5890 for (gsi
= gsi_start_phis (fin_bb
);
5891 !gsi_end_p (gsi
); gsi_next (&gsi
))
5893 gimple phi
= gsi_stmt (gsi
);
5894 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
5895 ep
, UNKNOWN_LOCATION
);
5898 gsi
= gsi_last_bb (entry_bb
);
5901 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
5902 t
= fold_convert (itype
, t
);
5903 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5904 true, GSI_SAME_STMT
);
5906 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
5907 t
= fold_convert (itype
, t
);
5908 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5909 true, GSI_SAME_STMT
);
5913 step
= fd
->loop
.step
;
5914 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5916 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5917 OMP_CLAUSE__LOOPTEMP_
);
5918 gcc_assert (innerc
);
5919 n1
= OMP_CLAUSE_DECL (innerc
);
5920 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5921 OMP_CLAUSE__LOOPTEMP_
);
5922 gcc_assert (innerc
);
5923 n2
= OMP_CLAUSE_DECL (innerc
);
5925 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
5926 true, NULL_TREE
, true, GSI_SAME_STMT
);
5927 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
5928 true, NULL_TREE
, true, GSI_SAME_STMT
);
5929 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
5930 true, NULL_TREE
, true, GSI_SAME_STMT
);
5932 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
5933 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
5934 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
5935 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
5936 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
5937 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5938 fold_build1 (NEGATE_EXPR
, itype
, t
),
5939 fold_build1 (NEGATE_EXPR
, itype
, step
));
5941 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
5942 t
= fold_convert (itype
, t
);
5943 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
5945 q
= create_tmp_reg (itype
, "q");
5946 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
5947 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
5948 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
5950 tt
= create_tmp_reg (itype
, "tt");
5951 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
5952 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
5953 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
5955 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
5956 stmt
= gimple_build_cond_empty (t
);
5957 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5959 second_bb
= split_block (entry_bb
, stmt
)->dest
;
5960 gsi
= gsi_last_bb (second_bb
);
5961 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5963 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
5965 stmt
= gimple_build_assign_with_ops (PLUS_EXPR
, q
, q
,
5966 build_int_cst (itype
, 1));
5967 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5969 third_bb
= split_block (second_bb
, stmt
)->dest
;
5970 gsi
= gsi_last_bb (third_bb
);
5971 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5973 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
5974 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
5975 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
5977 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
5978 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
5980 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
5981 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5983 /* Remove the GIMPLE_OMP_FOR statement. */
5984 gsi_remove (&gsi
, true);
5986 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5987 gsi
= gsi_start_bb (seq_start_bb
);
5989 tree startvar
= fd
->loop
.v
;
5990 tree endvar
= NULL_TREE
;
5992 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5994 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5995 ? gimple_omp_parallel_clauses (inner_stmt
)
5996 : gimple_omp_for_clauses (inner_stmt
);
5997 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5998 gcc_assert (innerc
);
5999 startvar
= OMP_CLAUSE_DECL (innerc
);
6000 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6001 OMP_CLAUSE__LOOPTEMP_
);
6002 gcc_assert (innerc
);
6003 endvar
= OMP_CLAUSE_DECL (innerc
);
6005 t
= fold_convert (itype
, s0
);
6006 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6007 if (POINTER_TYPE_P (type
))
6008 t
= fold_build_pointer_plus (n1
, t
);
6010 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6011 t
= fold_convert (TREE_TYPE (startvar
), t
);
6012 t
= force_gimple_operand_gsi (&gsi
, t
,
6014 && TREE_ADDRESSABLE (startvar
),
6015 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6016 stmt
= gimple_build_assign (startvar
, t
);
6017 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6019 t
= fold_convert (itype
, e0
);
6020 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6021 if (POINTER_TYPE_P (type
))
6022 t
= fold_build_pointer_plus (n1
, t
);
6024 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6025 t
= fold_convert (TREE_TYPE (startvar
), t
);
6026 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6027 false, GSI_CONTINUE_LINKING
);
6030 stmt
= gimple_build_assign (endvar
, e
);
6031 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6032 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6033 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6035 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6037 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6039 if (fd
->collapse
> 1)
6040 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6044 /* The code controlling the sequential loop replaces the
6045 GIMPLE_OMP_CONTINUE. */
6046 gsi
= gsi_last_bb (cont_bb
);
6047 stmt
= gsi_stmt (gsi
);
6048 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6049 vmain
= gimple_omp_continue_control_use (stmt
);
6050 vback
= gimple_omp_continue_control_def (stmt
);
6052 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6054 if (POINTER_TYPE_P (type
))
6055 t
= fold_build_pointer_plus (vmain
, step
);
6057 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6058 t
= force_gimple_operand_gsi (&gsi
, t
,
6060 && TREE_ADDRESSABLE (vback
),
6061 NULL_TREE
, true, GSI_SAME_STMT
);
6062 stmt
= gimple_build_assign (vback
, t
);
6063 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6065 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6066 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6068 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6071 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6072 gsi_remove (&gsi
, true);
6074 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6075 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6078 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6079 gsi
= gsi_last_bb (exit_bb
);
6080 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6082 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6083 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6085 gsi_remove (&gsi
, true);
6087 /* Connect all the blocks. */
6088 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6089 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6090 ep
= find_edge (entry_bb
, second_bb
);
6091 ep
->flags
= EDGE_TRUE_VALUE
;
6092 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6093 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6094 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6098 ep
= find_edge (cont_bb
, body_bb
);
6099 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6104 else if (fd
->collapse
> 1)
6107 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6110 ep
->flags
= EDGE_TRUE_VALUE
;
6111 find_edge (cont_bb
, fin_bb
)->flags
6112 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6115 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6116 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6117 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6119 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6120 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6121 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6122 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6124 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6126 struct loop
*loop
= alloc_loop ();
6127 loop
->header
= body_bb
;
6128 if (collapse_bb
== NULL
)
6129 loop
->latch
= cont_bb
;
6130 add_loop (loop
, body_bb
->loop_father
);
6135 /* A subroutine of expand_omp_for. Generate code for a parallel
6136 loop with static schedule and a specified chunk size. Given
6139 for (V = N1; V cond N2; V += STEP) BODY;
6141 where COND is "<" or ">", we generate pseudocode
6143 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6148 if ((__typeof (V)) -1 > 0 && cond is >)
6149 n = -(adj + N2 - N1) / -STEP;
6151 n = (adj + N2 - N1) / STEP;
6153 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6154 here so that V is defined
6155 if the loop is not entered
6157 s0 = (trip * nthreads + threadid) * CHUNK;
6158 e0 = min(s0 + CHUNK, n);
6159 if (s0 < n) goto L1; else goto L4;
6166 if (V cond e) goto L2; else goto L3;
6174 expand_omp_for_static_chunk (struct omp_region
*region
,
6175 struct omp_for_data
*fd
, gimple inner_stmt
)
6177 tree n
, s0
, e0
, e
, t
;
6178 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6179 tree type
, itype
, vmain
, vback
, vextra
;
6180 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6181 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6182 gimple_stmt_iterator gsi
;
6185 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6186 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6187 bool broken_loop
= region
->cont
== NULL
;
6188 tree
*counts
= NULL
;
6191 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6192 if (POINTER_TYPE_P (type
))
6193 itype
= signed_type_for (type
);
6195 entry_bb
= region
->entry
;
6196 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6198 iter_part_bb
= se
->dest
;
6199 cont_bb
= region
->cont
;
6200 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6201 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6202 gcc_assert (broken_loop
6203 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6204 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6205 body_bb
= single_succ (seq_start_bb
);
6208 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6209 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6210 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6212 exit_bb
= region
->exit
;
6214 /* Trip and adjustment setup goes in ENTRY_BB. */
6215 gsi
= gsi_last_bb (entry_bb
);
6216 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6218 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6220 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6221 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6224 if (fd
->collapse
> 1)
6226 int first_zero_iter
= -1;
6227 basic_block l2_dom_bb
= NULL
;
6229 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6230 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6231 fin_bb
, first_zero_iter
,
6235 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6236 t
= integer_one_node
;
6238 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6239 fold_convert (type
, fd
->loop
.n1
),
6240 fold_convert (type
, fd
->loop
.n2
));
6241 if (fd
->collapse
== 1
6242 && TYPE_UNSIGNED (type
)
6243 && (t
== NULL_TREE
|| !integer_onep (t
)))
6245 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6246 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6247 true, GSI_SAME_STMT
);
6248 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6249 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6250 true, GSI_SAME_STMT
);
6251 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6252 NULL_TREE
, NULL_TREE
);
6253 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6254 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
6255 expand_omp_regimplify_p
, NULL
, NULL
)
6256 || walk_tree (gimple_cond_rhs_ptr (stmt
),
6257 expand_omp_regimplify_p
, NULL
, NULL
))
6259 gsi
= gsi_for_stmt (stmt
);
6260 gimple_regimplify_operands (stmt
, &gsi
);
6262 se
= split_block (entry_bb
, stmt
);
6263 se
->flags
= EDGE_TRUE_VALUE
;
6264 entry_bb
= se
->dest
;
6265 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6266 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6267 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6268 if (gimple_in_ssa_p (cfun
))
6270 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6271 for (gsi
= gsi_start_phis (fin_bb
);
6272 !gsi_end_p (gsi
); gsi_next (&gsi
))
6274 gimple phi
= gsi_stmt (gsi
);
6275 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6276 se
, UNKNOWN_LOCATION
);
6279 gsi
= gsi_last_bb (entry_bb
);
6282 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6283 t
= fold_convert (itype
, t
);
6284 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6285 true, GSI_SAME_STMT
);
6287 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6288 t
= fold_convert (itype
, t
);
6289 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6290 true, GSI_SAME_STMT
);
6294 step
= fd
->loop
.step
;
6295 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6297 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6298 OMP_CLAUSE__LOOPTEMP_
);
6299 gcc_assert (innerc
);
6300 n1
= OMP_CLAUSE_DECL (innerc
);
6301 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6302 OMP_CLAUSE__LOOPTEMP_
);
6303 gcc_assert (innerc
);
6304 n2
= OMP_CLAUSE_DECL (innerc
);
6306 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6307 true, NULL_TREE
, true, GSI_SAME_STMT
);
6308 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6309 true, NULL_TREE
, true, GSI_SAME_STMT
);
6310 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6311 true, NULL_TREE
, true, GSI_SAME_STMT
);
6313 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
6314 true, NULL_TREE
, true, GSI_SAME_STMT
);
6316 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6317 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6318 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6319 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6320 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6321 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6322 fold_build1 (NEGATE_EXPR
, itype
, t
),
6323 fold_build1 (NEGATE_EXPR
, itype
, step
));
6325 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6326 t
= fold_convert (itype
, t
);
6327 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6328 true, GSI_SAME_STMT
);
6330 trip_var
= create_tmp_reg (itype
, ".trip");
6331 if (gimple_in_ssa_p (cfun
))
6333 trip_init
= make_ssa_name (trip_var
, NULL
);
6334 trip_main
= make_ssa_name (trip_var
, NULL
);
6335 trip_back
= make_ssa_name (trip_var
, NULL
);
6339 trip_init
= trip_var
;
6340 trip_main
= trip_var
;
6341 trip_back
= trip_var
;
6344 stmt
= gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
6345 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6347 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
6348 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6349 if (POINTER_TYPE_P (type
))
6350 t
= fold_build_pointer_plus (n1
, t
);
6352 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6353 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6354 true, GSI_SAME_STMT
);
6356 /* Remove the GIMPLE_OMP_FOR. */
6357 gsi_remove (&gsi
, true);
6359 /* Iteration space partitioning goes in ITER_PART_BB. */
6360 gsi
= gsi_last_bb (iter_part_bb
);
6362 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
6363 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
6364 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
6365 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6366 false, GSI_CONTINUE_LINKING
);
6368 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
6369 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
6370 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6371 false, GSI_CONTINUE_LINKING
);
6373 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
6374 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
6376 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6377 gsi
= gsi_start_bb (seq_start_bb
);
6379 tree startvar
= fd
->loop
.v
;
6380 tree endvar
= NULL_TREE
;
6382 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6384 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6385 ? gimple_omp_parallel_clauses (inner_stmt
)
6386 : gimple_omp_for_clauses (inner_stmt
);
6387 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6388 gcc_assert (innerc
);
6389 startvar
= OMP_CLAUSE_DECL (innerc
);
6390 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6391 OMP_CLAUSE__LOOPTEMP_
);
6392 gcc_assert (innerc
);
6393 endvar
= OMP_CLAUSE_DECL (innerc
);
6396 t
= fold_convert (itype
, s0
);
6397 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6398 if (POINTER_TYPE_P (type
))
6399 t
= fold_build_pointer_plus (n1
, t
);
6401 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6402 t
= fold_convert (TREE_TYPE (startvar
), t
);
6403 t
= force_gimple_operand_gsi (&gsi
, t
,
6405 && TREE_ADDRESSABLE (startvar
),
6406 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6407 stmt
= gimple_build_assign (startvar
, t
);
6408 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6410 t
= fold_convert (itype
, e0
);
6411 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6412 if (POINTER_TYPE_P (type
))
6413 t
= fold_build_pointer_plus (n1
, t
);
6415 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6416 t
= fold_convert (TREE_TYPE (startvar
), t
);
6417 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6418 false, GSI_CONTINUE_LINKING
);
6421 stmt
= gimple_build_assign (endvar
, e
);
6422 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6423 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6424 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6426 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6428 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6430 if (fd
->collapse
> 1)
6431 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6435 /* The code controlling the sequential loop goes in CONT_BB,
6436 replacing the GIMPLE_OMP_CONTINUE. */
6437 gsi
= gsi_last_bb (cont_bb
);
6438 stmt
= gsi_stmt (gsi
);
6439 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6440 vmain
= gimple_omp_continue_control_use (stmt
);
6441 vback
= gimple_omp_continue_control_def (stmt
);
6443 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6445 if (POINTER_TYPE_P (type
))
6446 t
= fold_build_pointer_plus (vmain
, step
);
6448 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6449 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
6450 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6451 true, GSI_SAME_STMT
);
6452 stmt
= gimple_build_assign (vback
, t
);
6453 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6455 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6456 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6458 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6461 /* Remove GIMPLE_OMP_CONTINUE. */
6462 gsi_remove (&gsi
, true);
6464 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6465 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6467 /* Trip update code goes into TRIP_UPDATE_BB. */
6468 gsi
= gsi_start_bb (trip_update_bb
);
6470 t
= build_int_cst (itype
, 1);
6471 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
6472 stmt
= gimple_build_assign (trip_back
, t
);
6473 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6476 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6477 gsi
= gsi_last_bb (exit_bb
);
6478 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6480 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6481 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6483 gsi_remove (&gsi
, true);
6485 /* Connect the new blocks. */
6486 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
6487 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
6491 se
= find_edge (cont_bb
, body_bb
);
6492 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6497 else if (fd
->collapse
> 1)
6500 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6503 se
->flags
= EDGE_TRUE_VALUE
;
6504 find_edge (cont_bb
, trip_update_bb
)->flags
6505 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6507 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
6510 if (gimple_in_ssa_p (cfun
))
6512 gimple_stmt_iterator psi
;
6515 edge_var_map_vector
*head
;
6519 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
6521 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6522 remove arguments of the phi nodes in fin_bb. We need to create
6523 appropriate phi nodes in iter_part_bb instead. */
6524 se
= single_pred_edge (fin_bb
);
6525 re
= single_succ_edge (trip_update_bb
);
6526 head
= redirect_edge_var_map_vector (re
);
6527 ene
= single_succ_edge (entry_bb
);
6529 psi
= gsi_start_phis (fin_bb
);
6530 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
6531 gsi_next (&psi
), ++i
)
6534 source_location locus
;
6536 phi
= gsi_stmt (psi
);
6537 t
= gimple_phi_result (phi
);
6538 gcc_assert (t
== redirect_edge_var_map_result (vm
));
6539 nphi
= create_phi_node (t
, iter_part_bb
);
6541 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
6542 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
6544 /* A special case -- fd->loop.v is not yet computed in
6545 iter_part_bb, we need to use vextra instead. */
6546 if (t
== fd
->loop
.v
)
6548 add_phi_arg (nphi
, t
, ene
, locus
);
6549 locus
= redirect_edge_var_map_location (vm
);
6550 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
6552 gcc_assert (!gsi_end_p (psi
) && i
== head
->length ());
6553 redirect_edge_var_map_clear (re
);
6556 psi
= gsi_start_phis (fin_bb
);
6557 if (gsi_end_p (psi
))
6559 remove_phi_node (&psi
, false);
6562 /* Make phi node for trip. */
6563 phi
= create_phi_node (trip_main
, iter_part_bb
);
6564 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
6566 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
6571 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
6572 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
6573 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
6574 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6575 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6576 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
6577 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
6578 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6579 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6583 struct loop
*trip_loop
= alloc_loop ();
6584 trip_loop
->header
= iter_part_bb
;
6585 trip_loop
->latch
= trip_update_bb
;
6586 add_loop (trip_loop
, iter_part_bb
->loop_father
);
6588 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6590 struct loop
*loop
= alloc_loop ();
6591 loop
->header
= body_bb
;
6592 if (collapse_bb
== NULL
)
6593 loop
->latch
= cont_bb
;
6594 add_loop (loop
, trip_loop
);
6600 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6601 loop. Given parameters:
6603 for (V = N1; V cond N2; V += STEP) BODY;
6605 where COND is "<" or ">", we generate pseudocode
6613 if (V cond N2) goto L0; else goto L2;
6616 For collapsed loops, given parameters:
6618 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6619 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6620 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6623 we generate pseudocode
6629 count3 = (adj + N32 - N31) / STEP3;
6634 count2 = (adj + N22 - N21) / STEP2;
6639 count1 = (adj + N12 - N11) / STEP1;
6640 count = count1 * count2 * count3;
6650 V2 += (V3 cond3 N32) ? 0 : STEP2;
6651 V3 = (V3 cond3 N32) ? V3 : N31;
6652 V1 += (V2 cond2 N22) ? 0 : STEP1;
6653 V2 = (V2 cond2 N22) ? V2 : N21;
6655 if (V < count) goto L0; else goto L2;
6661 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
6664 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
6665 gimple_stmt_iterator gsi
;
6667 bool broken_loop
= region
->cont
== NULL
;
6669 tree
*counts
= NULL
;
6671 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6672 OMP_CLAUSE_SAFELEN
);
6673 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6674 OMP_CLAUSE__SIMDUID_
);
6677 type
= TREE_TYPE (fd
->loop
.v
);
6678 entry_bb
= region
->entry
;
6679 cont_bb
= region
->cont
;
6680 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6681 gcc_assert (broken_loop
6682 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6683 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
6686 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
6687 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6688 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
6689 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6693 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
6694 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
6695 l2_bb
= single_succ (l1_bb
);
6697 exit_bb
= region
->exit
;
6700 gsi
= gsi_last_bb (entry_bb
);
6702 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6703 /* Not needed in SSA form right now. */
6704 gcc_assert (!gimple_in_ssa_p (cfun
));
6705 if (fd
->collapse
> 1)
6707 int first_zero_iter
= -1;
6708 basic_block zero_iter_bb
= l2_bb
;
6710 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6711 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6712 zero_iter_bb
, first_zero_iter
,
6715 if (l2_dom_bb
== NULL
)
6720 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6722 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6723 OMP_CLAUSE__LOOPTEMP_
);
6724 gcc_assert (innerc
);
6725 n1
= OMP_CLAUSE_DECL (innerc
);
6726 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6727 OMP_CLAUSE__LOOPTEMP_
);
6728 gcc_assert (innerc
);
6729 n2
= OMP_CLAUSE_DECL (innerc
);
6730 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
6731 fold_convert (type
, n1
));
6732 if (fd
->collapse
> 1)
6735 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
6741 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
6742 fold_convert (type
, fd
->loop
.n1
));
6743 if (fd
->collapse
> 1)
6744 for (i
= 0; i
< fd
->collapse
; i
++)
6746 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
6747 if (POINTER_TYPE_P (itype
))
6748 itype
= signed_type_for (itype
);
6749 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
6750 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
6754 /* Remove the GIMPLE_OMP_FOR statement. */
6755 gsi_remove (&gsi
, true);
6759 /* Code to control the increment goes in the CONT_BB. */
6760 gsi
= gsi_last_bb (cont_bb
);
6761 stmt
= gsi_stmt (gsi
);
6762 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6764 if (POINTER_TYPE_P (type
))
6765 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
6767 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
6768 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
6770 if (fd
->collapse
> 1)
6772 i
= fd
->collapse
- 1;
6773 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
6775 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
6776 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
6780 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
6782 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
6785 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
6787 for (i
= fd
->collapse
- 1; i
> 0; i
--)
6789 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
6790 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
6791 if (POINTER_TYPE_P (itype2
))
6792 itype2
= signed_type_for (itype2
);
6793 t
= build3 (COND_EXPR
, itype2
,
6794 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
6796 fold_convert (itype
, fd
->loops
[i
].n2
)),
6797 build_int_cst (itype2
, 0),
6798 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
6799 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
6800 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
6802 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
6803 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
6805 t
= build3 (COND_EXPR
, itype
,
6806 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
6808 fold_convert (itype
, fd
->loops
[i
].n2
)),
6810 fold_convert (itype
, fd
->loops
[i
].n1
));
6811 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
6815 /* Remove GIMPLE_OMP_CONTINUE. */
6816 gsi_remove (&gsi
, true);
6819 /* Emit the condition in L1_BB. */
6820 gsi
= gsi_start_bb (l1_bb
);
6822 t
= fold_convert (type
, n2
);
6823 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6824 false, GSI_CONTINUE_LINKING
);
6825 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
6826 stmt
= gimple_build_cond_empty (t
);
6827 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6828 if (walk_tree (gimple_cond_lhs_ptr (stmt
), expand_omp_regimplify_p
,
6830 || walk_tree (gimple_cond_rhs_ptr (stmt
), expand_omp_regimplify_p
,
6833 gsi
= gsi_for_stmt (stmt
);
6834 gimple_regimplify_operands (stmt
, &gsi
);
6837 /* Remove GIMPLE_OMP_RETURN. */
6838 gsi
= gsi_last_bb (exit_bb
);
6839 gsi_remove (&gsi
, true);
6841 /* Connect the new blocks. */
6842 remove_edge (FALLTHRU_EDGE (entry_bb
));
6846 remove_edge (BRANCH_EDGE (entry_bb
));
6847 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
6849 e
= BRANCH_EDGE (l1_bb
);
6850 ne
= FALLTHRU_EDGE (l1_bb
);
6851 e
->flags
= EDGE_TRUE_VALUE
;
6855 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6857 ne
= single_succ_edge (l1_bb
);
6858 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6861 ne
->flags
= EDGE_FALSE_VALUE
;
6862 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6863 ne
->probability
= REG_BR_PROB_BASE
/ 8;
6865 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
6866 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
6867 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
6871 struct loop
*loop
= alloc_loop ();
6872 loop
->header
= l1_bb
;
6873 loop
->latch
= cont_bb
;
6874 add_loop (loop
, l1_bb
->loop_father
);
6875 if (safelen
== NULL_TREE
)
6876 loop
->safelen
= INT_MAX
;
6879 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
6880 if (!tree_fits_uhwi_p (safelen
)
6881 || tree_to_uhwi (safelen
) > INT_MAX
)
6882 loop
->safelen
= INT_MAX
;
6884 loop
->safelen
= tree_to_uhwi (safelen
);
6885 if (loop
->safelen
== 1)
6890 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
6891 cfun
->has_simduid_loops
= true;
6893 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6895 if ((flag_tree_loop_vectorize
6896 || (!global_options_set
.x_flag_tree_loop_vectorize
6897 && !global_options_set
.x_flag_tree_vectorize
))
6898 && flag_tree_loop_optimize
6899 && loop
->safelen
> 1)
6901 loop
->force_vectorize
= true;
6902 cfun
->has_force_vectorize_loops
= true;
6908 /* Expand the OpenMP loop defined by REGION. */
6911 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
6913 struct omp_for_data fd
;
6914 struct omp_for_data_loop
*loops
;
6917 = (struct omp_for_data_loop
*)
6918 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
6919 * sizeof (struct omp_for_data_loop
));
6920 extract_omp_for_data (last_stmt (region
->entry
), &fd
, loops
);
6921 region
->sched_kind
= fd
.sched_kind
;
6923 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
6924 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
6925 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
6928 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
6929 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
6930 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
6933 /* If there isn't a continue then this is a degerate case where
6934 the introduction of abnormal edges during lowering will prevent
6935 original loops from being detected. Fix that up. */
6936 loops_state_set (LOOPS_NEED_FIXUP
);
6938 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
6939 expand_omp_simd (region
, &fd
);
6940 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
6941 && !fd
.have_ordered
)
6943 if (fd
.chunk_size
== NULL
)
6944 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
6946 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
6950 int fn_index
, start_ix
, next_ix
;
6952 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
6953 == GF_OMP_FOR_KIND_FOR
);
6954 if (fd
.chunk_size
== NULL
6955 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
6956 fd
.chunk_size
= integer_zero_node
;
6957 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
6958 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
6959 ? 3 : fd
.sched_kind
;
6960 fn_index
+= fd
.have_ordered
* 4;
6961 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
6962 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
6963 if (fd
.iter_type
== long_long_unsigned_type_node
)
6965 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6966 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
6967 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6968 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
6970 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
6971 (enum built_in_function
) next_ix
, inner_stmt
);
6974 if (gimple_in_ssa_p (cfun
))
6975 update_ssa (TODO_update_ssa_only_virtuals
);
6979 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6981 v = GOMP_sections_start (n);
6998 v = GOMP_sections_next ();
7003 If this is a combined parallel sections, replace the call to
7004 GOMP_sections_start with call to GOMP_sections_next. */
7007 expand_omp_sections (struct omp_region
*region
)
7009 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7011 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7012 gimple_stmt_iterator si
, switch_si
;
7013 gimple sections_stmt
, stmt
, cont
;
7016 struct omp_region
*inner
;
7018 bool exit_reachable
= region
->cont
!= NULL
;
7020 gcc_assert (region
->exit
!= NULL
);
7021 entry_bb
= region
->entry
;
7022 l0_bb
= single_succ (entry_bb
);
7023 l1_bb
= region
->cont
;
7024 l2_bb
= region
->exit
;
7025 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7026 l2
= gimple_block_label (l2_bb
);
7029 /* This can happen if there are reductions. */
7030 len
= EDGE_COUNT (l0_bb
->succs
);
7031 gcc_assert (len
> 0);
7032 e
= EDGE_SUCC (l0_bb
, len
- 1);
7033 si
= gsi_last_bb (e
->dest
);
7036 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7037 l2
= gimple_block_label (e
->dest
);
7039 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7041 si
= gsi_last_bb (e
->dest
);
7043 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7045 l2
= gimple_block_label (e
->dest
);
7051 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7053 default_bb
= create_empty_bb (l0_bb
);
7055 /* We will build a switch() with enough cases for all the
7056 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7057 and a default case to abort if something goes wrong. */
7058 len
= EDGE_COUNT (l0_bb
->succs
);
7060 /* Use vec::quick_push on label_vec throughout, since we know the size
7062 auto_vec
<tree
> label_vec (len
);
7064 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7065 GIMPLE_OMP_SECTIONS statement. */
7066 si
= gsi_last_bb (entry_bb
);
7067 sections_stmt
= gsi_stmt (si
);
7068 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
7069 vin
= gimple_omp_sections_control (sections_stmt
);
7070 if (!is_combined_parallel (region
))
7072 /* If we are not inside a combined parallel+sections region,
7073 call GOMP_sections_start. */
7074 t
= build_int_cst (unsigned_type_node
, len
- 1);
7075 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
7076 stmt
= gimple_build_call (u
, 1, t
);
7080 /* Otherwise, call GOMP_sections_next. */
7081 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7082 stmt
= gimple_build_call (u
, 0);
7084 gimple_call_set_lhs (stmt
, vin
);
7085 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7086 gsi_remove (&si
, true);
7088 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7090 switch_si
= gsi_last_bb (l0_bb
);
7091 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
7094 cont
= last_stmt (l1_bb
);
7095 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
7096 vmain
= gimple_omp_continue_control_use (cont
);
7097 vnext
= gimple_omp_continue_control_def (cont
);
7105 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
7106 label_vec
.quick_push (t
);
7109 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7110 for (inner
= region
->inner
, casei
= 1;
7112 inner
= inner
->next
, i
++, casei
++)
7114 basic_block s_entry_bb
, s_exit_bb
;
7116 /* Skip optional reduction region. */
7117 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
7124 s_entry_bb
= inner
->entry
;
7125 s_exit_bb
= inner
->exit
;
7127 t
= gimple_block_label (s_entry_bb
);
7128 u
= build_int_cst (unsigned_type_node
, casei
);
7129 u
= build_case_label (u
, NULL
, t
);
7130 label_vec
.quick_push (u
);
7132 si
= gsi_last_bb (s_entry_bb
);
7133 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
7134 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
7135 gsi_remove (&si
, true);
7136 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
7138 if (s_exit_bb
== NULL
)
7141 si
= gsi_last_bb (s_exit_bb
);
7142 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7143 gsi_remove (&si
, true);
7145 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
7148 /* Error handling code goes in DEFAULT_BB. */
7149 t
= gimple_block_label (default_bb
);
7150 u
= build_case_label (NULL
, NULL
, t
);
7151 make_edge (l0_bb
, default_bb
, 0);
7152 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
7154 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
7155 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
7156 gsi_remove (&switch_si
, true);
7158 si
= gsi_start_bb (default_bb
);
7159 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
7160 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
7166 /* Code to get the next section goes in L1_BB. */
7167 si
= gsi_last_bb (l1_bb
);
7168 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
7170 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7171 stmt
= gimple_build_call (bfn_decl
, 0);
7172 gimple_call_set_lhs (stmt
, vnext
);
7173 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7174 gsi_remove (&si
, true);
7176 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
7179 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7180 si
= gsi_last_bb (l2_bb
);
7181 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
7182 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
7183 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
7184 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
7186 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
7187 stmt
= gimple_build_call (t
, 0);
7188 if (gimple_omp_return_lhs (gsi_stmt (si
)))
7189 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
7190 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7191 gsi_remove (&si
, true);
7193 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
7197 /* Expand code for an OpenMP single directive. We've already expanded
7198 much of the code, here we simply place the GOMP_barrier call. */
7201 expand_omp_single (struct omp_region
*region
)
7203 basic_block entry_bb
, exit_bb
;
7204 gimple_stmt_iterator si
;
7206 entry_bb
= region
->entry
;
7207 exit_bb
= region
->exit
;
7209 si
= gsi_last_bb (entry_bb
);
7210 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
7211 gsi_remove (&si
, true);
7212 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7214 si
= gsi_last_bb (exit_bb
);
7215 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
7217 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
7218 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
7220 gsi_remove (&si
, true);
7221 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7225 /* Generic expansion for OpenMP synchronization directives: master,
7226 ordered and critical. All we need to do here is remove the entry
7227 and exit markers for REGION. */
7230 expand_omp_synch (struct omp_region
*region
)
7232 basic_block entry_bb
, exit_bb
;
7233 gimple_stmt_iterator si
;
7235 entry_bb
= region
->entry
;
7236 exit_bb
= region
->exit
;
7238 si
= gsi_last_bb (entry_bb
);
7239 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
7240 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
7241 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
7242 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
7243 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
7244 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
7245 gsi_remove (&si
, true);
7246 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7250 si
= gsi_last_bb (exit_bb
);
7251 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7252 gsi_remove (&si
, true);
7253 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7257 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7258 operation as a normal volatile load. */
7261 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
7262 tree loaded_val
, int index
)
7264 enum built_in_function tmpbase
;
7265 gimple_stmt_iterator gsi
;
7266 basic_block store_bb
;
7269 tree decl
, call
, type
, itype
;
7271 gsi
= gsi_last_bb (load_bb
);
7272 stmt
= gsi_stmt (gsi
);
7273 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7274 loc
= gimple_location (stmt
);
7276 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7277 is smaller than word size, then expand_atomic_load assumes that the load
7278 is atomic. We could avoid the builtin entirely in this case. */
7280 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7281 decl
= builtin_decl_explicit (tmpbase
);
7282 if (decl
== NULL_TREE
)
7285 type
= TREE_TYPE (loaded_val
);
7286 itype
= TREE_TYPE (TREE_TYPE (decl
));
7288 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
7289 build_int_cst (NULL
,
7290 gimple_omp_atomic_seq_cst_p (stmt
)
7292 : MEMMODEL_RELAXED
));
7293 if (!useless_type_conversion_p (type
, itype
))
7294 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7295 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7297 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7298 gsi_remove (&gsi
, true);
7300 store_bb
= single_succ (load_bb
);
7301 gsi
= gsi_last_bb (store_bb
);
7302 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7303 gsi_remove (&gsi
, true);
7305 if (gimple_in_ssa_p (cfun
))
7306 update_ssa (TODO_update_ssa_no_phi
);
7311 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7312 operation as a normal volatile store. */
7315 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
7316 tree loaded_val
, tree stored_val
, int index
)
7318 enum built_in_function tmpbase
;
7319 gimple_stmt_iterator gsi
;
7320 basic_block store_bb
= single_succ (load_bb
);
7323 tree decl
, call
, type
, itype
;
7324 enum machine_mode imode
;
7327 gsi
= gsi_last_bb (load_bb
);
7328 stmt
= gsi_stmt (gsi
);
7329 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7331 /* If the load value is needed, then this isn't a store but an exchange. */
7332 exchange
= gimple_omp_atomic_need_value_p (stmt
);
7334 gsi
= gsi_last_bb (store_bb
);
7335 stmt
= gsi_stmt (gsi
);
7336 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
7337 loc
= gimple_location (stmt
);
7339 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7340 is smaller than word size, then expand_atomic_store assumes that the store
7341 is atomic. We could avoid the builtin entirely in this case. */
7343 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
7344 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
7345 decl
= builtin_decl_explicit (tmpbase
);
7346 if (decl
== NULL_TREE
)
7349 type
= TREE_TYPE (stored_val
);
7351 /* Dig out the type of the function's second argument. */
7352 itype
= TREE_TYPE (decl
);
7353 itype
= TYPE_ARG_TYPES (itype
);
7354 itype
= TREE_CHAIN (itype
);
7355 itype
= TREE_VALUE (itype
);
7356 imode
= TYPE_MODE (itype
);
7358 if (exchange
&& !can_atomic_exchange_p (imode
, true))
7361 if (!useless_type_conversion_p (itype
, type
))
7362 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
7363 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
7364 build_int_cst (NULL
,
7365 gimple_omp_atomic_seq_cst_p (stmt
)
7367 : MEMMODEL_RELAXED
));
7370 if (!useless_type_conversion_p (type
, itype
))
7371 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7372 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7375 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7376 gsi_remove (&gsi
, true);
7378 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7379 gsi
= gsi_last_bb (load_bb
);
7380 gsi_remove (&gsi
, true);
7382 if (gimple_in_ssa_p (cfun
))
7383 update_ssa (TODO_update_ssa_no_phi
);
7388 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7389 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7390 size of the data type, and thus usable to find the index of the builtin
7391 decl. Returns false if the expression is not of the proper form. */
7394 expand_omp_atomic_fetch_op (basic_block load_bb
,
7395 tree addr
, tree loaded_val
,
7396 tree stored_val
, int index
)
7398 enum built_in_function oldbase
, newbase
, tmpbase
;
7399 tree decl
, itype
, call
;
7401 basic_block store_bb
= single_succ (load_bb
);
7402 gimple_stmt_iterator gsi
;
7405 enum tree_code code
;
7406 bool need_old
, need_new
;
7407 enum machine_mode imode
;
7410 /* We expect to find the following sequences:
7413 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7416 val = tmp OP something; (or: something OP tmp)
7417 GIMPLE_OMP_STORE (val)
7419 ???FIXME: Allow a more flexible sequence.
7420 Perhaps use data flow to pick the statements.
7424 gsi
= gsi_after_labels (store_bb
);
7425 stmt
= gsi_stmt (gsi
);
7426 loc
= gimple_location (stmt
);
7427 if (!is_gimple_assign (stmt
))
7430 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
7432 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
7433 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
7434 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
7435 gcc_checking_assert (!need_old
|| !need_new
);
7437 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
7440 /* Check for one of the supported fetch-op operations. */
7441 code
= gimple_assign_rhs_code (stmt
);
7445 case POINTER_PLUS_EXPR
:
7446 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
7447 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
7450 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
7451 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
7454 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
7455 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
7458 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
7459 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
7462 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
7463 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
7469 /* Make sure the expression is of the proper form. */
7470 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
7471 rhs
= gimple_assign_rhs2 (stmt
);
7472 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
7473 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
7474 rhs
= gimple_assign_rhs1 (stmt
);
7478 tmpbase
= ((enum built_in_function
)
7479 ((need_new
? newbase
: oldbase
) + index
+ 1));
7480 decl
= builtin_decl_explicit (tmpbase
);
7481 if (decl
== NULL_TREE
)
7483 itype
= TREE_TYPE (TREE_TYPE (decl
));
7484 imode
= TYPE_MODE (itype
);
7486 /* We could test all of the various optabs involved, but the fact of the
7487 matter is that (with the exception of i486 vs i586 and xadd) all targets
7488 that support any atomic operaton optab also implements compare-and-swap.
7489 Let optabs.c take care of expanding any compare-and-swap loop. */
7490 if (!can_compare_and_swap_p (imode
, true))
7493 gsi
= gsi_last_bb (load_bb
);
7494 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7496 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7497 It only requires that the operation happen atomically. Thus we can
7498 use the RELAXED memory model. */
7499 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
7500 fold_convert_loc (loc
, itype
, rhs
),
7501 build_int_cst (NULL
,
7502 seq_cst
? MEMMODEL_SEQ_CST
7503 : MEMMODEL_RELAXED
));
7505 if (need_old
|| need_new
)
7507 lhs
= need_old
? loaded_val
: stored_val
;
7508 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
7509 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
7512 call
= fold_convert_loc (loc
, void_type_node
, call
);
7513 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7514 gsi_remove (&gsi
, true);
7516 gsi
= gsi_last_bb (store_bb
);
7517 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7518 gsi_remove (&gsi
, true);
7519 gsi
= gsi_last_bb (store_bb
);
7520 gsi_remove (&gsi
, true);
7522 if (gimple_in_ssa_p (cfun
))
7523 update_ssa (TODO_update_ssa_no_phi
);
7528 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7532 newval = rhs; // with oldval replacing *addr in rhs
7533 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7534 if (oldval != newval)
7537 INDEX is log2 of the size of the data type, and thus usable to find the
7538 index of the builtin decl. */
7541 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
7542 tree addr
, tree loaded_val
, tree stored_val
,
7545 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
7546 tree type
, itype
, cmpxchg
, iaddr
;
7547 gimple_stmt_iterator si
;
7548 basic_block loop_header
= single_succ (load_bb
);
7551 enum built_in_function fncode
;
7553 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7554 order to use the RELAXED memory model effectively. */
7555 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7557 cmpxchg
= builtin_decl_explicit (fncode
);
7558 if (cmpxchg
== NULL_TREE
)
7560 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
7561 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
7563 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
7566 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7567 si
= gsi_last_bb (load_bb
);
7568 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7570 /* For floating-point values, we'll need to view-convert them to integers
7571 so that we can perform the atomic compare and swap. Simplify the
7572 following code by always setting up the "i"ntegral variables. */
7573 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
7577 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
7580 = force_gimple_operand_gsi (&si
,
7581 fold_convert (TREE_TYPE (iaddr
), addr
),
7582 false, NULL_TREE
, true, GSI_SAME_STMT
);
7583 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
7584 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7585 loadedi
= create_tmp_var (itype
, NULL
);
7586 if (gimple_in_ssa_p (cfun
))
7587 loadedi
= make_ssa_name (loadedi
, NULL
);
7592 loadedi
= loaded_val
;
7595 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7596 tree loaddecl
= builtin_decl_explicit (fncode
);
7599 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
7600 build_call_expr (loaddecl
, 2, iaddr
,
7601 build_int_cst (NULL_TREE
,
7602 MEMMODEL_RELAXED
)));
7604 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
7605 build_int_cst (TREE_TYPE (iaddr
), 0));
7608 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
7611 /* Move the value to the LOADEDI temporary. */
7612 if (gimple_in_ssa_p (cfun
))
7614 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
7615 phi
= create_phi_node (loadedi
, loop_header
);
7616 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
7620 gsi_insert_before (&si
,
7621 gimple_build_assign (loadedi
, initial
),
7623 if (loadedi
!= loaded_val
)
7625 gimple_stmt_iterator gsi2
;
7628 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
7629 gsi2
= gsi_start_bb (loop_header
);
7630 if (gimple_in_ssa_p (cfun
))
7633 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
7634 true, GSI_SAME_STMT
);
7635 stmt
= gimple_build_assign (loaded_val
, x
);
7636 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
7640 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
7641 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
7642 true, GSI_SAME_STMT
);
7645 gsi_remove (&si
, true);
7647 si
= gsi_last_bb (store_bb
);
7648 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
7651 storedi
= stored_val
;
7654 force_gimple_operand_gsi (&si
,
7655 build1 (VIEW_CONVERT_EXPR
, itype
,
7656 stored_val
), true, NULL_TREE
, true,
7659 /* Build the compare&swap statement. */
7660 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
7661 new_storedi
= force_gimple_operand_gsi (&si
,
7662 fold_convert (TREE_TYPE (loadedi
),
7665 true, GSI_SAME_STMT
);
7667 if (gimple_in_ssa_p (cfun
))
7671 old_vali
= create_tmp_var (TREE_TYPE (loadedi
), NULL
);
7672 stmt
= gimple_build_assign (old_vali
, loadedi
);
7673 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7675 stmt
= gimple_build_assign (loadedi
, new_storedi
);
7676 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7679 /* Note that we always perform the comparison as an integer, even for
7680 floating point. This allows the atomic operation to properly
7681 succeed even with NaNs and -0.0. */
7682 stmt
= gimple_build_cond_empty
7683 (build2 (NE_EXPR
, boolean_type_node
,
7684 new_storedi
, old_vali
));
7685 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7688 e
= single_succ_edge (store_bb
);
7689 e
->flags
&= ~EDGE_FALLTHRU
;
7690 e
->flags
|= EDGE_FALSE_VALUE
;
7692 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
7694 /* Copy the new value to loadedi (we already did that before the condition
7695 if we are not in SSA). */
7696 if (gimple_in_ssa_p (cfun
))
7698 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
7699 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
7702 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7703 gsi_remove (&si
, true);
7705 struct loop
*loop
= alloc_loop ();
7706 loop
->header
= loop_header
;
7707 loop
->latch
= store_bb
;
7708 add_loop (loop
, loop_header
->loop_father
);
7710 if (gimple_in_ssa_p (cfun
))
7711 update_ssa (TODO_update_ssa_no_phi
);
7716 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7718 GOMP_atomic_start ();
7722 The result is not globally atomic, but works so long as all parallel
7723 references are within #pragma omp atomic directives. According to
7724 responses received from omp@openmp.org, appears to be within spec.
7725 Which makes sense, since that's how several other compilers handle
7726 this situation as well.
7727 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7728 expanding. STORED_VAL is the operand of the matching
7729 GIMPLE_OMP_ATOMIC_STORE.
7732 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7736 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7741 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
7742 tree addr
, tree loaded_val
, tree stored_val
)
7744 gimple_stmt_iterator si
;
7748 si
= gsi_last_bb (load_bb
);
7749 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7751 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
7752 t
= build_call_expr (t
, 0);
7753 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7755 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
7756 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7757 gsi_remove (&si
, true);
7759 si
= gsi_last_bb (store_bb
);
7760 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
7762 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
7764 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7766 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
7767 t
= build_call_expr (t
, 0);
7768 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7769 gsi_remove (&si
, true);
7771 if (gimple_in_ssa_p (cfun
))
7772 update_ssa (TODO_update_ssa_no_phi
);
7776 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7777 using expand_omp_atomic_fetch_op. If it failed, we try to
7778 call expand_omp_atomic_pipeline, and if it fails too, the
7779 ultimate fallback is wrapping the operation in a mutex
7780 (expand_omp_atomic_mutex). REGION is the atomic region built
7781 by build_omp_regions_1(). */
7784 expand_omp_atomic (struct omp_region
*region
)
7786 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
7787 gimple load
= last_stmt (load_bb
), store
= last_stmt (store_bb
);
7788 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
7789 tree addr
= gimple_omp_atomic_load_rhs (load
);
7790 tree stored_val
= gimple_omp_atomic_store_val (store
);
7791 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
7792 HOST_WIDE_INT index
;
7794 /* Make sure the type is one of the supported sizes. */
7795 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
7796 index
= exact_log2 (index
);
7797 if (index
>= 0 && index
<= 4)
7799 unsigned int align
= TYPE_ALIGN_UNIT (type
);
7801 /* __sync builtins require strict data alignment. */
7802 if (exact_log2 (align
) >= index
)
7805 if (loaded_val
== stored_val
7806 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
7807 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
7808 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
7809 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
7813 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
7814 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
7815 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
7816 && store_bb
== single_succ (load_bb
)
7817 && first_stmt (store_bb
) == store
7818 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
7822 /* When possible, use specialized atomic update functions. */
7823 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
7824 && store_bb
== single_succ (load_bb
)
7825 && expand_omp_atomic_fetch_op (load_bb
, addr
,
7826 loaded_val
, stored_val
, index
))
7829 /* If we don't have specialized __sync builtins, try and implement
7830 as a compare and swap loop. */
7831 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
7832 loaded_val
, stored_val
, index
))
7837 /* The ultimate fallback is wrapping the operation in a mutex. */
7838 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
7842 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7845 expand_omp_target (struct omp_region
*region
)
7847 basic_block entry_bb
, exit_bb
, new_bb
;
7848 struct function
*child_cfun
= NULL
;
7849 tree child_fn
= NULL_TREE
, block
, t
;
7850 gimple_stmt_iterator gsi
;
7851 gimple entry_stmt
, stmt
;
7854 entry_stmt
= last_stmt (region
->entry
);
7855 new_bb
= region
->entry
;
7856 int kind
= gimple_omp_target_kind (entry_stmt
);
7857 if (kind
== GF_OMP_TARGET_KIND_REGION
)
7859 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
7860 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
7863 entry_bb
= region
->entry
;
7864 exit_bb
= region
->exit
;
7866 if (kind
== GF_OMP_TARGET_KIND_REGION
)
7868 unsigned srcidx
, dstidx
, num
;
7870 /* If the target region needs data sent from the parent
7871 function, then the very first statement (except possible
7872 tree profile counter updates) of the parallel body
7873 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7874 &.OMP_DATA_O is passed as an argument to the child function,
7875 we need to replace it with the argument as seen by the child
7878 In most cases, this will end up being the identity assignment
7879 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7880 a function call that has been inlined, the original PARM_DECL
7881 .OMP_DATA_I may have been converted into a different local
7882 variable. In which case, we need to keep the assignment. */
7883 if (gimple_omp_target_data_arg (entry_stmt
))
7885 basic_block entry_succ_bb
= single_succ (entry_bb
);
7886 gimple_stmt_iterator gsi
;
7888 gimple tgtcopy_stmt
= NULL
;
7890 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt
), 0);
7892 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
7894 gcc_assert (!gsi_end_p (gsi
));
7895 stmt
= gsi_stmt (gsi
);
7896 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
7899 if (gimple_num_ops (stmt
) == 2)
7901 tree arg
= gimple_assign_rhs1 (stmt
);
7903 /* We're ignoring the subcode because we're
7904 effectively doing a STRIP_NOPS. */
7906 if (TREE_CODE (arg
) == ADDR_EXPR
7907 && TREE_OPERAND (arg
, 0) == sender
)
7909 tgtcopy_stmt
= stmt
;
7915 gcc_assert (tgtcopy_stmt
!= NULL
);
7916 arg
= DECL_ARGUMENTS (child_fn
);
7918 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
7919 gsi_remove (&gsi
, true);
7922 /* Declare local variables needed in CHILD_CFUN. */
7923 block
= DECL_INITIAL (child_fn
);
7924 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
7925 /* The gimplifier could record temporaries in target block
7926 rather than in containing function's local_decls chain,
7927 which would mean cgraph missed finalizing them. Do it now. */
7928 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
7929 if (TREE_CODE (t
) == VAR_DECL
7931 && !DECL_EXTERNAL (t
))
7932 varpool_finalize_decl (t
);
7933 DECL_SAVED_TREE (child_fn
) = NULL
;
7934 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7935 gimple_set_body (child_fn
, NULL
);
7936 TREE_USED (block
) = 1;
7938 /* Reset DECL_CONTEXT on function arguments. */
7939 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
7940 DECL_CONTEXT (t
) = child_fn
;
7942 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7943 so that it can be moved to the child function. */
7944 gsi
= gsi_last_bb (entry_bb
);
7945 stmt
= gsi_stmt (gsi
);
7946 gcc_assert (stmt
&& gimple_code (stmt
) == GIMPLE_OMP_TARGET
7947 && gimple_omp_target_kind (stmt
)
7948 == GF_OMP_TARGET_KIND_REGION
);
7949 gsi_remove (&gsi
, true);
7950 e
= split_block (entry_bb
, stmt
);
7952 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7954 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7957 gsi
= gsi_last_bb (exit_bb
);
7958 gcc_assert (!gsi_end_p (gsi
)
7959 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
7960 stmt
= gimple_build_return (NULL
);
7961 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
7962 gsi_remove (&gsi
, true);
7965 /* Move the target region into CHILD_CFUN. */
7967 block
= gimple_block (entry_stmt
);
7969 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
7971 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
7972 /* When the OMP expansion process cannot guarantee an up-to-date
7973 loop tree arrange for the child function to fixup loops. */
7974 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
7975 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
7977 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7978 num
= vec_safe_length (child_cfun
->local_decls
);
7979 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
7981 t
= (*child_cfun
->local_decls
)[srcidx
];
7982 if (DECL_CONTEXT (t
) == cfun
->decl
)
7984 if (srcidx
!= dstidx
)
7985 (*child_cfun
->local_decls
)[dstidx
] = t
;
7989 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
7991 /* Inform the callgraph about the new function. */
7992 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
7993 cgraph_add_new_function (child_fn
, true);
7995 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7996 fixed in a following pass. */
7997 push_cfun (child_cfun
);
7998 rebuild_cgraph_edges ();
8000 /* Some EH regions might become dead, see PR34608. If
8001 pass_cleanup_cfg isn't the first pass to happen with the
8002 new child, these dead EH edges might cause problems.
8003 Clean them up now. */
8004 if (flag_exceptions
)
8007 bool changed
= false;
8009 FOR_EACH_BB_FN (bb
, cfun
)
8010 changed
|= gimple_purge_dead_eh_edges (bb
);
8012 cleanup_tree_cfg ();
8017 /* Emit a library call to launch the target region, or do data
8019 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
8020 enum built_in_function start_ix
;
8021 location_t clause_loc
;
8023 clauses
= gimple_omp_target_clauses (entry_stmt
);
8025 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8026 start_ix
= BUILT_IN_GOMP_TARGET
;
8027 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
8028 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
8030 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
8032 /* By default, the value of DEVICE is -1 (let runtime library choose)
8033 and there is no conditional. */
8035 device
= build_int_cst (integer_type_node
, -1);
8037 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
8039 cond
= OMP_CLAUSE_IF_EXPR (c
);
8041 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
8044 device
= OMP_CLAUSE_DEVICE_ID (c
);
8045 clause_loc
= OMP_CLAUSE_LOCATION (c
);
8048 clause_loc
= gimple_location (entry_stmt
);
8050 /* Ensure 'device' is of the correct type. */
8051 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
8053 /* If we found the clause 'if (cond)', build
8054 (cond ? device : -2). */
8057 cond
= gimple_boolify (cond
);
8059 basic_block cond_bb
, then_bb
, else_bb
;
8063 tmp_var
= create_tmp_var (TREE_TYPE (device
), NULL
);
8064 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8066 gsi
= gsi_last_bb (new_bb
);
8068 e
= split_block (new_bb
, gsi_stmt (gsi
));
8071 e
= split_block (new_bb
, NULL
);
8076 then_bb
= create_empty_bb (cond_bb
);
8077 else_bb
= create_empty_bb (then_bb
);
8078 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
8079 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
8081 stmt
= gimple_build_cond_empty (cond
);
8082 gsi
= gsi_last_bb (cond_bb
);
8083 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8085 gsi
= gsi_start_bb (then_bb
);
8086 stmt
= gimple_build_assign (tmp_var
, device
);
8087 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8089 gsi
= gsi_start_bb (else_bb
);
8090 stmt
= gimple_build_assign (tmp_var
,
8091 build_int_cst (integer_type_node
, -2));
8092 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8094 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
8095 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
8096 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
8097 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
8098 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
8099 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
8104 gsi
= gsi_last_bb (new_bb
);
8105 t
= gimple_omp_target_data_arg (entry_stmt
);
8108 t1
= size_zero_node
;
8109 t2
= build_zero_cst (ptr_type_node
);
8115 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
8116 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
8117 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
8118 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
8119 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
8123 /* FIXME: This will be address of
8124 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8125 symbol, as soon as the linker plugin is able to create it for us. */
8126 tree openmp_target
= build_zero_cst (ptr_type_node
);
8127 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8129 tree fnaddr
= build_fold_addr_expr (child_fn
);
8130 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 7,
8131 device
, fnaddr
, openmp_target
, t1
, t2
, t3
, t4
);
8134 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 6,
8135 device
, openmp_target
, t1
, t2
, t3
, t4
);
8136 gimple_set_location (g
, gimple_location (entry_stmt
));
8137 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
8138 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8141 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
8142 gsi_remove (&gsi
, true);
8144 if (kind
== GF_OMP_TARGET_KIND_DATA
&& region
->exit
)
8146 gsi
= gsi_last_bb (region
->exit
);
8148 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
8149 gsi_remove (&gsi
, true);
8154 /* Expand the parallel region tree rooted at REGION. Expansion
8155 proceeds in depth-first order. Innermost regions are expanded
8156 first. This way, parallel regions that require a new function to
8157 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8158 internal dependencies in their body. */
8161 expand_omp (struct omp_region
*region
)
8165 location_t saved_location
;
8166 gimple inner_stmt
= NULL
;
8168 /* First, determine whether this is a combined parallel+workshare
8170 if (region
->type
== GIMPLE_OMP_PARALLEL
)
8171 determine_parallel_type (region
);
8173 if (region
->type
== GIMPLE_OMP_FOR
8174 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
8175 inner_stmt
= last_stmt (region
->inner
->entry
);
8178 expand_omp (region
->inner
);
8180 saved_location
= input_location
;
8181 if (gimple_has_location (last_stmt (region
->entry
)))
8182 input_location
= gimple_location (last_stmt (region
->entry
));
8184 switch (region
->type
)
8186 case GIMPLE_OMP_PARALLEL
:
8187 case GIMPLE_OMP_TASK
:
8188 expand_omp_taskreg (region
);
8191 case GIMPLE_OMP_FOR
:
8192 expand_omp_for (region
, inner_stmt
);
8195 case GIMPLE_OMP_SECTIONS
:
8196 expand_omp_sections (region
);
8199 case GIMPLE_OMP_SECTION
:
8200 /* Individual omp sections are handled together with their
8201 parent GIMPLE_OMP_SECTIONS region. */
8204 case GIMPLE_OMP_SINGLE
:
8205 expand_omp_single (region
);
8208 case GIMPLE_OMP_MASTER
:
8209 case GIMPLE_OMP_TASKGROUP
:
8210 case GIMPLE_OMP_ORDERED
:
8211 case GIMPLE_OMP_CRITICAL
:
8212 case GIMPLE_OMP_TEAMS
:
8213 expand_omp_synch (region
);
8216 case GIMPLE_OMP_ATOMIC_LOAD
:
8217 expand_omp_atomic (region
);
8220 case GIMPLE_OMP_TARGET
:
8221 expand_omp_target (region
);
8228 input_location
= saved_location
;
8229 region
= region
->next
;
8234 /* Helper for build_omp_regions. Scan the dominator tree starting at
8235 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8236 true, the function ends once a single tree is built (otherwise, whole
8237 forest of OMP constructs may be built). */
8240 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
8243 gimple_stmt_iterator gsi
;
8247 gsi
= gsi_last_bb (bb
);
8248 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
8250 struct omp_region
*region
;
8251 enum gimple_code code
;
8253 stmt
= gsi_stmt (gsi
);
8254 code
= gimple_code (stmt
);
8255 if (code
== GIMPLE_OMP_RETURN
)
8257 /* STMT is the return point out of region PARENT. Mark it
8258 as the exit point and make PARENT the immediately
8259 enclosing region. */
8260 gcc_assert (parent
);
8263 parent
= parent
->outer
;
8265 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
8267 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8268 GIMPLE_OMP_RETURN, but matches with
8269 GIMPLE_OMP_ATOMIC_LOAD. */
8270 gcc_assert (parent
);
8271 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
8274 parent
= parent
->outer
;
8277 else if (code
== GIMPLE_OMP_CONTINUE
)
8279 gcc_assert (parent
);
8282 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
8284 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8285 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8288 else if (code
== GIMPLE_OMP_TARGET
8289 && gimple_omp_target_kind (stmt
) == GF_OMP_TARGET_KIND_UPDATE
)
8290 new_omp_region (bb
, code
, parent
);
8293 /* Otherwise, this directive becomes the parent for a new
8295 region
= new_omp_region (bb
, code
, parent
);
8300 if (single_tree
&& !parent
)
8303 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
8305 son
= next_dom_son (CDI_DOMINATORS
, son
))
8306 build_omp_regions_1 (son
, parent
, single_tree
);
8309 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8313 build_omp_regions_root (basic_block root
)
8315 gcc_assert (root_omp_region
== NULL
);
8316 build_omp_regions_1 (root
, NULL
, true);
8317 gcc_assert (root_omp_region
!= NULL
);
8320 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8323 omp_expand_local (basic_block head
)
8325 build_omp_regions_root (head
);
8326 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
8328 fprintf (dump_file
, "\nOMP region tree\n\n");
8329 dump_omp_region (dump_file
, root_omp_region
, 0);
8330 fprintf (dump_file
, "\n");
8333 remove_exit_barriers (root_omp_region
);
8334 expand_omp (root_omp_region
);
8336 free_omp_regions ();
8339 /* Scan the CFG and build a tree of OMP regions. Return the root of
8340 the OMP region tree. */
8343 build_omp_regions (void)
8345 gcc_assert (root_omp_region
== NULL
);
8346 calculate_dominance_info (CDI_DOMINATORS
);
8347 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
8350 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8353 execute_expand_omp (void)
8355 build_omp_regions ();
8357 if (!root_omp_region
)
8362 fprintf (dump_file
, "\nOMP region tree\n\n");
8363 dump_omp_region (dump_file
, root_omp_region
, 0);
8364 fprintf (dump_file
, "\n");
8367 remove_exit_barriers (root_omp_region
);
8369 expand_omp (root_omp_region
);
8371 cleanup_tree_cfg ();
8373 free_omp_regions ();
8378 /* OMP expansion -- the default pass, run before creation of SSA form. */
8382 const pass_data pass_data_expand_omp
=
8384 GIMPLE_PASS
, /* type */
8385 "ompexp", /* name */
8386 OPTGROUP_NONE
, /* optinfo_flags */
8387 true, /* has_execute */
8388 TV_NONE
, /* tv_id */
8389 PROP_gimple_any
, /* properties_required */
8390 0, /* properties_provided */
8391 0, /* properties_destroyed */
8392 0, /* todo_flags_start */
8393 0, /* todo_flags_finish */
8396 class pass_expand_omp
: public gimple_opt_pass
8399 pass_expand_omp (gcc::context
*ctxt
)
8400 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
8403 /* opt_pass methods: */
8404 virtual bool gate (function
*)
8406 return ((flag_openmp
!= 0 || flag_openmp_simd
!= 0
8407 || flag_cilkplus
!= 0) && !seen_error ());
8410 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
8412 }; // class pass_expand_omp
8417 make_pass_expand_omp (gcc::context
*ctxt
)
8419 return new pass_expand_omp (ctxt
);
8422 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8424 /* If ctx is a worksharing context inside of a cancellable parallel
8425 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8426 and conditional branch to parallel's cancel_label to handle
8427 cancellation in the implicit barrier. */
8430 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
8432 gimple omp_return
= gimple_seq_last_stmt (*body
);
8433 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
8434 if (gimple_omp_return_nowait_p (omp_return
))
8437 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
8438 && ctx
->outer
->cancellable
)
8440 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
8441 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
8442 tree lhs
= create_tmp_var (c_bool_type
, NULL
);
8443 gimple_omp_return_set_lhs (omp_return
, lhs
);
8444 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
8445 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
8446 fold_convert (c_bool_type
,
8447 boolean_false_node
),
8448 ctx
->outer
->cancel_label
, fallthru_label
);
8449 gimple_seq_add_stmt (body
, g
);
8450 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
8454 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8455 CTX is the enclosing OMP context for the current statement. */
8458 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8460 tree block
, control
;
8461 gimple_stmt_iterator tgsi
;
8462 gimple stmt
, new_stmt
, bind
, t
;
8463 gimple_seq ilist
, dlist
, olist
, new_body
;
8465 stmt
= gsi_stmt (*gsi_p
);
8467 push_gimplify_context ();
8471 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
8472 &ilist
, &dlist
, ctx
, NULL
);
8474 new_body
= gimple_omp_body (stmt
);
8475 gimple_omp_set_body (stmt
, NULL
);
8476 tgsi
= gsi_start (new_body
);
8477 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
8482 sec_start
= gsi_stmt (tgsi
);
8483 sctx
= maybe_lookup_ctx (sec_start
);
8486 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
8487 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
8488 GSI_CONTINUE_LINKING
);
8489 gimple_omp_set_body (sec_start
, NULL
);
8491 if (gsi_one_before_end_p (tgsi
))
8493 gimple_seq l
= NULL
;
8494 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
8496 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
8497 gimple_omp_section_set_last (sec_start
);
8500 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
8501 GSI_CONTINUE_LINKING
);
8504 block
= make_node (BLOCK
);
8505 bind
= gimple_build_bind (NULL
, new_body
, block
);
8508 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
8510 block
= make_node (BLOCK
);
8511 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
8512 gsi_replace (gsi_p
, new_stmt
, true);
8514 pop_gimplify_context (new_stmt
);
8515 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
8516 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8517 if (BLOCK_VARS (block
))
8518 TREE_USED (block
) = 1;
8521 gimple_seq_add_seq (&new_body
, ilist
);
8522 gimple_seq_add_stmt (&new_body
, stmt
);
8523 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
8524 gimple_seq_add_stmt (&new_body
, bind
);
8526 control
= create_tmp_var (unsigned_type_node
, ".section");
8527 t
= gimple_build_omp_continue (control
, control
);
8528 gimple_omp_sections_set_control (stmt
, control
);
8529 gimple_seq_add_stmt (&new_body
, t
);
8531 gimple_seq_add_seq (&new_body
, olist
);
8532 if (ctx
->cancellable
)
8533 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
8534 gimple_seq_add_seq (&new_body
, dlist
);
8536 new_body
= maybe_catch_exception (new_body
);
8538 t
= gimple_build_omp_return
8539 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
8540 OMP_CLAUSE_NOWAIT
));
8541 gimple_seq_add_stmt (&new_body
, t
);
8542 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
8544 gimple_bind_set_body (new_stmt
, new_body
);
8548 /* A subroutine of lower_omp_single. Expand the simple form of
8549 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8551 if (GOMP_single_start ())
8553 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8555 FIXME. It may be better to delay expanding the logic of this until
8556 pass_expand_omp. The expanded logic may make the job more difficult
8557 to a synchronization analysis pass. */
8560 lower_omp_single_simple (gimple single_stmt
, gimple_seq
*pre_p
)
8562 location_t loc
= gimple_location (single_stmt
);
8563 tree tlabel
= create_artificial_label (loc
);
8564 tree flabel
= create_artificial_label (loc
);
8568 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
8569 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)), NULL
);
8570 call
= gimple_build_call (decl
, 0);
8571 gimple_call_set_lhs (call
, lhs
);
8572 gimple_seq_add_stmt (pre_p
, call
);
8574 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
8575 fold_convert_loc (loc
, TREE_TYPE (lhs
),
8578 gimple_seq_add_stmt (pre_p
, cond
);
8579 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
8580 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
8581 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
8585 /* A subroutine of lower_omp_single. Expand the simple form of
8586 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8588 #pragma omp single copyprivate (a, b, c)
8590 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8593 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8599 GOMP_single_copy_end (©out);
8610 FIXME. It may be better to delay expanding the logic of this until
8611 pass_expand_omp. The expanded logic may make the job more difficult
8612 to a synchronization analysis pass. */
8615 lower_omp_single_copy (gimple single_stmt
, gimple_seq
*pre_p
, omp_context
*ctx
)
8617 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
8618 gimple_seq copyin_seq
;
8619 location_t loc
= gimple_location (single_stmt
);
8621 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
8623 ptr_type
= build_pointer_type (ctx
->record_type
);
8624 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
8626 l0
= create_artificial_label (loc
);
8627 l1
= create_artificial_label (loc
);
8628 l2
= create_artificial_label (loc
);
8630 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
8631 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
8632 t
= fold_convert_loc (loc
, ptr_type
, t
);
8633 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
8635 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
8636 build_int_cst (ptr_type
, 0));
8637 t
= build3 (COND_EXPR
, void_type_node
, t
,
8638 build_and_jump (&l0
), build_and_jump (&l1
));
8639 gimplify_and_add (t
, pre_p
);
8641 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
8643 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
8646 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
8649 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
8650 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
8651 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
8652 gimplify_and_add (t
, pre_p
);
8654 t
= build_and_jump (&l2
);
8655 gimplify_and_add (t
, pre_p
);
8657 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
8659 gimple_seq_add_seq (pre_p
, copyin_seq
);
8661 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
8665 /* Expand code for an OpenMP single directive. */
8668 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8671 gimple t
, bind
, single_stmt
= gsi_stmt (*gsi_p
);
8672 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
8674 push_gimplify_context ();
8676 block
= make_node (BLOCK
);
8677 bind
= gimple_build_bind (NULL
, NULL
, block
);
8678 gsi_replace (gsi_p
, bind
, true);
8681 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
8682 &bind_body
, &dlist
, ctx
, NULL
);
8683 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
8685 gimple_seq_add_stmt (&bind_body
, single_stmt
);
8687 if (ctx
->record_type
)
8688 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
8690 lower_omp_single_simple (single_stmt
, &bind_body
);
8692 gimple_omp_set_body (single_stmt
, NULL
);
8694 gimple_seq_add_seq (&bind_body
, dlist
);
8696 bind_body
= maybe_catch_exception (bind_body
);
8698 t
= gimple_build_omp_return
8699 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
8700 OMP_CLAUSE_NOWAIT
));
8701 gimple_seq_add_stmt (&bind_body_tail
, t
);
8702 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
8703 if (ctx
->record_type
)
8705 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
8706 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
8707 TREE_THIS_VOLATILE (clobber
) = 1;
8708 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
8709 clobber
), GSI_SAME_STMT
);
8711 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
8712 gimple_bind_set_body (bind
, bind_body
);
8714 pop_gimplify_context (bind
);
8716 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8717 BLOCK_VARS (block
) = ctx
->block_vars
;
8718 if (BLOCK_VARS (block
))
8719 TREE_USED (block
) = 1;
8723 /* Expand code for an OpenMP master directive. */
8726 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8728 tree block
, lab
= NULL
, x
, bfn_decl
;
8729 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
8730 location_t loc
= gimple_location (stmt
);
8733 push_gimplify_context ();
8735 block
= make_node (BLOCK
);
8736 bind
= gimple_build_bind (NULL
, NULL
, block
);
8737 gsi_replace (gsi_p
, bind
, true);
8738 gimple_bind_add_stmt (bind
, stmt
);
8740 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
8741 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
8742 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
8743 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
8745 gimplify_and_add (x
, &tseq
);
8746 gimple_bind_add_seq (bind
, tseq
);
8748 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8749 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
8750 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8751 gimple_omp_set_body (stmt
, NULL
);
8753 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
8755 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8757 pop_gimplify_context (bind
);
8759 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8760 BLOCK_VARS (block
) = ctx
->block_vars
;
8764 /* Expand code for an OpenMP taskgroup directive. */
8767 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8769 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
8770 tree block
= make_node (BLOCK
);
8772 bind
= gimple_build_bind (NULL
, NULL
, block
);
8773 gsi_replace (gsi_p
, bind
, true);
8774 gimple_bind_add_stmt (bind
, stmt
);
8776 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
8778 gimple_bind_add_stmt (bind
, x
);
8780 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8781 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8782 gimple_omp_set_body (stmt
, NULL
);
8784 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8786 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8787 BLOCK_VARS (block
) = ctx
->block_vars
;
8791 /* Expand code for an OpenMP ordered directive. */
8794 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8797 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
8799 push_gimplify_context ();
8801 block
= make_node (BLOCK
);
8802 bind
= gimple_build_bind (NULL
, NULL
, block
);
8803 gsi_replace (gsi_p
, bind
, true);
8804 gimple_bind_add_stmt (bind
, stmt
);
8806 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
8808 gimple_bind_add_stmt (bind
, x
);
8810 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8811 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
8812 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8813 gimple_omp_set_body (stmt
, NULL
);
8815 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
8816 gimple_bind_add_stmt (bind
, x
);
8818 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8820 pop_gimplify_context (bind
);
8822 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8823 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8827 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8828 substitution of a couple of function calls. But in the NAMED case,
8829 requires that languages coordinate a symbol name. It is therefore
8830 best put here in common code. */
8832 static GTY((param1_is (tree
), param2_is (tree
)))
8833 splay_tree critical_name_mutexes
;
8836 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8839 tree name
, lock
, unlock
;
8840 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
8841 location_t loc
= gimple_location (stmt
);
8844 name
= gimple_omp_critical_name (stmt
);
8850 if (!critical_name_mutexes
)
8851 critical_name_mutexes
8852 = splay_tree_new_ggc (splay_tree_compare_pointers
,
8853 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s
,
8854 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s
);
8856 n
= splay_tree_lookup (critical_name_mutexes
, (splay_tree_key
) name
);
8861 decl
= create_tmp_var_raw (ptr_type_node
, NULL
);
8863 new_str
= ACONCAT ((".gomp_critical_user_",
8864 IDENTIFIER_POINTER (name
), NULL
));
8865 DECL_NAME (decl
) = get_identifier (new_str
);
8866 TREE_PUBLIC (decl
) = 1;
8867 TREE_STATIC (decl
) = 1;
8868 DECL_COMMON (decl
) = 1;
8869 DECL_ARTIFICIAL (decl
) = 1;
8870 DECL_IGNORED_P (decl
) = 1;
8871 varpool_finalize_decl (decl
);
8873 splay_tree_insert (critical_name_mutexes
, (splay_tree_key
) name
,
8874 (splay_tree_value
) decl
);
8877 decl
= (tree
) n
->value
;
8879 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
8880 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
8882 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
8883 unlock
= build_call_expr_loc (loc
, unlock
, 1,
8884 build_fold_addr_expr_loc (loc
, decl
));
8888 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
8889 lock
= build_call_expr_loc (loc
, lock
, 0);
8891 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
8892 unlock
= build_call_expr_loc (loc
, unlock
, 0);
8895 push_gimplify_context ();
8897 block
= make_node (BLOCK
);
8898 bind
= gimple_build_bind (NULL
, NULL
, block
);
8899 gsi_replace (gsi_p
, bind
, true);
8900 gimple_bind_add_stmt (bind
, stmt
);
8902 tbody
= gimple_bind_body (bind
);
8903 gimplify_and_add (lock
, &tbody
);
8904 gimple_bind_set_body (bind
, tbody
);
8906 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8907 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
8908 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8909 gimple_omp_set_body (stmt
, NULL
);
8911 tbody
= gimple_bind_body (bind
);
8912 gimplify_and_add (unlock
, &tbody
);
8913 gimple_bind_set_body (bind
, tbody
);
8915 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8917 pop_gimplify_context (bind
);
8918 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8919 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8923 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8924 for a lastprivate clause. Given a loop control predicate of (V
8925 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8926 is appended to *DLIST, iterator initialization is appended to
8930 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
8931 gimple_seq
*dlist
, struct omp_context
*ctx
)
8933 tree clauses
, cond
, vinit
;
8934 enum tree_code cond_code
;
8937 cond_code
= fd
->loop
.cond_code
;
8938 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
8940 /* When possible, use a strict equality expression. This can let VRP
8941 type optimizations deduce the value and remove a copy. */
8942 if (tree_fits_shwi_p (fd
->loop
.step
))
8944 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
8945 if (step
== 1 || step
== -1)
8946 cond_code
= EQ_EXPR
;
8949 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, fd
->loop
.n2
);
8951 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
8953 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
8954 if (!gimple_seq_empty_p (stmts
))
8956 gimple_seq_add_seq (&stmts
, *dlist
);
8959 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8960 vinit
= fd
->loop
.n1
;
8961 if (cond_code
== EQ_EXPR
8962 && tree_fits_shwi_p (fd
->loop
.n2
)
8963 && ! integer_zerop (fd
->loop
.n2
))
8964 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
8966 vinit
= unshare_expr (vinit
);
8968 /* Initialize the iterator variable, so that threads that don't execute
8969 any iterations don't execute the lastprivate clauses by accident. */
8970 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
8975 /* Lower code for an OpenMP loop directive. */
8978 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8981 struct omp_for_data fd
, *fdp
= NULL
;
8982 gimple stmt
= gsi_stmt (*gsi_p
), new_stmt
;
8983 gimple_seq omp_for_body
, body
, dlist
;
8986 push_gimplify_context ();
8988 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
8990 block
= make_node (BLOCK
);
8991 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
8992 /* Replace at gsi right away, so that 'stmt' is no member
8993 of a sequence anymore as we're going to add to to a different
8995 gsi_replace (gsi_p
, new_stmt
, true);
8997 /* Move declaration of temporaries in the loop body before we make
8999 omp_for_body
= gimple_omp_body (stmt
);
9000 if (!gimple_seq_empty_p (omp_for_body
)
9001 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
9003 gimple inner_bind
= gimple_seq_first_stmt (omp_for_body
);
9004 tree vars
= gimple_bind_vars (inner_bind
);
9005 gimple_bind_append_vars (new_stmt
, vars
);
9006 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9007 keep them on the inner_bind and it's block. */
9008 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
9009 if (gimple_bind_block (inner_bind
))
9010 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
9013 if (gimple_omp_for_combined_into_p (stmt
))
9015 extract_omp_for_data (stmt
, &fd
, NULL
);
9018 /* We need two temporaries with fd.loop.v type (istart/iend)
9019 and then (fd.collapse - 1) temporaries with the same
9020 type for count2 ... countN-1 vars if not constant. */
9022 tree type
= fd
.iter_type
;
9024 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
9025 count
+= fd
.collapse
- 1;
9026 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
9027 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
9031 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
9032 OMP_CLAUSE__LOOPTEMP_
);
9033 for (i
= 0; i
< count
; i
++)
9038 gcc_assert (outerc
);
9039 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
9040 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
9041 OMP_CLAUSE__LOOPTEMP_
);
9044 temp
= create_tmp_var (type
, NULL
);
9045 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
9046 OMP_CLAUSE_DECL (*pc
) = temp
;
9047 pc
= &OMP_CLAUSE_CHAIN (*pc
);
9052 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9055 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
9057 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
9059 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9061 /* Lower the header expressions. At this point, we can assume that
9062 the header is of the form:
9064 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9066 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9067 using the .omp_data_s mapping, if needed. */
9068 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
9070 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
9071 if (!is_gimple_min_invariant (*rhs_p
))
9072 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9074 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
9075 if (!is_gimple_min_invariant (*rhs_p
))
9076 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9078 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
9079 if (!is_gimple_min_invariant (*rhs_p
))
9080 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9083 /* Once lowered, extract the bounds and clauses. */
9084 extract_omp_for_data (stmt
, &fd
, NULL
);
9086 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
9088 gimple_seq_add_stmt (&body
, stmt
);
9089 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
9091 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
9094 /* After the loop, add exit clauses. */
9095 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
9097 if (ctx
->cancellable
)
9098 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
9100 gimple_seq_add_seq (&body
, dlist
);
9102 body
= maybe_catch_exception (body
);
9104 /* Region exit marker goes at the end of the loop body. */
9105 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
9106 maybe_add_implicit_barrier_cancel (ctx
, &body
);
9107 pop_gimplify_context (new_stmt
);
9109 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
9110 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
9111 if (BLOCK_VARS (block
))
9112 TREE_USED (block
) = 1;
9114 gimple_bind_set_body (new_stmt
, body
);
9115 gimple_omp_set_body (stmt
, NULL
);
9116 gimple_omp_for_set_pre_body (stmt
, NULL
);
9119 /* Callback for walk_stmts. Check if the current statement only contains
9120 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9123 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
9124 bool *handled_ops_p
,
9125 struct walk_stmt_info
*wi
)
9127 int *info
= (int *) wi
->info
;
9128 gimple stmt
= gsi_stmt (*gsi_p
);
9130 *handled_ops_p
= true;
9131 switch (gimple_code (stmt
))
9135 case GIMPLE_OMP_FOR
:
9136 case GIMPLE_OMP_SECTIONS
:
9137 *info
= *info
== 0 ? 1 : -1;
9146 struct omp_taskcopy_context
9148 /* This field must be at the beginning, as we do "inheritance": Some
9149 callback functions for tree-inline.c (e.g., omp_copy_decl)
9150 receive a copy_body_data pointer that is up-casted to an
9151 omp_context pointer. */
9157 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
9159 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
9161 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
9162 return create_tmp_var (TREE_TYPE (var
), NULL
);
9168 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
9170 tree name
, new_fields
= NULL
, type
, f
;
9172 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
9173 name
= DECL_NAME (TYPE_NAME (orig_type
));
9174 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
9175 TYPE_DECL
, name
, type
);
9176 TYPE_NAME (type
) = name
;
9178 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
9180 tree new_f
= copy_node (f
);
9181 DECL_CONTEXT (new_f
) = type
;
9182 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
9183 TREE_CHAIN (new_f
) = new_fields
;
9184 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9185 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9186 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
9189 *pointer_map_insert (tcctx
->cb
.decl_map
, f
) = new_f
;
9191 TYPE_FIELDS (type
) = nreverse (new_fields
);
9196 /* Create task copyfn. */
9199 create_task_copyfn (gimple task_stmt
, omp_context
*ctx
)
9201 struct function
*child_cfun
;
9202 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
9203 tree record_type
, srecord_type
, bind
, list
;
9204 bool record_needs_remap
= false, srecord_needs_remap
= false;
9206 struct omp_taskcopy_context tcctx
;
9207 location_t loc
= gimple_location (task_stmt
);
9209 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
9210 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
9211 gcc_assert (child_cfun
->cfg
== NULL
);
9212 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
9214 /* Reset DECL_CONTEXT on function arguments. */
9215 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
9216 DECL_CONTEXT (t
) = child_fn
;
9218 /* Populate the function. */
9219 push_gimplify_context ();
9220 push_cfun (child_cfun
);
9222 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
9223 TREE_SIDE_EFFECTS (bind
) = 1;
9225 DECL_SAVED_TREE (child_fn
) = bind
;
9226 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
9228 /* Remap src and dst argument types if needed. */
9229 record_type
= ctx
->record_type
;
9230 srecord_type
= ctx
->srecord_type
;
9231 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
9232 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9234 record_needs_remap
= true;
9237 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
9238 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9240 srecord_needs_remap
= true;
9244 if (record_needs_remap
|| srecord_needs_remap
)
9246 memset (&tcctx
, '\0', sizeof (tcctx
));
9247 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
9248 tcctx
.cb
.dst_fn
= child_fn
;
9249 tcctx
.cb
.src_node
= cgraph_get_node (tcctx
.cb
.src_fn
);
9250 gcc_checking_assert (tcctx
.cb
.src_node
);
9251 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
9252 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
9253 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
9254 tcctx
.cb
.eh_lp_nr
= 0;
9255 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
9256 tcctx
.cb
.decl_map
= pointer_map_create ();
9259 if (record_needs_remap
)
9260 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
9261 if (srecord_needs_remap
)
9262 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
9265 tcctx
.cb
.decl_map
= NULL
;
9267 arg
= DECL_ARGUMENTS (child_fn
);
9268 TREE_TYPE (arg
) = build_pointer_type (record_type
);
9269 sarg
= DECL_CHAIN (arg
);
9270 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
9272 /* First pass: initialize temporaries used in record_type and srecord_type
9273 sizes and field offsets. */
9274 if (tcctx
.cb
.decl_map
)
9275 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9276 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9280 decl
= OMP_CLAUSE_DECL (c
);
9281 p
= (tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, decl
);
9284 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9285 sf
= (tree
) n
->value
;
9286 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9287 src
= build_simple_mem_ref_loc (loc
, sarg
);
9288 src
= omp_build_component_ref (src
, sf
);
9289 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
9290 append_to_statement_list (t
, &list
);
9293 /* Second pass: copy shared var pointers and copy construct non-VLA
9294 firstprivate vars. */
9295 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9296 switch (OMP_CLAUSE_CODE (c
))
9298 case OMP_CLAUSE_SHARED
:
9299 decl
= OMP_CLAUSE_DECL (c
);
9300 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9303 f
= (tree
) n
->value
;
9304 if (tcctx
.cb
.decl_map
)
9305 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9306 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9307 sf
= (tree
) n
->value
;
9308 if (tcctx
.cb
.decl_map
)
9309 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9310 src
= build_simple_mem_ref_loc (loc
, sarg
);
9311 src
= omp_build_component_ref (src
, sf
);
9312 dst
= build_simple_mem_ref_loc (loc
, arg
);
9313 dst
= omp_build_component_ref (dst
, f
);
9314 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9315 append_to_statement_list (t
, &list
);
9317 case OMP_CLAUSE_FIRSTPRIVATE
:
9318 decl
= OMP_CLAUSE_DECL (c
);
9319 if (is_variable_sized (decl
))
9321 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9324 f
= (tree
) n
->value
;
9325 if (tcctx
.cb
.decl_map
)
9326 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9327 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9330 sf
= (tree
) n
->value
;
9331 if (tcctx
.cb
.decl_map
)
9332 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9333 src
= build_simple_mem_ref_loc (loc
, sarg
);
9334 src
= omp_build_component_ref (src
, sf
);
9335 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
9336 src
= build_simple_mem_ref_loc (loc
, src
);
9340 dst
= build_simple_mem_ref_loc (loc
, arg
);
9341 dst
= omp_build_component_ref (dst
, f
);
9342 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9343 append_to_statement_list (t
, &list
);
9345 case OMP_CLAUSE_PRIVATE
:
9346 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
9348 decl
= OMP_CLAUSE_DECL (c
);
9349 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9350 f
= (tree
) n
->value
;
9351 if (tcctx
.cb
.decl_map
)
9352 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9353 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9356 sf
= (tree
) n
->value
;
9357 if (tcctx
.cb
.decl_map
)
9358 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9359 src
= build_simple_mem_ref_loc (loc
, sarg
);
9360 src
= omp_build_component_ref (src
, sf
);
9361 if (use_pointer_for_field (decl
, NULL
))
9362 src
= build_simple_mem_ref_loc (loc
, src
);
9366 dst
= build_simple_mem_ref_loc (loc
, arg
);
9367 dst
= omp_build_component_ref (dst
, f
);
9368 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9369 append_to_statement_list (t
, &list
);
9375 /* Last pass: handle VLA firstprivates. */
9376 if (tcctx
.cb
.decl_map
)
9377 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9378 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9382 decl
= OMP_CLAUSE_DECL (c
);
9383 if (!is_variable_sized (decl
))
9385 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9388 f
= (tree
) n
->value
;
9389 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9390 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
9391 ind
= DECL_VALUE_EXPR (decl
);
9392 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
9393 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
9394 n
= splay_tree_lookup (ctx
->sfield_map
,
9395 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9396 sf
= (tree
) n
->value
;
9397 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9398 src
= build_simple_mem_ref_loc (loc
, sarg
);
9399 src
= omp_build_component_ref (src
, sf
);
9400 src
= build_simple_mem_ref_loc (loc
, src
);
9401 dst
= build_simple_mem_ref_loc (loc
, arg
);
9402 dst
= omp_build_component_ref (dst
, f
);
9403 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9404 append_to_statement_list (t
, &list
);
9405 n
= splay_tree_lookup (ctx
->field_map
,
9406 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9407 df
= (tree
) n
->value
;
9408 df
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, df
);
9409 ptr
= build_simple_mem_ref_loc (loc
, arg
);
9410 ptr
= omp_build_component_ref (ptr
, df
);
9411 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
9412 build_fold_addr_expr_loc (loc
, dst
));
9413 append_to_statement_list (t
, &list
);
9416 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
9417 append_to_statement_list (t
, &list
);
9419 if (tcctx
.cb
.decl_map
)
9420 pointer_map_destroy (tcctx
.cb
.decl_map
);
9421 pop_gimplify_context (NULL
);
9422 BIND_EXPR_BODY (bind
) = list
;
9427 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
9431 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
9433 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
9435 gcc_assert (clauses
);
9436 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9437 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
9438 switch (OMP_CLAUSE_DEPEND_KIND (c
))
9440 case OMP_CLAUSE_DEPEND_IN
:
9443 case OMP_CLAUSE_DEPEND_OUT
:
9444 case OMP_CLAUSE_DEPEND_INOUT
:
9450 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
9451 tree array
= create_tmp_var (type
, NULL
);
9452 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
9454 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
9455 gimple_seq_add_stmt (iseq
, g
);
9456 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
9458 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
9459 gimple_seq_add_stmt (iseq
, g
);
9460 for (i
= 0; i
< 2; i
++)
9462 if ((i
? n_in
: n_out
) == 0)
9464 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9465 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
9466 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
9468 tree t
= OMP_CLAUSE_DECL (c
);
9469 t
= fold_convert (ptr_type_node
, t
);
9470 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
9471 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
9472 NULL_TREE
, NULL_TREE
);
9473 g
= gimple_build_assign (r
, t
);
9474 gimple_seq_add_stmt (iseq
, g
);
9477 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
9478 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
9479 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
9480 OMP_CLAUSE_CHAIN (c
) = *p
;
9482 tree clobber
= build_constructor (type
, NULL
);
9483 TREE_THIS_VOLATILE (clobber
) = 1;
9484 g
= gimple_build_assign (array
, clobber
);
9485 gimple_seq_add_stmt (oseq
, g
);
9488 /* Lower the OpenMP parallel or task directive in the current statement
9489 in GSI_P. CTX holds context information for the directive. */
9492 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9496 gimple stmt
= gsi_stmt (*gsi_p
);
9497 gimple par_bind
, bind
, dep_bind
= NULL
;
9498 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
9499 location_t loc
= gimple_location (stmt
);
9501 clauses
= gimple_omp_taskreg_clauses (stmt
);
9502 par_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
9503 par_body
= gimple_bind_body (par_bind
);
9504 child_fn
= ctx
->cb
.dst_fn
;
9505 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
9506 && !gimple_omp_parallel_combined_p (stmt
))
9508 struct walk_stmt_info wi
;
9511 memset (&wi
, 0, sizeof (wi
));
9514 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
9516 gimple_omp_parallel_set_combined_p (stmt
, true);
9518 gimple_seq dep_ilist
= NULL
;
9519 gimple_seq dep_olist
= NULL
;
9520 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
9521 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
9523 push_gimplify_context ();
9524 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
9525 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
9528 if (ctx
->srecord_type
)
9529 create_task_copyfn (stmt
, ctx
);
9531 push_gimplify_context ();
9536 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
9537 lower_omp (&par_body
, ctx
);
9538 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
9539 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
9541 /* Declare all the variables created by mapping and the variables
9542 declared in the scope of the parallel body. */
9543 record_vars_into (ctx
->block_vars
, child_fn
);
9544 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
9546 if (ctx
->record_type
)
9549 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
9550 : ctx
->record_type
, ".omp_data_o");
9551 DECL_NAMELESS (ctx
->sender_decl
) = 1;
9552 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
9553 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
9558 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
9559 lower_send_shared_vars (&ilist
, &olist
, ctx
);
9561 if (ctx
->record_type
)
9563 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
9564 TREE_THIS_VOLATILE (clobber
) = 1;
9565 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
9569 /* Once all the expansions are done, sequence all the different
9570 fragments inside gimple_omp_body. */
9574 if (ctx
->record_type
)
9576 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9577 /* fixup_child_record_type might have changed receiver_decl's type. */
9578 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
9579 gimple_seq_add_stmt (&new_body
,
9580 gimple_build_assign (ctx
->receiver_decl
, t
));
9583 gimple_seq_add_seq (&new_body
, par_ilist
);
9584 gimple_seq_add_seq (&new_body
, par_body
);
9585 gimple_seq_add_seq (&new_body
, par_rlist
);
9586 if (ctx
->cancellable
)
9587 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
9588 gimple_seq_add_seq (&new_body
, par_olist
);
9589 new_body
= maybe_catch_exception (new_body
);
9590 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
9591 gimple_omp_set_body (stmt
, new_body
);
9593 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
9594 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
9595 gimple_bind_add_seq (bind
, ilist
);
9596 gimple_bind_add_stmt (bind
, stmt
);
9597 gimple_bind_add_seq (bind
, olist
);
9599 pop_gimplify_context (NULL
);
9603 gimple_bind_add_seq (dep_bind
, dep_ilist
);
9604 gimple_bind_add_stmt (dep_bind
, bind
);
9605 gimple_bind_add_seq (dep_bind
, dep_olist
);
9606 pop_gimplify_context (dep_bind
);
9610 /* Lower the OpenMP target directive in the current statement
9611 in GSI_P. CTX holds context information for the directive. */
9614 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9617 tree child_fn
, t
, c
;
9618 gimple stmt
= gsi_stmt (*gsi_p
);
9619 gimple tgt_bind
= NULL
, bind
;
9620 gimple_seq tgt_body
= NULL
, olist
, ilist
, new_body
;
9621 location_t loc
= gimple_location (stmt
);
9622 int kind
= gimple_omp_target_kind (stmt
);
9623 unsigned int map_cnt
= 0;
9625 clauses
= gimple_omp_target_clauses (stmt
);
9626 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9628 tgt_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
9629 tgt_body
= gimple_bind_body (tgt_bind
);
9631 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
9632 tgt_body
= gimple_omp_body (stmt
);
9633 child_fn
= ctx
->cb
.dst_fn
;
9635 push_gimplify_context ();
9637 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9638 switch (OMP_CLAUSE_CODE (c
))
9644 case OMP_CLAUSE_MAP
:
9646 case OMP_CLAUSE_FROM
:
9647 var
= OMP_CLAUSE_DECL (c
);
9650 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
9651 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
9657 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
9659 tree var2
= DECL_VALUE_EXPR (var
);
9660 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
9661 var2
= TREE_OPERAND (var2
, 0);
9662 gcc_assert (DECL_P (var2
));
9666 if (!maybe_lookup_field (var
, ctx
))
9669 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9671 x
= build_receiver_ref (var
, true, ctx
);
9672 tree new_var
= lookup_decl (var
, ctx
);
9673 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
9674 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
9675 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
9676 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
9677 x
= build_simple_mem_ref (x
);
9678 SET_DECL_VALUE_EXPR (new_var
, x
);
9679 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
9684 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9686 target_nesting_level
++;
9687 lower_omp (&tgt_body
, ctx
);
9688 target_nesting_level
--;
9690 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
9691 lower_omp (&tgt_body
, ctx
);
9693 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9695 /* Declare all the variables created by mapping and the variables
9696 declared in the scope of the target body. */
9697 record_vars_into (ctx
->block_vars
, child_fn
);
9698 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
9703 if (ctx
->record_type
)
9706 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
9707 DECL_NAMELESS (ctx
->sender_decl
) = 1;
9708 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
9709 t
= make_tree_vec (3);
9710 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
9712 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
9714 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
9715 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
9716 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
9718 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node
,
9721 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
9722 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
9723 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
9724 gimple_omp_target_set_data_arg (stmt
, t
);
9726 vec
<constructor_elt
, va_gc
> *vsize
;
9727 vec
<constructor_elt
, va_gc
> *vkind
;
9728 vec_alloc (vsize
, map_cnt
);
9729 vec_alloc (vkind
, map_cnt
);
9730 unsigned int map_idx
= 0;
9732 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9733 switch (OMP_CLAUSE_CODE (c
))
9739 case OMP_CLAUSE_MAP
:
9741 case OMP_CLAUSE_FROM
:
9743 ovar
= OMP_CLAUSE_DECL (c
);
9746 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
9747 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
9749 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
9750 == get_base_address (ovar
));
9751 nc
= OMP_CLAUSE_CHAIN (c
);
9752 ovar
= OMP_CLAUSE_DECL (nc
);
9756 tree x
= build_sender_ref (ovar
, ctx
);
9758 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
9759 gimplify_assign (x
, v
, &ilist
);
9765 if (DECL_SIZE (ovar
)
9766 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
9768 tree ovar2
= DECL_VALUE_EXPR (ovar
);
9769 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
9770 ovar2
= TREE_OPERAND (ovar2
, 0);
9771 gcc_assert (DECL_P (ovar2
));
9774 if (!maybe_lookup_field (ovar
, ctx
))
9780 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
9781 tree x
= build_sender_ref (ovar
, ctx
);
9782 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
9783 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
9784 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
9785 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
9787 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
9789 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)), NULL
);
9790 mark_addressable (avar
);
9791 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
9792 avar
= build_fold_addr_expr (avar
);
9793 gimplify_assign (x
, avar
, &ilist
);
9795 else if (is_gimple_reg (var
))
9797 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
9798 tree avar
= create_tmp_var (TREE_TYPE (var
), NULL
);
9799 mark_addressable (avar
);
9800 if (OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_ALLOC
9801 && OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_FROM
)
9802 gimplify_assign (avar
, var
, &ilist
);
9803 avar
= build_fold_addr_expr (avar
);
9804 gimplify_assign (x
, avar
, &ilist
);
9805 if ((OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_FROM
9806 || OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_TOFROM
)
9807 && !TYPE_READONLY (TREE_TYPE (var
)))
9809 x
= build_sender_ref (ovar
, ctx
);
9810 x
= build_simple_mem_ref (x
);
9811 gimplify_assign (var
, x
, &olist
);
9816 var
= build_fold_addr_expr (var
);
9817 gimplify_assign (x
, var
, &ilist
);
9820 tree s
= OMP_CLAUSE_SIZE (c
);
9822 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
9823 s
= fold_convert (size_type_node
, s
);
9824 tree purpose
= size_int (map_idx
++);
9825 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
9826 if (TREE_CODE (s
) != INTEGER_CST
)
9827 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
9829 unsigned char tkind
= 0;
9830 switch (OMP_CLAUSE_CODE (c
))
9832 case OMP_CLAUSE_MAP
:
9833 tkind
= OMP_CLAUSE_MAP_KIND (c
);
9836 tkind
= OMP_CLAUSE_MAP_TO
;
9838 case OMP_CLAUSE_FROM
:
9839 tkind
= OMP_CLAUSE_MAP_FROM
;
9844 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
9845 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
9846 talign
= DECL_ALIGN_UNIT (ovar
);
9847 talign
= ceil_log2 (talign
);
9848 tkind
|= talign
<< 3;
9849 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
9850 build_int_cst (unsigned_char_type_node
,
9856 gcc_assert (map_idx
== map_cnt
);
9858 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
9859 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
9860 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
9861 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
9862 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
9864 gimple_seq initlist
= NULL
;
9865 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
9866 TREE_VEC_ELT (t
, 1)),
9867 &initlist
, true, NULL_TREE
);
9868 gimple_seq_add_seq (&ilist
, initlist
);
9870 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
9872 TREE_THIS_VOLATILE (clobber
) = 1;
9873 gimple_seq_add_stmt (&olist
,
9874 gimple_build_assign (TREE_VEC_ELT (t
, 1),
9878 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
9879 TREE_THIS_VOLATILE (clobber
) = 1;
9880 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
9884 /* Once all the expansions are done, sequence all the different
9885 fragments inside gimple_omp_body. */
9889 if (ctx
->record_type
&& kind
== GF_OMP_TARGET_KIND_REGION
)
9891 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9892 /* fixup_child_record_type might have changed receiver_decl's type. */
9893 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
9894 gimple_seq_add_stmt (&new_body
,
9895 gimple_build_assign (ctx
->receiver_decl
, t
));
9898 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9900 gimple_seq_add_seq (&new_body
, tgt_body
);
9901 new_body
= maybe_catch_exception (new_body
);
9903 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
9904 new_body
= tgt_body
;
9905 if (kind
!= GF_OMP_TARGET_KIND_UPDATE
)
9907 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
9908 gimple_omp_set_body (stmt
, new_body
);
9911 bind
= gimple_build_bind (NULL
, NULL
,
9912 tgt_bind
? gimple_bind_block (tgt_bind
)
9914 gsi_replace (gsi_p
, bind
, true);
9915 gimple_bind_add_seq (bind
, ilist
);
9916 gimple_bind_add_stmt (bind
, stmt
);
9917 gimple_bind_add_seq (bind
, olist
);
9919 pop_gimplify_context (NULL
);
9922 /* Expand code for an OpenMP teams directive. */
9925 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9927 gimple teams_stmt
= gsi_stmt (*gsi_p
);
9928 push_gimplify_context ();
9930 tree block
= make_node (BLOCK
);
9931 gimple bind
= gimple_build_bind (NULL
, NULL
, block
);
9932 gsi_replace (gsi_p
, bind
, true);
9933 gimple_seq bind_body
= NULL
;
9934 gimple_seq dlist
= NULL
;
9935 gimple_seq olist
= NULL
;
9937 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
9938 OMP_CLAUSE_NUM_TEAMS
);
9939 if (num_teams
== NULL_TREE
)
9940 num_teams
= build_int_cst (unsigned_type_node
, 0);
9943 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
9944 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
9945 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
9947 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
9948 OMP_CLAUSE_THREAD_LIMIT
);
9949 if (thread_limit
== NULL_TREE
)
9950 thread_limit
= build_int_cst (unsigned_type_node
, 0);
9953 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
9954 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
9955 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
9959 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
9960 &bind_body
, &dlist
, ctx
, NULL
);
9961 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
9962 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
9963 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
9965 location_t loc
= gimple_location (teams_stmt
);
9966 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
9967 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
9968 gimple_set_location (call
, loc
);
9969 gimple_seq_add_stmt (&bind_body
, call
);
9971 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
9972 gimple_omp_set_body (teams_stmt
, NULL
);
9973 gimple_seq_add_seq (&bind_body
, olist
);
9974 gimple_seq_add_seq (&bind_body
, dlist
);
9975 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
9976 gimple_bind_set_body (bind
, bind_body
);
9978 pop_gimplify_context (bind
);
9980 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9981 BLOCK_VARS (block
) = ctx
->block_vars
;
9982 if (BLOCK_VARS (block
))
9983 TREE_USED (block
) = 1;
9987 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9988 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9989 of OpenMP context, but with task_shared_vars set. */
9992 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
9997 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9998 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
10001 if (task_shared_vars
10003 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
10006 /* If a global variable has been privatized, TREE_CONSTANT on
10007 ADDR_EXPR might be wrong. */
10008 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
10009 recompute_tree_invariant_for_addr_expr (t
);
10011 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
10016 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10018 gimple stmt
= gsi_stmt (*gsi_p
);
10019 struct walk_stmt_info wi
;
10021 if (gimple_has_location (stmt
))
10022 input_location
= gimple_location (stmt
);
10024 if (task_shared_vars
)
10025 memset (&wi
, '\0', sizeof (wi
));
10027 /* If we have issued syntax errors, avoid doing any heavy lifting.
10028 Just replace the OpenMP directives with a NOP to avoid
10029 confusing RTL expansion. */
10030 if (seen_error () && is_gimple_omp (stmt
))
10032 gsi_replace (gsi_p
, gimple_build_nop (), true);
10036 switch (gimple_code (stmt
))
10039 if ((ctx
|| task_shared_vars
)
10040 && (walk_tree (gimple_cond_lhs_ptr (stmt
), lower_omp_regimplify_p
,
10041 ctx
? NULL
: &wi
, NULL
)
10042 || walk_tree (gimple_cond_rhs_ptr (stmt
), lower_omp_regimplify_p
,
10043 ctx
? NULL
: &wi
, NULL
)))
10044 gimple_regimplify_operands (stmt
, gsi_p
);
10047 lower_omp (gimple_catch_handler_ptr (stmt
), ctx
);
10049 case GIMPLE_EH_FILTER
:
10050 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
10053 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
10054 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
10056 case GIMPLE_TRANSACTION
:
10057 lower_omp (gimple_transaction_body_ptr (stmt
), ctx
);
10060 lower_omp (gimple_bind_body_ptr (stmt
), ctx
);
10062 case GIMPLE_OMP_PARALLEL
:
10063 case GIMPLE_OMP_TASK
:
10064 ctx
= maybe_lookup_ctx (stmt
);
10066 if (ctx
->cancellable
)
10067 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10068 lower_omp_taskreg (gsi_p
, ctx
);
10070 case GIMPLE_OMP_FOR
:
10071 ctx
= maybe_lookup_ctx (stmt
);
10073 if (ctx
->cancellable
)
10074 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10075 lower_omp_for (gsi_p
, ctx
);
10077 case GIMPLE_OMP_SECTIONS
:
10078 ctx
= maybe_lookup_ctx (stmt
);
10080 if (ctx
->cancellable
)
10081 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10082 lower_omp_sections (gsi_p
, ctx
);
10084 case GIMPLE_OMP_SINGLE
:
10085 ctx
= maybe_lookup_ctx (stmt
);
10087 lower_omp_single (gsi_p
, ctx
);
10089 case GIMPLE_OMP_MASTER
:
10090 ctx
= maybe_lookup_ctx (stmt
);
10092 lower_omp_master (gsi_p
, ctx
);
10094 case GIMPLE_OMP_TASKGROUP
:
10095 ctx
= maybe_lookup_ctx (stmt
);
10097 lower_omp_taskgroup (gsi_p
, ctx
);
10099 case GIMPLE_OMP_ORDERED
:
10100 ctx
= maybe_lookup_ctx (stmt
);
10102 lower_omp_ordered (gsi_p
, ctx
);
10104 case GIMPLE_OMP_CRITICAL
:
10105 ctx
= maybe_lookup_ctx (stmt
);
10107 lower_omp_critical (gsi_p
, ctx
);
10109 case GIMPLE_OMP_ATOMIC_LOAD
:
10110 if ((ctx
|| task_shared_vars
)
10111 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt
),
10112 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
10113 gimple_regimplify_operands (stmt
, gsi_p
);
10115 case GIMPLE_OMP_TARGET
:
10116 ctx
= maybe_lookup_ctx (stmt
);
10118 lower_omp_target (gsi_p
, ctx
);
10120 case GIMPLE_OMP_TEAMS
:
10121 ctx
= maybe_lookup_ctx (stmt
);
10123 lower_omp_teams (gsi_p
, ctx
);
10127 fndecl
= gimple_call_fndecl (stmt
);
10129 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
10130 switch (DECL_FUNCTION_CODE (fndecl
))
10132 case BUILT_IN_GOMP_BARRIER
:
10136 case BUILT_IN_GOMP_CANCEL
:
10137 case BUILT_IN_GOMP_CANCELLATION_POINT
:
10140 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
10141 cctx
= cctx
->outer
;
10142 gcc_assert (gimple_call_lhs (stmt
) == NULL_TREE
);
10143 if (!cctx
->cancellable
)
10145 if (DECL_FUNCTION_CODE (fndecl
)
10146 == BUILT_IN_GOMP_CANCELLATION_POINT
)
10148 stmt
= gimple_build_nop ();
10149 gsi_replace (gsi_p
, stmt
, false);
10153 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
10155 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
10156 gimple_call_set_fndecl (stmt
, fndecl
);
10157 gimple_call_set_fntype (stmt
, TREE_TYPE (fndecl
));
10160 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)), NULL
);
10161 gimple_call_set_lhs (stmt
, lhs
);
10162 tree fallthru_label
;
10163 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
10165 g
= gimple_build_label (fallthru_label
);
10166 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10167 g
= gimple_build_cond (NE_EXPR
, lhs
,
10168 fold_convert (TREE_TYPE (lhs
),
10169 boolean_false_node
),
10170 cctx
->cancel_label
, fallthru_label
);
10171 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10178 if ((ctx
|| task_shared_vars
)
10179 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
10182 /* Just remove clobbers, this should happen only if we have
10183 "privatized" local addressable variables in SIMD regions,
10184 the clobber isn't needed in that case and gimplifying address
10185 of the ARRAY_REF into a pointer and creating MEM_REF based
10186 clobber would create worse code than we get with the clobber
10188 if (gimple_clobber_p (stmt
))
10190 gsi_replace (gsi_p
, gimple_build_nop (), true);
10193 gimple_regimplify_operands (stmt
, gsi_p
);
10200 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
10202 location_t saved_location
= input_location
;
10203 gimple_stmt_iterator gsi
;
10204 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10205 lower_omp_1 (&gsi
, ctx
);
10206 /* During gimplification, we have not always invoked fold_stmt
10207 (gimplify.c:maybe_fold_stmt); call it now. */
10208 if (target_nesting_level
)
10209 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10211 input_location
= saved_location
;
10214 /* Main entry point. */
10216 static unsigned int
10217 execute_lower_omp (void)
10221 /* This pass always runs, to provide PROP_gimple_lomp.
10222 But there is nothing to do unless -fopenmp is given. */
10223 if (flag_openmp
== 0 && flag_openmp_simd
== 0 && flag_cilkplus
== 0)
10226 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
10227 delete_omp_context
);
10229 body
= gimple_body (current_function_decl
);
10230 scan_omp (&body
, NULL
);
10231 gcc_assert (taskreg_nesting_level
== 0);
10233 if (all_contexts
->root
)
10235 if (task_shared_vars
)
10236 push_gimplify_context ();
10237 lower_omp (&body
, NULL
);
10238 if (task_shared_vars
)
10239 pop_gimplify_context (NULL
);
10244 splay_tree_delete (all_contexts
);
10245 all_contexts
= NULL
;
10247 BITMAP_FREE (task_shared_vars
);
10253 const pass_data pass_data_lower_omp
=
10255 GIMPLE_PASS
, /* type */
10256 "omplower", /* name */
10257 OPTGROUP_NONE
, /* optinfo_flags */
10258 true, /* has_execute */
10259 TV_NONE
, /* tv_id */
10260 PROP_gimple_any
, /* properties_required */
10261 PROP_gimple_lomp
, /* properties_provided */
10262 0, /* properties_destroyed */
10263 0, /* todo_flags_start */
10264 0, /* todo_flags_finish */
10267 class pass_lower_omp
: public gimple_opt_pass
10270 pass_lower_omp (gcc::context
*ctxt
)
10271 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
10274 /* opt_pass methods: */
10275 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
10277 }; // class pass_lower_omp
10279 } // anon namespace
10282 make_pass_lower_omp (gcc::context
*ctxt
)
10284 return new pass_lower_omp (ctxt
);
10287 /* The following is a utility to diagnose OpenMP structured block violations.
10288 It is not part of the "omplower" pass, as that's invoked too late. It
10289 should be invoked by the respective front ends after gimplification. */
10291 static splay_tree all_labels
;
10293 /* Check for mismatched contexts and generate an error if needed. Return
10294 true if an error is detected. */
10297 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
10298 gimple branch_ctx
, gimple label_ctx
)
10300 if (label_ctx
== branch_ctx
)
10305 Previously we kept track of the label's entire context in diagnose_sb_[12]
10306 so we could traverse it and issue a correct "exit" or "enter" error
10307 message upon a structured block violation.
10309 We built the context by building a list with tree_cons'ing, but there is
10310 no easy counterpart in gimple tuples. It seems like far too much work
10311 for issuing exit/enter error messages. If someone really misses the
10312 distinct error message... patches welcome.
10316 /* Try to avoid confusing the user by producing and error message
10317 with correct "exit" or "enter" verbiage. We prefer "exit"
10318 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10319 if (branch_ctx
== NULL
)
10325 if (TREE_VALUE (label_ctx
) == branch_ctx
)
10330 label_ctx
= TREE_CHAIN (label_ctx
);
10335 error ("invalid exit from OpenMP structured block");
10337 error ("invalid entry to OpenMP structured block");
10340 bool cilkplus_block
= false;
10344 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
10345 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
10347 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
10348 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
10349 cilkplus_block
= true;
10352 /* If it's obvious we have an invalid entry, be specific about the error. */
10353 if (branch_ctx
== NULL
)
10355 if (cilkplus_block
)
10356 error ("invalid entry to Cilk Plus structured block");
10358 error ("invalid entry to OpenMP structured block");
10362 /* Otherwise, be vague and lazy, but efficient. */
10363 if (cilkplus_block
)
10364 error ("invalid branch to/from a Cilk Plus structured block");
10366 error ("invalid branch to/from an OpenMP structured block");
10369 gsi_replace (gsi_p
, gimple_build_nop (), false);
10373 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10374 where each label is found. */
10377 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10378 struct walk_stmt_info
*wi
)
10380 gimple context
= (gimple
) wi
->info
;
10381 gimple inner_context
;
10382 gimple stmt
= gsi_stmt (*gsi_p
);
10384 *handled_ops_p
= true;
10386 switch (gimple_code (stmt
))
10390 case GIMPLE_OMP_PARALLEL
:
10391 case GIMPLE_OMP_TASK
:
10392 case GIMPLE_OMP_SECTIONS
:
10393 case GIMPLE_OMP_SINGLE
:
10394 case GIMPLE_OMP_SECTION
:
10395 case GIMPLE_OMP_MASTER
:
10396 case GIMPLE_OMP_ORDERED
:
10397 case GIMPLE_OMP_CRITICAL
:
10398 case GIMPLE_OMP_TARGET
:
10399 case GIMPLE_OMP_TEAMS
:
10400 case GIMPLE_OMP_TASKGROUP
:
10401 /* The minimal context here is just the current OMP construct. */
10402 inner_context
= stmt
;
10403 wi
->info
= inner_context
;
10404 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10405 wi
->info
= context
;
10408 case GIMPLE_OMP_FOR
:
10409 inner_context
= stmt
;
10410 wi
->info
= inner_context
;
10411 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10413 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
10414 diagnose_sb_1
, NULL
, wi
);
10415 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10416 wi
->info
= context
;
10420 splay_tree_insert (all_labels
, (splay_tree_key
) gimple_label_label (stmt
),
10421 (splay_tree_value
) context
);
10431 /* Pass 2: Check each branch and see if its context differs from that of
10432 the destination label's context. */
10435 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10436 struct walk_stmt_info
*wi
)
10438 gimple context
= (gimple
) wi
->info
;
10440 gimple stmt
= gsi_stmt (*gsi_p
);
10442 *handled_ops_p
= true;
10444 switch (gimple_code (stmt
))
10448 case GIMPLE_OMP_PARALLEL
:
10449 case GIMPLE_OMP_TASK
:
10450 case GIMPLE_OMP_SECTIONS
:
10451 case GIMPLE_OMP_SINGLE
:
10452 case GIMPLE_OMP_SECTION
:
10453 case GIMPLE_OMP_MASTER
:
10454 case GIMPLE_OMP_ORDERED
:
10455 case GIMPLE_OMP_CRITICAL
:
10456 case GIMPLE_OMP_TARGET
:
10457 case GIMPLE_OMP_TEAMS
:
10458 case GIMPLE_OMP_TASKGROUP
:
10460 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10461 wi
->info
= context
;
10464 case GIMPLE_OMP_FOR
:
10466 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10468 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
10469 diagnose_sb_2
, NULL
, wi
);
10470 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10471 wi
->info
= context
;
10476 tree lab
= gimple_cond_true_label (stmt
);
10479 n
= splay_tree_lookup (all_labels
,
10480 (splay_tree_key
) lab
);
10481 diagnose_sb_0 (gsi_p
, context
,
10482 n
? (gimple
) n
->value
: NULL
);
10484 lab
= gimple_cond_false_label (stmt
);
10487 n
= splay_tree_lookup (all_labels
,
10488 (splay_tree_key
) lab
);
10489 diagnose_sb_0 (gsi_p
, context
,
10490 n
? (gimple
) n
->value
: NULL
);
10497 tree lab
= gimple_goto_dest (stmt
);
10498 if (TREE_CODE (lab
) != LABEL_DECL
)
10501 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10502 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
10506 case GIMPLE_SWITCH
:
10509 for (i
= 0; i
< gimple_switch_num_labels (stmt
); ++i
)
10511 tree lab
= CASE_LABEL (gimple_switch_label (stmt
, i
));
10512 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10513 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
10519 case GIMPLE_RETURN
:
10520 diagnose_sb_0 (gsi_p
, context
, NULL
);
10530 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10533 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
10536 gimple last
= last_stmt (bb
);
10537 enum gimple_code code
= gimple_code (last
);
10538 struct omp_region
*cur_region
= *region
;
10539 bool fallthru
= false;
10543 case GIMPLE_OMP_PARALLEL
:
10544 case GIMPLE_OMP_TASK
:
10545 case GIMPLE_OMP_FOR
:
10546 case GIMPLE_OMP_SINGLE
:
10547 case GIMPLE_OMP_TEAMS
:
10548 case GIMPLE_OMP_MASTER
:
10549 case GIMPLE_OMP_TASKGROUP
:
10550 case GIMPLE_OMP_ORDERED
:
10551 case GIMPLE_OMP_CRITICAL
:
10552 case GIMPLE_OMP_SECTION
:
10553 cur_region
= new_omp_region (bb
, code
, cur_region
);
10557 case GIMPLE_OMP_TARGET
:
10558 cur_region
= new_omp_region (bb
, code
, cur_region
);
10560 if (gimple_omp_target_kind (last
) == GF_OMP_TARGET_KIND_UPDATE
)
10561 cur_region
= cur_region
->outer
;
10564 case GIMPLE_OMP_SECTIONS
:
10565 cur_region
= new_omp_region (bb
, code
, cur_region
);
10569 case GIMPLE_OMP_SECTIONS_SWITCH
:
10573 case GIMPLE_OMP_ATOMIC_LOAD
:
10574 case GIMPLE_OMP_ATOMIC_STORE
:
10578 case GIMPLE_OMP_RETURN
:
10579 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10580 somewhere other than the next block. This will be
10582 cur_region
->exit
= bb
;
10583 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
10584 cur_region
= cur_region
->outer
;
10587 case GIMPLE_OMP_CONTINUE
:
10588 cur_region
->cont
= bb
;
10589 switch (cur_region
->type
)
10591 case GIMPLE_OMP_FOR
:
10592 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10593 succs edges as abnormal to prevent splitting
10595 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
10596 /* Make the loopback edge. */
10597 make_edge (bb
, single_succ (cur_region
->entry
),
10600 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10601 corresponds to the case that the body of the loop
10602 is not executed at all. */
10603 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
10604 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
10608 case GIMPLE_OMP_SECTIONS
:
10609 /* Wire up the edges into and out of the nested sections. */
10611 basic_block switch_bb
= single_succ (cur_region
->entry
);
10613 struct omp_region
*i
;
10614 for (i
= cur_region
->inner
; i
; i
= i
->next
)
10616 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
10617 make_edge (switch_bb
, i
->entry
, 0);
10618 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
10621 /* Make the loopback edge to the block with
10622 GIMPLE_OMP_SECTIONS_SWITCH. */
10623 make_edge (bb
, switch_bb
, 0);
10625 /* Make the edge from the switch to exit. */
10626 make_edge (switch_bb
, bb
->next_bb
, 0);
10632 gcc_unreachable ();
10637 gcc_unreachable ();
10640 if (*region
!= cur_region
)
10642 *region
= cur_region
;
10644 *region_idx
= cur_region
->entry
->index
;
10652 static unsigned int
10653 diagnose_omp_structured_block_errors (void)
10655 struct walk_stmt_info wi
;
10656 gimple_seq body
= gimple_body (current_function_decl
);
10658 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
10660 memset (&wi
, 0, sizeof (wi
));
10661 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
10663 memset (&wi
, 0, sizeof (wi
));
10664 wi
.want_locations
= true;
10665 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
10667 gimple_set_body (current_function_decl
, body
);
10669 splay_tree_delete (all_labels
);
10677 const pass_data pass_data_diagnose_omp_blocks
=
10679 GIMPLE_PASS
, /* type */
10680 "*diagnose_omp_blocks", /* name */
10681 OPTGROUP_NONE
, /* optinfo_flags */
10682 true, /* has_execute */
10683 TV_NONE
, /* tv_id */
10684 PROP_gimple_any
, /* properties_required */
10685 0, /* properties_provided */
10686 0, /* properties_destroyed */
10687 0, /* todo_flags_start */
10688 0, /* todo_flags_finish */
10691 class pass_diagnose_omp_blocks
: public gimple_opt_pass
10694 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
10695 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
10698 /* opt_pass methods: */
10699 virtual bool gate (function
*) { return flag_openmp
|| flag_cilkplus
; }
10700 virtual unsigned int execute (function
*)
10702 return diagnose_omp_structured_block_errors ();
10705 }; // class pass_diagnose_omp_blocks
10707 } // anon namespace
10710 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
10712 return new pass_diagnose_omp_blocks (ctxt
);
10715 /* SIMD clone supporting code. */
10717 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10718 of arguments to reserve space for. */
10720 static struct cgraph_simd_clone
*
10721 simd_clone_struct_alloc (int nargs
)
10723 struct cgraph_simd_clone
*clone_info
;
10724 size_t len
= (sizeof (struct cgraph_simd_clone
)
10725 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
10726 clone_info
= (struct cgraph_simd_clone
*)
10727 ggc_internal_cleared_alloc (len
);
10731 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10734 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
10735 struct cgraph_simd_clone
*from
)
10737 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
10738 + ((from
->nargs
- from
->inbranch
)
10739 * sizeof (struct cgraph_simd_clone_arg
))));
10742 /* Return vector of parameter types of function FNDECL. This uses
10743 TYPE_ARG_TYPES if available, otherwise falls back to types of
10744 DECL_ARGUMENTS types. */
10747 simd_clone_vector_of_formal_parm_types (tree fndecl
)
10749 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
10750 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
10751 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
10754 FOR_EACH_VEC_ELT (args
, i
, arg
)
10755 args
[i
] = TREE_TYPE (args
[i
]);
10759 /* Given a simd function in NODE, extract the simd specific
10760 information from the OMP clauses passed in CLAUSES, and return
10761 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10762 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10763 otherwise set to FALSE. */
10765 static struct cgraph_simd_clone
*
10766 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
10767 bool *inbranch_specified
)
10769 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
10772 *inbranch_specified
= false;
10774 n
= args
.length ();
10775 if (n
> 0 && args
.last () == void_type_node
)
10778 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10779 be cloned have a distinctive artificial label in addition to "omp
10783 && lookup_attribute ("cilk simd function",
10784 DECL_ATTRIBUTES (node
->decl
)));
10786 /* Allocate one more than needed just in case this is an in-branch
10787 clone which will require a mask argument. */
10788 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
10789 clone_info
->nargs
= n
;
10790 clone_info
->cilk_elemental
= cilk_clone
;
10797 clauses
= TREE_VALUE (clauses
);
10798 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
10801 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
10803 switch (OMP_CLAUSE_CODE (t
))
10805 case OMP_CLAUSE_INBRANCH
:
10806 clone_info
->inbranch
= 1;
10807 *inbranch_specified
= true;
10809 case OMP_CLAUSE_NOTINBRANCH
:
10810 clone_info
->inbranch
= 0;
10811 *inbranch_specified
= true;
10813 case OMP_CLAUSE_SIMDLEN
:
10814 clone_info
->simdlen
10815 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
10817 case OMP_CLAUSE_LINEAR
:
10819 tree decl
= OMP_CLAUSE_DECL (t
);
10820 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
10821 int argno
= TREE_INT_CST_LOW (decl
);
10822 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
10824 clone_info
->args
[argno
].arg_type
10825 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
10826 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
10827 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
10828 && clone_info
->args
[argno
].linear_step
< n
);
10832 if (POINTER_TYPE_P (args
[argno
]))
10833 step
= fold_convert (ssizetype
, step
);
10834 if (!tree_fits_shwi_p (step
))
10836 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
10837 "ignoring large linear step");
10841 else if (integer_zerop (step
))
10843 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
10844 "ignoring zero linear step");
10850 clone_info
->args
[argno
].arg_type
10851 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
10852 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
10857 case OMP_CLAUSE_UNIFORM
:
10859 tree decl
= OMP_CLAUSE_DECL (t
);
10860 int argno
= tree_to_uhwi (decl
);
10861 clone_info
->args
[argno
].arg_type
10862 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
10865 case OMP_CLAUSE_ALIGNED
:
10867 tree decl
= OMP_CLAUSE_DECL (t
);
10868 int argno
= tree_to_uhwi (decl
);
10869 clone_info
->args
[argno
].alignment
10870 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
10881 /* Given a SIMD clone in NODE, calculate the characteristic data
10882 type and return the coresponding type. The characteristic data
10883 type is computed as described in the Intel Vector ABI. */
10886 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
10887 struct cgraph_simd_clone
*clone_info
)
10889 tree type
= integer_type_node
;
10890 tree fndecl
= node
->decl
;
10892 /* a) For non-void function, the characteristic data type is the
10894 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
10895 type
= TREE_TYPE (TREE_TYPE (fndecl
));
10897 /* b) If the function has any non-uniform, non-linear parameters,
10898 then the characteristic data type is the type of the first
10902 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
10903 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
10904 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
10912 /* c) If the characteristic data type determined by a) or b) above
10913 is struct, union, or class type which is pass-by-value (except
10914 for the type that maps to the built-in complex data type), the
10915 characteristic data type is int. */
10916 if (RECORD_OR_UNION_TYPE_P (type
)
10917 && !aggregate_value_p (type
, NULL
)
10918 && TREE_CODE (type
) != COMPLEX_TYPE
)
10919 return integer_type_node
;
10921 /* d) If none of the above three classes is applicable, the
10922 characteristic data type is int. */
10926 /* e) For Intel Xeon Phi native and offload compilation, if the
10927 resulting characteristic data type is 8-bit or 16-bit integer
10928 data type, the characteristic data type is int. */
10929 /* Well, we don't handle Xeon Phi yet. */
10933 simd_clone_mangle (struct cgraph_node
*node
,
10934 struct cgraph_simd_clone
*clone_info
)
10936 char vecsize_mangle
= clone_info
->vecsize_mangle
;
10937 char mask
= clone_info
->inbranch
? 'M' : 'N';
10938 unsigned int simdlen
= clone_info
->simdlen
;
10942 gcc_assert (vecsize_mangle
&& simdlen
);
10944 pp_string (&pp
, "_ZGV");
10945 pp_character (&pp
, vecsize_mangle
);
10946 pp_character (&pp
, mask
);
10947 pp_decimal_int (&pp
, simdlen
);
10949 for (n
= 0; n
< clone_info
->nargs
; ++n
)
10951 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
10953 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
10954 pp_character (&pp
, 'u');
10955 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
10957 gcc_assert (arg
.linear_step
!= 0);
10958 pp_character (&pp
, 'l');
10959 if (arg
.linear_step
> 1)
10960 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
10961 else if (arg
.linear_step
< 0)
10963 pp_character (&pp
, 'n');
10964 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
10968 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
10970 pp_character (&pp
, 's');
10971 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
10974 pp_character (&pp
, 'v');
10977 pp_character (&pp
, 'a');
10978 pp_decimal_int (&pp
, arg
.alignment
);
10982 pp_underscore (&pp
);
10984 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
)));
10985 const char *str
= pp_formatted_text (&pp
);
10987 /* If there already is a SIMD clone with the same mangled name, don't
10988 add another one. This can happen e.g. for
10989 #pragma omp declare simd
10990 #pragma omp declare simd simdlen(8)
10991 int foo (int, int);
10992 if the simdlen is assumed to be 8 for the first one, etc. */
10993 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
10994 clone
= clone
->simdclone
->next_clone
)
10995 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
10999 return get_identifier (str
);
11002 /* Create a simd clone of OLD_NODE and return it. */
11004 static struct cgraph_node
*
11005 simd_clone_create (struct cgraph_node
*old_node
)
11007 struct cgraph_node
*new_node
;
11008 if (old_node
->definition
)
11010 if (!cgraph_function_with_gimple_body_p (old_node
))
11012 cgraph_get_body (old_node
);
11013 new_node
= cgraph_function_versioning (old_node
, vNULL
, NULL
, NULL
,
11014 false, NULL
, NULL
, "simdclone");
11018 tree old_decl
= old_node
->decl
;
11019 tree new_decl
= copy_node (old_node
->decl
);
11020 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
11021 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
11022 SET_DECL_RTL (new_decl
, NULL
);
11023 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
11024 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
11026 = cgraph_copy_node_for_versioning (old_node
, new_decl
, vNULL
, NULL
);
11027 cgraph_call_function_insertion_hooks (new_node
);
11029 if (new_node
== NULL
)
11032 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
11034 /* The function cgraph_function_versioning () will force the new
11035 symbol local. Undo this, and inherit external visability from
11037 new_node
->local
.local
= old_node
->local
.local
;
11038 new_node
->externally_visible
= old_node
->externally_visible
;
11043 /* Adjust the return type of the given function to its appropriate
11044 vector counterpart. Returns a simd array to be used throughout the
11045 function as a return value. */
11048 simd_clone_adjust_return_type (struct cgraph_node
*node
)
11050 tree fndecl
= node
->decl
;
11051 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
11052 unsigned int veclen
;
11055 /* Adjust the function return type. */
11056 if (orig_rettype
== void_type_node
)
11058 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
11059 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
)))
11060 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
))))
11061 veclen
= node
->simdclone
->vecsize_int
;
11063 veclen
= node
->simdclone
->vecsize_float
;
11064 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl
))));
11065 if (veclen
> node
->simdclone
->simdlen
)
11066 veclen
= node
->simdclone
->simdlen
;
11067 if (veclen
== node
->simdclone
->simdlen
)
11068 TREE_TYPE (TREE_TYPE (fndecl
))
11069 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)),
11070 node
->simdclone
->simdlen
);
11073 t
= build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)), veclen
);
11074 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
11075 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
11077 if (!node
->definition
)
11080 t
= DECL_RESULT (fndecl
);
11081 /* Adjust the DECL_RESULT. */
11082 gcc_assert (TREE_TYPE (t
) != void_type_node
);
11083 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
11086 tree atype
= build_array_type_nelts (orig_rettype
,
11087 node
->simdclone
->simdlen
);
11088 if (veclen
!= node
->simdclone
->simdlen
)
11089 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
11091 /* Set up a SIMD array to use as the return value. */
11092 tree retval
= create_tmp_var_raw (atype
, "retval");
11093 gimple_add_tmp_var (retval
);
11097 /* Each vector argument has a corresponding array to be used locally
11098 as part of the eventual loop. Create such temporary array and
11101 PREFIX is the prefix to be used for the temporary.
11103 TYPE is the inner element type.
11105 SIMDLEN is the number of elements. */
11108 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
11110 tree atype
= build_array_type_nelts (type
, simdlen
);
11111 tree avar
= create_tmp_var_raw (atype
, prefix
);
11112 gimple_add_tmp_var (avar
);
11116 /* Modify the function argument types to their corresponding vector
11117 counterparts if appropriate. Also, create one array for each simd
11118 argument to be used locally when using the function arguments as
11121 NODE is the function whose arguments are to be adjusted.
11123 Returns an adjustment vector that will be filled describing how the
11124 argument types will be adjusted. */
11126 static ipa_parm_adjustment_vec
11127 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
11130 ipa_parm_adjustment_vec adjustments
;
11132 if (node
->definition
)
11133 args
= ipa_get_vector_of_formal_parms (node
->decl
);
11135 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11136 adjustments
.create (args
.length ());
11137 unsigned i
, j
, veclen
;
11138 struct ipa_parm_adjustment adj
;
11139 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
11141 memset (&adj
, 0, sizeof (adj
));
11142 tree parm
= args
[i
];
11143 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
11144 adj
.base_index
= i
;
11147 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
11148 node
->simdclone
->args
[i
].orig_type
= parm_type
;
11150 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
11152 /* No adjustment necessary for scalar arguments. */
11153 adj
.op
= IPA_PARM_OP_COPY
;
11157 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
11158 veclen
= node
->simdclone
->vecsize_int
;
11160 veclen
= node
->simdclone
->vecsize_float
;
11161 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
11162 if (veclen
> node
->simdclone
->simdlen
)
11163 veclen
= node
->simdclone
->simdlen
;
11164 adj
.arg_prefix
= "simd";
11165 adj
.type
= build_vector_type (parm_type
, veclen
);
11166 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
11167 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11169 adjustments
.safe_push (adj
);
11172 memset (&adj
, 0, sizeof (adj
));
11173 adj
.op
= IPA_PARM_OP_NEW
;
11174 adj
.arg_prefix
= "simd";
11175 adj
.base_index
= i
;
11176 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
11180 if (node
->definition
)
11181 node
->simdclone
->args
[i
].simd_array
11182 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
11183 parm_type
, node
->simdclone
->simdlen
);
11185 adjustments
.safe_push (adj
);
11188 if (node
->simdclone
->inbranch
)
11191 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
11194 memset (&adj
, 0, sizeof (adj
));
11195 adj
.op
= IPA_PARM_OP_NEW
;
11196 adj
.arg_prefix
= "mask";
11198 adj
.base_index
= i
;
11199 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
11200 veclen
= node
->simdclone
->vecsize_int
;
11202 veclen
= node
->simdclone
->vecsize_float
;
11203 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
11204 if (veclen
> node
->simdclone
->simdlen
)
11205 veclen
= node
->simdclone
->simdlen
;
11206 adj
.type
= build_vector_type (base_type
, veclen
);
11207 adjustments
.safe_push (adj
);
11209 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11210 adjustments
.safe_push (adj
);
11212 /* We have previously allocated one extra entry for the mask. Use
11214 struct cgraph_simd_clone
*sc
= node
->simdclone
;
11216 if (node
->definition
)
11218 sc
->args
[i
].orig_arg
11219 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
11220 sc
->args
[i
].simd_array
11221 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
11223 sc
->args
[i
].orig_type
= base_type
;
11224 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
11227 if (node
->definition
)
11228 ipa_modify_formal_parameters (node
->decl
, adjustments
);
11231 tree new_arg_types
= NULL_TREE
, new_reversed
;
11232 bool last_parm_void
= false;
11233 if (args
.length () > 0 && args
.last () == void_type_node
)
11234 last_parm_void
= true;
11236 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
11237 j
= adjustments
.length ();
11238 for (i
= 0; i
< j
; i
++)
11240 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
11242 if (adj
->op
== IPA_PARM_OP_COPY
)
11243 ptype
= args
[adj
->base_index
];
11246 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
11248 new_reversed
= nreverse (new_arg_types
);
11249 if (last_parm_void
)
11252 TREE_CHAIN (new_arg_types
) = void_list_node
;
11254 new_reversed
= void_list_node
;
11257 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
11258 TYPE_ARG_TYPES (new_type
) = new_reversed
;
11259 TREE_TYPE (node
->decl
) = new_type
;
11261 adjustments
.release ();
11264 return adjustments
;
11267 /* Initialize and copy the function arguments in NODE to their
11268 corresponding local simd arrays. Returns a fresh gimple_seq with
11269 the instruction sequence generated. */
11272 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
11273 ipa_parm_adjustment_vec adjustments
)
11275 gimple_seq seq
= NULL
;
11276 unsigned i
= 0, j
= 0, k
;
11278 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
11280 arg
= DECL_CHAIN (arg
), i
++, j
++)
11282 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
11285 node
->simdclone
->args
[i
].vector_arg
= arg
;
11287 tree array
= node
->simdclone
->args
[i
].simd_array
;
11288 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
11290 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11291 tree ptr
= build_fold_addr_expr (array
);
11292 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11293 build_int_cst (ptype
, 0));
11294 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11295 gimplify_and_add (t
, &seq
);
11299 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
11300 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11301 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
11303 tree ptr
= build_fold_addr_expr (array
);
11307 arg
= DECL_CHAIN (arg
);
11311 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
11312 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11313 build_int_cst (ptype
, k
* elemsize
));
11314 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11315 gimplify_and_add (t
, &seq
);
11322 /* Callback info for ipa_simd_modify_stmt_ops below. */
11324 struct modify_stmt_info
{
11325 ipa_parm_adjustment_vec adjustments
;
11327 /* True if the parent statement was modified by
11328 ipa_simd_modify_stmt_ops. */
11332 /* Callback for walk_gimple_op.
11334 Adjust operands from a given statement as specified in the
11335 adjustments vector in the callback data. */
11338 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
11340 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
11341 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
11342 tree
*orig_tp
= tp
;
11343 if (TREE_CODE (*tp
) == ADDR_EXPR
)
11344 tp
= &TREE_OPERAND (*tp
, 0);
11345 struct ipa_parm_adjustment
*cand
= NULL
;
11346 if (TREE_CODE (*tp
) == PARM_DECL
)
11347 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
11351 *walk_subtrees
= 0;
11354 tree repl
= NULL_TREE
;
11356 repl
= unshare_expr (cand
->new_decl
);
11361 *walk_subtrees
= 0;
11362 bool modified
= info
->modified
;
11363 info
->modified
= false;
11364 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
11365 if (!info
->modified
)
11367 info
->modified
= modified
;
11370 info
->modified
= modified
;
11379 repl
= build_fold_addr_expr (repl
);
11381 = gimple_build_assign (make_ssa_name (TREE_TYPE (repl
), NULL
), repl
);
11382 repl
= gimple_assign_lhs (stmt
);
11383 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
11384 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11387 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
11389 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
11395 info
->modified
= true;
11399 /* Traverse the function body and perform all modifications as
11400 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11401 modified such that the replacement/reduction value will now be an
11402 offset into the corresponding simd_array.
11404 This function will replace all function argument uses with their
11405 corresponding simd array elements, and ajust the return values
11409 ipa_simd_modify_function_body (struct cgraph_node
*node
,
11410 ipa_parm_adjustment_vec adjustments
,
11411 tree retval_array
, tree iter
)
11414 unsigned int i
, j
, l
;
11416 /* Re-use the adjustments array, but this time use it to replace
11417 every function argument use to an offset into the corresponding
11419 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
11421 if (!node
->simdclone
->args
[i
].vector_arg
)
11424 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
11425 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
11426 adjustments
[j
].new_decl
11427 = build4 (ARRAY_REF
,
11429 node
->simdclone
->args
[i
].simd_array
,
11431 NULL_TREE
, NULL_TREE
);
11432 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
11433 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
11434 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
11437 l
= adjustments
.length ();
11438 for (i
= 1; i
< num_ssa_names
; i
++)
11440 tree name
= ssa_name (i
);
11442 && SSA_NAME_VAR (name
)
11443 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
11445 for (j
= 0; j
< l
; j
++)
11446 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
11447 && adjustments
[j
].new_decl
)
11450 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
11453 = copy_var_decl (adjustments
[j
].base
,
11454 DECL_NAME (adjustments
[j
].base
),
11455 TREE_TYPE (adjustments
[j
].base
));
11456 adjustments
[j
].new_ssa_base
= base_var
;
11459 base_var
= adjustments
[j
].new_ssa_base
;
11460 if (SSA_NAME_IS_DEFAULT_DEF (name
))
11462 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11463 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
11464 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
11465 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
11466 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11467 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
11468 gimple stmt
= gimple_build_assign (name
, new_decl
);
11469 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11472 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11477 struct modify_stmt_info info
;
11478 info
.adjustments
= adjustments
;
11480 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
11482 gimple_stmt_iterator gsi
;
11484 gsi
= gsi_start_bb (bb
);
11485 while (!gsi_end_p (gsi
))
11487 gimple stmt
= gsi_stmt (gsi
);
11489 struct walk_stmt_info wi
;
11491 memset (&wi
, 0, sizeof (wi
));
11492 info
.modified
= false;
11494 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
11496 if (gimple_code (stmt
) == GIMPLE_RETURN
)
11498 tree retval
= gimple_return_retval (stmt
);
11501 gsi_remove (&gsi
, true);
11505 /* Replace `return foo' with `retval_array[iter] = foo'. */
11506 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
11507 retval_array
, iter
, NULL
, NULL
);
11508 stmt
= gimple_build_assign (ref
, retval
);
11509 gsi_replace (&gsi
, stmt
, true);
11510 info
.modified
= true;
11515 update_stmt (stmt
);
11516 if (maybe_clean_eh_stmt (stmt
))
11517 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
11524 /* Adjust the argument types in NODE to their appropriate vector
11528 simd_clone_adjust (struct cgraph_node
*node
)
11530 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
11532 targetm
.simd_clone
.adjust (node
);
11534 tree retval
= simd_clone_adjust_return_type (node
);
11535 ipa_parm_adjustment_vec adjustments
11536 = simd_clone_adjust_argument_types (node
);
11538 push_gimplify_context ();
11540 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
11542 /* Adjust all uses of vector arguments accordingly. Adjust all
11543 return values accordingly. */
11544 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
11545 tree iter1
= make_ssa_name (iter
, NULL
);
11546 tree iter2
= make_ssa_name (iter
, NULL
);
11547 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
11549 /* Initialize the iteration variable. */
11550 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11551 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
11552 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
11553 /* Insert the SIMD array and iv initialization at function
11555 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
11557 pop_gimplify_context (NULL
);
11559 /* Create a new BB right before the original exit BB, to hold the
11560 iteration increment and the condition/branch. */
11561 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
11562 basic_block incr_bb
= create_empty_bb (orig_exit
);
11563 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11564 flag. Set it now to be a FALLTHRU_EDGE. */
11565 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
11566 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
11567 for (unsigned i
= 0;
11568 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
11570 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
11571 redirect_edge_succ (e
, incr_bb
);
11573 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
11574 e
->probability
= REG_BR_PROB_BASE
;
11575 gsi
= gsi_last_bb (incr_bb
);
11576 gimple g
= gimple_build_assign_with_ops (PLUS_EXPR
, iter2
, iter1
,
11577 build_int_cst (unsigned_type_node
,
11579 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11581 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11582 struct loop
*loop
= alloc_loop ();
11583 cfun
->has_force_vectorize_loops
= true;
11584 loop
->safelen
= node
->simdclone
->simdlen
;
11585 loop
->force_vectorize
= true;
11586 loop
->header
= body_bb
;
11587 add_bb_to_loop (incr_bb
, loop
);
11589 /* Branch around the body if the mask applies. */
11590 if (node
->simdclone
->inbranch
)
11592 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
11594 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
11595 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)), NULL
);
11596 tree aref
= build4 (ARRAY_REF
,
11597 TREE_TYPE (TREE_TYPE (mask_array
)),
11600 g
= gimple_build_assign (mask
, aref
);
11601 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11602 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
11603 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
11605 aref
= build1 (VIEW_CONVERT_EXPR
,
11606 build_nonstandard_integer_type (bitsize
, 0), mask
);
11607 mask
= make_ssa_name (TREE_TYPE (aref
), NULL
);
11608 g
= gimple_build_assign (mask
, aref
);
11609 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11612 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
11614 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11615 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
11616 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
11619 /* Generate the condition. */
11620 g
= gimple_build_cond (LT_EXPR
,
11622 build_int_cst (unsigned_type_node
,
11623 node
->simdclone
->simdlen
),
11625 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11626 e
= split_block (incr_bb
, gsi_stmt (gsi
));
11627 basic_block latch_bb
= e
->dest
;
11628 basic_block new_exit_bb
= e
->dest
;
11629 new_exit_bb
= split_block (latch_bb
, NULL
)->dest
;
11630 loop
->latch
= latch_bb
;
11632 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
11634 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
11635 /* The successor of incr_bb is already pointing to latch_bb; just
11637 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11638 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
11640 gimple phi
= create_phi_node (iter1
, body_bb
);
11641 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
11642 edge latch_edge
= single_succ_edge (latch_bb
);
11643 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
11645 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
11647 /* Generate the new return. */
11648 gsi
= gsi_last_bb (new_exit_bb
);
11650 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
11651 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
11652 retval
= TREE_OPERAND (retval
, 0);
11655 retval
= build1 (VIEW_CONVERT_EXPR
,
11656 TREE_TYPE (TREE_TYPE (node
->decl
)),
11658 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
11659 false, GSI_CONTINUE_LINKING
);
11661 g
= gimple_build_return (retval
);
11662 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11664 /* Handle aligned clauses by replacing default defs of the aligned
11665 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11666 lhs. Handle linear by adding PHIs. */
11667 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
11668 if (node
->simdclone
->args
[i
].alignment
11669 && node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
11670 && (node
->simdclone
->args
[i
].alignment
11671 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
11672 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
11675 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
11676 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
11677 tree def
= ssa_default_def (cfun
, orig_arg
);
11678 if (def
&& !has_zero_uses (def
))
11680 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
11681 gimple_seq seq
= NULL
;
11682 bool need_cvt
= false;
11684 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
11686 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
11689 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
, NULL
);
11690 gimple_call_set_lhs (g
, t
);
11691 gimple_seq_add_stmt_without_update (&seq
, g
);
11694 t
= make_ssa_name (orig_arg
, NULL
);
11695 g
= gimple_build_assign_with_ops (NOP_EXPR
, t
,
11696 gimple_call_lhs (g
),
11698 gimple_seq_add_stmt_without_update (&seq
, g
);
11700 gsi_insert_seq_on_edge_immediate
11701 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
11703 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11704 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
11706 cgraph_create_edge (node
, cgraph_get_create_node (fn
),
11707 call
, entry_bb
->count
, freq
);
11709 imm_use_iterator iter
;
11710 use_operand_p use_p
;
11712 tree repl
= gimple_get_lhs (g
);
11713 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
11714 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
11717 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
11718 SET_USE (use_p
, repl
);
11721 else if (node
->simdclone
->args
[i
].arg_type
11722 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
11724 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
11725 tree def
= ssa_default_def (cfun
, orig_arg
);
11726 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
11727 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
11728 if (def
&& !has_zero_uses (def
))
11730 iter1
= make_ssa_name (orig_arg
, NULL
);
11731 iter2
= make_ssa_name (orig_arg
, NULL
);
11732 phi
= create_phi_node (iter1
, body_bb
);
11733 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
11734 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
11735 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
11736 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
11737 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
11738 ? TREE_TYPE (orig_arg
) : sizetype
;
11740 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
11741 g
= gimple_build_assign_with_ops (code
, iter2
, iter1
, addcst
);
11742 gsi
= gsi_last_bb (incr_bb
);
11743 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
11745 imm_use_iterator iter
;
11746 use_operand_p use_p
;
11748 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
11749 if (use_stmt
== phi
)
11752 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
11753 SET_USE (use_p
, iter1
);
11757 calculate_dominance_info (CDI_DOMINATORS
);
11758 add_loop (loop
, loop
->header
->loop_father
);
11759 update_ssa (TODO_update_ssa
);
11764 /* If the function in NODE is tagged as an elemental SIMD function,
11765 create the appropriate SIMD clones. */
11768 expand_simd_clones (struct cgraph_node
*node
)
11770 tree attr
= lookup_attribute ("omp declare simd",
11771 DECL_ATTRIBUTES (node
->decl
));
11772 if (attr
== NULL_TREE
11773 || node
->global
.inlined_to
11774 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
11778 #pragma omp declare simd
11780 in C, there we don't know the argument types at all. */
11781 if (!node
->definition
11782 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
11787 /* Start with parsing the "omp declare simd" attribute(s). */
11788 bool inbranch_clause_specified
;
11789 struct cgraph_simd_clone
*clone_info
11790 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
11791 &inbranch_clause_specified
);
11792 if (clone_info
== NULL
)
11795 int orig_simdlen
= clone_info
->simdlen
;
11796 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
11797 /* The target can return 0 (no simd clones should be created),
11798 1 (just one ISA of simd clones should be created) or higher
11799 count of ISA variants. In that case, clone_info is initialized
11800 for the first ISA variant. */
11802 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
11807 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11808 also create one inbranch and one !inbranch clone of it. */
11809 for (int i
= 0; i
< count
* 2; i
++)
11811 struct cgraph_simd_clone
*clone
= clone_info
;
11812 if (inbranch_clause_specified
&& (i
& 1) != 0)
11817 clone
= simd_clone_struct_alloc (clone_info
->nargs
11819 simd_clone_struct_copy (clone
, clone_info
);
11820 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11821 and simd_clone_adjust_argument_types did to the first
11823 clone
->nargs
-= clone_info
->inbranch
;
11824 clone
->simdlen
= orig_simdlen
;
11825 /* And call the target hook again to get the right ISA. */
11826 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
11830 clone
->inbranch
= 1;
11833 /* simd_clone_mangle might fail if such a clone has been created
11835 tree id
= simd_clone_mangle (node
, clone
);
11836 if (id
== NULL_TREE
)
11839 /* Only when we are sure we want to create the clone actually
11840 clone the function (or definitions) or create another
11841 extern FUNCTION_DECL (for prototypes without definitions). */
11842 struct cgraph_node
*n
= simd_clone_create (node
);
11846 n
->simdclone
= clone
;
11847 clone
->origin
= node
;
11848 clone
->next_clone
= NULL
;
11849 if (node
->simd_clones
== NULL
)
11851 clone
->prev_clone
= n
;
11852 node
->simd_clones
= n
;
11856 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
11857 clone
->prev_clone
->simdclone
->next_clone
= n
;
11858 node
->simd_clones
->simdclone
->prev_clone
= n
;
11860 change_decl_assembler_name (n
->decl
, id
);
11861 /* And finally adjust the return type, parameters and for
11862 definitions also function body. */
11863 if (node
->definition
)
11864 simd_clone_adjust (n
);
11867 simd_clone_adjust_return_type (n
);
11868 simd_clone_adjust_argument_types (n
);
11872 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
11875 /* Entry point for IPA simd clone creation pass. */
11877 static unsigned int
11878 ipa_omp_simd_clone (void)
11880 struct cgraph_node
*node
;
11881 FOR_EACH_FUNCTION (node
)
11882 expand_simd_clones (node
);
11888 const pass_data pass_data_omp_simd_clone
=
11890 SIMPLE_IPA_PASS
, /* type */
11891 "simdclone", /* name */
11892 OPTGROUP_NONE
, /* optinfo_flags */
11893 true, /* has_execute */
11894 TV_NONE
, /* tv_id */
11895 ( PROP_ssa
| PROP_cfg
), /* properties_required */
11896 0, /* properties_provided */
11897 0, /* properties_destroyed */
11898 0, /* todo_flags_start */
11899 0, /* todo_flags_finish */
11902 class pass_omp_simd_clone
: public simple_ipa_opt_pass
11905 pass_omp_simd_clone(gcc::context
*ctxt
)
11906 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
11909 /* opt_pass methods: */
11910 virtual bool gate (function
*);
11911 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
11915 pass_omp_simd_clone::gate (function
*)
11917 return ((flag_openmp
|| flag_openmp_simd
11919 || (in_lto_p
&& !flag_wpa
))
11920 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
11923 } // anon namespace
11925 simple_ipa_opt_pass
*
11926 make_pass_omp_simd_clone (gcc::context
*ctxt
)
11928 return new pass_omp_simd_clone (ctxt
);
11931 #include "gt-omp-low.h"