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;
1683 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1684 decl
= OMP_CLAUSE_DECL (c
);
1686 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1687 (splay_tree_key
) decl
));
1689 = build_decl (OMP_CLAUSE_LOCATION (c
),
1690 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1691 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1692 insert_field_into_struct (ctx
->record_type
, field
);
1693 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1694 (splay_tree_value
) field
);
1699 case OMP_CLAUSE_NOWAIT
:
1700 case OMP_CLAUSE_ORDERED
:
1701 case OMP_CLAUSE_COLLAPSE
:
1702 case OMP_CLAUSE_UNTIED
:
1703 case OMP_CLAUSE_MERGEABLE
:
1704 case OMP_CLAUSE_PROC_BIND
:
1705 case OMP_CLAUSE_SAFELEN
:
1708 case OMP_CLAUSE_ALIGNED
:
1709 decl
= OMP_CLAUSE_DECL (c
);
1710 if (is_global_var (decl
)
1711 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1712 install_var_local (decl
, ctx
);
1720 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1722 switch (OMP_CLAUSE_CODE (c
))
1724 case OMP_CLAUSE_LASTPRIVATE
:
1725 /* Let the corresponding firstprivate clause create
1727 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1728 scan_array_reductions
= true;
1729 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1733 case OMP_CLAUSE_PRIVATE
:
1734 case OMP_CLAUSE_FIRSTPRIVATE
:
1735 case OMP_CLAUSE_REDUCTION
:
1736 case OMP_CLAUSE_LINEAR
:
1737 decl
= OMP_CLAUSE_DECL (c
);
1738 if (is_variable_sized (decl
))
1739 install_var_local (decl
, ctx
);
1740 fixup_remapped_decl (decl
, ctx
,
1741 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1742 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1743 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1744 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1745 scan_array_reductions
= true;
1746 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1747 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1748 scan_array_reductions
= true;
1751 case OMP_CLAUSE_SHARED
:
1752 /* Ignore shared directives in teams construct. */
1753 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1755 decl
= OMP_CLAUSE_DECL (c
);
1756 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1757 fixup_remapped_decl (decl
, ctx
, false);
1760 case OMP_CLAUSE_MAP
:
1761 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
)
1763 decl
= OMP_CLAUSE_DECL (c
);
1765 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1766 && lookup_attribute ("omp declare target",
1767 DECL_ATTRIBUTES (decl
)))
1771 if (OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1772 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1773 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1775 tree new_decl
= lookup_decl (decl
, ctx
);
1776 TREE_TYPE (new_decl
)
1777 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1779 else if (DECL_SIZE (decl
)
1780 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1782 tree decl2
= DECL_VALUE_EXPR (decl
);
1783 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1784 decl2
= TREE_OPERAND (decl2
, 0);
1785 gcc_assert (DECL_P (decl2
));
1786 fixup_remapped_decl (decl2
, ctx
, false);
1787 fixup_remapped_decl (decl
, ctx
, true);
1790 fixup_remapped_decl (decl
, ctx
, false);
1794 case OMP_CLAUSE_COPYPRIVATE
:
1795 case OMP_CLAUSE_COPYIN
:
1796 case OMP_CLAUSE_DEFAULT
:
1798 case OMP_CLAUSE_NUM_THREADS
:
1799 case OMP_CLAUSE_NUM_TEAMS
:
1800 case OMP_CLAUSE_THREAD_LIMIT
:
1801 case OMP_CLAUSE_DEVICE
:
1802 case OMP_CLAUSE_SCHEDULE
:
1803 case OMP_CLAUSE_DIST_SCHEDULE
:
1804 case OMP_CLAUSE_NOWAIT
:
1805 case OMP_CLAUSE_ORDERED
:
1806 case OMP_CLAUSE_COLLAPSE
:
1807 case OMP_CLAUSE_UNTIED
:
1808 case OMP_CLAUSE_FINAL
:
1809 case OMP_CLAUSE_MERGEABLE
:
1810 case OMP_CLAUSE_PROC_BIND
:
1811 case OMP_CLAUSE_SAFELEN
:
1812 case OMP_CLAUSE_ALIGNED
:
1813 case OMP_CLAUSE_DEPEND
:
1814 case OMP_CLAUSE__LOOPTEMP_
:
1816 case OMP_CLAUSE_FROM
:
1824 if (scan_array_reductions
)
1825 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1826 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1827 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1829 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
1830 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
1832 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
1833 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1834 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
1835 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1836 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1837 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
1840 /* Create a new name for omp child function. Returns an identifier. */
1843 create_omp_child_function_name (bool task_copy
)
1845 return (clone_function_name (current_function_decl
,
1846 task_copy
? "_omp_cpyfn" : "_omp_fn"));
1849 /* Build a decl for the omp child function. It'll not contain a body
1850 yet, just the bare decl. */
1853 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
1855 tree decl
, type
, name
, t
;
1857 name
= create_omp_child_function_name (task_copy
);
1859 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1860 ptr_type_node
, NULL_TREE
);
1862 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
1864 decl
= build_decl (gimple_location (ctx
->stmt
),
1865 FUNCTION_DECL
, name
, type
);
1868 ctx
->cb
.dst_fn
= decl
;
1870 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
1872 TREE_STATIC (decl
) = 1;
1873 TREE_USED (decl
) = 1;
1874 DECL_ARTIFICIAL (decl
) = 1;
1875 DECL_IGNORED_P (decl
) = 0;
1876 TREE_PUBLIC (decl
) = 0;
1877 DECL_UNINLINABLE (decl
) = 1;
1878 DECL_EXTERNAL (decl
) = 0;
1879 DECL_CONTEXT (decl
) = NULL_TREE
;
1880 DECL_INITIAL (decl
) = make_node (BLOCK
);
1881 bool target_p
= false;
1882 if (lookup_attribute ("omp declare target",
1883 DECL_ATTRIBUTES (current_function_decl
)))
1888 for (octx
= ctx
; octx
; octx
= octx
->outer
)
1889 if (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
1890 && gimple_omp_target_kind (octx
->stmt
)
1891 == GF_OMP_TARGET_KIND_REGION
)
1898 DECL_ATTRIBUTES (decl
)
1899 = tree_cons (get_identifier ("omp declare target"),
1900 NULL_TREE
, DECL_ATTRIBUTES (decl
));
1902 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1903 RESULT_DECL
, NULL_TREE
, void_type_node
);
1904 DECL_ARTIFICIAL (t
) = 1;
1905 DECL_IGNORED_P (t
) = 1;
1906 DECL_CONTEXT (t
) = decl
;
1907 DECL_RESULT (decl
) = t
;
1909 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1910 PARM_DECL
, get_identifier (".omp_data_i"), ptr_type_node
);
1911 DECL_ARTIFICIAL (t
) = 1;
1912 DECL_NAMELESS (t
) = 1;
1913 DECL_ARG_TYPE (t
) = ptr_type_node
;
1914 DECL_CONTEXT (t
) = current_function_decl
;
1916 DECL_ARGUMENTS (decl
) = t
;
1918 ctx
->receiver_decl
= t
;
1921 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1922 PARM_DECL
, get_identifier (".omp_data_o"),
1924 DECL_ARTIFICIAL (t
) = 1;
1925 DECL_NAMELESS (t
) = 1;
1926 DECL_ARG_TYPE (t
) = ptr_type_node
;
1927 DECL_CONTEXT (t
) = current_function_decl
;
1929 TREE_ADDRESSABLE (t
) = 1;
1930 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1931 DECL_ARGUMENTS (decl
) = t
;
1934 /* Allocate memory for the function structure. The call to
1935 allocate_struct_function clobbers CFUN, so we need to restore
1937 push_struct_function (decl
);
1938 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
1942 /* Callback for walk_gimple_seq. Check if combined parallel
1943 contains gimple_omp_for_combined_into_p OMP_FOR. */
1946 find_combined_for (gimple_stmt_iterator
*gsi_p
,
1947 bool *handled_ops_p
,
1948 struct walk_stmt_info
*wi
)
1950 gimple stmt
= gsi_stmt (*gsi_p
);
1952 *handled_ops_p
= true;
1953 switch (gimple_code (stmt
))
1957 case GIMPLE_OMP_FOR
:
1958 if (gimple_omp_for_combined_into_p (stmt
)
1959 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
1962 return integer_zero_node
;
1971 /* Scan an OpenMP parallel directive. */
1974 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
1978 gimple stmt
= gsi_stmt (*gsi
);
1980 /* Ignore parallel directives with empty bodies, unless there
1981 are copyin clauses. */
1983 && empty_body_p (gimple_omp_body (stmt
))
1984 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
1985 OMP_CLAUSE_COPYIN
) == NULL
)
1987 gsi_replace (gsi
, gimple_build_nop (), false);
1991 if (gimple_omp_parallel_combined_p (stmt
))
1994 struct walk_stmt_info wi
;
1996 memset (&wi
, 0, sizeof (wi
));
1998 walk_gimple_seq (gimple_omp_body (stmt
),
1999 find_combined_for
, NULL
, &wi
);
2000 for_stmt
= (gimple
) wi
.info
;
2003 struct omp_for_data fd
;
2004 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2005 /* We need two temporaries with fd.loop.v type (istart/iend)
2006 and then (fd.collapse - 1) temporaries with the same
2007 type for count2 ... countN-1 vars if not constant. */
2008 size_t count
= 2, i
;
2009 tree type
= fd
.iter_type
;
2011 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2012 count
+= fd
.collapse
- 1;
2013 for (i
= 0; i
< count
; i
++)
2015 tree temp
= create_tmp_var (type
, NULL
);
2016 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2017 OMP_CLAUSE__LOOPTEMP_
);
2018 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2019 OMP_CLAUSE_DECL (c
) = temp
;
2020 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2021 gimple_omp_parallel_set_clauses (stmt
, c
);
2026 ctx
= new_omp_context (stmt
, outer_ctx
);
2027 if (taskreg_nesting_level
> 1)
2028 ctx
->is_nested
= true;
2029 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2030 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2031 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2032 name
= create_tmp_var_name (".omp_data_s");
2033 name
= build_decl (gimple_location (stmt
),
2034 TYPE_DECL
, name
, ctx
->record_type
);
2035 DECL_ARTIFICIAL (name
) = 1;
2036 DECL_NAMELESS (name
) = 1;
2037 TYPE_NAME (ctx
->record_type
) = name
;
2038 create_omp_child_function (ctx
, false);
2039 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2041 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2042 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2044 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2045 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2048 layout_type (ctx
->record_type
);
2049 fixup_child_record_type (ctx
);
2053 /* Scan an OpenMP task directive. */
2056 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2060 gimple stmt
= gsi_stmt (*gsi
);
2061 location_t loc
= gimple_location (stmt
);
2063 /* Ignore task directives with empty bodies. */
2065 && empty_body_p (gimple_omp_body (stmt
)))
2067 gsi_replace (gsi
, gimple_build_nop (), false);
2071 ctx
= new_omp_context (stmt
, outer_ctx
);
2072 if (taskreg_nesting_level
> 1)
2073 ctx
->is_nested
= true;
2074 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2075 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2076 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2077 name
= create_tmp_var_name (".omp_data_s");
2078 name
= build_decl (gimple_location (stmt
),
2079 TYPE_DECL
, name
, ctx
->record_type
);
2080 DECL_ARTIFICIAL (name
) = 1;
2081 DECL_NAMELESS (name
) = 1;
2082 TYPE_NAME (ctx
->record_type
) = name
;
2083 create_omp_child_function (ctx
, false);
2084 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2086 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2088 if (ctx
->srecord_type
)
2090 name
= create_tmp_var_name (".omp_data_a");
2091 name
= build_decl (gimple_location (stmt
),
2092 TYPE_DECL
, name
, ctx
->srecord_type
);
2093 DECL_ARTIFICIAL (name
) = 1;
2094 DECL_NAMELESS (name
) = 1;
2095 TYPE_NAME (ctx
->srecord_type
) = name
;
2096 create_omp_child_function (ctx
, true);
2099 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2101 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2103 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2104 t
= build_int_cst (long_integer_type_node
, 0);
2105 gimple_omp_task_set_arg_size (stmt
, t
);
2106 t
= build_int_cst (long_integer_type_node
, 1);
2107 gimple_omp_task_set_arg_align (stmt
, t
);
2111 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2112 /* Move VLA fields to the end. */
2113 p
= &TYPE_FIELDS (ctx
->record_type
);
2115 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2116 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2119 *p
= TREE_CHAIN (*p
);
2120 TREE_CHAIN (*q
) = NULL_TREE
;
2121 q
= &TREE_CHAIN (*q
);
2124 p
= &DECL_CHAIN (*p
);
2126 layout_type (ctx
->record_type
);
2127 fixup_child_record_type (ctx
);
2128 if (ctx
->srecord_type
)
2129 layout_type (ctx
->srecord_type
);
2130 t
= fold_convert_loc (loc
, long_integer_type_node
,
2131 TYPE_SIZE_UNIT (ctx
->record_type
));
2132 gimple_omp_task_set_arg_size (stmt
, t
);
2133 t
= build_int_cst (long_integer_type_node
,
2134 TYPE_ALIGN_UNIT (ctx
->record_type
));
2135 gimple_omp_task_set_arg_align (stmt
, t
);
2140 /* Scan an OpenMP loop directive. */
2143 scan_omp_for (gimple stmt
, omp_context
*outer_ctx
)
2148 ctx
= new_omp_context (stmt
, outer_ctx
);
2150 scan_sharing_clauses (gimple_omp_for_clauses (stmt
), ctx
);
2152 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2153 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2155 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2156 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2157 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2158 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2160 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2163 /* Scan an OpenMP sections directive. */
2166 scan_omp_sections (gimple stmt
, omp_context
*outer_ctx
)
2170 ctx
= new_omp_context (stmt
, outer_ctx
);
2171 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2172 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2175 /* Scan an OpenMP single directive. */
2178 scan_omp_single (gimple stmt
, omp_context
*outer_ctx
)
2183 ctx
= new_omp_context (stmt
, outer_ctx
);
2184 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2185 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2186 name
= create_tmp_var_name (".omp_copy_s");
2187 name
= build_decl (gimple_location (stmt
),
2188 TYPE_DECL
, name
, ctx
->record_type
);
2189 TYPE_NAME (ctx
->record_type
) = name
;
2191 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2192 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2194 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2195 ctx
->record_type
= NULL
;
2197 layout_type (ctx
->record_type
);
2200 /* Scan an OpenMP target{, data, update} directive. */
2203 scan_omp_target (gimple stmt
, omp_context
*outer_ctx
)
2207 int kind
= gimple_omp_target_kind (stmt
);
2209 ctx
= new_omp_context (stmt
, outer_ctx
);
2210 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2211 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2212 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2213 name
= create_tmp_var_name (".omp_data_t");
2214 name
= build_decl (gimple_location (stmt
),
2215 TYPE_DECL
, name
, ctx
->record_type
);
2216 DECL_ARTIFICIAL (name
) = 1;
2217 DECL_NAMELESS (name
) = 1;
2218 TYPE_NAME (ctx
->record_type
) = name
;
2219 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2221 create_omp_child_function (ctx
, false);
2222 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2225 scan_sharing_clauses (gimple_omp_target_clauses (stmt
), ctx
);
2226 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2228 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2229 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2232 TYPE_FIELDS (ctx
->record_type
)
2233 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2234 #ifdef ENABLE_CHECKING
2236 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2237 for (field
= TYPE_FIELDS (ctx
->record_type
);
2239 field
= DECL_CHAIN (field
))
2240 gcc_assert (DECL_ALIGN (field
) == align
);
2242 layout_type (ctx
->record_type
);
2243 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2244 fixup_child_record_type (ctx
);
2248 /* Scan an OpenMP teams directive. */
2251 scan_omp_teams (gimple stmt
, omp_context
*outer_ctx
)
2253 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2254 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2255 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2258 /* Check OpenMP nesting restrictions. */
2260 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2264 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2265 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2267 error_at (gimple_location (stmt
),
2268 "OpenMP constructs may not be nested inside simd region");
2271 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2273 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2274 || (gimple_omp_for_kind (stmt
)
2275 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2276 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2278 error_at (gimple_location (stmt
),
2279 "only distribute or parallel constructs are allowed to "
2280 "be closely nested inside teams construct");
2285 switch (gimple_code (stmt
))
2287 case GIMPLE_OMP_FOR
:
2288 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2290 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2292 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2294 error_at (gimple_location (stmt
),
2295 "distribute construct must be closely nested inside "
2303 if (is_gimple_call (stmt
)
2304 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2305 == BUILT_IN_GOMP_CANCEL
2306 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2307 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2309 const char *bad
= NULL
;
2310 const char *kind
= NULL
;
2313 error_at (gimple_location (stmt
), "orphaned %qs construct",
2314 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2315 == BUILT_IN_GOMP_CANCEL
2316 ? "#pragma omp cancel"
2317 : "#pragma omp cancellation point");
2320 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2321 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2325 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2326 bad
= "#pragma omp parallel";
2327 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2328 == BUILT_IN_GOMP_CANCEL
2329 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2330 ctx
->cancellable
= true;
2334 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2335 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2336 bad
= "#pragma omp for";
2337 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2338 == BUILT_IN_GOMP_CANCEL
2339 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2341 ctx
->cancellable
= true;
2342 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2344 warning_at (gimple_location (stmt
), 0,
2345 "%<#pragma omp cancel for%> inside "
2346 "%<nowait%> for construct");
2347 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2348 OMP_CLAUSE_ORDERED
))
2349 warning_at (gimple_location (stmt
), 0,
2350 "%<#pragma omp cancel for%> inside "
2351 "%<ordered%> for construct");
2356 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2357 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2358 bad
= "#pragma omp sections";
2359 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2360 == BUILT_IN_GOMP_CANCEL
2361 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2363 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2365 ctx
->cancellable
= true;
2366 if (find_omp_clause (gimple_omp_sections_clauses
2369 warning_at (gimple_location (stmt
), 0,
2370 "%<#pragma omp cancel sections%> inside "
2371 "%<nowait%> sections construct");
2375 gcc_assert (ctx
->outer
2376 && gimple_code (ctx
->outer
->stmt
)
2377 == GIMPLE_OMP_SECTIONS
);
2378 ctx
->outer
->cancellable
= true;
2379 if (find_omp_clause (gimple_omp_sections_clauses
2382 warning_at (gimple_location (stmt
), 0,
2383 "%<#pragma omp cancel sections%> inside "
2384 "%<nowait%> sections construct");
2390 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2391 bad
= "#pragma omp task";
2393 ctx
->cancellable
= true;
2397 error_at (gimple_location (stmt
), "invalid arguments");
2402 error_at (gimple_location (stmt
),
2403 "%<%s %s%> construct not closely nested inside of %qs",
2404 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2405 == BUILT_IN_GOMP_CANCEL
2406 ? "#pragma omp cancel"
2407 : "#pragma omp cancellation point", kind
, bad
);
2412 case GIMPLE_OMP_SECTIONS
:
2413 case GIMPLE_OMP_SINGLE
:
2414 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2415 switch (gimple_code (ctx
->stmt
))
2417 case GIMPLE_OMP_FOR
:
2418 case GIMPLE_OMP_SECTIONS
:
2419 case GIMPLE_OMP_SINGLE
:
2420 case GIMPLE_OMP_ORDERED
:
2421 case GIMPLE_OMP_MASTER
:
2422 case GIMPLE_OMP_TASK
:
2423 case GIMPLE_OMP_CRITICAL
:
2424 if (is_gimple_call (stmt
))
2426 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2427 != BUILT_IN_GOMP_BARRIER
)
2429 error_at (gimple_location (stmt
),
2430 "barrier region may not be closely nested inside "
2431 "of work-sharing, critical, ordered, master or "
2432 "explicit task region");
2435 error_at (gimple_location (stmt
),
2436 "work-sharing region may not be closely nested inside "
2437 "of work-sharing, critical, ordered, master or explicit "
2440 case GIMPLE_OMP_PARALLEL
:
2446 case GIMPLE_OMP_MASTER
:
2447 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2448 switch (gimple_code (ctx
->stmt
))
2450 case GIMPLE_OMP_FOR
:
2451 case GIMPLE_OMP_SECTIONS
:
2452 case GIMPLE_OMP_SINGLE
:
2453 case GIMPLE_OMP_TASK
:
2454 error_at (gimple_location (stmt
),
2455 "master region may not be closely nested inside "
2456 "of work-sharing or explicit task region");
2458 case GIMPLE_OMP_PARALLEL
:
2464 case GIMPLE_OMP_ORDERED
:
2465 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2466 switch (gimple_code (ctx
->stmt
))
2468 case GIMPLE_OMP_CRITICAL
:
2469 case GIMPLE_OMP_TASK
:
2470 error_at (gimple_location (stmt
),
2471 "ordered region may not be closely nested inside "
2472 "of critical or explicit task region");
2474 case GIMPLE_OMP_FOR
:
2475 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2476 OMP_CLAUSE_ORDERED
) == NULL
)
2478 error_at (gimple_location (stmt
),
2479 "ordered region must be closely nested inside "
2480 "a loop region with an ordered clause");
2484 case GIMPLE_OMP_PARALLEL
:
2485 error_at (gimple_location (stmt
),
2486 "ordered region must be closely nested inside "
2487 "a loop region with an ordered clause");
2493 case GIMPLE_OMP_CRITICAL
:
2494 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2495 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_CRITICAL
2496 && (gimple_omp_critical_name (stmt
)
2497 == gimple_omp_critical_name (ctx
->stmt
)))
2499 error_at (gimple_location (stmt
),
2500 "critical region may not be nested inside a critical "
2501 "region with the same name");
2505 case GIMPLE_OMP_TEAMS
:
2507 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2508 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2510 error_at (gimple_location (stmt
),
2511 "teams construct not closely nested inside of target "
2516 case GIMPLE_OMP_TARGET
:
2517 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2518 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
2519 && gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_REGION
)
2522 switch (gimple_omp_target_kind (stmt
))
2524 case GF_OMP_TARGET_KIND_REGION
: name
= "target"; break;
2525 case GF_OMP_TARGET_KIND_DATA
: name
= "target data"; break;
2526 case GF_OMP_TARGET_KIND_UPDATE
: name
= "target update"; break;
2527 default: gcc_unreachable ();
2529 warning_at (gimple_location (stmt
), 0,
2530 "%s construct inside of target region", name
);
2540 /* Helper function scan_omp.
2542 Callback for walk_tree or operators in walk_gimple_stmt used to
2543 scan for OpenMP directives in TP. */
2546 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
2548 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
2549 omp_context
*ctx
= (omp_context
*) wi
->info
;
2552 switch (TREE_CODE (t
))
2559 *tp
= remap_decl (t
, &ctx
->cb
);
2563 if (ctx
&& TYPE_P (t
))
2564 *tp
= remap_type (t
, &ctx
->cb
);
2565 else if (!DECL_P (t
))
2570 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
2571 if (tem
!= TREE_TYPE (t
))
2573 if (TREE_CODE (t
) == INTEGER_CST
)
2574 *tp
= wide_int_to_tree (tem
, t
);
2576 TREE_TYPE (t
) = tem
;
2586 /* Return true if FNDECL is a setjmp or a longjmp. */
2589 setjmp_or_longjmp_p (const_tree fndecl
)
2591 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
2592 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
2593 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
2596 tree declname
= DECL_NAME (fndecl
);
2599 const char *name
= IDENTIFIER_POINTER (declname
);
2600 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
2604 /* Helper function for scan_omp.
2606 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2607 the current statement in GSI. */
2610 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
2611 struct walk_stmt_info
*wi
)
2613 gimple stmt
= gsi_stmt (*gsi
);
2614 omp_context
*ctx
= (omp_context
*) wi
->info
;
2616 if (gimple_has_location (stmt
))
2617 input_location
= gimple_location (stmt
);
2619 /* Check the OpenMP nesting restrictions. */
2620 bool remove
= false;
2621 if (is_gimple_omp (stmt
))
2622 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2623 else if (is_gimple_call (stmt
))
2625 tree fndecl
= gimple_call_fndecl (stmt
);
2628 if (setjmp_or_longjmp_p (fndecl
)
2630 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2631 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2634 error_at (gimple_location (stmt
),
2635 "setjmp/longjmp inside simd construct");
2637 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
2638 switch (DECL_FUNCTION_CODE (fndecl
))
2640 case BUILT_IN_GOMP_BARRIER
:
2641 case BUILT_IN_GOMP_CANCEL
:
2642 case BUILT_IN_GOMP_CANCELLATION_POINT
:
2643 case BUILT_IN_GOMP_TASKYIELD
:
2644 case BUILT_IN_GOMP_TASKWAIT
:
2645 case BUILT_IN_GOMP_TASKGROUP_START
:
2646 case BUILT_IN_GOMP_TASKGROUP_END
:
2647 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2656 stmt
= gimple_build_nop ();
2657 gsi_replace (gsi
, stmt
, false);
2660 *handled_ops_p
= true;
2662 switch (gimple_code (stmt
))
2664 case GIMPLE_OMP_PARALLEL
:
2665 taskreg_nesting_level
++;
2666 scan_omp_parallel (gsi
, ctx
);
2667 taskreg_nesting_level
--;
2670 case GIMPLE_OMP_TASK
:
2671 taskreg_nesting_level
++;
2672 scan_omp_task (gsi
, ctx
);
2673 taskreg_nesting_level
--;
2676 case GIMPLE_OMP_FOR
:
2677 scan_omp_for (stmt
, ctx
);
2680 case GIMPLE_OMP_SECTIONS
:
2681 scan_omp_sections (stmt
, ctx
);
2684 case GIMPLE_OMP_SINGLE
:
2685 scan_omp_single (stmt
, ctx
);
2688 case GIMPLE_OMP_SECTION
:
2689 case GIMPLE_OMP_MASTER
:
2690 case GIMPLE_OMP_TASKGROUP
:
2691 case GIMPLE_OMP_ORDERED
:
2692 case GIMPLE_OMP_CRITICAL
:
2693 ctx
= new_omp_context (stmt
, ctx
);
2694 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2697 case GIMPLE_OMP_TARGET
:
2698 scan_omp_target (stmt
, ctx
);
2701 case GIMPLE_OMP_TEAMS
:
2702 scan_omp_teams (stmt
, ctx
);
2709 *handled_ops_p
= false;
2711 for (var
= gimple_bind_vars (stmt
); var
; var
= DECL_CHAIN (var
))
2712 insert_decl_map (&ctx
->cb
, var
, var
);
2716 *handled_ops_p
= false;
2724 /* Scan all the statements starting at the current statement. CTX
2725 contains context information about the OpenMP directives and
2726 clauses found during the scan. */
2729 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
2731 location_t saved_location
;
2732 struct walk_stmt_info wi
;
2734 memset (&wi
, 0, sizeof (wi
));
2736 wi
.want_locations
= true;
2738 saved_location
= input_location
;
2739 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
2740 input_location
= saved_location
;
2743 /* Re-gimplification and code generation routines. */
2745 /* Build a call to GOMP_barrier. */
2748 build_omp_barrier (tree lhs
)
2750 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
2751 : BUILT_IN_GOMP_BARRIER
);
2752 gimple g
= gimple_build_call (fndecl
, 0);
2754 gimple_call_set_lhs (g
, lhs
);
2758 /* If a context was created for STMT when it was scanned, return it. */
2760 static omp_context
*
2761 maybe_lookup_ctx (gimple stmt
)
2764 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
2765 return n
? (omp_context
*) n
->value
: NULL
;
2769 /* Find the mapping for DECL in CTX or the immediately enclosing
2770 context that has a mapping for DECL.
2772 If CTX is a nested parallel directive, we may have to use the decl
2773 mappings created in CTX's parent context. Suppose that we have the
2774 following parallel nesting (variable UIDs showed for clarity):
2777 #omp parallel shared(iD.1562) -> outer parallel
2778 iD.1562 = iD.1562 + 1;
2780 #omp parallel shared (iD.1562) -> inner parallel
2781 iD.1562 = iD.1562 - 1;
2783 Each parallel structure will create a distinct .omp_data_s structure
2784 for copying iD.1562 in/out of the directive:
2786 outer parallel .omp_data_s.1.i -> iD.1562
2787 inner parallel .omp_data_s.2.i -> iD.1562
2789 A shared variable mapping will produce a copy-out operation before
2790 the parallel directive and a copy-in operation after it. So, in
2791 this case we would have:
2794 .omp_data_o.1.i = iD.1562;
2795 #omp parallel shared(iD.1562) -> outer parallel
2796 .omp_data_i.1 = &.omp_data_o.1
2797 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2799 .omp_data_o.2.i = iD.1562; -> **
2800 #omp parallel shared(iD.1562) -> inner parallel
2801 .omp_data_i.2 = &.omp_data_o.2
2802 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2805 ** This is a problem. The symbol iD.1562 cannot be referenced
2806 inside the body of the outer parallel region. But since we are
2807 emitting this copy operation while expanding the inner parallel
2808 directive, we need to access the CTX structure of the outer
2809 parallel directive to get the correct mapping:
2811 .omp_data_o.2.i = .omp_data_i.1->i
2813 Since there may be other workshare or parallel directives enclosing
2814 the parallel directive, it may be necessary to walk up the context
2815 parent chain. This is not a problem in general because nested
2816 parallelism happens only rarely. */
2819 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2824 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2825 t
= maybe_lookup_decl (decl
, up
);
2827 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
2829 return t
? t
: decl
;
2833 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2834 in outer contexts. */
2837 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2842 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2843 t
= maybe_lookup_decl (decl
, up
);
2845 return t
? t
: decl
;
2849 /* Construct the initialization value for reduction CLAUSE. */
2852 omp_reduction_init (tree clause
, tree type
)
2854 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
2855 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
2862 case TRUTH_ORIF_EXPR
:
2863 case TRUTH_XOR_EXPR
:
2865 return build_zero_cst (type
);
2868 case TRUTH_AND_EXPR
:
2869 case TRUTH_ANDIF_EXPR
:
2871 return fold_convert_loc (loc
, type
, integer_one_node
);
2874 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
2877 if (SCALAR_FLOAT_TYPE_P (type
))
2879 REAL_VALUE_TYPE max
, min
;
2880 if (HONOR_INFINITIES (TYPE_MODE (type
)))
2883 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
2886 real_maxval (&min
, 1, TYPE_MODE (type
));
2887 return build_real (type
, min
);
2891 gcc_assert (INTEGRAL_TYPE_P (type
));
2892 return TYPE_MIN_VALUE (type
);
2896 if (SCALAR_FLOAT_TYPE_P (type
))
2898 REAL_VALUE_TYPE max
;
2899 if (HONOR_INFINITIES (TYPE_MODE (type
)))
2902 real_maxval (&max
, 0, TYPE_MODE (type
));
2903 return build_real (type
, max
);
2907 gcc_assert (INTEGRAL_TYPE_P (type
));
2908 return TYPE_MAX_VALUE (type
);
2916 /* Return alignment to be assumed for var in CLAUSE, which should be
2917 OMP_CLAUSE_ALIGNED. */
2920 omp_clause_aligned_alignment (tree clause
)
2922 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
2923 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
2925 /* Otherwise return implementation defined alignment. */
2926 unsigned int al
= 1;
2927 enum machine_mode mode
, vmode
;
2928 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
2930 vs
= 1 << floor_log2 (vs
);
2931 static enum mode_class classes
[]
2932 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
2933 for (int i
= 0; i
< 4; i
+= 2)
2934 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
2936 mode
= GET_MODE_WIDER_MODE (mode
))
2938 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
2939 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
2942 && GET_MODE_SIZE (vmode
) < vs
2943 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
2944 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
2946 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
2947 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
2949 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
2950 / GET_MODE_SIZE (mode
));
2951 if (TYPE_MODE (type
) != vmode
)
2953 if (TYPE_ALIGN_UNIT (type
) > al
)
2954 al
= TYPE_ALIGN_UNIT (type
);
2956 return build_int_cst (integer_type_node
, al
);
2959 /* Return maximum possible vectorization factor for the target. */
2966 || !flag_tree_loop_optimize
2967 || (!flag_tree_loop_vectorize
2968 && (global_options_set
.x_flag_tree_loop_vectorize
2969 || global_options_set
.x_flag_tree_vectorize
)))
2972 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
2975 vs
= 1 << floor_log2 (vs
);
2978 enum machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
2979 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
2980 return GET_MODE_NUNITS (vqimode
);
2984 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2988 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
2989 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
2993 max_vf
= omp_max_vf ();
2996 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2997 OMP_CLAUSE_SAFELEN
);
2998 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3000 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3002 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3006 idx
= create_tmp_var (unsigned_type_node
, NULL
);
3007 lane
= create_tmp_var (unsigned_type_node
, NULL
);
3013 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3014 tree avar
= create_tmp_var_raw (atype
, NULL
);
3015 if (TREE_ADDRESSABLE (new_var
))
3016 TREE_ADDRESSABLE (avar
) = 1;
3017 DECL_ATTRIBUTES (avar
)
3018 = tree_cons (get_identifier ("omp simd array"), NULL
,
3019 DECL_ATTRIBUTES (avar
));
3020 gimple_add_tmp_var (avar
);
3021 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3022 NULL_TREE
, NULL_TREE
);
3023 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3024 NULL_TREE
, NULL_TREE
);
3025 if (DECL_P (new_var
))
3027 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3028 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3033 /* Helper function of lower_rec_input_clauses. For a reference
3034 in simd reduction, add an underlying variable it will reference. */
3037 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3039 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3040 if (TREE_CONSTANT (z
))
3042 const char *name
= NULL
;
3043 if (DECL_NAME (new_vard
))
3044 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3046 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3047 gimple_add_tmp_var (z
);
3048 TREE_ADDRESSABLE (z
) = 1;
3049 z
= build_fold_addr_expr_loc (loc
, z
);
3050 gimplify_assign (new_vard
, z
, ilist
);
3054 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3055 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3056 private variables. Initialization statements go in ILIST, while calls
3057 to destructors go in DLIST. */
3060 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3061 omp_context
*ctx
, struct omp_for_data
*fd
)
3063 tree c
, dtor
, copyin_seq
, x
, ptr
;
3064 bool copyin_by_ref
= false;
3065 bool lastprivate_firstprivate
= false;
3066 bool reduction_omp_orig_ref
= false;
3068 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3069 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3071 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3072 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3073 gimple_seq llist
[2] = { NULL
, NULL
};
3077 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3078 with data sharing clauses referencing variable sized vars. That
3079 is unnecessarily hard to support and very unlikely to result in
3080 vectorized code anyway. */
3082 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3083 switch (OMP_CLAUSE_CODE (c
))
3085 case OMP_CLAUSE_LINEAR
:
3086 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3089 case OMP_CLAUSE_REDUCTION
:
3090 case OMP_CLAUSE_PRIVATE
:
3091 case OMP_CLAUSE_FIRSTPRIVATE
:
3092 case OMP_CLAUSE_LASTPRIVATE
:
3093 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3100 /* Do all the fixed sized types in the first pass, and the variable sized
3101 types in the second pass. This makes sure that the scalar arguments to
3102 the variable sized types are processed before we use them in the
3103 variable sized operations. */
3104 for (pass
= 0; pass
< 2; ++pass
)
3106 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3108 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3111 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3115 case OMP_CLAUSE_PRIVATE
:
3116 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3119 case OMP_CLAUSE_SHARED
:
3120 /* Ignore shared directives in teams construct. */
3121 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3123 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3125 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3128 case OMP_CLAUSE_FIRSTPRIVATE
:
3129 case OMP_CLAUSE_COPYIN
:
3130 case OMP_CLAUSE_LINEAR
:
3132 case OMP_CLAUSE_REDUCTION
:
3133 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3134 reduction_omp_orig_ref
= true;
3136 case OMP_CLAUSE__LOOPTEMP_
:
3137 /* Handle _looptemp_ clauses only on parallel. */
3141 case OMP_CLAUSE_LASTPRIVATE
:
3142 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3144 lastprivate_firstprivate
= true;
3148 /* Even without corresponding firstprivate, if
3149 decl is Fortran allocatable, it needs outer var
3152 && lang_hooks
.decls
.omp_private_outer_ref
3153 (OMP_CLAUSE_DECL (c
)))
3154 lastprivate_firstprivate
= true;
3156 case OMP_CLAUSE_ALIGNED
:
3159 var
= OMP_CLAUSE_DECL (c
);
3160 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3161 && !is_global_var (var
))
3163 new_var
= maybe_lookup_decl (var
, ctx
);
3164 if (new_var
== NULL_TREE
)
3165 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3166 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3167 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3168 omp_clause_aligned_alignment (c
));
3169 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3170 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3171 gimplify_and_add (x
, ilist
);
3173 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3174 && is_global_var (var
))
3176 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3177 new_var
= lookup_decl (var
, ctx
);
3178 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3179 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3180 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3181 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3182 omp_clause_aligned_alignment (c
));
3183 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3184 x
= create_tmp_var (ptype
, NULL
);
3185 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3186 gimplify_and_add (t
, ilist
);
3187 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3188 SET_DECL_VALUE_EXPR (new_var
, t
);
3189 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3196 new_var
= var
= OMP_CLAUSE_DECL (c
);
3197 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3198 new_var
= lookup_decl (var
, ctx
);
3200 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3205 else if (is_variable_sized (var
))
3207 /* For variable sized types, we need to allocate the
3208 actual storage here. Call alloca and store the
3209 result in the pointer decl that we created elsewhere. */
3213 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3218 ptr
= DECL_VALUE_EXPR (new_var
);
3219 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3220 ptr
= TREE_OPERAND (ptr
, 0);
3221 gcc_assert (DECL_P (ptr
));
3222 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3224 /* void *tmp = __builtin_alloca */
3225 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3226 stmt
= gimple_build_call (atmp
, 1, x
);
3227 tmp
= create_tmp_var_raw (ptr_type_node
, NULL
);
3228 gimple_add_tmp_var (tmp
);
3229 gimple_call_set_lhs (stmt
, tmp
);
3231 gimple_seq_add_stmt (ilist
, stmt
);
3233 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3234 gimplify_assign (ptr
, x
, ilist
);
3237 else if (is_reference (var
))
3239 /* For references that are being privatized for Fortran,
3240 allocate new backing storage for the new pointer
3241 variable. This allows us to avoid changing all the
3242 code that expects a pointer to something that expects
3243 a direct variable. */
3247 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3248 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3250 x
= build_receiver_ref (var
, false, ctx
);
3251 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3253 else if (TREE_CONSTANT (x
))
3255 /* For reduction in SIMD loop, defer adding the
3256 initialization of the reference, because if we decide
3257 to use SIMD array for it, the initilization could cause
3259 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3263 const char *name
= NULL
;
3264 if (DECL_NAME (var
))
3265 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3267 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3269 gimple_add_tmp_var (x
);
3270 TREE_ADDRESSABLE (x
) = 1;
3271 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3276 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3277 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3282 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3283 gimplify_assign (new_var
, x
, ilist
);
3286 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3288 else if (c_kind
== OMP_CLAUSE_REDUCTION
3289 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3297 switch (OMP_CLAUSE_CODE (c
))
3299 case OMP_CLAUSE_SHARED
:
3300 /* Ignore shared directives in teams construct. */
3301 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3303 /* Shared global vars are just accessed directly. */
3304 if (is_global_var (new_var
))
3306 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3307 needs to be delayed until after fixup_child_record_type so
3308 that we get the correct type during the dereference. */
3309 by_ref
= use_pointer_for_field (var
, ctx
);
3310 x
= build_receiver_ref (var
, by_ref
, ctx
);
3311 SET_DECL_VALUE_EXPR (new_var
, x
);
3312 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3314 /* ??? If VAR is not passed by reference, and the variable
3315 hasn't been initialized yet, then we'll get a warning for
3316 the store into the omp_data_s structure. Ideally, we'd be
3317 able to notice this and not store anything at all, but
3318 we're generating code too early. Suppress the warning. */
3320 TREE_NO_WARNING (var
) = 1;
3323 case OMP_CLAUSE_LASTPRIVATE
:
3324 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3328 case OMP_CLAUSE_PRIVATE
:
3329 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3330 x
= build_outer_var_ref (var
, ctx
);
3331 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3333 if (is_task_ctx (ctx
))
3334 x
= build_receiver_ref (var
, false, ctx
);
3336 x
= build_outer_var_ref (var
, ctx
);
3342 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3345 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3346 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3347 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3348 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3349 idx
, lane
, ivar
, lvar
))
3352 x
= lang_hooks
.decls
.omp_clause_default_ctor
3353 (c
, unshare_expr (ivar
), x
);
3355 gimplify_and_add (x
, &llist
[0]);
3358 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3361 gimple_seq tseq
= NULL
;
3364 gimplify_stmt (&dtor
, &tseq
);
3365 gimple_seq_add_seq (&llist
[1], tseq
);
3372 gimplify_and_add (nx
, ilist
);
3376 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3379 gimple_seq tseq
= NULL
;
3382 gimplify_stmt (&dtor
, &tseq
);
3383 gimple_seq_add_seq (dlist
, tseq
);
3387 case OMP_CLAUSE_LINEAR
:
3388 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3389 goto do_firstprivate
;
3390 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3393 x
= build_outer_var_ref (var
, ctx
);
3396 case OMP_CLAUSE_FIRSTPRIVATE
:
3397 if (is_task_ctx (ctx
))
3399 if (is_reference (var
) || is_variable_sized (var
))
3401 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3403 || use_pointer_for_field (var
, NULL
))
3405 x
= build_receiver_ref (var
, false, ctx
);
3406 SET_DECL_VALUE_EXPR (new_var
, x
);
3407 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3412 x
= build_outer_var_ref (var
, ctx
);
3415 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3416 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3418 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3419 tree stept
= TREE_TYPE (t
);
3420 tree ct
= find_omp_clause (clauses
,
3421 OMP_CLAUSE__LOOPTEMP_
);
3423 tree l
= OMP_CLAUSE_DECL (ct
);
3424 tree n1
= fd
->loop
.n1
;
3425 tree step
= fd
->loop
.step
;
3426 tree itype
= TREE_TYPE (l
);
3427 if (POINTER_TYPE_P (itype
))
3428 itype
= signed_type_for (itype
);
3429 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3430 if (TYPE_UNSIGNED (itype
)
3431 && fd
->loop
.cond_code
== GT_EXPR
)
3432 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3433 fold_build1 (NEGATE_EXPR
, itype
, l
),
3434 fold_build1 (NEGATE_EXPR
,
3437 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3438 t
= fold_build2 (MULT_EXPR
, stept
,
3439 fold_convert (stept
, l
), t
);
3441 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3443 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3445 gimplify_and_add (x
, ilist
);
3449 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3450 x
= fold_build2 (POINTER_PLUS_EXPR
,
3451 TREE_TYPE (x
), x
, t
);
3453 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3456 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3457 || TREE_ADDRESSABLE (new_var
))
3458 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3459 idx
, lane
, ivar
, lvar
))
3461 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
3463 tree iv
= create_tmp_var (TREE_TYPE (new_var
), NULL
);
3464 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
3465 gimplify_and_add (x
, ilist
);
3466 gimple_stmt_iterator gsi
3467 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3469 = gimple_build_assign (unshare_expr (lvar
), iv
);
3470 gsi_insert_before_without_update (&gsi
, g
,
3472 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3473 enum tree_code code
= PLUS_EXPR
;
3474 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
3475 code
= POINTER_PLUS_EXPR
;
3476 g
= gimple_build_assign_with_ops (code
, iv
, iv
, t
);
3477 gsi_insert_before_without_update (&gsi
, g
,
3481 x
= lang_hooks
.decls
.omp_clause_copy_ctor
3482 (c
, unshare_expr (ivar
), x
);
3483 gimplify_and_add (x
, &llist
[0]);
3484 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3487 gimple_seq tseq
= NULL
;
3490 gimplify_stmt (&dtor
, &tseq
);
3491 gimple_seq_add_seq (&llist
[1], tseq
);
3496 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
3497 gimplify_and_add (x
, ilist
);
3500 case OMP_CLAUSE__LOOPTEMP_
:
3501 gcc_assert (is_parallel_ctx (ctx
));
3502 x
= build_outer_var_ref (var
, ctx
);
3503 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3504 gimplify_and_add (x
, ilist
);
3507 case OMP_CLAUSE_COPYIN
:
3508 by_ref
= use_pointer_for_field (var
, NULL
);
3509 x
= build_receiver_ref (var
, by_ref
, ctx
);
3510 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
3511 append_to_statement_list (x
, ©in_seq
);
3512 copyin_by_ref
|= by_ref
;
3515 case OMP_CLAUSE_REDUCTION
:
3516 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3518 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3520 x
= build_outer_var_ref (var
, ctx
);
3522 if (is_reference (var
)
3523 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
3525 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3526 SET_DECL_VALUE_EXPR (placeholder
, x
);
3527 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3528 tree new_vard
= new_var
;
3529 if (is_reference (var
))
3531 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3532 new_vard
= TREE_OPERAND (new_var
, 0);
3533 gcc_assert (DECL_P (new_vard
));
3536 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3537 idx
, lane
, ivar
, lvar
))
3539 if (new_vard
== new_var
)
3541 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
3542 SET_DECL_VALUE_EXPR (new_var
, ivar
);
3546 SET_DECL_VALUE_EXPR (new_vard
,
3547 build_fold_addr_expr (ivar
));
3548 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3550 x
= lang_hooks
.decls
.omp_clause_default_ctor
3551 (c
, unshare_expr (ivar
),
3552 build_outer_var_ref (var
, ctx
));
3554 gimplify_and_add (x
, &llist
[0]);
3555 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3557 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3558 lower_omp (&tseq
, ctx
);
3559 gimple_seq_add_seq (&llist
[0], tseq
);
3561 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3562 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3563 lower_omp (&tseq
, ctx
);
3564 gimple_seq_add_seq (&llist
[1], tseq
);
3565 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3566 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3567 if (new_vard
== new_var
)
3568 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3570 SET_DECL_VALUE_EXPR (new_vard
,
3571 build_fold_addr_expr (lvar
));
3572 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3577 gimplify_stmt (&dtor
, &tseq
);
3578 gimple_seq_add_seq (&llist
[1], tseq
);
3582 /* If this is a reference to constant size reduction var
3583 with placeholder, we haven't emitted the initializer
3584 for it because it is undesirable if SIMD arrays are used.
3585 But if they aren't used, we need to emit the deferred
3586 initialization now. */
3587 else if (is_reference (var
) && is_simd
)
3588 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3589 x
= lang_hooks
.decls
.omp_clause_default_ctor
3590 (c
, unshare_expr (new_var
),
3591 build_outer_var_ref (var
, ctx
));
3593 gimplify_and_add (x
, ilist
);
3594 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3596 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3597 lower_omp (&tseq
, ctx
);
3598 gimple_seq_add_seq (ilist
, tseq
);
3600 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3603 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3604 lower_omp (&tseq
, ctx
);
3605 gimple_seq_add_seq (dlist
, tseq
);
3606 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3608 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3613 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
3614 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
3615 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3617 /* reduction(-:var) sums up the partial results, so it
3618 acts identically to reduction(+:var). */
3619 if (code
== MINUS_EXPR
)
3622 tree new_vard
= new_var
;
3623 if (is_simd
&& is_reference (var
))
3625 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3626 new_vard
= TREE_OPERAND (new_var
, 0);
3627 gcc_assert (DECL_P (new_vard
));
3630 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3631 idx
, lane
, ivar
, lvar
))
3633 tree ref
= build_outer_var_ref (var
, ctx
);
3635 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
3637 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
3638 ref
= build_outer_var_ref (var
, ctx
);
3639 gimplify_assign (ref
, x
, &llist
[1]);
3641 if (new_vard
!= new_var
)
3643 SET_DECL_VALUE_EXPR (new_vard
,
3644 build_fold_addr_expr (lvar
));
3645 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3650 if (is_reference (var
) && is_simd
)
3651 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3652 gimplify_assign (new_var
, x
, ilist
);
3655 tree ref
= build_outer_var_ref (var
, ctx
);
3657 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3658 ref
= build_outer_var_ref (var
, ctx
);
3659 gimplify_assign (ref
, x
, dlist
);
3673 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
3674 /* Don't want uninit warnings on simduid, it is always uninitialized,
3675 but we use it not for the value, but for the DECL_UID only. */
3676 TREE_NO_WARNING (uid
) = 1;
3678 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
3679 gimple_call_set_lhs (g
, lane
);
3680 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3681 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
3682 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
3683 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
3684 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3685 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3686 g
= gimple_build_assign_with_ops (INTEGER_CST
, lane
,
3687 build_int_cst (unsigned_type_node
, 0),
3689 gimple_seq_add_stmt (ilist
, g
);
3690 for (int i
= 0; i
< 2; i
++)
3693 tree vf
= create_tmp_var (unsigned_type_node
, NULL
);
3694 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
3695 gimple_call_set_lhs (g
, vf
);
3696 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
3697 gimple_seq_add_stmt (seq
, g
);
3698 tree t
= build_int_cst (unsigned_type_node
, 0);
3699 g
= gimple_build_assign_with_ops (INTEGER_CST
, idx
, t
, NULL_TREE
);
3700 gimple_seq_add_stmt (seq
, g
);
3701 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
3702 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
3703 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
3704 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
3705 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
3706 gimple_seq_add_seq (seq
, llist
[i
]);
3707 t
= build_int_cst (unsigned_type_node
, 1);
3708 g
= gimple_build_assign_with_ops (PLUS_EXPR
, idx
, idx
, t
);
3709 gimple_seq_add_stmt (seq
, g
);
3710 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
3711 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
3712 gimple_seq_add_stmt (seq
, g
);
3713 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
3717 /* The copyin sequence is not to be executed by the main thread, since
3718 that would result in self-copies. Perhaps not visible to scalars,
3719 but it certainly is to C++ operator=. */
3722 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
3724 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
3725 build_int_cst (TREE_TYPE (x
), 0));
3726 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
3727 gimplify_and_add (x
, ilist
);
3730 /* If any copyin variable is passed by reference, we must ensure the
3731 master thread doesn't modify it before it is copied over in all
3732 threads. Similarly for variables in both firstprivate and
3733 lastprivate clauses we need to ensure the lastprivate copying
3734 happens after firstprivate copying in all threads. And similarly
3735 for UDRs if initializer expression refers to omp_orig. */
3736 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
3738 /* Don't add any barrier for #pragma omp simd or
3739 #pragma omp distribute. */
3740 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3741 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
3742 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
3745 /* If max_vf is non-zero, then we can use only a vectorization factor
3746 up to the max_vf we chose. So stick it into the safelen clause. */
3749 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3750 OMP_CLAUSE_SAFELEN
);
3752 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
3753 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3756 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
3757 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
3759 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3760 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3766 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3767 both parallel and workshare constructs. PREDICATE may be NULL if it's
3771 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
3774 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
3775 bool par_clauses
= false;
3776 tree simduid
= NULL
, lastlane
= NULL
;
3778 /* Early exit if there are no lastprivate or linear clauses. */
3779 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
3780 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
3781 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
3782 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
3784 if (clauses
== NULL
)
3786 /* If this was a workshare clause, see if it had been combined
3787 with its parallel. In that case, look for the clauses on the
3788 parallel statement itself. */
3789 if (is_parallel_ctx (ctx
))
3793 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
3796 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
3797 OMP_CLAUSE_LASTPRIVATE
);
3798 if (clauses
== NULL
)
3806 tree label_true
, arm1
, arm2
;
3808 label
= create_artificial_label (UNKNOWN_LOCATION
);
3809 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
3810 arm1
= TREE_OPERAND (predicate
, 0);
3811 arm2
= TREE_OPERAND (predicate
, 1);
3812 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3813 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3814 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
3816 gimple_seq_add_stmt (stmt_list
, stmt
);
3817 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
3820 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3821 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3823 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
3825 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
3828 for (c
= clauses
; c
;)
3831 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3833 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
3834 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3835 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
3837 var
= OMP_CLAUSE_DECL (c
);
3838 new_var
= lookup_decl (var
, ctx
);
3840 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
3842 tree val
= DECL_VALUE_EXPR (new_var
);
3843 if (TREE_CODE (val
) == ARRAY_REF
3844 && VAR_P (TREE_OPERAND (val
, 0))
3845 && lookup_attribute ("omp simd array",
3846 DECL_ATTRIBUTES (TREE_OPERAND (val
,
3849 if (lastlane
== NULL
)
3851 lastlane
= create_tmp_var (unsigned_type_node
, NULL
);
3853 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
3855 TREE_OPERAND (val
, 1));
3856 gimple_call_set_lhs (g
, lastlane
);
3857 gimple_seq_add_stmt (stmt_list
, g
);
3859 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
3860 TREE_OPERAND (val
, 0), lastlane
,
3861 NULL_TREE
, NULL_TREE
);
3865 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
3866 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
3868 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
3869 gimple_seq_add_seq (stmt_list
,
3870 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
3871 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
3873 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3874 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
3876 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
3877 gimple_seq_add_seq (stmt_list
,
3878 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
3879 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
3882 x
= build_outer_var_ref (var
, ctx
);
3883 if (is_reference (var
))
3884 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3885 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
3886 gimplify_and_add (x
, stmt_list
);
3888 c
= OMP_CLAUSE_CHAIN (c
);
3889 if (c
== NULL
&& !par_clauses
)
3891 /* If this was a workshare clause, see if it had been combined
3892 with its parallel. In that case, continue looking for the
3893 clauses also on the parallel statement itself. */
3894 if (is_parallel_ctx (ctx
))
3898 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
3901 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
3902 OMP_CLAUSE_LASTPRIVATE
);
3908 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
3912 /* Generate code to implement the REDUCTION clauses. */
3915 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
3917 gimple_seq sub_seq
= NULL
;
3922 /* SIMD reductions are handled in lower_rec_input_clauses. */
3923 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3924 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3927 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3928 update in that case, otherwise use a lock. */
3929 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
3930 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
3932 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3934 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3944 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3946 tree var
, ref
, new_var
;
3947 enum tree_code code
;
3948 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3950 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
3953 var
= OMP_CLAUSE_DECL (c
);
3954 new_var
= lookup_decl (var
, ctx
);
3955 if (is_reference (var
))
3956 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3957 ref
= build_outer_var_ref (var
, ctx
);
3958 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3960 /* reduction(-:var) sums up the partial results, so it acts
3961 identically to reduction(+:var). */
3962 if (code
== MINUS_EXPR
)
3967 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
3969 addr
= save_expr (addr
);
3970 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
3971 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
3972 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
3973 gimplify_and_add (x
, stmt_seqp
);
3977 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3979 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3981 if (is_reference (var
)
3982 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
3984 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
3985 SET_DECL_VALUE_EXPR (placeholder
, ref
);
3986 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3987 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
3988 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
3989 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3990 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
3994 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3995 ref
= build_outer_var_ref (var
, ctx
);
3996 gimplify_assign (ref
, x
, &sub_seq
);
4000 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4002 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4004 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4006 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4008 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4012 /* Generate code to implement the COPYPRIVATE clauses. */
4015 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4020 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4022 tree var
, new_var
, ref
, x
;
4024 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4026 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4029 var
= OMP_CLAUSE_DECL (c
);
4030 by_ref
= use_pointer_for_field (var
, NULL
);
4032 ref
= build_sender_ref (var
, ctx
);
4033 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4036 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4037 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4039 gimplify_assign (ref
, x
, slist
);
4041 ref
= build_receiver_ref (var
, false, ctx
);
4044 ref
= fold_convert_loc (clause_loc
,
4045 build_pointer_type (TREE_TYPE (new_var
)),
4047 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4049 if (is_reference (var
))
4051 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4052 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4053 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4055 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4056 gimplify_and_add (x
, rlist
);
4061 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4062 and REDUCTION from the sender (aka parent) side. */
4065 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4070 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4072 tree val
, ref
, x
, var
;
4073 bool by_ref
, do_in
= false, do_out
= false;
4074 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4076 switch (OMP_CLAUSE_CODE (c
))
4078 case OMP_CLAUSE_PRIVATE
:
4079 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4082 case OMP_CLAUSE_FIRSTPRIVATE
:
4083 case OMP_CLAUSE_COPYIN
:
4084 case OMP_CLAUSE_LASTPRIVATE
:
4085 case OMP_CLAUSE_REDUCTION
:
4086 case OMP_CLAUSE__LOOPTEMP_
:
4092 val
= OMP_CLAUSE_DECL (c
);
4093 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4095 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4096 && is_global_var (var
))
4098 if (is_variable_sized (val
))
4100 by_ref
= use_pointer_for_field (val
, NULL
);
4102 switch (OMP_CLAUSE_CODE (c
))
4104 case OMP_CLAUSE_PRIVATE
:
4105 case OMP_CLAUSE_FIRSTPRIVATE
:
4106 case OMP_CLAUSE_COPYIN
:
4107 case OMP_CLAUSE__LOOPTEMP_
:
4111 case OMP_CLAUSE_LASTPRIVATE
:
4112 if (by_ref
|| is_reference (val
))
4114 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4121 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4126 case OMP_CLAUSE_REDUCTION
:
4128 do_out
= !(by_ref
|| is_reference (val
));
4137 ref
= build_sender_ref (val
, ctx
);
4138 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4139 gimplify_assign (ref
, x
, ilist
);
4140 if (is_task_ctx (ctx
))
4141 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4146 ref
= build_sender_ref (val
, ctx
);
4147 gimplify_assign (var
, ref
, olist
);
4152 /* Generate code to implement SHARED from the sender (aka parent)
4153 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4154 list things that got automatically shared. */
4157 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4159 tree var
, ovar
, nvar
, f
, x
, record_type
;
4161 if (ctx
->record_type
== NULL
)
4164 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4165 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4167 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4168 nvar
= maybe_lookup_decl (ovar
, ctx
);
4169 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4172 /* If CTX is a nested parallel directive. Find the immediately
4173 enclosing parallel or workshare construct that contains a
4174 mapping for OVAR. */
4175 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4177 if (use_pointer_for_field (ovar
, ctx
))
4179 x
= build_sender_ref (ovar
, ctx
);
4180 var
= build_fold_addr_expr (var
);
4181 gimplify_assign (x
, var
, ilist
);
4185 x
= build_sender_ref (ovar
, ctx
);
4186 gimplify_assign (x
, var
, ilist
);
4188 if (!TREE_READONLY (var
)
4189 /* We don't need to receive a new reference to a result
4190 or parm decl. In fact we may not store to it as we will
4191 invalidate any pending RSO and generate wrong gimple
4193 && !((TREE_CODE (var
) == RESULT_DECL
4194 || TREE_CODE (var
) == PARM_DECL
)
4195 && DECL_BY_REFERENCE (var
)))
4197 x
= build_sender_ref (ovar
, ctx
);
4198 gimplify_assign (var
, x
, olist
);
4205 /* A convenience function to build an empty GIMPLE_COND with just the
4209 gimple_build_cond_empty (tree cond
)
4211 enum tree_code pred_code
;
4214 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4215 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4219 /* Build the function calls to GOMP_parallel_start etc to actually
4220 generate the parallel operation. REGION is the parallel region
4221 being expanded. BB is the block where to insert the code. WS_ARGS
4222 will be set if this is a call to a combined parallel+workshare
4223 construct, it contains the list of additional arguments needed by
4224 the workshare construct. */
4227 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4228 gimple entry_stmt
, vec
<tree
, va_gc
> *ws_args
)
4230 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4231 gimple_stmt_iterator gsi
;
4233 enum built_in_function start_ix
;
4235 location_t clause_loc
;
4236 vec
<tree
, va_gc
> *args
;
4238 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4240 /* Determine what flavor of GOMP_parallel we will be
4242 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4243 if (is_combined_parallel (region
))
4245 switch (region
->inner
->type
)
4247 case GIMPLE_OMP_FOR
:
4248 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4249 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4250 + (region
->inner
->sched_kind
4251 == OMP_CLAUSE_SCHEDULE_RUNTIME
4252 ? 3 : region
->inner
->sched_kind
));
4253 start_ix
= (enum built_in_function
)start_ix2
;
4255 case GIMPLE_OMP_SECTIONS
:
4256 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4263 /* By default, the value of NUM_THREADS is zero (selected at run time)
4264 and there is no conditional. */
4266 val
= build_int_cst (unsigned_type_node
, 0);
4267 flags
= build_int_cst (unsigned_type_node
, 0);
4269 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4271 cond
= OMP_CLAUSE_IF_EXPR (c
);
4273 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4276 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4277 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4280 clause_loc
= gimple_location (entry_stmt
);
4282 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4284 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4286 /* Ensure 'val' is of the correct type. */
4287 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4289 /* If we found the clause 'if (cond)', build either
4290 (cond != 0) or (cond ? val : 1u). */
4293 cond
= gimple_boolify (cond
);
4295 if (integer_zerop (val
))
4296 val
= fold_build2_loc (clause_loc
,
4297 EQ_EXPR
, unsigned_type_node
, cond
,
4298 build_int_cst (TREE_TYPE (cond
), 0));
4301 basic_block cond_bb
, then_bb
, else_bb
;
4302 edge e
, e_then
, e_else
;
4303 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4305 tmp_var
= create_tmp_var (TREE_TYPE (val
), NULL
);
4306 if (gimple_in_ssa_p (cfun
))
4308 tmp_then
= make_ssa_name (tmp_var
, NULL
);
4309 tmp_else
= make_ssa_name (tmp_var
, NULL
);
4310 tmp_join
= make_ssa_name (tmp_var
, NULL
);
4319 e
= split_block (bb
, NULL
);
4324 then_bb
= create_empty_bb (cond_bb
);
4325 else_bb
= create_empty_bb (then_bb
);
4326 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4327 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4329 stmt
= gimple_build_cond_empty (cond
);
4330 gsi
= gsi_start_bb (cond_bb
);
4331 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4333 gsi
= gsi_start_bb (then_bb
);
4334 stmt
= gimple_build_assign (tmp_then
, val
);
4335 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4337 gsi
= gsi_start_bb (else_bb
);
4338 stmt
= gimple_build_assign
4339 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4340 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4342 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4343 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4344 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4345 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4346 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4347 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4349 if (gimple_in_ssa_p (cfun
))
4351 gimple phi
= create_phi_node (tmp_join
, bb
);
4352 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4353 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4359 gsi
= gsi_start_bb (bb
);
4360 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4361 false, GSI_CONTINUE_LINKING
);
4364 gsi
= gsi_last_bb (bb
);
4365 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4367 t1
= null_pointer_node
;
4369 t1
= build_fold_addr_expr (t
);
4370 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4372 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4373 args
->quick_push (t2
);
4374 args
->quick_push (t1
);
4375 args
->quick_push (val
);
4377 args
->splice (*ws_args
);
4378 args
->quick_push (flags
);
4380 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4381 builtin_decl_explicit (start_ix
), args
);
4383 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4384 false, GSI_CONTINUE_LINKING
);
4388 /* Build the function call to GOMP_task to actually
4389 generate the task operation. BB is the block where to insert the code. */
4392 expand_task_call (basic_block bb
, gimple entry_stmt
)
4394 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
4395 gimple_stmt_iterator gsi
;
4396 location_t loc
= gimple_location (entry_stmt
);
4398 clauses
= gimple_omp_task_clauses (entry_stmt
);
4400 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4402 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
4404 cond
= boolean_true_node
;
4406 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
4407 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
4408 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
4409 flags
= build_int_cst (unsigned_type_node
,
4410 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
4412 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
4415 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
4416 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
4417 build_int_cst (unsigned_type_node
, 2),
4418 build_int_cst (unsigned_type_node
, 0));
4419 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
4422 depend
= OMP_CLAUSE_DECL (depend
);
4424 depend
= build_int_cst (ptr_type_node
, 0);
4426 gsi
= gsi_last_bb (bb
);
4427 t
= gimple_omp_task_data_arg (entry_stmt
);
4429 t2
= null_pointer_node
;
4431 t2
= build_fold_addr_expr_loc (loc
, t
);
4432 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
4433 t
= gimple_omp_task_copy_fn (entry_stmt
);
4435 t3
= null_pointer_node
;
4437 t3
= build_fold_addr_expr_loc (loc
, t
);
4439 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
4441 gimple_omp_task_arg_size (entry_stmt
),
4442 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
4445 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4446 false, GSI_CONTINUE_LINKING
);
4450 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4451 catch handler and return it. This prevents programs from violating the
4452 structured block semantics with throws. */
4455 maybe_catch_exception (gimple_seq body
)
4460 if (!flag_exceptions
)
4463 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
4464 decl
= lang_hooks
.eh_protect_cleanup_actions ();
4466 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
4468 g
= gimple_build_eh_must_not_throw (decl
);
4469 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
4472 return gimple_seq_alloc_with_stmt (g
);
4475 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4478 vec2chain (vec
<tree
, va_gc
> *v
)
4480 tree chain
= NULL_TREE
, t
;
4483 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
4485 DECL_CHAIN (t
) = chain
;
4493 /* Remove barriers in REGION->EXIT's block. Note that this is only
4494 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4495 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4496 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4500 remove_exit_barrier (struct omp_region
*region
)
4502 gimple_stmt_iterator gsi
;
4503 basic_block exit_bb
;
4507 int any_addressable_vars
= -1;
4509 exit_bb
= region
->exit
;
4511 /* If the parallel region doesn't return, we don't have REGION->EXIT
4516 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4517 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4518 statements that can appear in between are extremely limited -- no
4519 memory operations at all. Here, we allow nothing at all, so the
4520 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4521 gsi
= gsi_last_bb (exit_bb
);
4522 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
4524 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
4527 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
4529 gsi
= gsi_last_bb (e
->src
);
4530 if (gsi_end_p (gsi
))
4532 stmt
= gsi_stmt (gsi
);
4533 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
4534 && !gimple_omp_return_nowait_p (stmt
))
4536 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4537 in many cases. If there could be tasks queued, the barrier
4538 might be needed to let the tasks run before some local
4539 variable of the parallel that the task uses as shared
4540 runs out of scope. The task can be spawned either
4541 from within current function (this would be easy to check)
4542 or from some function it calls and gets passed an address
4543 of such a variable. */
4544 if (any_addressable_vars
< 0)
4546 gimple parallel_stmt
= last_stmt (region
->entry
);
4547 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
4548 tree local_decls
, block
, decl
;
4551 any_addressable_vars
= 0;
4552 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
4553 if (TREE_ADDRESSABLE (decl
))
4555 any_addressable_vars
= 1;
4558 for (block
= gimple_block (stmt
);
4559 !any_addressable_vars
4561 && TREE_CODE (block
) == BLOCK
;
4562 block
= BLOCK_SUPERCONTEXT (block
))
4564 for (local_decls
= BLOCK_VARS (block
);
4566 local_decls
= DECL_CHAIN (local_decls
))
4567 if (TREE_ADDRESSABLE (local_decls
))
4569 any_addressable_vars
= 1;
4572 if (block
== gimple_block (parallel_stmt
))
4576 if (!any_addressable_vars
)
4577 gimple_omp_return_set_nowait (stmt
);
4583 remove_exit_barriers (struct omp_region
*region
)
4585 if (region
->type
== GIMPLE_OMP_PARALLEL
)
4586 remove_exit_barrier (region
);
4590 region
= region
->inner
;
4591 remove_exit_barriers (region
);
4592 while (region
->next
)
4594 region
= region
->next
;
4595 remove_exit_barriers (region
);
4600 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4601 calls. These can't be declared as const functions, but
4602 within one parallel body they are constant, so they can be
4603 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4604 which are declared const. Similarly for task body, except
4605 that in untied task omp_get_thread_num () can change at any task
4606 scheduling point. */
4609 optimize_omp_library_calls (gimple entry_stmt
)
4612 gimple_stmt_iterator gsi
;
4613 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4614 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
4615 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4616 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
4617 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
4618 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
4619 OMP_CLAUSE_UNTIED
) != NULL
);
4621 FOR_EACH_BB_FN (bb
, cfun
)
4622 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4624 gimple call
= gsi_stmt (gsi
);
4627 if (is_gimple_call (call
)
4628 && (decl
= gimple_call_fndecl (call
))
4629 && DECL_EXTERNAL (decl
)
4630 && TREE_PUBLIC (decl
)
4631 && DECL_INITIAL (decl
) == NULL
)
4635 if (DECL_NAME (decl
) == thr_num_id
)
4637 /* In #pragma omp task untied omp_get_thread_num () can change
4638 during the execution of the task region. */
4641 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4643 else if (DECL_NAME (decl
) == num_thr_id
)
4644 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4648 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
4649 || gimple_call_num_args (call
) != 0)
4652 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
4655 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
4656 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
4657 TREE_TYPE (TREE_TYPE (built_in
))))
4660 gimple_call_set_fndecl (call
, built_in
);
4665 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4669 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
4673 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4674 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
4677 if (TREE_CODE (t
) == ADDR_EXPR
)
4678 recompute_tree_invariant_for_addr_expr (t
);
4680 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
4684 /* Prepend TO = FROM assignment before *GSI_P. */
4687 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
4689 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
4690 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
4691 true, GSI_SAME_STMT
);
4692 gimple stmt
= gimple_build_assign (to
, from
);
4693 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
4694 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
4695 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
4697 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
4698 gimple_regimplify_operands (stmt
, &gsi
);
4702 /* Expand the OpenMP parallel or task directive starting at REGION. */
4705 expand_omp_taskreg (struct omp_region
*region
)
4707 basic_block entry_bb
, exit_bb
, new_bb
;
4708 struct function
*child_cfun
;
4709 tree child_fn
, block
, t
;
4710 gimple_stmt_iterator gsi
;
4711 gimple entry_stmt
, stmt
;
4713 vec
<tree
, va_gc
> *ws_args
;
4715 entry_stmt
= last_stmt (region
->entry
);
4716 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
4717 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
4719 entry_bb
= region
->entry
;
4720 exit_bb
= region
->exit
;
4722 if (is_combined_parallel (region
))
4723 ws_args
= region
->ws_args
;
4727 if (child_cfun
->cfg
)
4729 /* Due to inlining, it may happen that we have already outlined
4730 the region, in which case all we need to do is make the
4731 sub-graph unreachable and emit the parallel call. */
4732 edge entry_succ_e
, exit_succ_e
;
4734 entry_succ_e
= single_succ_edge (entry_bb
);
4736 gsi
= gsi_last_bb (entry_bb
);
4737 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
4738 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
4739 gsi_remove (&gsi
, true);
4744 exit_succ_e
= single_succ_edge (exit_bb
);
4745 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
4747 remove_edge_and_dominated_blocks (entry_succ_e
);
4751 unsigned srcidx
, dstidx
, num
;
4753 /* If the parallel region needs data sent from the parent
4754 function, then the very first statement (except possible
4755 tree profile counter updates) of the parallel body
4756 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4757 &.OMP_DATA_O is passed as an argument to the child function,
4758 we need to replace it with the argument as seen by the child
4761 In most cases, this will end up being the identity assignment
4762 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4763 a function call that has been inlined, the original PARM_DECL
4764 .OMP_DATA_I may have been converted into a different local
4765 variable. In which case, we need to keep the assignment. */
4766 if (gimple_omp_taskreg_data_arg (entry_stmt
))
4768 basic_block entry_succ_bb
= single_succ (entry_bb
);
4770 gimple parcopy_stmt
= NULL
;
4772 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
4776 gcc_assert (!gsi_end_p (gsi
));
4777 stmt
= gsi_stmt (gsi
);
4778 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
4781 if (gimple_num_ops (stmt
) == 2)
4783 tree arg
= gimple_assign_rhs1 (stmt
);
4785 /* We're ignore the subcode because we're
4786 effectively doing a STRIP_NOPS. */
4788 if (TREE_CODE (arg
) == ADDR_EXPR
4789 && TREE_OPERAND (arg
, 0)
4790 == gimple_omp_taskreg_data_arg (entry_stmt
))
4792 parcopy_stmt
= stmt
;
4798 gcc_assert (parcopy_stmt
!= NULL
);
4799 arg
= DECL_ARGUMENTS (child_fn
);
4801 if (!gimple_in_ssa_p (cfun
))
4803 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
4804 gsi_remove (&gsi
, true);
4807 /* ?? Is setting the subcode really necessary ?? */
4808 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
4809 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
4814 /* If we are in ssa form, we must load the value from the default
4815 definition of the argument. That should not be defined now,
4816 since the argument is not used uninitialized. */
4817 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
4818 narg
= make_ssa_name (arg
, gimple_build_nop ());
4819 set_ssa_default_def (cfun
, arg
, narg
);
4820 /* ?? Is setting the subcode really necessary ?? */
4821 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
4822 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
4823 update_stmt (parcopy_stmt
);
4827 /* Declare local variables needed in CHILD_CFUN. */
4828 block
= DECL_INITIAL (child_fn
);
4829 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
4830 /* The gimplifier could record temporaries in parallel/task block
4831 rather than in containing function's local_decls chain,
4832 which would mean cgraph missed finalizing them. Do it now. */
4833 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
4834 if (TREE_CODE (t
) == VAR_DECL
4836 && !DECL_EXTERNAL (t
))
4837 varpool_finalize_decl (t
);
4838 DECL_SAVED_TREE (child_fn
) = NULL
;
4839 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4840 gimple_set_body (child_fn
, NULL
);
4841 TREE_USED (block
) = 1;
4843 /* Reset DECL_CONTEXT on function arguments. */
4844 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
4845 DECL_CONTEXT (t
) = child_fn
;
4847 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4848 so that it can be moved to the child function. */
4849 gsi
= gsi_last_bb (entry_bb
);
4850 stmt
= gsi_stmt (gsi
);
4851 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
4852 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
4853 gsi_remove (&gsi
, true);
4854 e
= split_block (entry_bb
, stmt
);
4856 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
4858 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4861 gsi
= gsi_last_bb (exit_bb
);
4862 gcc_assert (!gsi_end_p (gsi
)
4863 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
4864 stmt
= gimple_build_return (NULL
);
4865 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
4866 gsi_remove (&gsi
, true);
4869 /* Move the parallel region into CHILD_CFUN. */
4871 if (gimple_in_ssa_p (cfun
))
4873 init_tree_ssa (child_cfun
);
4874 init_ssa_operands (child_cfun
);
4875 child_cfun
->gimple_df
->in_ssa_p
= true;
4879 block
= gimple_block (entry_stmt
);
4881 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
4883 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
4884 /* When the OMP expansion process cannot guarantee an up-to-date
4885 loop tree arrange for the child function to fixup loops. */
4886 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
4887 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
4889 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4890 num
= vec_safe_length (child_cfun
->local_decls
);
4891 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
4893 t
= (*child_cfun
->local_decls
)[srcidx
];
4894 if (DECL_CONTEXT (t
) == cfun
->decl
)
4896 if (srcidx
!= dstidx
)
4897 (*child_cfun
->local_decls
)[dstidx
] = t
;
4901 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
4903 /* Inform the callgraph about the new function. */
4904 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
4905 cgraph_add_new_function (child_fn
, true);
4907 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4908 fixed in a following pass. */
4909 push_cfun (child_cfun
);
4911 optimize_omp_library_calls (entry_stmt
);
4912 rebuild_cgraph_edges ();
4914 /* Some EH regions might become dead, see PR34608. If
4915 pass_cleanup_cfg isn't the first pass to happen with the
4916 new child, these dead EH edges might cause problems.
4917 Clean them up now. */
4918 if (flag_exceptions
)
4921 bool changed
= false;
4923 FOR_EACH_BB_FN (bb
, cfun
)
4924 changed
|= gimple_purge_dead_eh_edges (bb
);
4926 cleanup_tree_cfg ();
4928 if (gimple_in_ssa_p (cfun
))
4929 update_ssa (TODO_update_ssa
);
4933 /* Emit a library call to launch the children threads. */
4934 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
4935 expand_parallel_call (region
, new_bb
, entry_stmt
, ws_args
);
4937 expand_task_call (new_bb
, entry_stmt
);
4938 if (gimple_in_ssa_p (cfun
))
4939 update_ssa (TODO_update_ssa_only_virtuals
);
4943 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4944 of the combined collapse > 1 loop constructs, generate code like:
4945 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4950 count3 = (adj + N32 - N31) / STEP3;
4951 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4956 count2 = (adj + N22 - N21) / STEP2;
4957 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4962 count1 = (adj + N12 - N11) / STEP1;
4963 count = count1 * count2 * count3;
4964 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4966 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4967 of the combined loop constructs, just initialize COUNTS array
4968 from the _looptemp_ clauses. */
4970 /* NOTE: It *could* be better to moosh all of the BBs together,
4971 creating one larger BB with all the computation and the unexpected
4972 jump at the end. I.e.
4974 bool zero3, zero2, zero1, zero;
4977 count3 = (N32 - N31) /[cl] STEP3;
4979 count2 = (N22 - N21) /[cl] STEP2;
4981 count1 = (N12 - N11) /[cl] STEP1;
4982 zero = zero3 || zero2 || zero1;
4983 count = count1 * count2 * count3;
4984 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4986 After all, we expect the zero=false, and thus we expect to have to
4987 evaluate all of the comparison expressions, so short-circuiting
4988 oughtn't be a win. Since the condition isn't protecting a
4989 denominator, we're not concerned about divide-by-zero, so we can
4990 fully evaluate count even if a numerator turned out to be wrong.
4992 It seems like putting this all together would create much better
4993 scheduling opportunities, and less pressure on the chip's branch
4997 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
4998 basic_block
&entry_bb
, tree
*counts
,
4999 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5000 basic_block
&l2_dom_bb
)
5002 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5007 /* Collapsed loops need work for expansion into SSA form. */
5008 gcc_assert (!gimple_in_ssa_p (cfun
));
5010 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5011 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5013 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5014 isn't supposed to be handled, as the inner loop doesn't
5016 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5017 OMP_CLAUSE__LOOPTEMP_
);
5018 gcc_assert (innerc
);
5019 for (i
= 0; i
< fd
->collapse
; i
++)
5021 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5022 OMP_CLAUSE__LOOPTEMP_
);
5023 gcc_assert (innerc
);
5025 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5027 counts
[0] = NULL_TREE
;
5032 for (i
= 0; i
< fd
->collapse
; i
++)
5034 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5036 if (SSA_VAR_P (fd
->loop
.n2
)
5037 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5038 fold_convert (itype
, fd
->loops
[i
].n1
),
5039 fold_convert (itype
, fd
->loops
[i
].n2
)))
5040 == NULL_TREE
|| !integer_onep (t
)))
5043 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5044 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5045 true, GSI_SAME_STMT
);
5046 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5047 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5048 true, GSI_SAME_STMT
);
5049 stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5050 NULL_TREE
, NULL_TREE
);
5051 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5052 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
5053 expand_omp_regimplify_p
, NULL
, NULL
)
5054 || walk_tree (gimple_cond_rhs_ptr (stmt
),
5055 expand_omp_regimplify_p
, NULL
, NULL
))
5057 *gsi
= gsi_for_stmt (stmt
);
5058 gimple_regimplify_operands (stmt
, gsi
);
5060 e
= split_block (entry_bb
, stmt
);
5061 if (zero_iter_bb
== NULL
)
5063 first_zero_iter
= i
;
5064 zero_iter_bb
= create_empty_bb (entry_bb
);
5065 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5066 *gsi
= gsi_after_labels (zero_iter_bb
);
5067 stmt
= gimple_build_assign (fd
->loop
.n2
,
5068 build_zero_cst (type
));
5069 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5070 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5073 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5074 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5075 e
->flags
= EDGE_TRUE_VALUE
;
5076 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5077 if (l2_dom_bb
== NULL
)
5078 l2_dom_bb
= entry_bb
;
5080 *gsi
= gsi_last_bb (entry_bb
);
5083 if (POINTER_TYPE_P (itype
))
5084 itype
= signed_type_for (itype
);
5085 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5087 t
= fold_build2 (PLUS_EXPR
, itype
,
5088 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5089 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5090 fold_convert (itype
, fd
->loops
[i
].n2
));
5091 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5092 fold_convert (itype
, fd
->loops
[i
].n1
));
5093 /* ?? We could probably use CEIL_DIV_EXPR instead of
5094 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5095 generate the same code in the end because generically we
5096 don't know that the values involved must be negative for
5098 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5099 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5100 fold_build1 (NEGATE_EXPR
, itype
, t
),
5101 fold_build1 (NEGATE_EXPR
, itype
,
5102 fold_convert (itype
,
5103 fd
->loops
[i
].step
)));
5105 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5106 fold_convert (itype
, fd
->loops
[i
].step
));
5107 t
= fold_convert (type
, t
);
5108 if (TREE_CODE (t
) == INTEGER_CST
)
5112 counts
[i
] = create_tmp_reg (type
, ".count");
5113 expand_omp_build_assign (gsi
, counts
[i
], t
);
5115 if (SSA_VAR_P (fd
->loop
.n2
))
5120 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5121 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5127 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5129 V3 = N31 + (T % count3) * STEP3;
5131 V2 = N21 + (T % count2) * STEP2;
5133 V1 = N11 + T * STEP1;
5134 if this loop doesn't have an inner loop construct combined with it.
5135 If it does have an inner loop construct combined with it and the
5136 iteration count isn't known constant, store values from counts array
5137 into its _looptemp_ temporaries instead. */
5140 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5141 tree
*counts
, gimple inner_stmt
, tree startvar
)
5144 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5146 /* If fd->loop.n2 is constant, then no propagation of the counts
5147 is needed, they are constant. */
5148 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5151 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5152 ? gimple_omp_parallel_clauses (inner_stmt
)
5153 : gimple_omp_for_clauses (inner_stmt
);
5154 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5155 isn't supposed to be handled, as the inner loop doesn't
5157 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5158 gcc_assert (innerc
);
5159 for (i
= 0; i
< fd
->collapse
; i
++)
5161 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5162 OMP_CLAUSE__LOOPTEMP_
);
5163 gcc_assert (innerc
);
5166 tree tem
= OMP_CLAUSE_DECL (innerc
);
5167 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5168 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5169 false, GSI_CONTINUE_LINKING
);
5170 gimple stmt
= gimple_build_assign (tem
, t
);
5171 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5177 tree type
= TREE_TYPE (fd
->loop
.v
);
5178 tree tem
= create_tmp_reg (type
, ".tem");
5179 gimple stmt
= gimple_build_assign (tem
, startvar
);
5180 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5182 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5184 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5186 if (POINTER_TYPE_P (vtype
))
5187 itype
= signed_type_for (vtype
);
5189 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5192 t
= fold_convert (itype
, t
);
5193 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5194 fold_convert (itype
, fd
->loops
[i
].step
));
5195 if (POINTER_TYPE_P (vtype
))
5196 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5198 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5199 t
= force_gimple_operand_gsi (gsi
, t
,
5200 DECL_P (fd
->loops
[i
].v
)
5201 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5203 GSI_CONTINUE_LINKING
);
5204 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5205 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5208 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5209 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5210 false, GSI_CONTINUE_LINKING
);
5211 stmt
= gimple_build_assign (tem
, t
);
5212 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5218 /* Helper function for expand_omp_for_*. Generate code like:
5221 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5225 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5232 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5233 basic_block body_bb
)
5235 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5237 gimple_stmt_iterator gsi
;
5243 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5245 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5247 bb
= create_empty_bb (last_bb
);
5248 add_bb_to_loop (bb
, last_bb
->loop_father
);
5249 gsi
= gsi_start_bb (bb
);
5251 if (i
< fd
->collapse
- 1)
5253 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5254 e
->probability
= REG_BR_PROB_BASE
/ 8;
5256 t
= fd
->loops
[i
+ 1].n1
;
5257 t
= force_gimple_operand_gsi (&gsi
, t
,
5258 DECL_P (fd
->loops
[i
+ 1].v
)
5259 && TREE_ADDRESSABLE (fd
->loops
[i
5262 GSI_CONTINUE_LINKING
);
5263 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5264 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5269 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5271 if (POINTER_TYPE_P (vtype
))
5272 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5274 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5275 t
= force_gimple_operand_gsi (&gsi
, t
,
5276 DECL_P (fd
->loops
[i
].v
)
5277 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5278 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5279 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5280 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5284 t
= fd
->loops
[i
].n2
;
5285 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5286 false, GSI_CONTINUE_LINKING
);
5287 tree v
= fd
->loops
[i
].v
;
5288 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5289 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5290 false, GSI_CONTINUE_LINKING
);
5291 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5292 stmt
= gimple_build_cond_empty (t
);
5293 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5294 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5295 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5298 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5306 /* A subroutine of expand_omp_for. Generate code for a parallel
5307 loop with any schedule. Given parameters:
5309 for (V = N1; V cond N2; V += STEP) BODY;
5311 where COND is "<" or ">", we generate pseudocode
5313 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5314 if (more) goto L0; else goto L3;
5321 if (V cond iend) goto L1; else goto L2;
5323 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5326 If this is a combined omp parallel loop, instead of the call to
5327 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5328 If this is gimple_omp_for_combined_p loop, then instead of assigning
5329 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5330 inner GIMPLE_OMP_FOR and V += STEP; and
5331 if (V cond iend) goto L1; else goto L2; are removed.
5333 For collapsed loops, given parameters:
5335 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5336 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5337 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5340 we generate pseudocode
5342 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5347 count3 = (adj + N32 - N31) / STEP3;
5348 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5353 count2 = (adj + N22 - N21) / STEP2;
5354 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5359 count1 = (adj + N12 - N11) / STEP1;
5360 count = count1 * count2 * count3;
5365 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5366 if (more) goto L0; else goto L3;
5370 V3 = N31 + (T % count3) * STEP3;
5372 V2 = N21 + (T % count2) * STEP2;
5374 V1 = N11 + T * STEP1;
5379 if (V < iend) goto L10; else goto L2;
5382 if (V3 cond3 N32) goto L1; else goto L11;
5386 if (V2 cond2 N22) goto L1; else goto L12;
5392 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5398 expand_omp_for_generic (struct omp_region
*region
,
5399 struct omp_for_data
*fd
,
5400 enum built_in_function start_fn
,
5401 enum built_in_function next_fn
,
5404 tree type
, istart0
, iend0
, iend
;
5405 tree t
, vmain
, vback
, bias
= NULL_TREE
;
5406 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
5407 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
5408 gimple_stmt_iterator gsi
;
5410 bool in_combined_parallel
= is_combined_parallel (region
);
5411 bool broken_loop
= region
->cont
== NULL
;
5413 tree
*counts
= NULL
;
5416 gcc_assert (!broken_loop
|| !in_combined_parallel
);
5417 gcc_assert (fd
->iter_type
== long_integer_type_node
5418 || !in_combined_parallel
);
5420 type
= TREE_TYPE (fd
->loop
.v
);
5421 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
5422 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
5423 TREE_ADDRESSABLE (istart0
) = 1;
5424 TREE_ADDRESSABLE (iend0
) = 1;
5426 /* See if we need to bias by LLONG_MIN. */
5427 if (fd
->iter_type
== long_long_unsigned_type_node
5428 && TREE_CODE (type
) == INTEGER_TYPE
5429 && !TYPE_UNSIGNED (type
))
5433 if (fd
->loop
.cond_code
== LT_EXPR
)
5436 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5440 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5443 if (TREE_CODE (n1
) != INTEGER_CST
5444 || TREE_CODE (n2
) != INTEGER_CST
5445 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
5446 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
5449 entry_bb
= region
->entry
;
5450 cont_bb
= region
->cont
;
5452 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5453 gcc_assert (broken_loop
5454 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
5455 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
5456 l1_bb
= single_succ (l0_bb
);
5459 l2_bb
= create_empty_bb (cont_bb
);
5460 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
5461 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5465 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5466 exit_bb
= region
->exit
;
5468 gsi
= gsi_last_bb (entry_bb
);
5470 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5471 if (fd
->collapse
> 1)
5473 int first_zero_iter
= -1;
5474 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
5476 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5477 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5478 zero_iter_bb
, first_zero_iter
,
5483 /* Some counts[i] vars might be uninitialized if
5484 some loop has zero iterations. But the body shouldn't
5485 be executed in that case, so just avoid uninit warnings. */
5486 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
5487 if (SSA_VAR_P (counts
[i
]))
5488 TREE_NO_WARNING (counts
[i
]) = 1;
5490 e
= split_block (entry_bb
, gsi_stmt (gsi
));
5492 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
5493 gsi
= gsi_last_bb (entry_bb
);
5494 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
5495 get_immediate_dominator (CDI_DOMINATORS
,
5499 if (in_combined_parallel
)
5501 /* In a combined parallel loop, emit a call to
5502 GOMP_loop_foo_next. */
5503 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5504 build_fold_addr_expr (istart0
),
5505 build_fold_addr_expr (iend0
));
5509 tree t0
, t1
, t2
, t3
, t4
;
5510 /* If this is not a combined parallel loop, emit a call to
5511 GOMP_loop_foo_start in ENTRY_BB. */
5512 t4
= build_fold_addr_expr (iend0
);
5513 t3
= build_fold_addr_expr (istart0
);
5514 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
5517 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5519 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5520 OMP_CLAUSE__LOOPTEMP_
);
5521 gcc_assert (innerc
);
5522 t0
= OMP_CLAUSE_DECL (innerc
);
5523 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5524 OMP_CLAUSE__LOOPTEMP_
);
5525 gcc_assert (innerc
);
5526 t1
= OMP_CLAUSE_DECL (innerc
);
5528 if (POINTER_TYPE_P (TREE_TYPE (t0
))
5529 && TYPE_PRECISION (TREE_TYPE (t0
))
5530 != TYPE_PRECISION (fd
->iter_type
))
5532 /* Avoid casting pointers to integer of a different size. */
5533 tree itype
= signed_type_for (type
);
5534 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
5535 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
5539 t1
= fold_convert (fd
->iter_type
, t1
);
5540 t0
= fold_convert (fd
->iter_type
, t0
);
5544 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
5545 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
5547 if (fd
->iter_type
== long_integer_type_node
)
5551 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5552 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5553 6, t0
, t1
, t2
, t
, t3
, t4
);
5556 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5557 5, t0
, t1
, t2
, t3
, t4
);
5565 /* The GOMP_loop_ull_*start functions have additional boolean
5566 argument, true for < loops and false for > loops.
5567 In Fortran, the C bool type can be different from
5568 boolean_type_node. */
5569 bfn_decl
= builtin_decl_explicit (start_fn
);
5570 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
5571 t5
= build_int_cst (c_bool_type
,
5572 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
5575 tree bfn_decl
= builtin_decl_explicit (start_fn
);
5576 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5577 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
5580 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5581 6, t5
, t0
, t1
, t2
, t3
, t4
);
5584 if (TREE_TYPE (t
) != boolean_type_node
)
5585 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5586 t
, build_int_cst (TREE_TYPE (t
), 0));
5587 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5588 true, GSI_SAME_STMT
);
5589 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5591 /* Remove the GIMPLE_OMP_FOR statement. */
5592 gsi_remove (&gsi
, true);
5594 /* Iteration setup for sequential loop goes in L0_BB. */
5595 tree startvar
= fd
->loop
.v
;
5596 tree endvar
= NULL_TREE
;
5598 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5600 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
5601 && gimple_omp_for_kind (inner_stmt
)
5602 == GF_OMP_FOR_KIND_SIMD
);
5603 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
5604 OMP_CLAUSE__LOOPTEMP_
);
5605 gcc_assert (innerc
);
5606 startvar
= OMP_CLAUSE_DECL (innerc
);
5607 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5608 OMP_CLAUSE__LOOPTEMP_
);
5609 gcc_assert (innerc
);
5610 endvar
= OMP_CLAUSE_DECL (innerc
);
5613 gsi
= gsi_start_bb (l0_bb
);
5616 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5617 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5618 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5619 t
= fold_convert (TREE_TYPE (startvar
), t
);
5620 t
= force_gimple_operand_gsi (&gsi
, t
,
5622 && TREE_ADDRESSABLE (startvar
),
5623 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5624 stmt
= gimple_build_assign (startvar
, t
);
5625 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5629 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5630 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5631 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5632 t
= fold_convert (TREE_TYPE (startvar
), t
);
5633 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5634 false, GSI_CONTINUE_LINKING
);
5637 stmt
= gimple_build_assign (endvar
, iend
);
5638 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5639 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
5640 stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
5642 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, iend
,
5644 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5646 if (fd
->collapse
> 1)
5647 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
5651 /* Code to control the increment and predicate for the sequential
5652 loop goes in the CONT_BB. */
5653 gsi
= gsi_last_bb (cont_bb
);
5654 stmt
= gsi_stmt (gsi
);
5655 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
5656 vmain
= gimple_omp_continue_control_use (stmt
);
5657 vback
= gimple_omp_continue_control_def (stmt
);
5659 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5661 if (POINTER_TYPE_P (type
))
5662 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
5664 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
5665 t
= force_gimple_operand_gsi (&gsi
, t
,
5667 && TREE_ADDRESSABLE (vback
),
5668 NULL_TREE
, true, GSI_SAME_STMT
);
5669 stmt
= gimple_build_assign (vback
, t
);
5670 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5672 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
5673 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
5675 stmt
= gimple_build_cond_empty (t
);
5676 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5679 /* Remove GIMPLE_OMP_CONTINUE. */
5680 gsi_remove (&gsi
, true);
5682 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
5683 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
5685 /* Emit code to get the next parallel iteration in L2_BB. */
5686 gsi
= gsi_start_bb (l2_bb
);
5688 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5689 build_fold_addr_expr (istart0
),
5690 build_fold_addr_expr (iend0
));
5691 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5692 false, GSI_CONTINUE_LINKING
);
5693 if (TREE_TYPE (t
) != boolean_type_node
)
5694 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5695 t
, build_int_cst (TREE_TYPE (t
), 0));
5696 stmt
= gimple_build_cond_empty (t
);
5697 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5700 /* Add the loop cleanup function. */
5701 gsi
= gsi_last_bb (exit_bb
);
5702 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
5703 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
5704 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5705 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
5707 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
5708 stmt
= gimple_build_call (t
, 0);
5709 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5710 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
5711 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5712 gsi_remove (&gsi
, true);
5714 /* Connect the new blocks. */
5715 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
5716 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
5722 e
= find_edge (cont_bb
, l3_bb
);
5723 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
5725 phis
= phi_nodes (l3_bb
);
5726 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5728 gimple phi
= gsi_stmt (gsi
);
5729 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
5730 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
5734 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
5735 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
5736 e
= find_edge (cont_bb
, l1_bb
);
5737 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5742 else if (fd
->collapse
> 1)
5745 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
5748 e
->flags
= EDGE_TRUE_VALUE
;
5751 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5752 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
5756 e
= find_edge (cont_bb
, l2_bb
);
5757 e
->flags
= EDGE_FALLTHRU
;
5759 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
5761 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
5762 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
5763 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
5764 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
5765 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
5766 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
5767 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
5768 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
5770 struct loop
*outer_loop
= alloc_loop ();
5771 outer_loop
->header
= l0_bb
;
5772 outer_loop
->latch
= l2_bb
;
5773 add_loop (outer_loop
, l0_bb
->loop_father
);
5775 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5777 struct loop
*loop
= alloc_loop ();
5778 loop
->header
= l1_bb
;
5779 /* The loop may have multiple latches. */
5780 add_loop (loop
, outer_loop
);
5786 /* A subroutine of expand_omp_for. Generate code for a parallel
5787 loop with static schedule and no specified chunk size. Given
5790 for (V = N1; V cond N2; V += STEP) BODY;
5792 where COND is "<" or ">", we generate pseudocode
5794 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5799 if ((__typeof (V)) -1 > 0 && cond is >)
5800 n = -(adj + N2 - N1) / -STEP;
5802 n = (adj + N2 - N1) / STEP;
5805 if (threadid < tt) goto L3; else goto L4;
5810 s0 = q * threadid + tt;
5813 if (s0 >= e0) goto L2; else goto L0;
5819 if (V cond e) goto L1;
5824 expand_omp_for_static_nochunk (struct omp_region
*region
,
5825 struct omp_for_data
*fd
,
5828 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
5829 tree type
, itype
, vmain
, vback
;
5830 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
5831 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
5833 gimple_stmt_iterator gsi
;
5836 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
5837 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
5838 bool broken_loop
= region
->cont
== NULL
;
5839 tree
*counts
= NULL
;
5842 itype
= type
= TREE_TYPE (fd
->loop
.v
);
5843 if (POINTER_TYPE_P (type
))
5844 itype
= signed_type_for (type
);
5846 entry_bb
= region
->entry
;
5847 cont_bb
= region
->cont
;
5848 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5849 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5850 gcc_assert (broken_loop
5851 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
5852 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
5853 body_bb
= single_succ (seq_start_bb
);
5856 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
5857 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5859 exit_bb
= region
->exit
;
5861 /* Iteration space partitioning goes in ENTRY_BB. */
5862 gsi
= gsi_last_bb (entry_bb
);
5863 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5865 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
5867 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
5868 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
5871 if (fd
->collapse
> 1)
5873 int first_zero_iter
= -1;
5874 basic_block l2_dom_bb
= NULL
;
5876 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5877 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5878 fin_bb
, first_zero_iter
,
5882 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5883 t
= integer_one_node
;
5885 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
5886 fold_convert (type
, fd
->loop
.n1
),
5887 fold_convert (type
, fd
->loop
.n2
));
5888 if (fd
->collapse
== 1
5889 && TYPE_UNSIGNED (type
)
5890 && (t
== NULL_TREE
|| !integer_onep (t
)))
5892 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
5893 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
5894 true, GSI_SAME_STMT
);
5895 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
5896 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
5897 true, GSI_SAME_STMT
);
5898 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
5899 NULL_TREE
, NULL_TREE
);
5900 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5901 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
5902 expand_omp_regimplify_p
, NULL
, NULL
)
5903 || walk_tree (gimple_cond_rhs_ptr (stmt
),
5904 expand_omp_regimplify_p
, NULL
, NULL
))
5906 gsi
= gsi_for_stmt (stmt
);
5907 gimple_regimplify_operands (stmt
, &gsi
);
5909 ep
= split_block (entry_bb
, stmt
);
5910 ep
->flags
= EDGE_TRUE_VALUE
;
5911 entry_bb
= ep
->dest
;
5912 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
5913 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
5914 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5915 if (gimple_in_ssa_p (cfun
))
5917 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
5918 for (gsi
= gsi_start_phis (fin_bb
);
5919 !gsi_end_p (gsi
); gsi_next (&gsi
))
5921 gimple phi
= gsi_stmt (gsi
);
5922 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
5923 ep
, UNKNOWN_LOCATION
);
5926 gsi
= gsi_last_bb (entry_bb
);
5929 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
5930 t
= fold_convert (itype
, t
);
5931 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5932 true, GSI_SAME_STMT
);
5934 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
5935 t
= fold_convert (itype
, t
);
5936 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5937 true, GSI_SAME_STMT
);
5941 step
= fd
->loop
.step
;
5942 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5944 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5945 OMP_CLAUSE__LOOPTEMP_
);
5946 gcc_assert (innerc
);
5947 n1
= OMP_CLAUSE_DECL (innerc
);
5948 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5949 OMP_CLAUSE__LOOPTEMP_
);
5950 gcc_assert (innerc
);
5951 n2
= OMP_CLAUSE_DECL (innerc
);
5953 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
5954 true, NULL_TREE
, true, GSI_SAME_STMT
);
5955 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
5956 true, NULL_TREE
, true, GSI_SAME_STMT
);
5957 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
5958 true, NULL_TREE
, true, GSI_SAME_STMT
);
5960 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
5961 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
5962 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
5963 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
5964 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
5965 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5966 fold_build1 (NEGATE_EXPR
, itype
, t
),
5967 fold_build1 (NEGATE_EXPR
, itype
, step
));
5969 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
5970 t
= fold_convert (itype
, t
);
5971 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
5973 q
= create_tmp_reg (itype
, "q");
5974 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
5975 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
5976 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
5978 tt
= create_tmp_reg (itype
, "tt");
5979 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
5980 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
5981 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
5983 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
5984 stmt
= gimple_build_cond_empty (t
);
5985 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5987 second_bb
= split_block (entry_bb
, stmt
)->dest
;
5988 gsi
= gsi_last_bb (second_bb
);
5989 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5991 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
5993 stmt
= gimple_build_assign_with_ops (PLUS_EXPR
, q
, q
,
5994 build_int_cst (itype
, 1));
5995 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5997 third_bb
= split_block (second_bb
, stmt
)->dest
;
5998 gsi
= gsi_last_bb (third_bb
);
5999 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6001 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6002 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6003 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6005 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6006 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6008 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6009 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6011 /* Remove the GIMPLE_OMP_FOR statement. */
6012 gsi_remove (&gsi
, true);
6014 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6015 gsi
= gsi_start_bb (seq_start_bb
);
6017 tree startvar
= fd
->loop
.v
;
6018 tree endvar
= NULL_TREE
;
6020 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6022 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6023 ? gimple_omp_parallel_clauses (inner_stmt
)
6024 : gimple_omp_for_clauses (inner_stmt
);
6025 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6026 gcc_assert (innerc
);
6027 startvar
= OMP_CLAUSE_DECL (innerc
);
6028 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6029 OMP_CLAUSE__LOOPTEMP_
);
6030 gcc_assert (innerc
);
6031 endvar
= OMP_CLAUSE_DECL (innerc
);
6033 t
= fold_convert (itype
, s0
);
6034 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6035 if (POINTER_TYPE_P (type
))
6036 t
= fold_build_pointer_plus (n1
, t
);
6038 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6039 t
= fold_convert (TREE_TYPE (startvar
), t
);
6040 t
= force_gimple_operand_gsi (&gsi
, t
,
6042 && TREE_ADDRESSABLE (startvar
),
6043 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6044 stmt
= gimple_build_assign (startvar
, t
);
6045 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6047 t
= fold_convert (itype
, e0
);
6048 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6049 if (POINTER_TYPE_P (type
))
6050 t
= fold_build_pointer_plus (n1
, t
);
6052 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6053 t
= fold_convert (TREE_TYPE (startvar
), t
);
6054 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6055 false, GSI_CONTINUE_LINKING
);
6058 stmt
= gimple_build_assign (endvar
, e
);
6059 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6060 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6061 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6063 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6065 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6067 if (fd
->collapse
> 1)
6068 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6072 /* The code controlling the sequential loop replaces the
6073 GIMPLE_OMP_CONTINUE. */
6074 gsi
= gsi_last_bb (cont_bb
);
6075 stmt
= gsi_stmt (gsi
);
6076 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6077 vmain
= gimple_omp_continue_control_use (stmt
);
6078 vback
= gimple_omp_continue_control_def (stmt
);
6080 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6082 if (POINTER_TYPE_P (type
))
6083 t
= fold_build_pointer_plus (vmain
, step
);
6085 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6086 t
= force_gimple_operand_gsi (&gsi
, t
,
6088 && TREE_ADDRESSABLE (vback
),
6089 NULL_TREE
, true, GSI_SAME_STMT
);
6090 stmt
= gimple_build_assign (vback
, t
);
6091 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6093 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6094 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6096 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6099 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6100 gsi_remove (&gsi
, true);
6102 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6103 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6106 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6107 gsi
= gsi_last_bb (exit_bb
);
6108 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6110 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6111 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6113 gsi_remove (&gsi
, true);
6115 /* Connect all the blocks. */
6116 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6117 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6118 ep
= find_edge (entry_bb
, second_bb
);
6119 ep
->flags
= EDGE_TRUE_VALUE
;
6120 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6121 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6122 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6126 ep
= find_edge (cont_bb
, body_bb
);
6127 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6132 else if (fd
->collapse
> 1)
6135 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6138 ep
->flags
= EDGE_TRUE_VALUE
;
6139 find_edge (cont_bb
, fin_bb
)->flags
6140 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6143 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6144 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6145 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6147 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6148 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6149 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6150 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6152 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6154 struct loop
*loop
= alloc_loop ();
6155 loop
->header
= body_bb
;
6156 if (collapse_bb
== NULL
)
6157 loop
->latch
= cont_bb
;
6158 add_loop (loop
, body_bb
->loop_father
);
6163 /* A subroutine of expand_omp_for. Generate code for a parallel
6164 loop with static schedule and a specified chunk size. Given
6167 for (V = N1; V cond N2; V += STEP) BODY;
6169 where COND is "<" or ">", we generate pseudocode
6171 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6176 if ((__typeof (V)) -1 > 0 && cond is >)
6177 n = -(adj + N2 - N1) / -STEP;
6179 n = (adj + N2 - N1) / STEP;
6181 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6182 here so that V is defined
6183 if the loop is not entered
6185 s0 = (trip * nthreads + threadid) * CHUNK;
6186 e0 = min(s0 + CHUNK, n);
6187 if (s0 < n) goto L1; else goto L4;
6194 if (V cond e) goto L2; else goto L3;
6202 expand_omp_for_static_chunk (struct omp_region
*region
,
6203 struct omp_for_data
*fd
, gimple inner_stmt
)
6205 tree n
, s0
, e0
, e
, t
;
6206 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6207 tree type
, itype
, vmain
, vback
, vextra
;
6208 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6209 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6210 gimple_stmt_iterator gsi
;
6213 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6214 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6215 bool broken_loop
= region
->cont
== NULL
;
6216 tree
*counts
= NULL
;
6219 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6220 if (POINTER_TYPE_P (type
))
6221 itype
= signed_type_for (type
);
6223 entry_bb
= region
->entry
;
6224 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6226 iter_part_bb
= se
->dest
;
6227 cont_bb
= region
->cont
;
6228 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6229 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6230 gcc_assert (broken_loop
6231 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6232 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6233 body_bb
= single_succ (seq_start_bb
);
6236 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6237 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6238 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6240 exit_bb
= region
->exit
;
6242 /* Trip and adjustment setup goes in ENTRY_BB. */
6243 gsi
= gsi_last_bb (entry_bb
);
6244 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6246 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6248 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6249 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6252 if (fd
->collapse
> 1)
6254 int first_zero_iter
= -1;
6255 basic_block l2_dom_bb
= NULL
;
6257 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6258 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6259 fin_bb
, first_zero_iter
,
6263 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6264 t
= integer_one_node
;
6266 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6267 fold_convert (type
, fd
->loop
.n1
),
6268 fold_convert (type
, fd
->loop
.n2
));
6269 if (fd
->collapse
== 1
6270 && TYPE_UNSIGNED (type
)
6271 && (t
== NULL_TREE
|| !integer_onep (t
)))
6273 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6274 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6275 true, GSI_SAME_STMT
);
6276 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6277 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6278 true, GSI_SAME_STMT
);
6279 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6280 NULL_TREE
, NULL_TREE
);
6281 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6282 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
6283 expand_omp_regimplify_p
, NULL
, NULL
)
6284 || walk_tree (gimple_cond_rhs_ptr (stmt
),
6285 expand_omp_regimplify_p
, NULL
, NULL
))
6287 gsi
= gsi_for_stmt (stmt
);
6288 gimple_regimplify_operands (stmt
, &gsi
);
6290 se
= split_block (entry_bb
, stmt
);
6291 se
->flags
= EDGE_TRUE_VALUE
;
6292 entry_bb
= se
->dest
;
6293 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6294 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6295 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6296 if (gimple_in_ssa_p (cfun
))
6298 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6299 for (gsi
= gsi_start_phis (fin_bb
);
6300 !gsi_end_p (gsi
); gsi_next (&gsi
))
6302 gimple phi
= gsi_stmt (gsi
);
6303 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6304 se
, UNKNOWN_LOCATION
);
6307 gsi
= gsi_last_bb (entry_bb
);
6310 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6311 t
= fold_convert (itype
, t
);
6312 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6313 true, GSI_SAME_STMT
);
6315 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6316 t
= fold_convert (itype
, t
);
6317 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6318 true, GSI_SAME_STMT
);
6322 step
= fd
->loop
.step
;
6323 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6325 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6326 OMP_CLAUSE__LOOPTEMP_
);
6327 gcc_assert (innerc
);
6328 n1
= OMP_CLAUSE_DECL (innerc
);
6329 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6330 OMP_CLAUSE__LOOPTEMP_
);
6331 gcc_assert (innerc
);
6332 n2
= OMP_CLAUSE_DECL (innerc
);
6334 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6335 true, NULL_TREE
, true, GSI_SAME_STMT
);
6336 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6337 true, NULL_TREE
, true, GSI_SAME_STMT
);
6338 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6339 true, NULL_TREE
, true, GSI_SAME_STMT
);
6341 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
6342 true, NULL_TREE
, true, GSI_SAME_STMT
);
6344 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6345 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6346 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6347 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6348 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6349 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6350 fold_build1 (NEGATE_EXPR
, itype
, t
),
6351 fold_build1 (NEGATE_EXPR
, itype
, step
));
6353 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6354 t
= fold_convert (itype
, t
);
6355 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6356 true, GSI_SAME_STMT
);
6358 trip_var
= create_tmp_reg (itype
, ".trip");
6359 if (gimple_in_ssa_p (cfun
))
6361 trip_init
= make_ssa_name (trip_var
, NULL
);
6362 trip_main
= make_ssa_name (trip_var
, NULL
);
6363 trip_back
= make_ssa_name (trip_var
, NULL
);
6367 trip_init
= trip_var
;
6368 trip_main
= trip_var
;
6369 trip_back
= trip_var
;
6372 stmt
= gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
6373 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6375 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
6376 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6377 if (POINTER_TYPE_P (type
))
6378 t
= fold_build_pointer_plus (n1
, t
);
6380 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6381 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6382 true, GSI_SAME_STMT
);
6384 /* Remove the GIMPLE_OMP_FOR. */
6385 gsi_remove (&gsi
, true);
6387 /* Iteration space partitioning goes in ITER_PART_BB. */
6388 gsi
= gsi_last_bb (iter_part_bb
);
6390 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
6391 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
6392 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
6393 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6394 false, GSI_CONTINUE_LINKING
);
6396 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
6397 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
6398 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6399 false, GSI_CONTINUE_LINKING
);
6401 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
6402 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
6404 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6405 gsi
= gsi_start_bb (seq_start_bb
);
6407 tree startvar
= fd
->loop
.v
;
6408 tree endvar
= NULL_TREE
;
6410 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6412 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6413 ? gimple_omp_parallel_clauses (inner_stmt
)
6414 : gimple_omp_for_clauses (inner_stmt
);
6415 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6416 gcc_assert (innerc
);
6417 startvar
= OMP_CLAUSE_DECL (innerc
);
6418 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6419 OMP_CLAUSE__LOOPTEMP_
);
6420 gcc_assert (innerc
);
6421 endvar
= OMP_CLAUSE_DECL (innerc
);
6424 t
= fold_convert (itype
, s0
);
6425 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6426 if (POINTER_TYPE_P (type
))
6427 t
= fold_build_pointer_plus (n1
, t
);
6429 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6430 t
= fold_convert (TREE_TYPE (startvar
), t
);
6431 t
= force_gimple_operand_gsi (&gsi
, t
,
6433 && TREE_ADDRESSABLE (startvar
),
6434 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6435 stmt
= gimple_build_assign (startvar
, t
);
6436 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6438 t
= fold_convert (itype
, e0
);
6439 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6440 if (POINTER_TYPE_P (type
))
6441 t
= fold_build_pointer_plus (n1
, t
);
6443 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6444 t
= fold_convert (TREE_TYPE (startvar
), t
);
6445 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6446 false, GSI_CONTINUE_LINKING
);
6449 stmt
= gimple_build_assign (endvar
, e
);
6450 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6451 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6452 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6454 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6456 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6458 if (fd
->collapse
> 1)
6459 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6463 /* The code controlling the sequential loop goes in CONT_BB,
6464 replacing the GIMPLE_OMP_CONTINUE. */
6465 gsi
= gsi_last_bb (cont_bb
);
6466 stmt
= gsi_stmt (gsi
);
6467 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6468 vmain
= gimple_omp_continue_control_use (stmt
);
6469 vback
= gimple_omp_continue_control_def (stmt
);
6471 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6473 if (POINTER_TYPE_P (type
))
6474 t
= fold_build_pointer_plus (vmain
, step
);
6476 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6477 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
6478 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6479 true, GSI_SAME_STMT
);
6480 stmt
= gimple_build_assign (vback
, t
);
6481 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6483 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6484 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6486 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6489 /* Remove GIMPLE_OMP_CONTINUE. */
6490 gsi_remove (&gsi
, true);
6492 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6493 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6495 /* Trip update code goes into TRIP_UPDATE_BB. */
6496 gsi
= gsi_start_bb (trip_update_bb
);
6498 t
= build_int_cst (itype
, 1);
6499 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
6500 stmt
= gimple_build_assign (trip_back
, t
);
6501 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6504 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6505 gsi
= gsi_last_bb (exit_bb
);
6506 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6508 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6509 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6511 gsi_remove (&gsi
, true);
6513 /* Connect the new blocks. */
6514 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
6515 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
6519 se
= find_edge (cont_bb
, body_bb
);
6520 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6525 else if (fd
->collapse
> 1)
6528 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6531 se
->flags
= EDGE_TRUE_VALUE
;
6532 find_edge (cont_bb
, trip_update_bb
)->flags
6533 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6535 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
6538 if (gimple_in_ssa_p (cfun
))
6540 gimple_stmt_iterator psi
;
6543 edge_var_map_vector
*head
;
6547 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
6549 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6550 remove arguments of the phi nodes in fin_bb. We need to create
6551 appropriate phi nodes in iter_part_bb instead. */
6552 se
= single_pred_edge (fin_bb
);
6553 re
= single_succ_edge (trip_update_bb
);
6554 head
= redirect_edge_var_map_vector (re
);
6555 ene
= single_succ_edge (entry_bb
);
6557 psi
= gsi_start_phis (fin_bb
);
6558 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
6559 gsi_next (&psi
), ++i
)
6562 source_location locus
;
6564 phi
= gsi_stmt (psi
);
6565 t
= gimple_phi_result (phi
);
6566 gcc_assert (t
== redirect_edge_var_map_result (vm
));
6567 nphi
= create_phi_node (t
, iter_part_bb
);
6569 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
6570 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
6572 /* A special case -- fd->loop.v is not yet computed in
6573 iter_part_bb, we need to use vextra instead. */
6574 if (t
== fd
->loop
.v
)
6576 add_phi_arg (nphi
, t
, ene
, locus
);
6577 locus
= redirect_edge_var_map_location (vm
);
6578 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
6580 gcc_assert (!gsi_end_p (psi
) && i
== head
->length ());
6581 redirect_edge_var_map_clear (re
);
6584 psi
= gsi_start_phis (fin_bb
);
6585 if (gsi_end_p (psi
))
6587 remove_phi_node (&psi
, false);
6590 /* Make phi node for trip. */
6591 phi
= create_phi_node (trip_main
, iter_part_bb
);
6592 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
6594 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
6599 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
6600 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
6601 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
6602 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6603 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6604 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
6605 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
6606 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6607 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6611 struct loop
*trip_loop
= alloc_loop ();
6612 trip_loop
->header
= iter_part_bb
;
6613 trip_loop
->latch
= trip_update_bb
;
6614 add_loop (trip_loop
, iter_part_bb
->loop_father
);
6616 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6618 struct loop
*loop
= alloc_loop ();
6619 loop
->header
= body_bb
;
6620 if (collapse_bb
== NULL
)
6621 loop
->latch
= cont_bb
;
6622 add_loop (loop
, trip_loop
);
6628 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6629 loop. Given parameters:
6631 for (V = N1; V cond N2; V += STEP) BODY;
6633 where COND is "<" or ">", we generate pseudocode
6641 if (V cond N2) goto L0; else goto L2;
6644 For collapsed loops, given parameters:
6646 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6647 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6648 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6651 we generate pseudocode
6657 count3 = (adj + N32 - N31) / STEP3;
6662 count2 = (adj + N22 - N21) / STEP2;
6667 count1 = (adj + N12 - N11) / STEP1;
6668 count = count1 * count2 * count3;
6678 V2 += (V3 cond3 N32) ? 0 : STEP2;
6679 V3 = (V3 cond3 N32) ? V3 : N31;
6680 V1 += (V2 cond2 N22) ? 0 : STEP1;
6681 V2 = (V2 cond2 N22) ? V2 : N21;
6683 if (V < count) goto L0; else goto L2;
6689 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
6692 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
6693 gimple_stmt_iterator gsi
;
6695 bool broken_loop
= region
->cont
== NULL
;
6697 tree
*counts
= NULL
;
6699 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6700 OMP_CLAUSE_SAFELEN
);
6701 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6702 OMP_CLAUSE__SIMDUID_
);
6705 type
= TREE_TYPE (fd
->loop
.v
);
6706 entry_bb
= region
->entry
;
6707 cont_bb
= region
->cont
;
6708 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6709 gcc_assert (broken_loop
6710 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6711 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
6714 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
6715 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6716 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
6717 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6721 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
6722 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
6723 l2_bb
= single_succ (l1_bb
);
6725 exit_bb
= region
->exit
;
6728 gsi
= gsi_last_bb (entry_bb
);
6730 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6731 /* Not needed in SSA form right now. */
6732 gcc_assert (!gimple_in_ssa_p (cfun
));
6733 if (fd
->collapse
> 1)
6735 int first_zero_iter
= -1;
6736 basic_block zero_iter_bb
= l2_bb
;
6738 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6739 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6740 zero_iter_bb
, first_zero_iter
,
6743 if (l2_dom_bb
== NULL
)
6748 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6750 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6751 OMP_CLAUSE__LOOPTEMP_
);
6752 gcc_assert (innerc
);
6753 n1
= OMP_CLAUSE_DECL (innerc
);
6754 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6755 OMP_CLAUSE__LOOPTEMP_
);
6756 gcc_assert (innerc
);
6757 n2
= OMP_CLAUSE_DECL (innerc
);
6758 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
6759 fold_convert (type
, n1
));
6760 if (fd
->collapse
> 1)
6763 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
6769 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
6770 fold_convert (type
, fd
->loop
.n1
));
6771 if (fd
->collapse
> 1)
6772 for (i
= 0; i
< fd
->collapse
; i
++)
6774 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
6775 if (POINTER_TYPE_P (itype
))
6776 itype
= signed_type_for (itype
);
6777 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
6778 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
6782 /* Remove the GIMPLE_OMP_FOR statement. */
6783 gsi_remove (&gsi
, true);
6787 /* Code to control the increment goes in the CONT_BB. */
6788 gsi
= gsi_last_bb (cont_bb
);
6789 stmt
= gsi_stmt (gsi
);
6790 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6792 if (POINTER_TYPE_P (type
))
6793 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
6795 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
6796 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
6798 if (fd
->collapse
> 1)
6800 i
= fd
->collapse
- 1;
6801 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
6803 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
6804 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
6808 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
6810 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
6813 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
6815 for (i
= fd
->collapse
- 1; i
> 0; i
--)
6817 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
6818 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
6819 if (POINTER_TYPE_P (itype2
))
6820 itype2
= signed_type_for (itype2
);
6821 t
= build3 (COND_EXPR
, itype2
,
6822 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
6824 fold_convert (itype
, fd
->loops
[i
].n2
)),
6825 build_int_cst (itype2
, 0),
6826 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
6827 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
6828 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
6830 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
6831 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
6833 t
= build3 (COND_EXPR
, itype
,
6834 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
6836 fold_convert (itype
, fd
->loops
[i
].n2
)),
6838 fold_convert (itype
, fd
->loops
[i
].n1
));
6839 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
6843 /* Remove GIMPLE_OMP_CONTINUE. */
6844 gsi_remove (&gsi
, true);
6847 /* Emit the condition in L1_BB. */
6848 gsi
= gsi_start_bb (l1_bb
);
6850 t
= fold_convert (type
, n2
);
6851 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6852 false, GSI_CONTINUE_LINKING
);
6853 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
6854 stmt
= gimple_build_cond_empty (t
);
6855 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6856 if (walk_tree (gimple_cond_lhs_ptr (stmt
), expand_omp_regimplify_p
,
6858 || walk_tree (gimple_cond_rhs_ptr (stmt
), expand_omp_regimplify_p
,
6861 gsi
= gsi_for_stmt (stmt
);
6862 gimple_regimplify_operands (stmt
, &gsi
);
6865 /* Remove GIMPLE_OMP_RETURN. */
6866 gsi
= gsi_last_bb (exit_bb
);
6867 gsi_remove (&gsi
, true);
6869 /* Connect the new blocks. */
6870 remove_edge (FALLTHRU_EDGE (entry_bb
));
6874 remove_edge (BRANCH_EDGE (entry_bb
));
6875 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
6877 e
= BRANCH_EDGE (l1_bb
);
6878 ne
= FALLTHRU_EDGE (l1_bb
);
6879 e
->flags
= EDGE_TRUE_VALUE
;
6883 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6885 ne
= single_succ_edge (l1_bb
);
6886 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6889 ne
->flags
= EDGE_FALSE_VALUE
;
6890 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6891 ne
->probability
= REG_BR_PROB_BASE
/ 8;
6893 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
6894 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
6895 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
6899 struct loop
*loop
= alloc_loop ();
6900 loop
->header
= l1_bb
;
6901 loop
->latch
= cont_bb
;
6902 add_loop (loop
, l1_bb
->loop_father
);
6903 if (safelen
== NULL_TREE
)
6904 loop
->safelen
= INT_MAX
;
6907 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
6908 if (TREE_CODE (safelen
) != INTEGER_CST
)
6910 else if (!tree_fits_uhwi_p (safelen
)
6911 || tree_to_uhwi (safelen
) > INT_MAX
)
6912 loop
->safelen
= INT_MAX
;
6914 loop
->safelen
= tree_to_uhwi (safelen
);
6915 if (loop
->safelen
== 1)
6920 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
6921 cfun
->has_simduid_loops
= true;
6923 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6925 if ((flag_tree_loop_vectorize
6926 || (!global_options_set
.x_flag_tree_loop_vectorize
6927 && !global_options_set
.x_flag_tree_vectorize
))
6928 && flag_tree_loop_optimize
6929 && loop
->safelen
> 1)
6931 loop
->force_vectorize
= true;
6932 cfun
->has_force_vectorize_loops
= true;
6938 /* Expand the OpenMP loop defined by REGION. */
6941 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
6943 struct omp_for_data fd
;
6944 struct omp_for_data_loop
*loops
;
6947 = (struct omp_for_data_loop
*)
6948 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
6949 * sizeof (struct omp_for_data_loop
));
6950 extract_omp_for_data (last_stmt (region
->entry
), &fd
, loops
);
6951 region
->sched_kind
= fd
.sched_kind
;
6953 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
6954 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
6955 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
6958 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
6959 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
6960 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
6963 /* If there isn't a continue then this is a degerate case where
6964 the introduction of abnormal edges during lowering will prevent
6965 original loops from being detected. Fix that up. */
6966 loops_state_set (LOOPS_NEED_FIXUP
);
6968 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
6969 expand_omp_simd (region
, &fd
);
6970 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
6971 && !fd
.have_ordered
)
6973 if (fd
.chunk_size
== NULL
)
6974 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
6976 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
6980 int fn_index
, start_ix
, next_ix
;
6982 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
6983 == GF_OMP_FOR_KIND_FOR
);
6984 if (fd
.chunk_size
== NULL
6985 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
6986 fd
.chunk_size
= integer_zero_node
;
6987 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
6988 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
6989 ? 3 : fd
.sched_kind
;
6990 fn_index
+= fd
.have_ordered
* 4;
6991 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
6992 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
6993 if (fd
.iter_type
== long_long_unsigned_type_node
)
6995 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6996 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
6997 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6998 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7000 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7001 (enum built_in_function
) next_ix
, inner_stmt
);
7004 if (gimple_in_ssa_p (cfun
))
7005 update_ssa (TODO_update_ssa_only_virtuals
);
7009 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7011 v = GOMP_sections_start (n);
7028 v = GOMP_sections_next ();
7033 If this is a combined parallel sections, replace the call to
7034 GOMP_sections_start with call to GOMP_sections_next. */
7037 expand_omp_sections (struct omp_region
*region
)
7039 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7041 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7042 gimple_stmt_iterator si
, switch_si
;
7043 gimple sections_stmt
, stmt
, cont
;
7046 struct omp_region
*inner
;
7048 bool exit_reachable
= region
->cont
!= NULL
;
7050 gcc_assert (region
->exit
!= NULL
);
7051 entry_bb
= region
->entry
;
7052 l0_bb
= single_succ (entry_bb
);
7053 l1_bb
= region
->cont
;
7054 l2_bb
= region
->exit
;
7055 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7056 l2
= gimple_block_label (l2_bb
);
7059 /* This can happen if there are reductions. */
7060 len
= EDGE_COUNT (l0_bb
->succs
);
7061 gcc_assert (len
> 0);
7062 e
= EDGE_SUCC (l0_bb
, len
- 1);
7063 si
= gsi_last_bb (e
->dest
);
7066 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7067 l2
= gimple_block_label (e
->dest
);
7069 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7071 si
= gsi_last_bb (e
->dest
);
7073 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7075 l2
= gimple_block_label (e
->dest
);
7081 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7083 default_bb
= create_empty_bb (l0_bb
);
7085 /* We will build a switch() with enough cases for all the
7086 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7087 and a default case to abort if something goes wrong. */
7088 len
= EDGE_COUNT (l0_bb
->succs
);
7090 /* Use vec::quick_push on label_vec throughout, since we know the size
7092 auto_vec
<tree
> label_vec (len
);
7094 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7095 GIMPLE_OMP_SECTIONS statement. */
7096 si
= gsi_last_bb (entry_bb
);
7097 sections_stmt
= gsi_stmt (si
);
7098 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
7099 vin
= gimple_omp_sections_control (sections_stmt
);
7100 if (!is_combined_parallel (region
))
7102 /* If we are not inside a combined parallel+sections region,
7103 call GOMP_sections_start. */
7104 t
= build_int_cst (unsigned_type_node
, len
- 1);
7105 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
7106 stmt
= gimple_build_call (u
, 1, t
);
7110 /* Otherwise, call GOMP_sections_next. */
7111 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7112 stmt
= gimple_build_call (u
, 0);
7114 gimple_call_set_lhs (stmt
, vin
);
7115 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7116 gsi_remove (&si
, true);
7118 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7120 switch_si
= gsi_last_bb (l0_bb
);
7121 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
7124 cont
= last_stmt (l1_bb
);
7125 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
7126 vmain
= gimple_omp_continue_control_use (cont
);
7127 vnext
= gimple_omp_continue_control_def (cont
);
7135 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
7136 label_vec
.quick_push (t
);
7139 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7140 for (inner
= region
->inner
, casei
= 1;
7142 inner
= inner
->next
, i
++, casei
++)
7144 basic_block s_entry_bb
, s_exit_bb
;
7146 /* Skip optional reduction region. */
7147 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
7154 s_entry_bb
= inner
->entry
;
7155 s_exit_bb
= inner
->exit
;
7157 t
= gimple_block_label (s_entry_bb
);
7158 u
= build_int_cst (unsigned_type_node
, casei
);
7159 u
= build_case_label (u
, NULL
, t
);
7160 label_vec
.quick_push (u
);
7162 si
= gsi_last_bb (s_entry_bb
);
7163 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
7164 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
7165 gsi_remove (&si
, true);
7166 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
7168 if (s_exit_bb
== NULL
)
7171 si
= gsi_last_bb (s_exit_bb
);
7172 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7173 gsi_remove (&si
, true);
7175 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
7178 /* Error handling code goes in DEFAULT_BB. */
7179 t
= gimple_block_label (default_bb
);
7180 u
= build_case_label (NULL
, NULL
, t
);
7181 make_edge (l0_bb
, default_bb
, 0);
7182 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
7184 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
7185 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
7186 gsi_remove (&switch_si
, true);
7188 si
= gsi_start_bb (default_bb
);
7189 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
7190 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
7196 /* Code to get the next section goes in L1_BB. */
7197 si
= gsi_last_bb (l1_bb
);
7198 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
7200 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7201 stmt
= gimple_build_call (bfn_decl
, 0);
7202 gimple_call_set_lhs (stmt
, vnext
);
7203 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7204 gsi_remove (&si
, true);
7206 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
7209 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7210 si
= gsi_last_bb (l2_bb
);
7211 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
7212 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
7213 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
7214 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
7216 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
7217 stmt
= gimple_build_call (t
, 0);
7218 if (gimple_omp_return_lhs (gsi_stmt (si
)))
7219 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
7220 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7221 gsi_remove (&si
, true);
7223 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
7227 /* Expand code for an OpenMP single directive. We've already expanded
7228 much of the code, here we simply place the GOMP_barrier call. */
7231 expand_omp_single (struct omp_region
*region
)
7233 basic_block entry_bb
, exit_bb
;
7234 gimple_stmt_iterator si
;
7236 entry_bb
= region
->entry
;
7237 exit_bb
= region
->exit
;
7239 si
= gsi_last_bb (entry_bb
);
7240 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
7241 gsi_remove (&si
, true);
7242 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7244 si
= gsi_last_bb (exit_bb
);
7245 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
7247 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
7248 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
7250 gsi_remove (&si
, true);
7251 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7255 /* Generic expansion for OpenMP synchronization directives: master,
7256 ordered and critical. All we need to do here is remove the entry
7257 and exit markers for REGION. */
7260 expand_omp_synch (struct omp_region
*region
)
7262 basic_block entry_bb
, exit_bb
;
7263 gimple_stmt_iterator si
;
7265 entry_bb
= region
->entry
;
7266 exit_bb
= region
->exit
;
7268 si
= gsi_last_bb (entry_bb
);
7269 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
7270 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
7271 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
7272 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
7273 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
7274 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
7275 gsi_remove (&si
, true);
7276 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7280 si
= gsi_last_bb (exit_bb
);
7281 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7282 gsi_remove (&si
, true);
7283 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7287 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7288 operation as a normal volatile load. */
7291 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
7292 tree loaded_val
, int index
)
7294 enum built_in_function tmpbase
;
7295 gimple_stmt_iterator gsi
;
7296 basic_block store_bb
;
7299 tree decl
, call
, type
, itype
;
7301 gsi
= gsi_last_bb (load_bb
);
7302 stmt
= gsi_stmt (gsi
);
7303 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7304 loc
= gimple_location (stmt
);
7306 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7307 is smaller than word size, then expand_atomic_load assumes that the load
7308 is atomic. We could avoid the builtin entirely in this case. */
7310 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7311 decl
= builtin_decl_explicit (tmpbase
);
7312 if (decl
== NULL_TREE
)
7315 type
= TREE_TYPE (loaded_val
);
7316 itype
= TREE_TYPE (TREE_TYPE (decl
));
7318 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
7319 build_int_cst (NULL
,
7320 gimple_omp_atomic_seq_cst_p (stmt
)
7322 : MEMMODEL_RELAXED
));
7323 if (!useless_type_conversion_p (type
, itype
))
7324 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7325 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7327 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7328 gsi_remove (&gsi
, true);
7330 store_bb
= single_succ (load_bb
);
7331 gsi
= gsi_last_bb (store_bb
);
7332 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7333 gsi_remove (&gsi
, true);
7335 if (gimple_in_ssa_p (cfun
))
7336 update_ssa (TODO_update_ssa_no_phi
);
7341 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7342 operation as a normal volatile store. */
7345 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
7346 tree loaded_val
, tree stored_val
, int index
)
7348 enum built_in_function tmpbase
;
7349 gimple_stmt_iterator gsi
;
7350 basic_block store_bb
= single_succ (load_bb
);
7353 tree decl
, call
, type
, itype
;
7354 enum machine_mode imode
;
7357 gsi
= gsi_last_bb (load_bb
);
7358 stmt
= gsi_stmt (gsi
);
7359 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7361 /* If the load value is needed, then this isn't a store but an exchange. */
7362 exchange
= gimple_omp_atomic_need_value_p (stmt
);
7364 gsi
= gsi_last_bb (store_bb
);
7365 stmt
= gsi_stmt (gsi
);
7366 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
7367 loc
= gimple_location (stmt
);
7369 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7370 is smaller than word size, then expand_atomic_store assumes that the store
7371 is atomic. We could avoid the builtin entirely in this case. */
7373 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
7374 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
7375 decl
= builtin_decl_explicit (tmpbase
);
7376 if (decl
== NULL_TREE
)
7379 type
= TREE_TYPE (stored_val
);
7381 /* Dig out the type of the function's second argument. */
7382 itype
= TREE_TYPE (decl
);
7383 itype
= TYPE_ARG_TYPES (itype
);
7384 itype
= TREE_CHAIN (itype
);
7385 itype
= TREE_VALUE (itype
);
7386 imode
= TYPE_MODE (itype
);
7388 if (exchange
&& !can_atomic_exchange_p (imode
, true))
7391 if (!useless_type_conversion_p (itype
, type
))
7392 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
7393 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
7394 build_int_cst (NULL
,
7395 gimple_omp_atomic_seq_cst_p (stmt
)
7397 : MEMMODEL_RELAXED
));
7400 if (!useless_type_conversion_p (type
, itype
))
7401 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7402 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7405 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7406 gsi_remove (&gsi
, true);
7408 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7409 gsi
= gsi_last_bb (load_bb
);
7410 gsi_remove (&gsi
, true);
7412 if (gimple_in_ssa_p (cfun
))
7413 update_ssa (TODO_update_ssa_no_phi
);
7418 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7419 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7420 size of the data type, and thus usable to find the index of the builtin
7421 decl. Returns false if the expression is not of the proper form. */
7424 expand_omp_atomic_fetch_op (basic_block load_bb
,
7425 tree addr
, tree loaded_val
,
7426 tree stored_val
, int index
)
7428 enum built_in_function oldbase
, newbase
, tmpbase
;
7429 tree decl
, itype
, call
;
7431 basic_block store_bb
= single_succ (load_bb
);
7432 gimple_stmt_iterator gsi
;
7435 enum tree_code code
;
7436 bool need_old
, need_new
;
7437 enum machine_mode imode
;
7440 /* We expect to find the following sequences:
7443 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7446 val = tmp OP something; (or: something OP tmp)
7447 GIMPLE_OMP_STORE (val)
7449 ???FIXME: Allow a more flexible sequence.
7450 Perhaps use data flow to pick the statements.
7454 gsi
= gsi_after_labels (store_bb
);
7455 stmt
= gsi_stmt (gsi
);
7456 loc
= gimple_location (stmt
);
7457 if (!is_gimple_assign (stmt
))
7460 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
7462 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
7463 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
7464 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
7465 gcc_checking_assert (!need_old
|| !need_new
);
7467 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
7470 /* Check for one of the supported fetch-op operations. */
7471 code
= gimple_assign_rhs_code (stmt
);
7475 case POINTER_PLUS_EXPR
:
7476 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
7477 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
7480 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
7481 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
7484 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
7485 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
7488 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
7489 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
7492 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
7493 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
7499 /* Make sure the expression is of the proper form. */
7500 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
7501 rhs
= gimple_assign_rhs2 (stmt
);
7502 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
7503 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
7504 rhs
= gimple_assign_rhs1 (stmt
);
7508 tmpbase
= ((enum built_in_function
)
7509 ((need_new
? newbase
: oldbase
) + index
+ 1));
7510 decl
= builtin_decl_explicit (tmpbase
);
7511 if (decl
== NULL_TREE
)
7513 itype
= TREE_TYPE (TREE_TYPE (decl
));
7514 imode
= TYPE_MODE (itype
);
7516 /* We could test all of the various optabs involved, but the fact of the
7517 matter is that (with the exception of i486 vs i586 and xadd) all targets
7518 that support any atomic operaton optab also implements compare-and-swap.
7519 Let optabs.c take care of expanding any compare-and-swap loop. */
7520 if (!can_compare_and_swap_p (imode
, true))
7523 gsi
= gsi_last_bb (load_bb
);
7524 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7526 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7527 It only requires that the operation happen atomically. Thus we can
7528 use the RELAXED memory model. */
7529 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
7530 fold_convert_loc (loc
, itype
, rhs
),
7531 build_int_cst (NULL
,
7532 seq_cst
? MEMMODEL_SEQ_CST
7533 : MEMMODEL_RELAXED
));
7535 if (need_old
|| need_new
)
7537 lhs
= need_old
? loaded_val
: stored_val
;
7538 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
7539 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
7542 call
= fold_convert_loc (loc
, void_type_node
, call
);
7543 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7544 gsi_remove (&gsi
, true);
7546 gsi
= gsi_last_bb (store_bb
);
7547 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7548 gsi_remove (&gsi
, true);
7549 gsi
= gsi_last_bb (store_bb
);
7550 gsi_remove (&gsi
, true);
7552 if (gimple_in_ssa_p (cfun
))
7553 update_ssa (TODO_update_ssa_no_phi
);
7558 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7562 newval = rhs; // with oldval replacing *addr in rhs
7563 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7564 if (oldval != newval)
7567 INDEX is log2 of the size of the data type, and thus usable to find the
7568 index of the builtin decl. */
7571 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
7572 tree addr
, tree loaded_val
, tree stored_val
,
7575 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
7576 tree type
, itype
, cmpxchg
, iaddr
;
7577 gimple_stmt_iterator si
;
7578 basic_block loop_header
= single_succ (load_bb
);
7581 enum built_in_function fncode
;
7583 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7584 order to use the RELAXED memory model effectively. */
7585 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7587 cmpxchg
= builtin_decl_explicit (fncode
);
7588 if (cmpxchg
== NULL_TREE
)
7590 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
7591 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
7593 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
7596 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7597 si
= gsi_last_bb (load_bb
);
7598 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7600 /* For floating-point values, we'll need to view-convert them to integers
7601 so that we can perform the atomic compare and swap. Simplify the
7602 following code by always setting up the "i"ntegral variables. */
7603 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
7607 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
7610 = force_gimple_operand_gsi (&si
,
7611 fold_convert (TREE_TYPE (iaddr
), addr
),
7612 false, NULL_TREE
, true, GSI_SAME_STMT
);
7613 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
7614 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7615 loadedi
= create_tmp_var (itype
, NULL
);
7616 if (gimple_in_ssa_p (cfun
))
7617 loadedi
= make_ssa_name (loadedi
, NULL
);
7622 loadedi
= loaded_val
;
7625 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7626 tree loaddecl
= builtin_decl_explicit (fncode
);
7629 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
7630 build_call_expr (loaddecl
, 2, iaddr
,
7631 build_int_cst (NULL_TREE
,
7632 MEMMODEL_RELAXED
)));
7634 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
7635 build_int_cst (TREE_TYPE (iaddr
), 0));
7638 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
7641 /* Move the value to the LOADEDI temporary. */
7642 if (gimple_in_ssa_p (cfun
))
7644 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
7645 phi
= create_phi_node (loadedi
, loop_header
);
7646 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
7650 gsi_insert_before (&si
,
7651 gimple_build_assign (loadedi
, initial
),
7653 if (loadedi
!= loaded_val
)
7655 gimple_stmt_iterator gsi2
;
7658 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
7659 gsi2
= gsi_start_bb (loop_header
);
7660 if (gimple_in_ssa_p (cfun
))
7663 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
7664 true, GSI_SAME_STMT
);
7665 stmt
= gimple_build_assign (loaded_val
, x
);
7666 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
7670 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
7671 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
7672 true, GSI_SAME_STMT
);
7675 gsi_remove (&si
, true);
7677 si
= gsi_last_bb (store_bb
);
7678 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
7681 storedi
= stored_val
;
7684 force_gimple_operand_gsi (&si
,
7685 build1 (VIEW_CONVERT_EXPR
, itype
,
7686 stored_val
), true, NULL_TREE
, true,
7689 /* Build the compare&swap statement. */
7690 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
7691 new_storedi
= force_gimple_operand_gsi (&si
,
7692 fold_convert (TREE_TYPE (loadedi
),
7695 true, GSI_SAME_STMT
);
7697 if (gimple_in_ssa_p (cfun
))
7701 old_vali
= create_tmp_var (TREE_TYPE (loadedi
), NULL
);
7702 stmt
= gimple_build_assign (old_vali
, loadedi
);
7703 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7705 stmt
= gimple_build_assign (loadedi
, new_storedi
);
7706 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7709 /* Note that we always perform the comparison as an integer, even for
7710 floating point. This allows the atomic operation to properly
7711 succeed even with NaNs and -0.0. */
7712 stmt
= gimple_build_cond_empty
7713 (build2 (NE_EXPR
, boolean_type_node
,
7714 new_storedi
, old_vali
));
7715 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7718 e
= single_succ_edge (store_bb
);
7719 e
->flags
&= ~EDGE_FALLTHRU
;
7720 e
->flags
|= EDGE_FALSE_VALUE
;
7722 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
7724 /* Copy the new value to loadedi (we already did that before the condition
7725 if we are not in SSA). */
7726 if (gimple_in_ssa_p (cfun
))
7728 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
7729 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
7732 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7733 gsi_remove (&si
, true);
7735 struct loop
*loop
= alloc_loop ();
7736 loop
->header
= loop_header
;
7737 loop
->latch
= store_bb
;
7738 add_loop (loop
, loop_header
->loop_father
);
7740 if (gimple_in_ssa_p (cfun
))
7741 update_ssa (TODO_update_ssa_no_phi
);
7746 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7748 GOMP_atomic_start ();
7752 The result is not globally atomic, but works so long as all parallel
7753 references are within #pragma omp atomic directives. According to
7754 responses received from omp@openmp.org, appears to be within spec.
7755 Which makes sense, since that's how several other compilers handle
7756 this situation as well.
7757 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7758 expanding. STORED_VAL is the operand of the matching
7759 GIMPLE_OMP_ATOMIC_STORE.
7762 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7766 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7771 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
7772 tree addr
, tree loaded_val
, tree stored_val
)
7774 gimple_stmt_iterator si
;
7778 si
= gsi_last_bb (load_bb
);
7779 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7781 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
7782 t
= build_call_expr (t
, 0);
7783 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7785 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
7786 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7787 gsi_remove (&si
, true);
7789 si
= gsi_last_bb (store_bb
);
7790 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
7792 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
7794 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7796 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
7797 t
= build_call_expr (t
, 0);
7798 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7799 gsi_remove (&si
, true);
7801 if (gimple_in_ssa_p (cfun
))
7802 update_ssa (TODO_update_ssa_no_phi
);
7806 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7807 using expand_omp_atomic_fetch_op. If it failed, we try to
7808 call expand_omp_atomic_pipeline, and if it fails too, the
7809 ultimate fallback is wrapping the operation in a mutex
7810 (expand_omp_atomic_mutex). REGION is the atomic region built
7811 by build_omp_regions_1(). */
7814 expand_omp_atomic (struct omp_region
*region
)
7816 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
7817 gimple load
= last_stmt (load_bb
), store
= last_stmt (store_bb
);
7818 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
7819 tree addr
= gimple_omp_atomic_load_rhs (load
);
7820 tree stored_val
= gimple_omp_atomic_store_val (store
);
7821 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
7822 HOST_WIDE_INT index
;
7824 /* Make sure the type is one of the supported sizes. */
7825 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
7826 index
= exact_log2 (index
);
7827 if (index
>= 0 && index
<= 4)
7829 unsigned int align
= TYPE_ALIGN_UNIT (type
);
7831 /* __sync builtins require strict data alignment. */
7832 if (exact_log2 (align
) >= index
)
7835 if (loaded_val
== stored_val
7836 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
7837 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
7838 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
7839 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
7843 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
7844 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
7845 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
7846 && store_bb
== single_succ (load_bb
)
7847 && first_stmt (store_bb
) == store
7848 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
7852 /* When possible, use specialized atomic update functions. */
7853 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
7854 && store_bb
== single_succ (load_bb
)
7855 && expand_omp_atomic_fetch_op (load_bb
, addr
,
7856 loaded_val
, stored_val
, index
))
7859 /* If we don't have specialized __sync builtins, try and implement
7860 as a compare and swap loop. */
7861 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
7862 loaded_val
, stored_val
, index
))
7867 /* The ultimate fallback is wrapping the operation in a mutex. */
7868 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
7872 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7875 expand_omp_target (struct omp_region
*region
)
7877 basic_block entry_bb
, exit_bb
, new_bb
;
7878 struct function
*child_cfun
= NULL
;
7879 tree child_fn
= NULL_TREE
, block
, t
;
7880 gimple_stmt_iterator gsi
;
7881 gimple entry_stmt
, stmt
;
7884 entry_stmt
= last_stmt (region
->entry
);
7885 new_bb
= region
->entry
;
7886 int kind
= gimple_omp_target_kind (entry_stmt
);
7887 if (kind
== GF_OMP_TARGET_KIND_REGION
)
7889 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
7890 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
7893 entry_bb
= region
->entry
;
7894 exit_bb
= region
->exit
;
7896 if (kind
== GF_OMP_TARGET_KIND_REGION
)
7898 unsigned srcidx
, dstidx
, num
;
7900 /* If the target region needs data sent from the parent
7901 function, then the very first statement (except possible
7902 tree profile counter updates) of the parallel body
7903 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7904 &.OMP_DATA_O is passed as an argument to the child function,
7905 we need to replace it with the argument as seen by the child
7908 In most cases, this will end up being the identity assignment
7909 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7910 a function call that has been inlined, the original PARM_DECL
7911 .OMP_DATA_I may have been converted into a different local
7912 variable. In which case, we need to keep the assignment. */
7913 if (gimple_omp_target_data_arg (entry_stmt
))
7915 basic_block entry_succ_bb
= single_succ (entry_bb
);
7916 gimple_stmt_iterator gsi
;
7918 gimple tgtcopy_stmt
= NULL
;
7920 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt
), 0);
7922 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
7924 gcc_assert (!gsi_end_p (gsi
));
7925 stmt
= gsi_stmt (gsi
);
7926 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
7929 if (gimple_num_ops (stmt
) == 2)
7931 tree arg
= gimple_assign_rhs1 (stmt
);
7933 /* We're ignoring the subcode because we're
7934 effectively doing a STRIP_NOPS. */
7936 if (TREE_CODE (arg
) == ADDR_EXPR
7937 && TREE_OPERAND (arg
, 0) == sender
)
7939 tgtcopy_stmt
= stmt
;
7945 gcc_assert (tgtcopy_stmt
!= NULL
);
7946 arg
= DECL_ARGUMENTS (child_fn
);
7948 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
7949 gsi_remove (&gsi
, true);
7952 /* Declare local variables needed in CHILD_CFUN. */
7953 block
= DECL_INITIAL (child_fn
);
7954 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
7955 /* The gimplifier could record temporaries in target block
7956 rather than in containing function's local_decls chain,
7957 which would mean cgraph missed finalizing them. Do it now. */
7958 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
7959 if (TREE_CODE (t
) == VAR_DECL
7961 && !DECL_EXTERNAL (t
))
7962 varpool_finalize_decl (t
);
7963 DECL_SAVED_TREE (child_fn
) = NULL
;
7964 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7965 gimple_set_body (child_fn
, NULL
);
7966 TREE_USED (block
) = 1;
7968 /* Reset DECL_CONTEXT on function arguments. */
7969 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
7970 DECL_CONTEXT (t
) = child_fn
;
7972 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7973 so that it can be moved to the child function. */
7974 gsi
= gsi_last_bb (entry_bb
);
7975 stmt
= gsi_stmt (gsi
);
7976 gcc_assert (stmt
&& gimple_code (stmt
) == GIMPLE_OMP_TARGET
7977 && gimple_omp_target_kind (stmt
)
7978 == GF_OMP_TARGET_KIND_REGION
);
7979 gsi_remove (&gsi
, true);
7980 e
= split_block (entry_bb
, stmt
);
7982 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7984 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7987 gsi
= gsi_last_bb (exit_bb
);
7988 gcc_assert (!gsi_end_p (gsi
)
7989 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
7990 stmt
= gimple_build_return (NULL
);
7991 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
7992 gsi_remove (&gsi
, true);
7995 /* Move the target region into CHILD_CFUN. */
7997 block
= gimple_block (entry_stmt
);
7999 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
8001 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
8002 /* When the OMP expansion process cannot guarantee an up-to-date
8003 loop tree arrange for the child function to fixup loops. */
8004 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
8005 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
8007 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8008 num
= vec_safe_length (child_cfun
->local_decls
);
8009 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
8011 t
= (*child_cfun
->local_decls
)[srcidx
];
8012 if (DECL_CONTEXT (t
) == cfun
->decl
)
8014 if (srcidx
!= dstidx
)
8015 (*child_cfun
->local_decls
)[dstidx
] = t
;
8019 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
8021 /* Inform the callgraph about the new function. */
8022 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
8023 cgraph_add_new_function (child_fn
, true);
8025 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8026 fixed in a following pass. */
8027 push_cfun (child_cfun
);
8028 rebuild_cgraph_edges ();
8030 /* Some EH regions might become dead, see PR34608. If
8031 pass_cleanup_cfg isn't the first pass to happen with the
8032 new child, these dead EH edges might cause problems.
8033 Clean them up now. */
8034 if (flag_exceptions
)
8037 bool changed
= false;
8039 FOR_EACH_BB_FN (bb
, cfun
)
8040 changed
|= gimple_purge_dead_eh_edges (bb
);
8042 cleanup_tree_cfg ();
8047 /* Emit a library call to launch the target region, or do data
8049 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
8050 enum built_in_function start_ix
;
8051 location_t clause_loc
;
8053 clauses
= gimple_omp_target_clauses (entry_stmt
);
8055 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8056 start_ix
= BUILT_IN_GOMP_TARGET
;
8057 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
8058 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
8060 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
8062 /* By default, the value of DEVICE is -1 (let runtime library choose)
8063 and there is no conditional. */
8065 device
= build_int_cst (integer_type_node
, -1);
8067 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
8069 cond
= OMP_CLAUSE_IF_EXPR (c
);
8071 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
8074 device
= OMP_CLAUSE_DEVICE_ID (c
);
8075 clause_loc
= OMP_CLAUSE_LOCATION (c
);
8078 clause_loc
= gimple_location (entry_stmt
);
8080 /* Ensure 'device' is of the correct type. */
8081 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
8083 /* If we found the clause 'if (cond)', build
8084 (cond ? device : -2). */
8087 cond
= gimple_boolify (cond
);
8089 basic_block cond_bb
, then_bb
, else_bb
;
8093 tmp_var
= create_tmp_var (TREE_TYPE (device
), NULL
);
8094 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8096 gsi
= gsi_last_bb (new_bb
);
8098 e
= split_block (new_bb
, gsi_stmt (gsi
));
8101 e
= split_block (new_bb
, NULL
);
8106 then_bb
= create_empty_bb (cond_bb
);
8107 else_bb
= create_empty_bb (then_bb
);
8108 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
8109 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
8111 stmt
= gimple_build_cond_empty (cond
);
8112 gsi
= gsi_last_bb (cond_bb
);
8113 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8115 gsi
= gsi_start_bb (then_bb
);
8116 stmt
= gimple_build_assign (tmp_var
, device
);
8117 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8119 gsi
= gsi_start_bb (else_bb
);
8120 stmt
= gimple_build_assign (tmp_var
,
8121 build_int_cst (integer_type_node
, -2));
8122 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8124 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
8125 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
8126 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
8127 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
8128 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
8129 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
8134 gsi
= gsi_last_bb (new_bb
);
8135 t
= gimple_omp_target_data_arg (entry_stmt
);
8138 t1
= size_zero_node
;
8139 t2
= build_zero_cst (ptr_type_node
);
8145 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
8146 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
8147 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
8148 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
8149 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
8153 /* FIXME: This will be address of
8154 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8155 symbol, as soon as the linker plugin is able to create it for us. */
8156 tree openmp_target
= build_zero_cst (ptr_type_node
);
8157 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8159 tree fnaddr
= build_fold_addr_expr (child_fn
);
8160 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 7,
8161 device
, fnaddr
, openmp_target
, t1
, t2
, t3
, t4
);
8164 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 6,
8165 device
, openmp_target
, t1
, t2
, t3
, t4
);
8166 gimple_set_location (g
, gimple_location (entry_stmt
));
8167 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
8168 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8171 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
8172 gsi_remove (&gsi
, true);
8174 if (kind
== GF_OMP_TARGET_KIND_DATA
&& region
->exit
)
8176 gsi
= gsi_last_bb (region
->exit
);
8178 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
8179 gsi_remove (&gsi
, true);
8184 /* Expand the parallel region tree rooted at REGION. Expansion
8185 proceeds in depth-first order. Innermost regions are expanded
8186 first. This way, parallel regions that require a new function to
8187 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8188 internal dependencies in their body. */
8191 expand_omp (struct omp_region
*region
)
8195 location_t saved_location
;
8196 gimple inner_stmt
= NULL
;
8198 /* First, determine whether this is a combined parallel+workshare
8200 if (region
->type
== GIMPLE_OMP_PARALLEL
)
8201 determine_parallel_type (region
);
8203 if (region
->type
== GIMPLE_OMP_FOR
8204 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
8205 inner_stmt
= last_stmt (region
->inner
->entry
);
8208 expand_omp (region
->inner
);
8210 saved_location
= input_location
;
8211 if (gimple_has_location (last_stmt (region
->entry
)))
8212 input_location
= gimple_location (last_stmt (region
->entry
));
8214 switch (region
->type
)
8216 case GIMPLE_OMP_PARALLEL
:
8217 case GIMPLE_OMP_TASK
:
8218 expand_omp_taskreg (region
);
8221 case GIMPLE_OMP_FOR
:
8222 expand_omp_for (region
, inner_stmt
);
8225 case GIMPLE_OMP_SECTIONS
:
8226 expand_omp_sections (region
);
8229 case GIMPLE_OMP_SECTION
:
8230 /* Individual omp sections are handled together with their
8231 parent GIMPLE_OMP_SECTIONS region. */
8234 case GIMPLE_OMP_SINGLE
:
8235 expand_omp_single (region
);
8238 case GIMPLE_OMP_MASTER
:
8239 case GIMPLE_OMP_TASKGROUP
:
8240 case GIMPLE_OMP_ORDERED
:
8241 case GIMPLE_OMP_CRITICAL
:
8242 case GIMPLE_OMP_TEAMS
:
8243 expand_omp_synch (region
);
8246 case GIMPLE_OMP_ATOMIC_LOAD
:
8247 expand_omp_atomic (region
);
8250 case GIMPLE_OMP_TARGET
:
8251 expand_omp_target (region
);
8258 input_location
= saved_location
;
8259 region
= region
->next
;
8264 /* Helper for build_omp_regions. Scan the dominator tree starting at
8265 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8266 true, the function ends once a single tree is built (otherwise, whole
8267 forest of OMP constructs may be built). */
8270 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
8273 gimple_stmt_iterator gsi
;
8277 gsi
= gsi_last_bb (bb
);
8278 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
8280 struct omp_region
*region
;
8281 enum gimple_code code
;
8283 stmt
= gsi_stmt (gsi
);
8284 code
= gimple_code (stmt
);
8285 if (code
== GIMPLE_OMP_RETURN
)
8287 /* STMT is the return point out of region PARENT. Mark it
8288 as the exit point and make PARENT the immediately
8289 enclosing region. */
8290 gcc_assert (parent
);
8293 parent
= parent
->outer
;
8295 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
8297 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8298 GIMPLE_OMP_RETURN, but matches with
8299 GIMPLE_OMP_ATOMIC_LOAD. */
8300 gcc_assert (parent
);
8301 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
8304 parent
= parent
->outer
;
8307 else if (code
== GIMPLE_OMP_CONTINUE
)
8309 gcc_assert (parent
);
8312 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
8314 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8315 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8318 else if (code
== GIMPLE_OMP_TARGET
8319 && gimple_omp_target_kind (stmt
) == GF_OMP_TARGET_KIND_UPDATE
)
8320 new_omp_region (bb
, code
, parent
);
8323 /* Otherwise, this directive becomes the parent for a new
8325 region
= new_omp_region (bb
, code
, parent
);
8330 if (single_tree
&& !parent
)
8333 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
8335 son
= next_dom_son (CDI_DOMINATORS
, son
))
8336 build_omp_regions_1 (son
, parent
, single_tree
);
8339 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8343 build_omp_regions_root (basic_block root
)
8345 gcc_assert (root_omp_region
== NULL
);
8346 build_omp_regions_1 (root
, NULL
, true);
8347 gcc_assert (root_omp_region
!= NULL
);
8350 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8353 omp_expand_local (basic_block head
)
8355 build_omp_regions_root (head
);
8356 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
8358 fprintf (dump_file
, "\nOMP region tree\n\n");
8359 dump_omp_region (dump_file
, root_omp_region
, 0);
8360 fprintf (dump_file
, "\n");
8363 remove_exit_barriers (root_omp_region
);
8364 expand_omp (root_omp_region
);
8366 free_omp_regions ();
8369 /* Scan the CFG and build a tree of OMP regions. Return the root of
8370 the OMP region tree. */
8373 build_omp_regions (void)
8375 gcc_assert (root_omp_region
== NULL
);
8376 calculate_dominance_info (CDI_DOMINATORS
);
8377 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
8380 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8383 execute_expand_omp (void)
8385 build_omp_regions ();
8387 if (!root_omp_region
)
8392 fprintf (dump_file
, "\nOMP region tree\n\n");
8393 dump_omp_region (dump_file
, root_omp_region
, 0);
8394 fprintf (dump_file
, "\n");
8397 remove_exit_barriers (root_omp_region
);
8399 expand_omp (root_omp_region
);
8401 cleanup_tree_cfg ();
8403 free_omp_regions ();
8408 /* OMP expansion -- the default pass, run before creation of SSA form. */
8412 const pass_data pass_data_expand_omp
=
8414 GIMPLE_PASS
, /* type */
8415 "ompexp", /* name */
8416 OPTGROUP_NONE
, /* optinfo_flags */
8417 TV_NONE
, /* tv_id */
8418 PROP_gimple_any
, /* properties_required */
8419 0, /* properties_provided */
8420 0, /* properties_destroyed */
8421 0, /* todo_flags_start */
8422 0, /* todo_flags_finish */
8425 class pass_expand_omp
: public gimple_opt_pass
8428 pass_expand_omp (gcc::context
*ctxt
)
8429 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
8432 /* opt_pass methods: */
8433 virtual bool gate (function
*)
8435 return ((flag_openmp
!= 0 || flag_openmp_simd
!= 0
8436 || flag_cilkplus
!= 0) && !seen_error ());
8439 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
8441 }; // class pass_expand_omp
8446 make_pass_expand_omp (gcc::context
*ctxt
)
8448 return new pass_expand_omp (ctxt
);
8451 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8453 /* If ctx is a worksharing context inside of a cancellable parallel
8454 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8455 and conditional branch to parallel's cancel_label to handle
8456 cancellation in the implicit barrier. */
8459 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
8461 gimple omp_return
= gimple_seq_last_stmt (*body
);
8462 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
8463 if (gimple_omp_return_nowait_p (omp_return
))
8466 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
8467 && ctx
->outer
->cancellable
)
8469 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
8470 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
8471 tree lhs
= create_tmp_var (c_bool_type
, NULL
);
8472 gimple_omp_return_set_lhs (omp_return
, lhs
);
8473 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
8474 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
8475 fold_convert (c_bool_type
,
8476 boolean_false_node
),
8477 ctx
->outer
->cancel_label
, fallthru_label
);
8478 gimple_seq_add_stmt (body
, g
);
8479 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
8483 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8484 CTX is the enclosing OMP context for the current statement. */
8487 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8489 tree block
, control
;
8490 gimple_stmt_iterator tgsi
;
8491 gimple stmt
, new_stmt
, bind
, t
;
8492 gimple_seq ilist
, dlist
, olist
, new_body
;
8494 stmt
= gsi_stmt (*gsi_p
);
8496 push_gimplify_context ();
8500 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
8501 &ilist
, &dlist
, ctx
, NULL
);
8503 new_body
= gimple_omp_body (stmt
);
8504 gimple_omp_set_body (stmt
, NULL
);
8505 tgsi
= gsi_start (new_body
);
8506 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
8511 sec_start
= gsi_stmt (tgsi
);
8512 sctx
= maybe_lookup_ctx (sec_start
);
8515 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
8516 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
8517 GSI_CONTINUE_LINKING
);
8518 gimple_omp_set_body (sec_start
, NULL
);
8520 if (gsi_one_before_end_p (tgsi
))
8522 gimple_seq l
= NULL
;
8523 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
8525 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
8526 gimple_omp_section_set_last (sec_start
);
8529 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
8530 GSI_CONTINUE_LINKING
);
8533 block
= make_node (BLOCK
);
8534 bind
= gimple_build_bind (NULL
, new_body
, block
);
8537 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
8539 block
= make_node (BLOCK
);
8540 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
8541 gsi_replace (gsi_p
, new_stmt
, true);
8543 pop_gimplify_context (new_stmt
);
8544 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
8545 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8546 if (BLOCK_VARS (block
))
8547 TREE_USED (block
) = 1;
8550 gimple_seq_add_seq (&new_body
, ilist
);
8551 gimple_seq_add_stmt (&new_body
, stmt
);
8552 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
8553 gimple_seq_add_stmt (&new_body
, bind
);
8555 control
= create_tmp_var (unsigned_type_node
, ".section");
8556 t
= gimple_build_omp_continue (control
, control
);
8557 gimple_omp_sections_set_control (stmt
, control
);
8558 gimple_seq_add_stmt (&new_body
, t
);
8560 gimple_seq_add_seq (&new_body
, olist
);
8561 if (ctx
->cancellable
)
8562 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
8563 gimple_seq_add_seq (&new_body
, dlist
);
8565 new_body
= maybe_catch_exception (new_body
);
8567 t
= gimple_build_omp_return
8568 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
8569 OMP_CLAUSE_NOWAIT
));
8570 gimple_seq_add_stmt (&new_body
, t
);
8571 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
8573 gimple_bind_set_body (new_stmt
, new_body
);
8577 /* A subroutine of lower_omp_single. Expand the simple form of
8578 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8580 if (GOMP_single_start ())
8582 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8584 FIXME. It may be better to delay expanding the logic of this until
8585 pass_expand_omp. The expanded logic may make the job more difficult
8586 to a synchronization analysis pass. */
8589 lower_omp_single_simple (gimple single_stmt
, gimple_seq
*pre_p
)
8591 location_t loc
= gimple_location (single_stmt
);
8592 tree tlabel
= create_artificial_label (loc
);
8593 tree flabel
= create_artificial_label (loc
);
8597 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
8598 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)), NULL
);
8599 call
= gimple_build_call (decl
, 0);
8600 gimple_call_set_lhs (call
, lhs
);
8601 gimple_seq_add_stmt (pre_p
, call
);
8603 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
8604 fold_convert_loc (loc
, TREE_TYPE (lhs
),
8607 gimple_seq_add_stmt (pre_p
, cond
);
8608 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
8609 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
8610 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
8614 /* A subroutine of lower_omp_single. Expand the simple form of
8615 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8617 #pragma omp single copyprivate (a, b, c)
8619 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8622 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8628 GOMP_single_copy_end (©out);
8639 FIXME. It may be better to delay expanding the logic of this until
8640 pass_expand_omp. The expanded logic may make the job more difficult
8641 to a synchronization analysis pass. */
8644 lower_omp_single_copy (gimple single_stmt
, gimple_seq
*pre_p
, omp_context
*ctx
)
8646 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
8647 gimple_seq copyin_seq
;
8648 location_t loc
= gimple_location (single_stmt
);
8650 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
8652 ptr_type
= build_pointer_type (ctx
->record_type
);
8653 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
8655 l0
= create_artificial_label (loc
);
8656 l1
= create_artificial_label (loc
);
8657 l2
= create_artificial_label (loc
);
8659 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
8660 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
8661 t
= fold_convert_loc (loc
, ptr_type
, t
);
8662 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
8664 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
8665 build_int_cst (ptr_type
, 0));
8666 t
= build3 (COND_EXPR
, void_type_node
, t
,
8667 build_and_jump (&l0
), build_and_jump (&l1
));
8668 gimplify_and_add (t
, pre_p
);
8670 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
8672 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
8675 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
8678 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
8679 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
8680 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
8681 gimplify_and_add (t
, pre_p
);
8683 t
= build_and_jump (&l2
);
8684 gimplify_and_add (t
, pre_p
);
8686 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
8688 gimple_seq_add_seq (pre_p
, copyin_seq
);
8690 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
8694 /* Expand code for an OpenMP single directive. */
8697 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8700 gimple t
, bind
, single_stmt
= gsi_stmt (*gsi_p
);
8701 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
8703 push_gimplify_context ();
8705 block
= make_node (BLOCK
);
8706 bind
= gimple_build_bind (NULL
, NULL
, block
);
8707 gsi_replace (gsi_p
, bind
, true);
8710 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
8711 &bind_body
, &dlist
, ctx
, NULL
);
8712 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
8714 gimple_seq_add_stmt (&bind_body
, single_stmt
);
8716 if (ctx
->record_type
)
8717 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
8719 lower_omp_single_simple (single_stmt
, &bind_body
);
8721 gimple_omp_set_body (single_stmt
, NULL
);
8723 gimple_seq_add_seq (&bind_body
, dlist
);
8725 bind_body
= maybe_catch_exception (bind_body
);
8727 t
= gimple_build_omp_return
8728 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
8729 OMP_CLAUSE_NOWAIT
));
8730 gimple_seq_add_stmt (&bind_body_tail
, t
);
8731 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
8732 if (ctx
->record_type
)
8734 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
8735 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
8736 TREE_THIS_VOLATILE (clobber
) = 1;
8737 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
8738 clobber
), GSI_SAME_STMT
);
8740 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
8741 gimple_bind_set_body (bind
, bind_body
);
8743 pop_gimplify_context (bind
);
8745 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8746 BLOCK_VARS (block
) = ctx
->block_vars
;
8747 if (BLOCK_VARS (block
))
8748 TREE_USED (block
) = 1;
8752 /* Expand code for an OpenMP master directive. */
8755 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8757 tree block
, lab
= NULL
, x
, bfn_decl
;
8758 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
8759 location_t loc
= gimple_location (stmt
);
8762 push_gimplify_context ();
8764 block
= make_node (BLOCK
);
8765 bind
= gimple_build_bind (NULL
, NULL
, block
);
8766 gsi_replace (gsi_p
, bind
, true);
8767 gimple_bind_add_stmt (bind
, stmt
);
8769 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
8770 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
8771 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
8772 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
8774 gimplify_and_add (x
, &tseq
);
8775 gimple_bind_add_seq (bind
, tseq
);
8777 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8778 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
8779 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8780 gimple_omp_set_body (stmt
, NULL
);
8782 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
8784 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8786 pop_gimplify_context (bind
);
8788 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8789 BLOCK_VARS (block
) = ctx
->block_vars
;
8793 /* Expand code for an OpenMP taskgroup directive. */
8796 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8798 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
8799 tree block
= make_node (BLOCK
);
8801 bind
= gimple_build_bind (NULL
, NULL
, block
);
8802 gsi_replace (gsi_p
, bind
, true);
8803 gimple_bind_add_stmt (bind
, stmt
);
8805 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
8807 gimple_bind_add_stmt (bind
, x
);
8809 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8810 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8811 gimple_omp_set_body (stmt
, NULL
);
8813 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8815 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8816 BLOCK_VARS (block
) = ctx
->block_vars
;
8820 /* Expand code for an OpenMP ordered directive. */
8823 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8826 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
8828 push_gimplify_context ();
8830 block
= make_node (BLOCK
);
8831 bind
= gimple_build_bind (NULL
, NULL
, block
);
8832 gsi_replace (gsi_p
, bind
, true);
8833 gimple_bind_add_stmt (bind
, stmt
);
8835 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
8837 gimple_bind_add_stmt (bind
, x
);
8839 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8840 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
8841 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8842 gimple_omp_set_body (stmt
, NULL
);
8844 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
8845 gimple_bind_add_stmt (bind
, x
);
8847 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8849 pop_gimplify_context (bind
);
8851 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8852 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8856 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8857 substitution of a couple of function calls. But in the NAMED case,
8858 requires that languages coordinate a symbol name. It is therefore
8859 best put here in common code. */
8861 static GTY((param1_is (tree
), param2_is (tree
)))
8862 splay_tree critical_name_mutexes
;
8865 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8868 tree name
, lock
, unlock
;
8869 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
8870 location_t loc
= gimple_location (stmt
);
8873 name
= gimple_omp_critical_name (stmt
);
8879 if (!critical_name_mutexes
)
8880 critical_name_mutexes
8881 = splay_tree_new_ggc (splay_tree_compare_pointers
,
8882 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s
,
8883 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s
);
8885 n
= splay_tree_lookup (critical_name_mutexes
, (splay_tree_key
) name
);
8890 decl
= create_tmp_var_raw (ptr_type_node
, NULL
);
8892 new_str
= ACONCAT ((".gomp_critical_user_",
8893 IDENTIFIER_POINTER (name
), NULL
));
8894 DECL_NAME (decl
) = get_identifier (new_str
);
8895 TREE_PUBLIC (decl
) = 1;
8896 TREE_STATIC (decl
) = 1;
8897 DECL_COMMON (decl
) = 1;
8898 DECL_ARTIFICIAL (decl
) = 1;
8899 DECL_IGNORED_P (decl
) = 1;
8900 varpool_finalize_decl (decl
);
8902 splay_tree_insert (critical_name_mutexes
, (splay_tree_key
) name
,
8903 (splay_tree_value
) decl
);
8906 decl
= (tree
) n
->value
;
8908 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
8909 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
8911 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
8912 unlock
= build_call_expr_loc (loc
, unlock
, 1,
8913 build_fold_addr_expr_loc (loc
, decl
));
8917 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
8918 lock
= build_call_expr_loc (loc
, lock
, 0);
8920 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
8921 unlock
= build_call_expr_loc (loc
, unlock
, 0);
8924 push_gimplify_context ();
8926 block
= make_node (BLOCK
);
8927 bind
= gimple_build_bind (NULL
, NULL
, block
);
8928 gsi_replace (gsi_p
, bind
, true);
8929 gimple_bind_add_stmt (bind
, stmt
);
8931 tbody
= gimple_bind_body (bind
);
8932 gimplify_and_add (lock
, &tbody
);
8933 gimple_bind_set_body (bind
, tbody
);
8935 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
8936 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
8937 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
8938 gimple_omp_set_body (stmt
, NULL
);
8940 tbody
= gimple_bind_body (bind
);
8941 gimplify_and_add (unlock
, &tbody
);
8942 gimple_bind_set_body (bind
, tbody
);
8944 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
8946 pop_gimplify_context (bind
);
8947 gimple_bind_append_vars (bind
, ctx
->block_vars
);
8948 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8952 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8953 for a lastprivate clause. Given a loop control predicate of (V
8954 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8955 is appended to *DLIST, iterator initialization is appended to
8959 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
8960 gimple_seq
*dlist
, struct omp_context
*ctx
)
8962 tree clauses
, cond
, vinit
;
8963 enum tree_code cond_code
;
8966 cond_code
= fd
->loop
.cond_code
;
8967 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
8969 /* When possible, use a strict equality expression. This can let VRP
8970 type optimizations deduce the value and remove a copy. */
8971 if (tree_fits_shwi_p (fd
->loop
.step
))
8973 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
8974 if (step
== 1 || step
== -1)
8975 cond_code
= EQ_EXPR
;
8978 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, fd
->loop
.n2
);
8980 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
8982 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
8983 if (!gimple_seq_empty_p (stmts
))
8985 gimple_seq_add_seq (&stmts
, *dlist
);
8988 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8989 vinit
= fd
->loop
.n1
;
8990 if (cond_code
== EQ_EXPR
8991 && tree_fits_shwi_p (fd
->loop
.n2
)
8992 && ! integer_zerop (fd
->loop
.n2
))
8993 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
8995 vinit
= unshare_expr (vinit
);
8997 /* Initialize the iterator variable, so that threads that don't execute
8998 any iterations don't execute the lastprivate clauses by accident. */
8999 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
9004 /* Lower code for an OpenMP loop directive. */
9007 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9010 struct omp_for_data fd
, *fdp
= NULL
;
9011 gimple stmt
= gsi_stmt (*gsi_p
), new_stmt
;
9012 gimple_seq omp_for_body
, body
, dlist
;
9015 push_gimplify_context ();
9017 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
9019 block
= make_node (BLOCK
);
9020 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
9021 /* Replace at gsi right away, so that 'stmt' is no member
9022 of a sequence anymore as we're going to add to to a different
9024 gsi_replace (gsi_p
, new_stmt
, true);
9026 /* Move declaration of temporaries in the loop body before we make
9028 omp_for_body
= gimple_omp_body (stmt
);
9029 if (!gimple_seq_empty_p (omp_for_body
)
9030 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
9032 gimple inner_bind
= gimple_seq_first_stmt (omp_for_body
);
9033 tree vars
= gimple_bind_vars (inner_bind
);
9034 gimple_bind_append_vars (new_stmt
, vars
);
9035 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9036 keep them on the inner_bind and it's block. */
9037 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
9038 if (gimple_bind_block (inner_bind
))
9039 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
9042 if (gimple_omp_for_combined_into_p (stmt
))
9044 extract_omp_for_data (stmt
, &fd
, NULL
);
9047 /* We need two temporaries with fd.loop.v type (istart/iend)
9048 and then (fd.collapse - 1) temporaries with the same
9049 type for count2 ... countN-1 vars if not constant. */
9051 tree type
= fd
.iter_type
;
9053 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
9054 count
+= fd
.collapse
- 1;
9055 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
9056 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
9060 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
9061 OMP_CLAUSE__LOOPTEMP_
);
9062 for (i
= 0; i
< count
; i
++)
9067 gcc_assert (outerc
);
9068 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
9069 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
9070 OMP_CLAUSE__LOOPTEMP_
);
9074 temp
= create_tmp_var (type
, NULL
);
9075 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
9077 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
9078 OMP_CLAUSE_DECL (*pc
) = temp
;
9079 pc
= &OMP_CLAUSE_CHAIN (*pc
);
9084 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9087 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
9089 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
9091 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9093 /* Lower the header expressions. At this point, we can assume that
9094 the header is of the form:
9096 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9098 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9099 using the .omp_data_s mapping, if needed. */
9100 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
9102 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
9103 if (!is_gimple_min_invariant (*rhs_p
))
9104 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9106 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
9107 if (!is_gimple_min_invariant (*rhs_p
))
9108 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9110 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
9111 if (!is_gimple_min_invariant (*rhs_p
))
9112 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9115 /* Once lowered, extract the bounds and clauses. */
9116 extract_omp_for_data (stmt
, &fd
, NULL
);
9118 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
9120 gimple_seq_add_stmt (&body
, stmt
);
9121 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
9123 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
9126 /* After the loop, add exit clauses. */
9127 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
9129 if (ctx
->cancellable
)
9130 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
9132 gimple_seq_add_seq (&body
, dlist
);
9134 body
= maybe_catch_exception (body
);
9136 /* Region exit marker goes at the end of the loop body. */
9137 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
9138 maybe_add_implicit_barrier_cancel (ctx
, &body
);
9139 pop_gimplify_context (new_stmt
);
9141 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
9142 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
9143 if (BLOCK_VARS (block
))
9144 TREE_USED (block
) = 1;
9146 gimple_bind_set_body (new_stmt
, body
);
9147 gimple_omp_set_body (stmt
, NULL
);
9148 gimple_omp_for_set_pre_body (stmt
, NULL
);
9151 /* Callback for walk_stmts. Check if the current statement only contains
9152 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9155 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
9156 bool *handled_ops_p
,
9157 struct walk_stmt_info
*wi
)
9159 int *info
= (int *) wi
->info
;
9160 gimple stmt
= gsi_stmt (*gsi_p
);
9162 *handled_ops_p
= true;
9163 switch (gimple_code (stmt
))
9167 case GIMPLE_OMP_FOR
:
9168 case GIMPLE_OMP_SECTIONS
:
9169 *info
= *info
== 0 ? 1 : -1;
9178 struct omp_taskcopy_context
9180 /* This field must be at the beginning, as we do "inheritance": Some
9181 callback functions for tree-inline.c (e.g., omp_copy_decl)
9182 receive a copy_body_data pointer that is up-casted to an
9183 omp_context pointer. */
9189 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
9191 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
9193 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
9194 return create_tmp_var (TREE_TYPE (var
), NULL
);
9200 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
9202 tree name
, new_fields
= NULL
, type
, f
;
9204 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
9205 name
= DECL_NAME (TYPE_NAME (orig_type
));
9206 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
9207 TYPE_DECL
, name
, type
);
9208 TYPE_NAME (type
) = name
;
9210 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
9212 tree new_f
= copy_node (f
);
9213 DECL_CONTEXT (new_f
) = type
;
9214 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
9215 TREE_CHAIN (new_f
) = new_fields
;
9216 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9217 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9218 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
9221 *pointer_map_insert (tcctx
->cb
.decl_map
, f
) = new_f
;
9223 TYPE_FIELDS (type
) = nreverse (new_fields
);
9228 /* Create task copyfn. */
9231 create_task_copyfn (gimple task_stmt
, omp_context
*ctx
)
9233 struct function
*child_cfun
;
9234 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
9235 tree record_type
, srecord_type
, bind
, list
;
9236 bool record_needs_remap
= false, srecord_needs_remap
= false;
9238 struct omp_taskcopy_context tcctx
;
9239 location_t loc
= gimple_location (task_stmt
);
9241 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
9242 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
9243 gcc_assert (child_cfun
->cfg
== NULL
);
9244 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
9246 /* Reset DECL_CONTEXT on function arguments. */
9247 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
9248 DECL_CONTEXT (t
) = child_fn
;
9250 /* Populate the function. */
9251 push_gimplify_context ();
9252 push_cfun (child_cfun
);
9254 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
9255 TREE_SIDE_EFFECTS (bind
) = 1;
9257 DECL_SAVED_TREE (child_fn
) = bind
;
9258 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
9260 /* Remap src and dst argument types if needed. */
9261 record_type
= ctx
->record_type
;
9262 srecord_type
= ctx
->srecord_type
;
9263 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
9264 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9266 record_needs_remap
= true;
9269 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
9270 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9272 srecord_needs_remap
= true;
9276 if (record_needs_remap
|| srecord_needs_remap
)
9278 memset (&tcctx
, '\0', sizeof (tcctx
));
9279 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
9280 tcctx
.cb
.dst_fn
= child_fn
;
9281 tcctx
.cb
.src_node
= cgraph_get_node (tcctx
.cb
.src_fn
);
9282 gcc_checking_assert (tcctx
.cb
.src_node
);
9283 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
9284 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
9285 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
9286 tcctx
.cb
.eh_lp_nr
= 0;
9287 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
9288 tcctx
.cb
.decl_map
= pointer_map_create ();
9291 if (record_needs_remap
)
9292 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
9293 if (srecord_needs_remap
)
9294 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
9297 tcctx
.cb
.decl_map
= NULL
;
9299 arg
= DECL_ARGUMENTS (child_fn
);
9300 TREE_TYPE (arg
) = build_pointer_type (record_type
);
9301 sarg
= DECL_CHAIN (arg
);
9302 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
9304 /* First pass: initialize temporaries used in record_type and srecord_type
9305 sizes and field offsets. */
9306 if (tcctx
.cb
.decl_map
)
9307 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9308 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9312 decl
= OMP_CLAUSE_DECL (c
);
9313 p
= (tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, decl
);
9316 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9317 sf
= (tree
) n
->value
;
9318 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9319 src
= build_simple_mem_ref_loc (loc
, sarg
);
9320 src
= omp_build_component_ref (src
, sf
);
9321 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
9322 append_to_statement_list (t
, &list
);
9325 /* Second pass: copy shared var pointers and copy construct non-VLA
9326 firstprivate vars. */
9327 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9328 switch (OMP_CLAUSE_CODE (c
))
9330 case OMP_CLAUSE_SHARED
:
9331 decl
= OMP_CLAUSE_DECL (c
);
9332 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9335 f
= (tree
) n
->value
;
9336 if (tcctx
.cb
.decl_map
)
9337 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9338 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9339 sf
= (tree
) n
->value
;
9340 if (tcctx
.cb
.decl_map
)
9341 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9342 src
= build_simple_mem_ref_loc (loc
, sarg
);
9343 src
= omp_build_component_ref (src
, sf
);
9344 dst
= build_simple_mem_ref_loc (loc
, arg
);
9345 dst
= omp_build_component_ref (dst
, f
);
9346 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9347 append_to_statement_list (t
, &list
);
9349 case OMP_CLAUSE_FIRSTPRIVATE
:
9350 decl
= OMP_CLAUSE_DECL (c
);
9351 if (is_variable_sized (decl
))
9353 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9356 f
= (tree
) n
->value
;
9357 if (tcctx
.cb
.decl_map
)
9358 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9359 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9362 sf
= (tree
) n
->value
;
9363 if (tcctx
.cb
.decl_map
)
9364 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9365 src
= build_simple_mem_ref_loc (loc
, sarg
);
9366 src
= omp_build_component_ref (src
, sf
);
9367 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
9368 src
= build_simple_mem_ref_loc (loc
, src
);
9372 dst
= build_simple_mem_ref_loc (loc
, arg
);
9373 dst
= omp_build_component_ref (dst
, f
);
9374 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9375 append_to_statement_list (t
, &list
);
9377 case OMP_CLAUSE_PRIVATE
:
9378 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
9380 decl
= OMP_CLAUSE_DECL (c
);
9381 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9382 f
= (tree
) n
->value
;
9383 if (tcctx
.cb
.decl_map
)
9384 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9385 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9388 sf
= (tree
) n
->value
;
9389 if (tcctx
.cb
.decl_map
)
9390 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9391 src
= build_simple_mem_ref_loc (loc
, sarg
);
9392 src
= omp_build_component_ref (src
, sf
);
9393 if (use_pointer_for_field (decl
, NULL
))
9394 src
= build_simple_mem_ref_loc (loc
, src
);
9398 dst
= build_simple_mem_ref_loc (loc
, arg
);
9399 dst
= omp_build_component_ref (dst
, f
);
9400 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9401 append_to_statement_list (t
, &list
);
9407 /* Last pass: handle VLA firstprivates. */
9408 if (tcctx
.cb
.decl_map
)
9409 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9410 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9414 decl
= OMP_CLAUSE_DECL (c
);
9415 if (!is_variable_sized (decl
))
9417 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9420 f
= (tree
) n
->value
;
9421 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
9422 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
9423 ind
= DECL_VALUE_EXPR (decl
);
9424 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
9425 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
9426 n
= splay_tree_lookup (ctx
->sfield_map
,
9427 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9428 sf
= (tree
) n
->value
;
9429 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
9430 src
= build_simple_mem_ref_loc (loc
, sarg
);
9431 src
= omp_build_component_ref (src
, sf
);
9432 src
= build_simple_mem_ref_loc (loc
, src
);
9433 dst
= build_simple_mem_ref_loc (loc
, arg
);
9434 dst
= omp_build_component_ref (dst
, f
);
9435 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9436 append_to_statement_list (t
, &list
);
9437 n
= splay_tree_lookup (ctx
->field_map
,
9438 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9439 df
= (tree
) n
->value
;
9440 df
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, df
);
9441 ptr
= build_simple_mem_ref_loc (loc
, arg
);
9442 ptr
= omp_build_component_ref (ptr
, df
);
9443 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
9444 build_fold_addr_expr_loc (loc
, dst
));
9445 append_to_statement_list (t
, &list
);
9448 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
9449 append_to_statement_list (t
, &list
);
9451 if (tcctx
.cb
.decl_map
)
9452 pointer_map_destroy (tcctx
.cb
.decl_map
);
9453 pop_gimplify_context (NULL
);
9454 BIND_EXPR_BODY (bind
) = list
;
9459 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
9463 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
9465 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
9467 gcc_assert (clauses
);
9468 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9469 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
9470 switch (OMP_CLAUSE_DEPEND_KIND (c
))
9472 case OMP_CLAUSE_DEPEND_IN
:
9475 case OMP_CLAUSE_DEPEND_OUT
:
9476 case OMP_CLAUSE_DEPEND_INOUT
:
9482 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
9483 tree array
= create_tmp_var (type
, NULL
);
9484 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
9486 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
9487 gimple_seq_add_stmt (iseq
, g
);
9488 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
9490 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
9491 gimple_seq_add_stmt (iseq
, g
);
9492 for (i
= 0; i
< 2; i
++)
9494 if ((i
? n_in
: n_out
) == 0)
9496 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9497 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
9498 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
9500 tree t
= OMP_CLAUSE_DECL (c
);
9501 t
= fold_convert (ptr_type_node
, t
);
9502 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
9503 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
9504 NULL_TREE
, NULL_TREE
);
9505 g
= gimple_build_assign (r
, t
);
9506 gimple_seq_add_stmt (iseq
, g
);
9509 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
9510 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
9511 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
9512 OMP_CLAUSE_CHAIN (c
) = *p
;
9514 tree clobber
= build_constructor (type
, NULL
);
9515 TREE_THIS_VOLATILE (clobber
) = 1;
9516 g
= gimple_build_assign (array
, clobber
);
9517 gimple_seq_add_stmt (oseq
, g
);
9520 /* Lower the OpenMP parallel or task directive in the current statement
9521 in GSI_P. CTX holds context information for the directive. */
9524 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9528 gimple stmt
= gsi_stmt (*gsi_p
);
9529 gimple par_bind
, bind
, dep_bind
= NULL
;
9530 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
9531 location_t loc
= gimple_location (stmt
);
9533 clauses
= gimple_omp_taskreg_clauses (stmt
);
9534 par_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
9535 par_body
= gimple_bind_body (par_bind
);
9536 child_fn
= ctx
->cb
.dst_fn
;
9537 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
9538 && !gimple_omp_parallel_combined_p (stmt
))
9540 struct walk_stmt_info wi
;
9543 memset (&wi
, 0, sizeof (wi
));
9546 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
9548 gimple_omp_parallel_set_combined_p (stmt
, true);
9550 gimple_seq dep_ilist
= NULL
;
9551 gimple_seq dep_olist
= NULL
;
9552 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
9553 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
9555 push_gimplify_context ();
9556 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
9557 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
9560 if (ctx
->srecord_type
)
9561 create_task_copyfn (stmt
, ctx
);
9563 push_gimplify_context ();
9568 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
9569 lower_omp (&par_body
, ctx
);
9570 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
9571 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
9573 /* Declare all the variables created by mapping and the variables
9574 declared in the scope of the parallel body. */
9575 record_vars_into (ctx
->block_vars
, child_fn
);
9576 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
9578 if (ctx
->record_type
)
9581 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
9582 : ctx
->record_type
, ".omp_data_o");
9583 DECL_NAMELESS (ctx
->sender_decl
) = 1;
9584 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
9585 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
9590 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
9591 lower_send_shared_vars (&ilist
, &olist
, ctx
);
9593 if (ctx
->record_type
)
9595 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
9596 TREE_THIS_VOLATILE (clobber
) = 1;
9597 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
9601 /* Once all the expansions are done, sequence all the different
9602 fragments inside gimple_omp_body. */
9606 if (ctx
->record_type
)
9608 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9609 /* fixup_child_record_type might have changed receiver_decl's type. */
9610 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
9611 gimple_seq_add_stmt (&new_body
,
9612 gimple_build_assign (ctx
->receiver_decl
, t
));
9615 gimple_seq_add_seq (&new_body
, par_ilist
);
9616 gimple_seq_add_seq (&new_body
, par_body
);
9617 gimple_seq_add_seq (&new_body
, par_rlist
);
9618 if (ctx
->cancellable
)
9619 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
9620 gimple_seq_add_seq (&new_body
, par_olist
);
9621 new_body
= maybe_catch_exception (new_body
);
9622 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
9623 gimple_omp_set_body (stmt
, new_body
);
9625 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
9626 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
9627 gimple_bind_add_seq (bind
, ilist
);
9628 gimple_bind_add_stmt (bind
, stmt
);
9629 gimple_bind_add_seq (bind
, olist
);
9631 pop_gimplify_context (NULL
);
9635 gimple_bind_add_seq (dep_bind
, dep_ilist
);
9636 gimple_bind_add_stmt (dep_bind
, bind
);
9637 gimple_bind_add_seq (dep_bind
, dep_olist
);
9638 pop_gimplify_context (dep_bind
);
9642 /* Lower the OpenMP target directive in the current statement
9643 in GSI_P. CTX holds context information for the directive. */
9646 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9649 tree child_fn
, t
, c
;
9650 gimple stmt
= gsi_stmt (*gsi_p
);
9651 gimple tgt_bind
= NULL
, bind
;
9652 gimple_seq tgt_body
= NULL
, olist
, ilist
, new_body
;
9653 location_t loc
= gimple_location (stmt
);
9654 int kind
= gimple_omp_target_kind (stmt
);
9655 unsigned int map_cnt
= 0;
9657 clauses
= gimple_omp_target_clauses (stmt
);
9658 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9660 tgt_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
9661 tgt_body
= gimple_bind_body (tgt_bind
);
9663 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
9664 tgt_body
= gimple_omp_body (stmt
);
9665 child_fn
= ctx
->cb
.dst_fn
;
9667 push_gimplify_context ();
9669 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9670 switch (OMP_CLAUSE_CODE (c
))
9676 case OMP_CLAUSE_MAP
:
9678 case OMP_CLAUSE_FROM
:
9679 var
= OMP_CLAUSE_DECL (c
);
9682 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
9683 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
9689 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
9691 tree var2
= DECL_VALUE_EXPR (var
);
9692 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
9693 var2
= TREE_OPERAND (var2
, 0);
9694 gcc_assert (DECL_P (var2
));
9698 if (!maybe_lookup_field (var
, ctx
))
9701 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9703 x
= build_receiver_ref (var
, true, ctx
);
9704 tree new_var
= lookup_decl (var
, ctx
);
9705 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
9706 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
9707 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
9708 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
9709 x
= build_simple_mem_ref (x
);
9710 SET_DECL_VALUE_EXPR (new_var
, x
);
9711 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
9716 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9718 target_nesting_level
++;
9719 lower_omp (&tgt_body
, ctx
);
9720 target_nesting_level
--;
9722 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
9723 lower_omp (&tgt_body
, ctx
);
9725 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9727 /* Declare all the variables created by mapping and the variables
9728 declared in the scope of the target body. */
9729 record_vars_into (ctx
->block_vars
, child_fn
);
9730 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
9735 if (ctx
->record_type
)
9738 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
9739 DECL_NAMELESS (ctx
->sender_decl
) = 1;
9740 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
9741 t
= make_tree_vec (3);
9742 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
9744 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
9746 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
9747 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
9748 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
9750 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node
,
9753 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
9754 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
9755 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
9756 gimple_omp_target_set_data_arg (stmt
, t
);
9758 vec
<constructor_elt
, va_gc
> *vsize
;
9759 vec
<constructor_elt
, va_gc
> *vkind
;
9760 vec_alloc (vsize
, map_cnt
);
9761 vec_alloc (vkind
, map_cnt
);
9762 unsigned int map_idx
= 0;
9764 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9765 switch (OMP_CLAUSE_CODE (c
))
9771 case OMP_CLAUSE_MAP
:
9773 case OMP_CLAUSE_FROM
:
9775 ovar
= OMP_CLAUSE_DECL (c
);
9778 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
9779 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
9781 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
9782 == get_base_address (ovar
));
9783 nc
= OMP_CLAUSE_CHAIN (c
);
9784 ovar
= OMP_CLAUSE_DECL (nc
);
9788 tree x
= build_sender_ref (ovar
, ctx
);
9790 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
9791 gimplify_assign (x
, v
, &ilist
);
9797 if (DECL_SIZE (ovar
)
9798 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
9800 tree ovar2
= DECL_VALUE_EXPR (ovar
);
9801 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
9802 ovar2
= TREE_OPERAND (ovar2
, 0);
9803 gcc_assert (DECL_P (ovar2
));
9806 if (!maybe_lookup_field (ovar
, ctx
))
9812 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
9813 tree x
= build_sender_ref (ovar
, ctx
);
9814 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
9815 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
9816 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
9817 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
9819 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
9821 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)), NULL
);
9822 mark_addressable (avar
);
9823 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
9824 avar
= build_fold_addr_expr (avar
);
9825 gimplify_assign (x
, avar
, &ilist
);
9827 else if (is_gimple_reg (var
))
9829 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
9830 tree avar
= create_tmp_var (TREE_TYPE (var
), NULL
);
9831 mark_addressable (avar
);
9832 if (OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_ALLOC
9833 && OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_FROM
)
9834 gimplify_assign (avar
, var
, &ilist
);
9835 avar
= build_fold_addr_expr (avar
);
9836 gimplify_assign (x
, avar
, &ilist
);
9837 if ((OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_FROM
9838 || OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_TOFROM
)
9839 && !TYPE_READONLY (TREE_TYPE (var
)))
9841 x
= build_sender_ref (ovar
, ctx
);
9842 x
= build_simple_mem_ref (x
);
9843 gimplify_assign (var
, x
, &olist
);
9848 var
= build_fold_addr_expr (var
);
9849 gimplify_assign (x
, var
, &ilist
);
9852 tree s
= OMP_CLAUSE_SIZE (c
);
9854 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
9855 s
= fold_convert (size_type_node
, s
);
9856 tree purpose
= size_int (map_idx
++);
9857 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
9858 if (TREE_CODE (s
) != INTEGER_CST
)
9859 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
9861 unsigned char tkind
= 0;
9862 switch (OMP_CLAUSE_CODE (c
))
9864 case OMP_CLAUSE_MAP
:
9865 tkind
= OMP_CLAUSE_MAP_KIND (c
);
9868 tkind
= OMP_CLAUSE_MAP_TO
;
9870 case OMP_CLAUSE_FROM
:
9871 tkind
= OMP_CLAUSE_MAP_FROM
;
9876 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
9877 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
9878 talign
= DECL_ALIGN_UNIT (ovar
);
9879 talign
= ceil_log2 (talign
);
9880 tkind
|= talign
<< 3;
9881 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
9882 build_int_cst (unsigned_char_type_node
,
9888 gcc_assert (map_idx
== map_cnt
);
9890 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
9891 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
9892 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
9893 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
9894 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
9896 gimple_seq initlist
= NULL
;
9897 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
9898 TREE_VEC_ELT (t
, 1)),
9899 &initlist
, true, NULL_TREE
);
9900 gimple_seq_add_seq (&ilist
, initlist
);
9902 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
9904 TREE_THIS_VOLATILE (clobber
) = 1;
9905 gimple_seq_add_stmt (&olist
,
9906 gimple_build_assign (TREE_VEC_ELT (t
, 1),
9910 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
9911 TREE_THIS_VOLATILE (clobber
) = 1;
9912 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
9916 /* Once all the expansions are done, sequence all the different
9917 fragments inside gimple_omp_body. */
9921 if (ctx
->record_type
&& kind
== GF_OMP_TARGET_KIND_REGION
)
9923 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9924 /* fixup_child_record_type might have changed receiver_decl's type. */
9925 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
9926 gimple_seq_add_stmt (&new_body
,
9927 gimple_build_assign (ctx
->receiver_decl
, t
));
9930 if (kind
== GF_OMP_TARGET_KIND_REGION
)
9932 gimple_seq_add_seq (&new_body
, tgt_body
);
9933 new_body
= maybe_catch_exception (new_body
);
9935 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
9936 new_body
= tgt_body
;
9937 if (kind
!= GF_OMP_TARGET_KIND_UPDATE
)
9939 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
9940 gimple_omp_set_body (stmt
, new_body
);
9943 bind
= gimple_build_bind (NULL
, NULL
,
9944 tgt_bind
? gimple_bind_block (tgt_bind
)
9946 gsi_replace (gsi_p
, bind
, true);
9947 gimple_bind_add_seq (bind
, ilist
);
9948 gimple_bind_add_stmt (bind
, stmt
);
9949 gimple_bind_add_seq (bind
, olist
);
9951 pop_gimplify_context (NULL
);
9954 /* Expand code for an OpenMP teams directive. */
9957 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9959 gimple teams_stmt
= gsi_stmt (*gsi_p
);
9960 push_gimplify_context ();
9962 tree block
= make_node (BLOCK
);
9963 gimple bind
= gimple_build_bind (NULL
, NULL
, block
);
9964 gsi_replace (gsi_p
, bind
, true);
9965 gimple_seq bind_body
= NULL
;
9966 gimple_seq dlist
= NULL
;
9967 gimple_seq olist
= NULL
;
9969 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
9970 OMP_CLAUSE_NUM_TEAMS
);
9971 if (num_teams
== NULL_TREE
)
9972 num_teams
= build_int_cst (unsigned_type_node
, 0);
9975 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
9976 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
9977 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
9979 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
9980 OMP_CLAUSE_THREAD_LIMIT
);
9981 if (thread_limit
== NULL_TREE
)
9982 thread_limit
= build_int_cst (unsigned_type_node
, 0);
9985 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
9986 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
9987 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
9991 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
9992 &bind_body
, &dlist
, ctx
, NULL
);
9993 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
9994 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
9995 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
9997 location_t loc
= gimple_location (teams_stmt
);
9998 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
9999 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
10000 gimple_set_location (call
, loc
);
10001 gimple_seq_add_stmt (&bind_body
, call
);
10003 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
10004 gimple_omp_set_body (teams_stmt
, NULL
);
10005 gimple_seq_add_seq (&bind_body
, olist
);
10006 gimple_seq_add_seq (&bind_body
, dlist
);
10007 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
10008 gimple_bind_set_body (bind
, bind_body
);
10010 pop_gimplify_context (bind
);
10012 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10013 BLOCK_VARS (block
) = ctx
->block_vars
;
10014 if (BLOCK_VARS (block
))
10015 TREE_USED (block
) = 1;
10019 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10020 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10021 of OpenMP context, but with task_shared_vars set. */
10024 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
10029 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10030 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
10033 if (task_shared_vars
10035 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
10038 /* If a global variable has been privatized, TREE_CONSTANT on
10039 ADDR_EXPR might be wrong. */
10040 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
10041 recompute_tree_invariant_for_addr_expr (t
);
10043 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
10048 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10050 gimple stmt
= gsi_stmt (*gsi_p
);
10051 struct walk_stmt_info wi
;
10053 if (gimple_has_location (stmt
))
10054 input_location
= gimple_location (stmt
);
10056 if (task_shared_vars
)
10057 memset (&wi
, '\0', sizeof (wi
));
10059 /* If we have issued syntax errors, avoid doing any heavy lifting.
10060 Just replace the OpenMP directives with a NOP to avoid
10061 confusing RTL expansion. */
10062 if (seen_error () && is_gimple_omp (stmt
))
10064 gsi_replace (gsi_p
, gimple_build_nop (), true);
10068 switch (gimple_code (stmt
))
10071 if ((ctx
|| task_shared_vars
)
10072 && (walk_tree (gimple_cond_lhs_ptr (stmt
), lower_omp_regimplify_p
,
10073 ctx
? NULL
: &wi
, NULL
)
10074 || walk_tree (gimple_cond_rhs_ptr (stmt
), lower_omp_regimplify_p
,
10075 ctx
? NULL
: &wi
, NULL
)))
10076 gimple_regimplify_operands (stmt
, gsi_p
);
10079 lower_omp (gimple_catch_handler_ptr (stmt
), ctx
);
10081 case GIMPLE_EH_FILTER
:
10082 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
10085 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
10086 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
10088 case GIMPLE_TRANSACTION
:
10089 lower_omp (gimple_transaction_body_ptr (stmt
), ctx
);
10092 lower_omp (gimple_bind_body_ptr (stmt
), ctx
);
10094 case GIMPLE_OMP_PARALLEL
:
10095 case GIMPLE_OMP_TASK
:
10096 ctx
= maybe_lookup_ctx (stmt
);
10098 if (ctx
->cancellable
)
10099 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10100 lower_omp_taskreg (gsi_p
, ctx
);
10102 case GIMPLE_OMP_FOR
:
10103 ctx
= maybe_lookup_ctx (stmt
);
10105 if (ctx
->cancellable
)
10106 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10107 lower_omp_for (gsi_p
, ctx
);
10109 case GIMPLE_OMP_SECTIONS
:
10110 ctx
= maybe_lookup_ctx (stmt
);
10112 if (ctx
->cancellable
)
10113 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10114 lower_omp_sections (gsi_p
, ctx
);
10116 case GIMPLE_OMP_SINGLE
:
10117 ctx
= maybe_lookup_ctx (stmt
);
10119 lower_omp_single (gsi_p
, ctx
);
10121 case GIMPLE_OMP_MASTER
:
10122 ctx
= maybe_lookup_ctx (stmt
);
10124 lower_omp_master (gsi_p
, ctx
);
10126 case GIMPLE_OMP_TASKGROUP
:
10127 ctx
= maybe_lookup_ctx (stmt
);
10129 lower_omp_taskgroup (gsi_p
, ctx
);
10131 case GIMPLE_OMP_ORDERED
:
10132 ctx
= maybe_lookup_ctx (stmt
);
10134 lower_omp_ordered (gsi_p
, ctx
);
10136 case GIMPLE_OMP_CRITICAL
:
10137 ctx
= maybe_lookup_ctx (stmt
);
10139 lower_omp_critical (gsi_p
, ctx
);
10141 case GIMPLE_OMP_ATOMIC_LOAD
:
10142 if ((ctx
|| task_shared_vars
)
10143 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt
),
10144 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
10145 gimple_regimplify_operands (stmt
, gsi_p
);
10147 case GIMPLE_OMP_TARGET
:
10148 ctx
= maybe_lookup_ctx (stmt
);
10150 lower_omp_target (gsi_p
, ctx
);
10152 case GIMPLE_OMP_TEAMS
:
10153 ctx
= maybe_lookup_ctx (stmt
);
10155 lower_omp_teams (gsi_p
, ctx
);
10159 fndecl
= gimple_call_fndecl (stmt
);
10161 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
10162 switch (DECL_FUNCTION_CODE (fndecl
))
10164 case BUILT_IN_GOMP_BARRIER
:
10168 case BUILT_IN_GOMP_CANCEL
:
10169 case BUILT_IN_GOMP_CANCELLATION_POINT
:
10172 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
10173 cctx
= cctx
->outer
;
10174 gcc_assert (gimple_call_lhs (stmt
) == NULL_TREE
);
10175 if (!cctx
->cancellable
)
10177 if (DECL_FUNCTION_CODE (fndecl
)
10178 == BUILT_IN_GOMP_CANCELLATION_POINT
)
10180 stmt
= gimple_build_nop ();
10181 gsi_replace (gsi_p
, stmt
, false);
10185 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
10187 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
10188 gimple_call_set_fndecl (stmt
, fndecl
);
10189 gimple_call_set_fntype (stmt
, TREE_TYPE (fndecl
));
10192 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)), NULL
);
10193 gimple_call_set_lhs (stmt
, lhs
);
10194 tree fallthru_label
;
10195 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
10197 g
= gimple_build_label (fallthru_label
);
10198 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10199 g
= gimple_build_cond (NE_EXPR
, lhs
,
10200 fold_convert (TREE_TYPE (lhs
),
10201 boolean_false_node
),
10202 cctx
->cancel_label
, fallthru_label
);
10203 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10210 if ((ctx
|| task_shared_vars
)
10211 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
10214 /* Just remove clobbers, this should happen only if we have
10215 "privatized" local addressable variables in SIMD regions,
10216 the clobber isn't needed in that case and gimplifying address
10217 of the ARRAY_REF into a pointer and creating MEM_REF based
10218 clobber would create worse code than we get with the clobber
10220 if (gimple_clobber_p (stmt
))
10222 gsi_replace (gsi_p
, gimple_build_nop (), true);
10225 gimple_regimplify_operands (stmt
, gsi_p
);
10232 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
10234 location_t saved_location
= input_location
;
10235 gimple_stmt_iterator gsi
;
10236 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10237 lower_omp_1 (&gsi
, ctx
);
10238 /* During gimplification, we have not always invoked fold_stmt
10239 (gimplify.c:maybe_fold_stmt); call it now. */
10240 if (target_nesting_level
)
10241 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10243 input_location
= saved_location
;
10246 /* Main entry point. */
10248 static unsigned int
10249 execute_lower_omp (void)
10253 /* This pass always runs, to provide PROP_gimple_lomp.
10254 But there is nothing to do unless -fopenmp is given. */
10255 if (flag_openmp
== 0 && flag_openmp_simd
== 0 && flag_cilkplus
== 0)
10258 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
10259 delete_omp_context
);
10261 body
= gimple_body (current_function_decl
);
10262 scan_omp (&body
, NULL
);
10263 gcc_assert (taskreg_nesting_level
== 0);
10265 if (all_contexts
->root
)
10267 if (task_shared_vars
)
10268 push_gimplify_context ();
10269 lower_omp (&body
, NULL
);
10270 if (task_shared_vars
)
10271 pop_gimplify_context (NULL
);
10276 splay_tree_delete (all_contexts
);
10277 all_contexts
= NULL
;
10279 BITMAP_FREE (task_shared_vars
);
10285 const pass_data pass_data_lower_omp
=
10287 GIMPLE_PASS
, /* type */
10288 "omplower", /* name */
10289 OPTGROUP_NONE
, /* optinfo_flags */
10290 TV_NONE
, /* tv_id */
10291 PROP_gimple_any
, /* properties_required */
10292 PROP_gimple_lomp
, /* properties_provided */
10293 0, /* properties_destroyed */
10294 0, /* todo_flags_start */
10295 0, /* todo_flags_finish */
10298 class pass_lower_omp
: public gimple_opt_pass
10301 pass_lower_omp (gcc::context
*ctxt
)
10302 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
10305 /* opt_pass methods: */
10306 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
10308 }; // class pass_lower_omp
10310 } // anon namespace
10313 make_pass_lower_omp (gcc::context
*ctxt
)
10315 return new pass_lower_omp (ctxt
);
10318 /* The following is a utility to diagnose OpenMP structured block violations.
10319 It is not part of the "omplower" pass, as that's invoked too late. It
10320 should be invoked by the respective front ends after gimplification. */
10322 static splay_tree all_labels
;
10324 /* Check for mismatched contexts and generate an error if needed. Return
10325 true if an error is detected. */
10328 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
10329 gimple branch_ctx
, gimple label_ctx
)
10331 if (label_ctx
== branch_ctx
)
10336 Previously we kept track of the label's entire context in diagnose_sb_[12]
10337 so we could traverse it and issue a correct "exit" or "enter" error
10338 message upon a structured block violation.
10340 We built the context by building a list with tree_cons'ing, but there is
10341 no easy counterpart in gimple tuples. It seems like far too much work
10342 for issuing exit/enter error messages. If someone really misses the
10343 distinct error message... patches welcome.
10347 /* Try to avoid confusing the user by producing and error message
10348 with correct "exit" or "enter" verbiage. We prefer "exit"
10349 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10350 if (branch_ctx
== NULL
)
10356 if (TREE_VALUE (label_ctx
) == branch_ctx
)
10361 label_ctx
= TREE_CHAIN (label_ctx
);
10366 error ("invalid exit from OpenMP structured block");
10368 error ("invalid entry to OpenMP structured block");
10371 bool cilkplus_block
= false;
10375 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
10376 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
10378 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
10379 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
10380 cilkplus_block
= true;
10383 /* If it's obvious we have an invalid entry, be specific about the error. */
10384 if (branch_ctx
== NULL
)
10386 if (cilkplus_block
)
10387 error ("invalid entry to Cilk Plus structured block");
10389 error ("invalid entry to OpenMP structured block");
10393 /* Otherwise, be vague and lazy, but efficient. */
10394 if (cilkplus_block
)
10395 error ("invalid branch to/from a Cilk Plus structured block");
10397 error ("invalid branch to/from an OpenMP structured block");
10400 gsi_replace (gsi_p
, gimple_build_nop (), false);
10404 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10405 where each label is found. */
10408 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10409 struct walk_stmt_info
*wi
)
10411 gimple context
= (gimple
) wi
->info
;
10412 gimple inner_context
;
10413 gimple stmt
= gsi_stmt (*gsi_p
);
10415 *handled_ops_p
= true;
10417 switch (gimple_code (stmt
))
10421 case GIMPLE_OMP_PARALLEL
:
10422 case GIMPLE_OMP_TASK
:
10423 case GIMPLE_OMP_SECTIONS
:
10424 case GIMPLE_OMP_SINGLE
:
10425 case GIMPLE_OMP_SECTION
:
10426 case GIMPLE_OMP_MASTER
:
10427 case GIMPLE_OMP_ORDERED
:
10428 case GIMPLE_OMP_CRITICAL
:
10429 case GIMPLE_OMP_TARGET
:
10430 case GIMPLE_OMP_TEAMS
:
10431 case GIMPLE_OMP_TASKGROUP
:
10432 /* The minimal context here is just the current OMP construct. */
10433 inner_context
= stmt
;
10434 wi
->info
= inner_context
;
10435 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10436 wi
->info
= context
;
10439 case GIMPLE_OMP_FOR
:
10440 inner_context
= stmt
;
10441 wi
->info
= inner_context
;
10442 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10444 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
10445 diagnose_sb_1
, NULL
, wi
);
10446 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10447 wi
->info
= context
;
10451 splay_tree_insert (all_labels
, (splay_tree_key
) gimple_label_label (stmt
),
10452 (splay_tree_value
) context
);
10462 /* Pass 2: Check each branch and see if its context differs from that of
10463 the destination label's context. */
10466 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10467 struct walk_stmt_info
*wi
)
10469 gimple context
= (gimple
) wi
->info
;
10471 gimple stmt
= gsi_stmt (*gsi_p
);
10473 *handled_ops_p
= true;
10475 switch (gimple_code (stmt
))
10479 case GIMPLE_OMP_PARALLEL
:
10480 case GIMPLE_OMP_TASK
:
10481 case GIMPLE_OMP_SECTIONS
:
10482 case GIMPLE_OMP_SINGLE
:
10483 case GIMPLE_OMP_SECTION
:
10484 case GIMPLE_OMP_MASTER
:
10485 case GIMPLE_OMP_ORDERED
:
10486 case GIMPLE_OMP_CRITICAL
:
10487 case GIMPLE_OMP_TARGET
:
10488 case GIMPLE_OMP_TEAMS
:
10489 case GIMPLE_OMP_TASKGROUP
:
10491 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10492 wi
->info
= context
;
10495 case GIMPLE_OMP_FOR
:
10497 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10499 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
10500 diagnose_sb_2
, NULL
, wi
);
10501 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10502 wi
->info
= context
;
10507 tree lab
= gimple_cond_true_label (stmt
);
10510 n
= splay_tree_lookup (all_labels
,
10511 (splay_tree_key
) lab
);
10512 diagnose_sb_0 (gsi_p
, context
,
10513 n
? (gimple
) n
->value
: NULL
);
10515 lab
= gimple_cond_false_label (stmt
);
10518 n
= splay_tree_lookup (all_labels
,
10519 (splay_tree_key
) lab
);
10520 diagnose_sb_0 (gsi_p
, context
,
10521 n
? (gimple
) n
->value
: NULL
);
10528 tree lab
= gimple_goto_dest (stmt
);
10529 if (TREE_CODE (lab
) != LABEL_DECL
)
10532 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10533 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
10537 case GIMPLE_SWITCH
:
10540 for (i
= 0; i
< gimple_switch_num_labels (stmt
); ++i
)
10542 tree lab
= CASE_LABEL (gimple_switch_label (stmt
, i
));
10543 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10544 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
10550 case GIMPLE_RETURN
:
10551 diagnose_sb_0 (gsi_p
, context
, NULL
);
10561 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10564 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
10567 gimple last
= last_stmt (bb
);
10568 enum gimple_code code
= gimple_code (last
);
10569 struct omp_region
*cur_region
= *region
;
10570 bool fallthru
= false;
10574 case GIMPLE_OMP_PARALLEL
:
10575 case GIMPLE_OMP_TASK
:
10576 case GIMPLE_OMP_FOR
:
10577 case GIMPLE_OMP_SINGLE
:
10578 case GIMPLE_OMP_TEAMS
:
10579 case GIMPLE_OMP_MASTER
:
10580 case GIMPLE_OMP_TASKGROUP
:
10581 case GIMPLE_OMP_ORDERED
:
10582 case GIMPLE_OMP_CRITICAL
:
10583 case GIMPLE_OMP_SECTION
:
10584 cur_region
= new_omp_region (bb
, code
, cur_region
);
10588 case GIMPLE_OMP_TARGET
:
10589 cur_region
= new_omp_region (bb
, code
, cur_region
);
10591 if (gimple_omp_target_kind (last
) == GF_OMP_TARGET_KIND_UPDATE
)
10592 cur_region
= cur_region
->outer
;
10595 case GIMPLE_OMP_SECTIONS
:
10596 cur_region
= new_omp_region (bb
, code
, cur_region
);
10600 case GIMPLE_OMP_SECTIONS_SWITCH
:
10604 case GIMPLE_OMP_ATOMIC_LOAD
:
10605 case GIMPLE_OMP_ATOMIC_STORE
:
10609 case GIMPLE_OMP_RETURN
:
10610 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10611 somewhere other than the next block. This will be
10613 cur_region
->exit
= bb
;
10614 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
10615 cur_region
= cur_region
->outer
;
10618 case GIMPLE_OMP_CONTINUE
:
10619 cur_region
->cont
= bb
;
10620 switch (cur_region
->type
)
10622 case GIMPLE_OMP_FOR
:
10623 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10624 succs edges as abnormal to prevent splitting
10626 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
10627 /* Make the loopback edge. */
10628 make_edge (bb
, single_succ (cur_region
->entry
),
10631 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10632 corresponds to the case that the body of the loop
10633 is not executed at all. */
10634 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
10635 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
10639 case GIMPLE_OMP_SECTIONS
:
10640 /* Wire up the edges into and out of the nested sections. */
10642 basic_block switch_bb
= single_succ (cur_region
->entry
);
10644 struct omp_region
*i
;
10645 for (i
= cur_region
->inner
; i
; i
= i
->next
)
10647 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
10648 make_edge (switch_bb
, i
->entry
, 0);
10649 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
10652 /* Make the loopback edge to the block with
10653 GIMPLE_OMP_SECTIONS_SWITCH. */
10654 make_edge (bb
, switch_bb
, 0);
10656 /* Make the edge from the switch to exit. */
10657 make_edge (switch_bb
, bb
->next_bb
, 0);
10663 gcc_unreachable ();
10668 gcc_unreachable ();
10671 if (*region
!= cur_region
)
10673 *region
= cur_region
;
10675 *region_idx
= cur_region
->entry
->index
;
10683 static unsigned int
10684 diagnose_omp_structured_block_errors (void)
10686 struct walk_stmt_info wi
;
10687 gimple_seq body
= gimple_body (current_function_decl
);
10689 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
10691 memset (&wi
, 0, sizeof (wi
));
10692 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
10694 memset (&wi
, 0, sizeof (wi
));
10695 wi
.want_locations
= true;
10696 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
10698 gimple_set_body (current_function_decl
, body
);
10700 splay_tree_delete (all_labels
);
10708 const pass_data pass_data_diagnose_omp_blocks
=
10710 GIMPLE_PASS
, /* type */
10711 "*diagnose_omp_blocks", /* name */
10712 OPTGROUP_NONE
, /* optinfo_flags */
10713 TV_NONE
, /* tv_id */
10714 PROP_gimple_any
, /* properties_required */
10715 0, /* properties_provided */
10716 0, /* properties_destroyed */
10717 0, /* todo_flags_start */
10718 0, /* todo_flags_finish */
10721 class pass_diagnose_omp_blocks
: public gimple_opt_pass
10724 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
10725 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
10728 /* opt_pass methods: */
10729 virtual bool gate (function
*) { return flag_openmp
|| flag_cilkplus
; }
10730 virtual unsigned int execute (function
*)
10732 return diagnose_omp_structured_block_errors ();
10735 }; // class pass_diagnose_omp_blocks
10737 } // anon namespace
10740 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
10742 return new pass_diagnose_omp_blocks (ctxt
);
10745 /* SIMD clone supporting code. */
10747 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
10748 of arguments to reserve space for. */
10750 static struct cgraph_simd_clone
*
10751 simd_clone_struct_alloc (int nargs
)
10753 struct cgraph_simd_clone
*clone_info
;
10754 size_t len
= (sizeof (struct cgraph_simd_clone
)
10755 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
10756 clone_info
= (struct cgraph_simd_clone
*)
10757 ggc_internal_cleared_alloc (len
);
10761 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
10764 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
10765 struct cgraph_simd_clone
*from
)
10767 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
10768 + ((from
->nargs
- from
->inbranch
)
10769 * sizeof (struct cgraph_simd_clone_arg
))));
10772 /* Return vector of parameter types of function FNDECL. This uses
10773 TYPE_ARG_TYPES if available, otherwise falls back to types of
10774 DECL_ARGUMENTS types. */
10777 simd_clone_vector_of_formal_parm_types (tree fndecl
)
10779 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
10780 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
10781 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
10784 FOR_EACH_VEC_ELT (args
, i
, arg
)
10785 args
[i
] = TREE_TYPE (args
[i
]);
10789 /* Given a simd function in NODE, extract the simd specific
10790 information from the OMP clauses passed in CLAUSES, and return
10791 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
10792 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
10793 otherwise set to FALSE. */
10795 static struct cgraph_simd_clone
*
10796 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
10797 bool *inbranch_specified
)
10799 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
10802 *inbranch_specified
= false;
10804 n
= args
.length ();
10805 if (n
> 0 && args
.last () == void_type_node
)
10808 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
10809 be cloned have a distinctive artificial label in addition to "omp
10813 && lookup_attribute ("cilk simd function",
10814 DECL_ATTRIBUTES (node
->decl
)));
10816 /* Allocate one more than needed just in case this is an in-branch
10817 clone which will require a mask argument. */
10818 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
10819 clone_info
->nargs
= n
;
10820 clone_info
->cilk_elemental
= cilk_clone
;
10827 clauses
= TREE_VALUE (clauses
);
10828 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
10831 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
10833 switch (OMP_CLAUSE_CODE (t
))
10835 case OMP_CLAUSE_INBRANCH
:
10836 clone_info
->inbranch
= 1;
10837 *inbranch_specified
= true;
10839 case OMP_CLAUSE_NOTINBRANCH
:
10840 clone_info
->inbranch
= 0;
10841 *inbranch_specified
= true;
10843 case OMP_CLAUSE_SIMDLEN
:
10844 clone_info
->simdlen
10845 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
10847 case OMP_CLAUSE_LINEAR
:
10849 tree decl
= OMP_CLAUSE_DECL (t
);
10850 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
10851 int argno
= TREE_INT_CST_LOW (decl
);
10852 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
10854 clone_info
->args
[argno
].arg_type
10855 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
10856 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
10857 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
10858 && clone_info
->args
[argno
].linear_step
< n
);
10862 if (POINTER_TYPE_P (args
[argno
]))
10863 step
= fold_convert (ssizetype
, step
);
10864 if (!tree_fits_shwi_p (step
))
10866 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
10867 "ignoring large linear step");
10871 else if (integer_zerop (step
))
10873 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
10874 "ignoring zero linear step");
10880 clone_info
->args
[argno
].arg_type
10881 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
10882 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
10887 case OMP_CLAUSE_UNIFORM
:
10889 tree decl
= OMP_CLAUSE_DECL (t
);
10890 int argno
= tree_to_uhwi (decl
);
10891 clone_info
->args
[argno
].arg_type
10892 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
10895 case OMP_CLAUSE_ALIGNED
:
10897 tree decl
= OMP_CLAUSE_DECL (t
);
10898 int argno
= tree_to_uhwi (decl
);
10899 clone_info
->args
[argno
].alignment
10900 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
10911 /* Given a SIMD clone in NODE, calculate the characteristic data
10912 type and return the coresponding type. The characteristic data
10913 type is computed as described in the Intel Vector ABI. */
10916 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
10917 struct cgraph_simd_clone
*clone_info
)
10919 tree type
= integer_type_node
;
10920 tree fndecl
= node
->decl
;
10922 /* a) For non-void function, the characteristic data type is the
10924 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
10925 type
= TREE_TYPE (TREE_TYPE (fndecl
));
10927 /* b) If the function has any non-uniform, non-linear parameters,
10928 then the characteristic data type is the type of the first
10932 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
10933 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
10934 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
10942 /* c) If the characteristic data type determined by a) or b) above
10943 is struct, union, or class type which is pass-by-value (except
10944 for the type that maps to the built-in complex data type), the
10945 characteristic data type is int. */
10946 if (RECORD_OR_UNION_TYPE_P (type
)
10947 && !aggregate_value_p (type
, NULL
)
10948 && TREE_CODE (type
) != COMPLEX_TYPE
)
10949 return integer_type_node
;
10951 /* d) If none of the above three classes is applicable, the
10952 characteristic data type is int. */
10956 /* e) For Intel Xeon Phi native and offload compilation, if the
10957 resulting characteristic data type is 8-bit or 16-bit integer
10958 data type, the characteristic data type is int. */
10959 /* Well, we don't handle Xeon Phi yet. */
10963 simd_clone_mangle (struct cgraph_node
*node
,
10964 struct cgraph_simd_clone
*clone_info
)
10966 char vecsize_mangle
= clone_info
->vecsize_mangle
;
10967 char mask
= clone_info
->inbranch
? 'M' : 'N';
10968 unsigned int simdlen
= clone_info
->simdlen
;
10972 gcc_assert (vecsize_mangle
&& simdlen
);
10974 pp_string (&pp
, "_ZGV");
10975 pp_character (&pp
, vecsize_mangle
);
10976 pp_character (&pp
, mask
);
10977 pp_decimal_int (&pp
, simdlen
);
10979 for (n
= 0; n
< clone_info
->nargs
; ++n
)
10981 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
10983 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
10984 pp_character (&pp
, 'u');
10985 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
10987 gcc_assert (arg
.linear_step
!= 0);
10988 pp_character (&pp
, 'l');
10989 if (arg
.linear_step
> 1)
10990 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
10991 else if (arg
.linear_step
< 0)
10993 pp_character (&pp
, 'n');
10994 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
10998 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
11000 pp_character (&pp
, 's');
11001 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
11004 pp_character (&pp
, 'v');
11007 pp_character (&pp
, 'a');
11008 pp_decimal_int (&pp
, arg
.alignment
);
11012 pp_underscore (&pp
);
11014 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
)));
11015 const char *str
= pp_formatted_text (&pp
);
11017 /* If there already is a SIMD clone with the same mangled name, don't
11018 add another one. This can happen e.g. for
11019 #pragma omp declare simd
11020 #pragma omp declare simd simdlen(8)
11021 int foo (int, int);
11022 if the simdlen is assumed to be 8 for the first one, etc. */
11023 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
11024 clone
= clone
->simdclone
->next_clone
)
11025 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
11029 return get_identifier (str
);
11032 /* Create a simd clone of OLD_NODE and return it. */
11034 static struct cgraph_node
*
11035 simd_clone_create (struct cgraph_node
*old_node
)
11037 struct cgraph_node
*new_node
;
11038 if (old_node
->definition
)
11040 if (!cgraph_function_with_gimple_body_p (old_node
))
11042 cgraph_get_body (old_node
);
11043 new_node
= cgraph_function_versioning (old_node
, vNULL
, NULL
, NULL
,
11044 false, NULL
, NULL
, "simdclone");
11048 tree old_decl
= old_node
->decl
;
11049 tree new_decl
= copy_node (old_node
->decl
);
11050 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
11051 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
11052 SET_DECL_RTL (new_decl
, NULL
);
11053 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
11054 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
11056 = cgraph_copy_node_for_versioning (old_node
, new_decl
, vNULL
, NULL
);
11057 cgraph_call_function_insertion_hooks (new_node
);
11059 if (new_node
== NULL
)
11062 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
11064 /* The function cgraph_function_versioning () will force the new
11065 symbol local. Undo this, and inherit external visability from
11067 new_node
->local
.local
= old_node
->local
.local
;
11068 new_node
->externally_visible
= old_node
->externally_visible
;
11073 /* Adjust the return type of the given function to its appropriate
11074 vector counterpart. Returns a simd array to be used throughout the
11075 function as a return value. */
11078 simd_clone_adjust_return_type (struct cgraph_node
*node
)
11080 tree fndecl
= node
->decl
;
11081 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
11082 unsigned int veclen
;
11085 /* Adjust the function return type. */
11086 if (orig_rettype
== void_type_node
)
11088 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
11089 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
)))
11090 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
))))
11091 veclen
= node
->simdclone
->vecsize_int
;
11093 veclen
= node
->simdclone
->vecsize_float
;
11094 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl
))));
11095 if (veclen
> node
->simdclone
->simdlen
)
11096 veclen
= node
->simdclone
->simdlen
;
11097 if (veclen
== node
->simdclone
->simdlen
)
11098 TREE_TYPE (TREE_TYPE (fndecl
))
11099 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)),
11100 node
->simdclone
->simdlen
);
11103 t
= build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)), veclen
);
11104 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
11105 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
11107 if (!node
->definition
)
11110 t
= DECL_RESULT (fndecl
);
11111 /* Adjust the DECL_RESULT. */
11112 gcc_assert (TREE_TYPE (t
) != void_type_node
);
11113 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
11116 tree atype
= build_array_type_nelts (orig_rettype
,
11117 node
->simdclone
->simdlen
);
11118 if (veclen
!= node
->simdclone
->simdlen
)
11119 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
11121 /* Set up a SIMD array to use as the return value. */
11122 tree retval
= create_tmp_var_raw (atype
, "retval");
11123 gimple_add_tmp_var (retval
);
11127 /* Each vector argument has a corresponding array to be used locally
11128 as part of the eventual loop. Create such temporary array and
11131 PREFIX is the prefix to be used for the temporary.
11133 TYPE is the inner element type.
11135 SIMDLEN is the number of elements. */
11138 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
11140 tree atype
= build_array_type_nelts (type
, simdlen
);
11141 tree avar
= create_tmp_var_raw (atype
, prefix
);
11142 gimple_add_tmp_var (avar
);
11146 /* Modify the function argument types to their corresponding vector
11147 counterparts if appropriate. Also, create one array for each simd
11148 argument to be used locally when using the function arguments as
11151 NODE is the function whose arguments are to be adjusted.
11153 Returns an adjustment vector that will be filled describing how the
11154 argument types will be adjusted. */
11156 static ipa_parm_adjustment_vec
11157 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
11160 ipa_parm_adjustment_vec adjustments
;
11162 if (node
->definition
)
11163 args
= ipa_get_vector_of_formal_parms (node
->decl
);
11165 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11166 adjustments
.create (args
.length ());
11167 unsigned i
, j
, veclen
;
11168 struct ipa_parm_adjustment adj
;
11169 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
11171 memset (&adj
, 0, sizeof (adj
));
11172 tree parm
= args
[i
];
11173 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
11174 adj
.base_index
= i
;
11177 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
11178 node
->simdclone
->args
[i
].orig_type
= parm_type
;
11180 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
11182 /* No adjustment necessary for scalar arguments. */
11183 adj
.op
= IPA_PARM_OP_COPY
;
11187 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
11188 veclen
= node
->simdclone
->vecsize_int
;
11190 veclen
= node
->simdclone
->vecsize_float
;
11191 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
11192 if (veclen
> node
->simdclone
->simdlen
)
11193 veclen
= node
->simdclone
->simdlen
;
11194 adj
.arg_prefix
= "simd";
11195 adj
.type
= build_vector_type (parm_type
, veclen
);
11196 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
11197 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11199 adjustments
.safe_push (adj
);
11202 memset (&adj
, 0, sizeof (adj
));
11203 adj
.op
= IPA_PARM_OP_NEW
;
11204 adj
.arg_prefix
= "simd";
11205 adj
.base_index
= i
;
11206 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
11210 if (node
->definition
)
11211 node
->simdclone
->args
[i
].simd_array
11212 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
11213 parm_type
, node
->simdclone
->simdlen
);
11215 adjustments
.safe_push (adj
);
11218 if (node
->simdclone
->inbranch
)
11221 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
11224 memset (&adj
, 0, sizeof (adj
));
11225 adj
.op
= IPA_PARM_OP_NEW
;
11226 adj
.arg_prefix
= "mask";
11228 adj
.base_index
= i
;
11229 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
11230 veclen
= node
->simdclone
->vecsize_int
;
11232 veclen
= node
->simdclone
->vecsize_float
;
11233 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
11234 if (veclen
> node
->simdclone
->simdlen
)
11235 veclen
= node
->simdclone
->simdlen
;
11236 adj
.type
= build_vector_type (base_type
, veclen
);
11237 adjustments
.safe_push (adj
);
11239 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11240 adjustments
.safe_push (adj
);
11242 /* We have previously allocated one extra entry for the mask. Use
11244 struct cgraph_simd_clone
*sc
= node
->simdclone
;
11246 if (node
->definition
)
11248 sc
->args
[i
].orig_arg
11249 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
11250 sc
->args
[i
].simd_array
11251 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
11253 sc
->args
[i
].orig_type
= base_type
;
11254 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
11257 if (node
->definition
)
11258 ipa_modify_formal_parameters (node
->decl
, adjustments
);
11261 tree new_arg_types
= NULL_TREE
, new_reversed
;
11262 bool last_parm_void
= false;
11263 if (args
.length () > 0 && args
.last () == void_type_node
)
11264 last_parm_void
= true;
11266 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
11267 j
= adjustments
.length ();
11268 for (i
= 0; i
< j
; i
++)
11270 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
11272 if (adj
->op
== IPA_PARM_OP_COPY
)
11273 ptype
= args
[adj
->base_index
];
11276 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
11278 new_reversed
= nreverse (new_arg_types
);
11279 if (last_parm_void
)
11282 TREE_CHAIN (new_arg_types
) = void_list_node
;
11284 new_reversed
= void_list_node
;
11287 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
11288 TYPE_ARG_TYPES (new_type
) = new_reversed
;
11289 TREE_TYPE (node
->decl
) = new_type
;
11291 adjustments
.release ();
11294 return adjustments
;
11297 /* Initialize and copy the function arguments in NODE to their
11298 corresponding local simd arrays. Returns a fresh gimple_seq with
11299 the instruction sequence generated. */
11302 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
11303 ipa_parm_adjustment_vec adjustments
)
11305 gimple_seq seq
= NULL
;
11306 unsigned i
= 0, j
= 0, k
;
11308 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
11310 arg
= DECL_CHAIN (arg
), i
++, j
++)
11312 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
11315 node
->simdclone
->args
[i
].vector_arg
= arg
;
11317 tree array
= node
->simdclone
->args
[i
].simd_array
;
11318 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
11320 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11321 tree ptr
= build_fold_addr_expr (array
);
11322 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11323 build_int_cst (ptype
, 0));
11324 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11325 gimplify_and_add (t
, &seq
);
11329 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
11330 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11331 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
11333 tree ptr
= build_fold_addr_expr (array
);
11337 arg
= DECL_CHAIN (arg
);
11341 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
11342 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11343 build_int_cst (ptype
, k
* elemsize
));
11344 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11345 gimplify_and_add (t
, &seq
);
11352 /* Callback info for ipa_simd_modify_stmt_ops below. */
11354 struct modify_stmt_info
{
11355 ipa_parm_adjustment_vec adjustments
;
11357 /* True if the parent statement was modified by
11358 ipa_simd_modify_stmt_ops. */
11362 /* Callback for walk_gimple_op.
11364 Adjust operands from a given statement as specified in the
11365 adjustments vector in the callback data. */
11368 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
11370 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
11371 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
11372 tree
*orig_tp
= tp
;
11373 if (TREE_CODE (*tp
) == ADDR_EXPR
)
11374 tp
= &TREE_OPERAND (*tp
, 0);
11375 struct ipa_parm_adjustment
*cand
= NULL
;
11376 if (TREE_CODE (*tp
) == PARM_DECL
)
11377 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
11381 *walk_subtrees
= 0;
11384 tree repl
= NULL_TREE
;
11386 repl
= unshare_expr (cand
->new_decl
);
11391 *walk_subtrees
= 0;
11392 bool modified
= info
->modified
;
11393 info
->modified
= false;
11394 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
11395 if (!info
->modified
)
11397 info
->modified
= modified
;
11400 info
->modified
= modified
;
11409 repl
= build_fold_addr_expr (repl
);
11411 = gimple_build_assign (make_ssa_name (TREE_TYPE (repl
), NULL
), repl
);
11412 repl
= gimple_assign_lhs (stmt
);
11413 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
11414 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11417 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
11419 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
11425 info
->modified
= true;
11429 /* Traverse the function body and perform all modifications as
11430 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11431 modified such that the replacement/reduction value will now be an
11432 offset into the corresponding simd_array.
11434 This function will replace all function argument uses with their
11435 corresponding simd array elements, and ajust the return values
11439 ipa_simd_modify_function_body (struct cgraph_node
*node
,
11440 ipa_parm_adjustment_vec adjustments
,
11441 tree retval_array
, tree iter
)
11444 unsigned int i
, j
, l
;
11446 /* Re-use the adjustments array, but this time use it to replace
11447 every function argument use to an offset into the corresponding
11449 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
11451 if (!node
->simdclone
->args
[i
].vector_arg
)
11454 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
11455 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
11456 adjustments
[j
].new_decl
11457 = build4 (ARRAY_REF
,
11459 node
->simdclone
->args
[i
].simd_array
,
11461 NULL_TREE
, NULL_TREE
);
11462 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
11463 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
11464 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
11467 l
= adjustments
.length ();
11468 for (i
= 1; i
< num_ssa_names
; i
++)
11470 tree name
= ssa_name (i
);
11472 && SSA_NAME_VAR (name
)
11473 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
11475 for (j
= 0; j
< l
; j
++)
11476 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
11477 && adjustments
[j
].new_decl
)
11480 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
11483 = copy_var_decl (adjustments
[j
].base
,
11484 DECL_NAME (adjustments
[j
].base
),
11485 TREE_TYPE (adjustments
[j
].base
));
11486 adjustments
[j
].new_ssa_base
= base_var
;
11489 base_var
= adjustments
[j
].new_ssa_base
;
11490 if (SSA_NAME_IS_DEFAULT_DEF (name
))
11492 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11493 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
11494 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
11495 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
11496 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11497 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
11498 gimple stmt
= gimple_build_assign (name
, new_decl
);
11499 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11502 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11507 struct modify_stmt_info info
;
11508 info
.adjustments
= adjustments
;
11510 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
11512 gimple_stmt_iterator gsi
;
11514 gsi
= gsi_start_bb (bb
);
11515 while (!gsi_end_p (gsi
))
11517 gimple stmt
= gsi_stmt (gsi
);
11519 struct walk_stmt_info wi
;
11521 memset (&wi
, 0, sizeof (wi
));
11522 info
.modified
= false;
11524 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
11526 if (gimple_code (stmt
) == GIMPLE_RETURN
)
11528 tree retval
= gimple_return_retval (stmt
);
11531 gsi_remove (&gsi
, true);
11535 /* Replace `return foo' with `retval_array[iter] = foo'. */
11536 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
11537 retval_array
, iter
, NULL
, NULL
);
11538 stmt
= gimple_build_assign (ref
, retval
);
11539 gsi_replace (&gsi
, stmt
, true);
11540 info
.modified
= true;
11545 update_stmt (stmt
);
11546 if (maybe_clean_eh_stmt (stmt
))
11547 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
11554 /* Adjust the argument types in NODE to their appropriate vector
11558 simd_clone_adjust (struct cgraph_node
*node
)
11560 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
11562 targetm
.simd_clone
.adjust (node
);
11564 tree retval
= simd_clone_adjust_return_type (node
);
11565 ipa_parm_adjustment_vec adjustments
11566 = simd_clone_adjust_argument_types (node
);
11568 push_gimplify_context ();
11570 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
11572 /* Adjust all uses of vector arguments accordingly. Adjust all
11573 return values accordingly. */
11574 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
11575 tree iter1
= make_ssa_name (iter
, NULL
);
11576 tree iter2
= make_ssa_name (iter
, NULL
);
11577 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
11579 /* Initialize the iteration variable. */
11580 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11581 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
11582 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
11583 /* Insert the SIMD array and iv initialization at function
11585 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
11587 pop_gimplify_context (NULL
);
11589 /* Create a new BB right before the original exit BB, to hold the
11590 iteration increment and the condition/branch. */
11591 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
11592 basic_block incr_bb
= create_empty_bb (orig_exit
);
11593 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11594 flag. Set it now to be a FALLTHRU_EDGE. */
11595 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
11596 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
11597 for (unsigned i
= 0;
11598 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
11600 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
11601 redirect_edge_succ (e
, incr_bb
);
11603 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
11604 e
->probability
= REG_BR_PROB_BASE
;
11605 gsi
= gsi_last_bb (incr_bb
);
11606 gimple g
= gimple_build_assign_with_ops (PLUS_EXPR
, iter2
, iter1
,
11607 build_int_cst (unsigned_type_node
,
11609 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11611 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
11612 struct loop
*loop
= alloc_loop ();
11613 cfun
->has_force_vectorize_loops
= true;
11614 loop
->safelen
= node
->simdclone
->simdlen
;
11615 loop
->force_vectorize
= true;
11616 loop
->header
= body_bb
;
11617 add_bb_to_loop (incr_bb
, loop
);
11619 /* Branch around the body if the mask applies. */
11620 if (node
->simdclone
->inbranch
)
11622 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
11624 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
11625 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)), NULL
);
11626 tree aref
= build4 (ARRAY_REF
,
11627 TREE_TYPE (TREE_TYPE (mask_array
)),
11630 g
= gimple_build_assign (mask
, aref
);
11631 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11632 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
11633 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
11635 aref
= build1 (VIEW_CONVERT_EXPR
,
11636 build_nonstandard_integer_type (bitsize
, 0), mask
);
11637 mask
= make_ssa_name (TREE_TYPE (aref
), NULL
);
11638 g
= gimple_build_assign (mask
, aref
);
11639 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11642 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
11644 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11645 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
11646 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
11649 /* Generate the condition. */
11650 g
= gimple_build_cond (LT_EXPR
,
11652 build_int_cst (unsigned_type_node
,
11653 node
->simdclone
->simdlen
),
11655 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11656 e
= split_block (incr_bb
, gsi_stmt (gsi
));
11657 basic_block latch_bb
= e
->dest
;
11658 basic_block new_exit_bb
= e
->dest
;
11659 new_exit_bb
= split_block (latch_bb
, NULL
)->dest
;
11660 loop
->latch
= latch_bb
;
11662 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
11664 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
11665 /* The successor of incr_bb is already pointing to latch_bb; just
11667 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
11668 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
11670 gimple phi
= create_phi_node (iter1
, body_bb
);
11671 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
11672 edge latch_edge
= single_succ_edge (latch_bb
);
11673 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
11675 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
11677 /* Generate the new return. */
11678 gsi
= gsi_last_bb (new_exit_bb
);
11680 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
11681 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
11682 retval
= TREE_OPERAND (retval
, 0);
11685 retval
= build1 (VIEW_CONVERT_EXPR
,
11686 TREE_TYPE (TREE_TYPE (node
->decl
)),
11688 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
11689 false, GSI_CONTINUE_LINKING
);
11691 g
= gimple_build_return (retval
);
11692 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
11694 /* Handle aligned clauses by replacing default defs of the aligned
11695 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
11696 lhs. Handle linear by adding PHIs. */
11697 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
11698 if (node
->simdclone
->args
[i
].alignment
11699 && node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
11700 && (node
->simdclone
->args
[i
].alignment
11701 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
11702 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
11705 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
11706 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
11707 tree def
= ssa_default_def (cfun
, orig_arg
);
11708 if (def
&& !has_zero_uses (def
))
11710 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
11711 gimple_seq seq
= NULL
;
11712 bool need_cvt
= false;
11714 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
11716 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
11719 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
, NULL
);
11720 gimple_call_set_lhs (g
, t
);
11721 gimple_seq_add_stmt_without_update (&seq
, g
);
11724 t
= make_ssa_name (orig_arg
, NULL
);
11725 g
= gimple_build_assign_with_ops (NOP_EXPR
, t
,
11726 gimple_call_lhs (g
),
11728 gimple_seq_add_stmt_without_update (&seq
, g
);
11730 gsi_insert_seq_on_edge_immediate
11731 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
11733 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11734 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
11736 cgraph_create_edge (node
, cgraph_get_create_node (fn
),
11737 call
, entry_bb
->count
, freq
);
11739 imm_use_iterator iter
;
11740 use_operand_p use_p
;
11742 tree repl
= gimple_get_lhs (g
);
11743 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
11744 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
11747 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
11748 SET_USE (use_p
, repl
);
11751 else if (node
->simdclone
->args
[i
].arg_type
11752 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
11754 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
11755 tree def
= ssa_default_def (cfun
, orig_arg
);
11756 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
11757 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
11758 if (def
&& !has_zero_uses (def
))
11760 iter1
= make_ssa_name (orig_arg
, NULL
);
11761 iter2
= make_ssa_name (orig_arg
, NULL
);
11762 phi
= create_phi_node (iter1
, body_bb
);
11763 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
11764 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
11765 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
11766 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
11767 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
11768 ? TREE_TYPE (orig_arg
) : sizetype
;
11770 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
11771 g
= gimple_build_assign_with_ops (code
, iter2
, iter1
, addcst
);
11772 gsi
= gsi_last_bb (incr_bb
);
11773 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
11775 imm_use_iterator iter
;
11776 use_operand_p use_p
;
11778 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
11779 if (use_stmt
== phi
)
11782 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
11783 SET_USE (use_p
, iter1
);
11787 calculate_dominance_info (CDI_DOMINATORS
);
11788 add_loop (loop
, loop
->header
->loop_father
);
11789 update_ssa (TODO_update_ssa
);
11794 /* If the function in NODE is tagged as an elemental SIMD function,
11795 create the appropriate SIMD clones. */
11798 expand_simd_clones (struct cgraph_node
*node
)
11800 tree attr
= lookup_attribute ("omp declare simd",
11801 DECL_ATTRIBUTES (node
->decl
));
11802 if (attr
== NULL_TREE
11803 || node
->global
.inlined_to
11804 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
11808 #pragma omp declare simd
11810 in C, there we don't know the argument types at all. */
11811 if (!node
->definition
11812 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
11817 /* Start with parsing the "omp declare simd" attribute(s). */
11818 bool inbranch_clause_specified
;
11819 struct cgraph_simd_clone
*clone_info
11820 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
11821 &inbranch_clause_specified
);
11822 if (clone_info
== NULL
)
11825 int orig_simdlen
= clone_info
->simdlen
;
11826 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
11827 /* The target can return 0 (no simd clones should be created),
11828 1 (just one ISA of simd clones should be created) or higher
11829 count of ISA variants. In that case, clone_info is initialized
11830 for the first ISA variant. */
11832 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
11837 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
11838 also create one inbranch and one !inbranch clone of it. */
11839 for (int i
= 0; i
< count
* 2; i
++)
11841 struct cgraph_simd_clone
*clone
= clone_info
;
11842 if (inbranch_clause_specified
&& (i
& 1) != 0)
11847 clone
= simd_clone_struct_alloc (clone_info
->nargs
11849 simd_clone_struct_copy (clone
, clone_info
);
11850 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
11851 and simd_clone_adjust_argument_types did to the first
11853 clone
->nargs
-= clone_info
->inbranch
;
11854 clone
->simdlen
= orig_simdlen
;
11855 /* And call the target hook again to get the right ISA. */
11856 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
11860 clone
->inbranch
= 1;
11863 /* simd_clone_mangle might fail if such a clone has been created
11865 tree id
= simd_clone_mangle (node
, clone
);
11866 if (id
== NULL_TREE
)
11869 /* Only when we are sure we want to create the clone actually
11870 clone the function (or definitions) or create another
11871 extern FUNCTION_DECL (for prototypes without definitions). */
11872 struct cgraph_node
*n
= simd_clone_create (node
);
11876 n
->simdclone
= clone
;
11877 clone
->origin
= node
;
11878 clone
->next_clone
= NULL
;
11879 if (node
->simd_clones
== NULL
)
11881 clone
->prev_clone
= n
;
11882 node
->simd_clones
= n
;
11886 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
11887 clone
->prev_clone
->simdclone
->next_clone
= n
;
11888 node
->simd_clones
->simdclone
->prev_clone
= n
;
11890 change_decl_assembler_name (n
->decl
, id
);
11891 /* And finally adjust the return type, parameters and for
11892 definitions also function body. */
11893 if (node
->definition
)
11894 simd_clone_adjust (n
);
11897 simd_clone_adjust_return_type (n
);
11898 simd_clone_adjust_argument_types (n
);
11902 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
11905 /* Entry point for IPA simd clone creation pass. */
11907 static unsigned int
11908 ipa_omp_simd_clone (void)
11910 struct cgraph_node
*node
;
11911 FOR_EACH_FUNCTION (node
)
11912 expand_simd_clones (node
);
11918 const pass_data pass_data_omp_simd_clone
=
11920 SIMPLE_IPA_PASS
, /* type */
11921 "simdclone", /* name */
11922 OPTGROUP_NONE
, /* optinfo_flags */
11923 TV_NONE
, /* tv_id */
11924 ( PROP_ssa
| PROP_cfg
), /* properties_required */
11925 0, /* properties_provided */
11926 0, /* properties_destroyed */
11927 0, /* todo_flags_start */
11928 0, /* todo_flags_finish */
11931 class pass_omp_simd_clone
: public simple_ipa_opt_pass
11934 pass_omp_simd_clone(gcc::context
*ctxt
)
11935 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
11938 /* opt_pass methods: */
11939 virtual bool gate (function
*);
11940 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
11944 pass_omp_simd_clone::gate (function
*)
11946 return ((flag_openmp
|| flag_openmp_simd
11948 || (in_lto_p
&& !flag_wpa
))
11949 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
11952 } // anon namespace
11954 simple_ipa_opt_pass
*
11955 make_pass_omp_simd_clone (gcc::context
*ctxt
)
11957 return new pass_omp_simd_clone (ctxt
);
11960 #include "gt-omp-low.h"