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"
37 #include "hard-reg-set.h"
40 #include "dominance.h"
43 #include "basic-block.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-fold.h"
47 #include "gimple-expr.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
60 #include "plugin-api.h"
64 #include "tree-phinodes.h"
65 #include "ssa-iterators.h"
66 #include "tree-ssanames.h"
67 #include "tree-into-ssa.h"
73 #include "tree-pass.h"
75 #include "splay-tree.h"
76 #include "insn-codes.h"
81 #include "gimple-low.h"
82 #include "tree-cfgcleanup.h"
83 #include "pretty-print.h"
84 #include "alloc-pool.h"
86 #include "tree-nested.h"
91 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
92 phases. The first phase scans the function looking for OMP statements
93 and then for variables that must be replaced to satisfy data sharing
94 clauses. The second phase expands code for the constructs, as well as
95 re-gimplifying things when variables have been replaced with complex
98 Final code generation is done by pass_expand_omp. The flowgraph is
99 scanned for parallel regions which are then moved to a new
100 function, to be invoked by the thread library. */
102 /* Parallel region information. Every parallel and workshare
103 directive is enclosed between two markers, the OMP_* directive
104 and a corresponding OMP_RETURN statement. */
108 /* The enclosing region. */
109 struct omp_region
*outer
;
111 /* First child region. */
112 struct omp_region
*inner
;
114 /* Next peer region. */
115 struct omp_region
*next
;
117 /* Block containing the omp directive as its last stmt. */
120 /* Block containing the OMP_RETURN as its last stmt. */
123 /* Block containing the OMP_CONTINUE as its last stmt. */
126 /* If this is a combined parallel+workshare region, this is a list
127 of additional arguments needed by the combined parallel+workshare
129 vec
<tree
, va_gc
> *ws_args
;
131 /* The code for the omp directive of this region. */
132 enum gimple_code type
;
134 /* Schedule kind, only used for OMP_FOR type regions. */
135 enum omp_clause_schedule_kind sched_kind
;
137 /* True if this is a combined parallel+workshare region. */
138 bool is_combined_parallel
;
141 /* Context structure. Used to store information about each parallel
142 directive in the code. */
144 typedef struct omp_context
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context
*outer
;
156 /* Map variables to fields in a structure that allows communication
157 between sending and receiving threads. */
158 splay_tree field_map
;
163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map
;
171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
175 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
176 barriers should jump to during omplower pass. */
179 /* What to do with variables with implicitly determined sharing
181 enum omp_clause_default_kind default_kind
;
183 /* Nesting depth of this context. Used to beautify error messages re
184 invalid gotos. The outermost ctx is depth 1, with depth 0 being
185 reserved for the main body of the function. */
188 /* True if this parallel directive is nested within another. */
191 /* True if this construct can be cancelled. */
196 struct omp_for_data_loop
198 tree v
, n1
, n2
, step
;
199 enum tree_code cond_code
;
202 /* A structure describing the main elements of a parallel loop. */
206 struct omp_for_data_loop loop
;
211 bool have_nowait
, have_ordered
;
212 enum omp_clause_schedule_kind sched_kind
;
213 struct omp_for_data_loop
*loops
;
217 static splay_tree all_contexts
;
218 static int taskreg_nesting_level
;
219 static int target_nesting_level
;
220 static struct omp_region
*root_omp_region
;
221 static bitmap task_shared_vars
;
222 static vec
<omp_context
*> taskreg_contexts
;
224 static void scan_omp (gimple_seq
*, omp_context
*);
225 static tree
scan_omp_1_op (tree
*, int *, void *);
227 #define WALK_SUBSTMTS \
231 case GIMPLE_EH_FILTER: \
232 case GIMPLE_TRANSACTION: \
233 /* The sub-statements for these should be walked. */ \
234 *handled_ops_p = false; \
237 /* Convenience function for calling scan_omp_1_op on tree operands. */
240 scan_omp_op (tree
*tp
, omp_context
*ctx
)
242 struct walk_stmt_info wi
;
244 memset (&wi
, 0, sizeof (wi
));
246 wi
.want_locations
= true;
248 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
251 static void lower_omp (gimple_seq
*, omp_context
*);
252 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
253 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
255 /* Find an OpenMP clause of type KIND within CLAUSES. */
258 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
260 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
261 if (OMP_CLAUSE_CODE (clauses
) == kind
)
267 /* Return true if CTX is for an omp parallel. */
270 is_parallel_ctx (omp_context
*ctx
)
272 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
276 /* Return true if CTX is for an omp task. */
279 is_task_ctx (omp_context
*ctx
)
281 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
285 /* Return true if CTX is for an omp parallel or omp task. */
288 is_taskreg_ctx (omp_context
*ctx
)
290 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
291 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
295 /* Return true if REGION is a combined parallel+workshare region. */
298 is_combined_parallel (struct omp_region
*region
)
300 return region
->is_combined_parallel
;
304 /* Extract the header elements of parallel loop FOR_STMT and store
308 extract_omp_for_data (gimple for_stmt
, struct omp_for_data
*fd
,
309 struct omp_for_data_loop
*loops
)
311 tree t
, var
, *collapse_iter
, *collapse_count
;
312 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
313 struct omp_for_data_loop
*loop
;
315 struct omp_for_data_loop dummy_loop
;
316 location_t loc
= gimple_location (for_stmt
);
317 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
318 bool distribute
= gimple_omp_for_kind (for_stmt
)
319 == GF_OMP_FOR_KIND_DISTRIBUTE
;
321 fd
->for_stmt
= for_stmt
;
323 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
324 if (fd
->collapse
> 1)
327 fd
->loops
= &fd
->loop
;
329 fd
->have_nowait
= distribute
|| simd
;
330 fd
->have_ordered
= false;
331 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
332 fd
->chunk_size
= NULL_TREE
;
333 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
334 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
335 collapse_iter
= NULL
;
336 collapse_count
= NULL
;
338 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
339 switch (OMP_CLAUSE_CODE (t
))
341 case OMP_CLAUSE_NOWAIT
:
342 fd
->have_nowait
= true;
344 case OMP_CLAUSE_ORDERED
:
345 fd
->have_ordered
= true;
347 case OMP_CLAUSE_SCHEDULE
:
348 gcc_assert (!distribute
);
349 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
350 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
352 case OMP_CLAUSE_DIST_SCHEDULE
:
353 gcc_assert (distribute
);
354 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
356 case OMP_CLAUSE_COLLAPSE
:
357 if (fd
->collapse
> 1)
359 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
360 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
367 /* FIXME: for now map schedule(auto) to schedule(static).
368 There should be analysis to determine whether all iterations
369 are approximately the same amount of work (then schedule(static)
370 is best) or if it varies (then schedule(dynamic,N) is better). */
371 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
373 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
374 gcc_assert (fd
->chunk_size
== NULL
);
376 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
377 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
378 gcc_assert (fd
->chunk_size
== NULL
);
379 else if (fd
->chunk_size
== NULL
)
381 /* We only need to compute a default chunk size for ordered
382 static loops and dynamic loops. */
383 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
385 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
386 ? integer_zero_node
: integer_one_node
;
389 for (i
= 0; i
< fd
->collapse
; i
++)
391 if (fd
->collapse
== 1)
393 else if (loops
!= NULL
)
398 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
399 gcc_assert (SSA_VAR_P (loop
->v
));
400 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
401 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
402 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
403 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
405 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
406 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
407 switch (loop
->cond_code
)
413 gcc_assert (gimple_omp_for_kind (for_stmt
)
414 == GF_OMP_FOR_KIND_CILKSIMD
415 || (gimple_omp_for_kind (for_stmt
)
416 == GF_OMP_FOR_KIND_CILKFOR
));
419 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
420 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
422 loop
->n2
= fold_build2_loc (loc
,
423 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
424 build_int_cst (TREE_TYPE (loop
->n2
), 1));
425 loop
->cond_code
= LT_EXPR
;
428 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
429 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
431 loop
->n2
= fold_build2_loc (loc
,
432 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
433 build_int_cst (TREE_TYPE (loop
->n2
), 1));
434 loop
->cond_code
= GT_EXPR
;
440 t
= gimple_omp_for_incr (for_stmt
, i
);
441 gcc_assert (TREE_OPERAND (t
, 0) == var
);
442 switch (TREE_CODE (t
))
445 loop
->step
= TREE_OPERAND (t
, 1);
447 case POINTER_PLUS_EXPR
:
448 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
451 loop
->step
= TREE_OPERAND (t
, 1);
452 loop
->step
= fold_build1_loc (loc
,
453 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
461 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
462 && !fd
->have_ordered
))
464 if (fd
->collapse
== 1)
465 iter_type
= TREE_TYPE (loop
->v
);
467 || TYPE_PRECISION (iter_type
)
468 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
470 = build_nonstandard_integer_type
471 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
473 else if (iter_type
!= long_long_unsigned_type_node
)
475 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
476 iter_type
= long_long_unsigned_type_node
;
477 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
478 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
479 >= TYPE_PRECISION (iter_type
))
483 if (loop
->cond_code
== LT_EXPR
)
484 n
= fold_build2_loc (loc
,
485 PLUS_EXPR
, TREE_TYPE (loop
->v
),
486 loop
->n2
, loop
->step
);
489 if (TREE_CODE (n
) != INTEGER_CST
490 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
491 iter_type
= long_long_unsigned_type_node
;
493 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
494 > TYPE_PRECISION (iter_type
))
498 if (loop
->cond_code
== LT_EXPR
)
501 n2
= fold_build2_loc (loc
,
502 PLUS_EXPR
, TREE_TYPE (loop
->v
),
503 loop
->n2
, loop
->step
);
507 n1
= fold_build2_loc (loc
,
508 MINUS_EXPR
, TREE_TYPE (loop
->v
),
509 loop
->n2
, loop
->step
);
512 if (TREE_CODE (n1
) != INTEGER_CST
513 || TREE_CODE (n2
) != INTEGER_CST
514 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
515 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
516 iter_type
= long_long_unsigned_type_node
;
520 if (collapse_count
&& *collapse_count
== NULL
)
522 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
523 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
524 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
525 if (t
&& integer_zerop (t
))
526 count
= build_zero_cst (long_long_unsigned_type_node
);
527 else if ((i
== 0 || count
!= NULL_TREE
)
528 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
529 && TREE_CONSTANT (loop
->n1
)
530 && TREE_CONSTANT (loop
->n2
)
531 && TREE_CODE (loop
->step
) == INTEGER_CST
)
533 tree itype
= TREE_TYPE (loop
->v
);
535 if (POINTER_TYPE_P (itype
))
536 itype
= signed_type_for (itype
);
537 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
538 t
= fold_build2_loc (loc
,
540 fold_convert_loc (loc
, itype
, loop
->step
), t
);
541 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
542 fold_convert_loc (loc
, itype
, loop
->n2
));
543 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
544 fold_convert_loc (loc
, itype
, loop
->n1
));
545 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
546 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
547 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
548 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
549 fold_convert_loc (loc
, itype
,
552 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
553 fold_convert_loc (loc
, itype
, loop
->step
));
554 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
555 if (count
!= NULL_TREE
)
556 count
= fold_build2_loc (loc
,
557 MULT_EXPR
, long_long_unsigned_type_node
,
561 if (TREE_CODE (count
) != INTEGER_CST
)
564 else if (count
&& !integer_zerop (count
))
571 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
572 || fd
->have_ordered
))
574 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
575 iter_type
= long_long_unsigned_type_node
;
577 iter_type
= long_integer_type_node
;
579 else if (collapse_iter
&& *collapse_iter
!= NULL
)
580 iter_type
= TREE_TYPE (*collapse_iter
);
581 fd
->iter_type
= iter_type
;
582 if (collapse_iter
&& *collapse_iter
== NULL
)
583 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
584 if (collapse_count
&& *collapse_count
== NULL
)
587 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
589 *collapse_count
= create_tmp_var (iter_type
, ".count");
592 if (fd
->collapse
> 1)
594 fd
->loop
.v
= *collapse_iter
;
595 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
596 fd
->loop
.n2
= *collapse_count
;
597 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
598 fd
->loop
.cond_code
= LT_EXPR
;
603 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
604 is the immediate dominator of PAR_ENTRY_BB, return true if there
605 are no data dependencies that would prevent expanding the parallel
606 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
608 When expanding a combined parallel+workshare region, the call to
609 the child function may need additional arguments in the case of
610 GIMPLE_OMP_FOR regions. In some cases, these arguments are
611 computed out of variables passed in from the parent to the child
612 via 'struct .omp_data_s'. For instance:
614 #pragma omp parallel for schedule (guided, i * 4)
619 # BLOCK 2 (PAR_ENTRY_BB)
621 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
623 # BLOCK 3 (WS_ENTRY_BB)
624 .omp_data_i = &.omp_data_o;
625 D.1667 = .omp_data_i->i;
627 #pragma omp for schedule (guided, D.1598)
629 When we outline the parallel region, the call to the child function
630 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
631 that value is computed *after* the call site. So, in principle we
632 cannot do the transformation.
634 To see whether the code in WS_ENTRY_BB blocks the combined
635 parallel+workshare call, we collect all the variables used in the
636 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
637 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
640 FIXME. If we had the SSA form built at this point, we could merely
641 hoist the code in block 3 into block 2 and be done with it. But at
642 this point we don't have dataflow information and though we could
643 hack something up here, it is really not worth the aggravation. */
646 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
648 struct omp_for_data fd
;
649 gimple ws_stmt
= last_stmt (ws_entry_bb
);
651 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
654 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
656 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
658 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
660 if (fd
.iter_type
!= long_integer_type_node
)
663 /* FIXME. We give up too easily here. If any of these arguments
664 are not constants, they will likely involve variables that have
665 been mapped into fields of .omp_data_s for sharing with the child
666 function. With appropriate data flow, it would be possible to
668 if (!is_gimple_min_invariant (fd
.loop
.n1
)
669 || !is_gimple_min_invariant (fd
.loop
.n2
)
670 || !is_gimple_min_invariant (fd
.loop
.step
)
671 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
678 /* Collect additional arguments needed to emit a combined
679 parallel+workshare call. WS_STMT is the workshare directive being
682 static vec
<tree
, va_gc
> *
683 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
686 location_t loc
= gimple_location (ws_stmt
);
687 vec
<tree
, va_gc
> *ws_args
;
689 if (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
)
691 struct omp_for_data fd
;
694 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
698 if (gimple_omp_for_combined_into_p (ws_stmt
))
701 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
702 OMP_CLAUSE__LOOPTEMP_
);
704 n1
= OMP_CLAUSE_DECL (innerc
);
705 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
706 OMP_CLAUSE__LOOPTEMP_
);
708 n2
= OMP_CLAUSE_DECL (innerc
);
711 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
713 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
714 ws_args
->quick_push (t
);
716 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
717 ws_args
->quick_push (t
);
719 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
720 ws_args
->quick_push (t
);
724 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
725 ws_args
->quick_push (t
);
730 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
732 /* Number of sections is equal to the number of edges from the
733 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
734 the exit of the sections region. */
735 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
736 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
737 vec_alloc (ws_args
, 1);
738 ws_args
->quick_push (t
);
746 /* Discover whether REGION is a combined parallel+workshare region. */
749 determine_parallel_type (struct omp_region
*region
)
751 basic_block par_entry_bb
, par_exit_bb
;
752 basic_block ws_entry_bb
, ws_exit_bb
;
754 if (region
== NULL
|| region
->inner
== NULL
755 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
756 || region
->inner
->cont
== NULL
)
759 /* We only support parallel+for and parallel+sections. */
760 if (region
->type
!= GIMPLE_OMP_PARALLEL
761 || (region
->inner
->type
!= GIMPLE_OMP_FOR
762 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
765 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
766 WS_EXIT_BB -> PAR_EXIT_BB. */
767 par_entry_bb
= region
->entry
;
768 par_exit_bb
= region
->exit
;
769 ws_entry_bb
= region
->inner
->entry
;
770 ws_exit_bb
= region
->inner
->exit
;
772 if (single_succ (par_entry_bb
) == ws_entry_bb
773 && single_succ (ws_exit_bb
) == par_exit_bb
774 && workshare_safe_to_combine_p (ws_entry_bb
)
775 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
776 || (last_and_only_stmt (ws_entry_bb
)
777 && last_and_only_stmt (par_exit_bb
))))
779 gimple par_stmt
= last_stmt (par_entry_bb
);
780 gimple ws_stmt
= last_stmt (ws_entry_bb
);
782 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
784 /* If this is a combined parallel loop, we need to determine
785 whether or not to use the combined library calls. There
786 are two cases where we do not apply the transformation:
787 static loops and any kind of ordered loop. In the first
788 case, we already open code the loop so there is no need
789 to do anything else. In the latter case, the combined
790 parallel loop call would still need extra synchronization
791 to implement ordered semantics, so there would not be any
792 gain in using the combined call. */
793 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
794 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
796 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
797 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
799 region
->is_combined_parallel
= false;
800 region
->inner
->is_combined_parallel
= false;
805 region
->is_combined_parallel
= true;
806 region
->inner
->is_combined_parallel
= true;
807 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
812 /* Return true if EXPR is variable sized. */
815 is_variable_sized (const_tree expr
)
817 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
820 /* Return true if DECL is a reference type. */
823 is_reference (tree decl
)
825 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
828 /* Lookup variables in the decl or field splay trees. The "maybe" form
829 allows for the variable form to not have been entered, otherwise we
830 assert that the variable must have been entered. */
833 lookup_decl (tree var
, omp_context
*ctx
)
835 tree
*n
= ctx
->cb
.decl_map
->get (var
);
840 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
842 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
843 return n
? *n
: NULL_TREE
;
847 lookup_field (tree var
, omp_context
*ctx
)
850 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
851 return (tree
) n
->value
;
855 lookup_sfield (tree var
, omp_context
*ctx
)
858 n
= splay_tree_lookup (ctx
->sfield_map
859 ? ctx
->sfield_map
: ctx
->field_map
,
860 (splay_tree_key
) var
);
861 return (tree
) n
->value
;
865 maybe_lookup_field (tree var
, omp_context
*ctx
)
868 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
869 return n
? (tree
) n
->value
: NULL_TREE
;
872 /* Return true if DECL should be copied by pointer. SHARED_CTX is
873 the parallel context if DECL is to be shared. */
876 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
878 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
881 /* We can only use copy-in/copy-out semantics for shared variables
882 when we know the value is not accessible from an outer scope. */
885 /* ??? Trivially accessible from anywhere. But why would we even
886 be passing an address in this case? Should we simply assert
887 this to be false, or should we have a cleanup pass that removes
888 these from the list of mappings? */
889 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
892 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
893 without analyzing the expression whether or not its location
894 is accessible to anyone else. In the case of nested parallel
895 regions it certainly may be. */
896 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
899 /* Do not use copy-in/copy-out for variables that have their
901 if (TREE_ADDRESSABLE (decl
))
904 /* lower_send_shared_vars only uses copy-in, but not copy-out
906 if (TREE_READONLY (decl
)
907 || ((TREE_CODE (decl
) == RESULT_DECL
908 || TREE_CODE (decl
) == PARM_DECL
)
909 && DECL_BY_REFERENCE (decl
)))
912 /* Disallow copy-in/out in nested parallel if
913 decl is shared in outer parallel, otherwise
914 each thread could store the shared variable
915 in its own copy-in location, making the
916 variable no longer really shared. */
917 if (shared_ctx
->is_nested
)
921 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
922 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
929 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
930 c
; c
= OMP_CLAUSE_CHAIN (c
))
931 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
932 && OMP_CLAUSE_DECL (c
) == decl
)
936 goto maybe_mark_addressable_and_ret
;
940 /* For tasks avoid using copy-in/out. As tasks can be
941 deferred or executed in different thread, when GOMP_task
942 returns, the task hasn't necessarily terminated. */
943 if (is_task_ctx (shared_ctx
))
946 maybe_mark_addressable_and_ret
:
947 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
948 if (is_gimple_reg (outer
))
950 /* Taking address of OUTER in lower_send_shared_vars
951 might need regimplification of everything that uses the
953 if (!task_shared_vars
)
954 task_shared_vars
= BITMAP_ALLOC (NULL
);
955 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
956 TREE_ADDRESSABLE (outer
) = 1;
965 /* Construct a new automatic decl similar to VAR. */
968 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
970 tree copy
= copy_var_decl (var
, name
, type
);
972 DECL_CONTEXT (copy
) = current_function_decl
;
973 DECL_CHAIN (copy
) = ctx
->block_vars
;
974 ctx
->block_vars
= copy
;
980 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
982 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
985 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
988 omp_build_component_ref (tree obj
, tree field
)
990 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
991 if (TREE_THIS_VOLATILE (field
))
992 TREE_THIS_VOLATILE (ret
) |= 1;
993 if (TREE_READONLY (field
))
994 TREE_READONLY (ret
) |= 1;
998 /* Build tree nodes to access the field for VAR on the receiver side. */
1001 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1003 tree x
, field
= lookup_field (var
, ctx
);
1005 /* If the receiver record type was remapped in the child function,
1006 remap the field into the new record type. */
1007 x
= maybe_lookup_field (field
, ctx
);
1011 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1012 x
= omp_build_component_ref (x
, field
);
1014 x
= build_simple_mem_ref (x
);
1019 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1020 of a parallel, this is a component reference; for workshare constructs
1021 this is some variable. */
1024 build_outer_var_ref (tree var
, omp_context
*ctx
)
1028 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1030 else if (is_variable_sized (var
))
1032 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1033 x
= build_outer_var_ref (x
, ctx
);
1034 x
= build_simple_mem_ref (x
);
1036 else if (is_taskreg_ctx (ctx
))
1038 bool by_ref
= use_pointer_for_field (var
, NULL
);
1039 x
= build_receiver_ref (var
, by_ref
, ctx
);
1041 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1042 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1044 /* #pragma omp simd isn't a worksharing construct, and can reference even
1045 private vars in its linear etc. clauses. */
1047 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1048 x
= lookup_decl (var
, ctx
->outer
);
1049 else if (ctx
->outer
)
1050 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1054 else if (ctx
->outer
)
1055 x
= lookup_decl (var
, ctx
->outer
);
1056 else if (is_reference (var
))
1057 /* This can happen with orphaned constructs. If var is reference, it is
1058 possible it is shared and as such valid. */
1063 if (is_reference (var
))
1064 x
= build_simple_mem_ref (x
);
1069 /* Build tree nodes to access the field for VAR on the sender side. */
1072 build_sender_ref (tree var
, omp_context
*ctx
)
1074 tree field
= lookup_sfield (var
, ctx
);
1075 return omp_build_component_ref (ctx
->sender_decl
, field
);
1078 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1081 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1083 tree field
, type
, sfield
= NULL_TREE
;
1085 gcc_assert ((mask
& 1) == 0
1086 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1087 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1088 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1090 type
= TREE_TYPE (var
);
1093 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1094 type
= build_pointer_type (build_pointer_type (type
));
1097 type
= build_pointer_type (type
);
1098 else if ((mask
& 3) == 1 && is_reference (var
))
1099 type
= TREE_TYPE (type
);
1101 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1102 FIELD_DECL
, DECL_NAME (var
), type
);
1104 /* Remember what variable this field was created for. This does have a
1105 side effect of making dwarf2out ignore this member, so for helpful
1106 debugging we clear it later in delete_omp_context. */
1107 DECL_ABSTRACT_ORIGIN (field
) = var
;
1108 if (type
== TREE_TYPE (var
))
1110 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1111 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1112 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1115 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1117 if ((mask
& 3) == 3)
1119 insert_field_into_struct (ctx
->record_type
, field
);
1120 if (ctx
->srecord_type
)
1122 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1123 FIELD_DECL
, DECL_NAME (var
), type
);
1124 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1125 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1126 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1127 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1128 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1133 if (ctx
->srecord_type
== NULL_TREE
)
1137 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1138 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1139 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1141 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1142 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1143 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1144 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1145 splay_tree_insert (ctx
->sfield_map
,
1146 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1147 (splay_tree_value
) sfield
);
1151 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1152 : ctx
->srecord_type
, field
);
1156 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1157 (splay_tree_value
) field
);
1158 if ((mask
& 2) && ctx
->sfield_map
)
1159 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1160 (splay_tree_value
) sfield
);
1164 install_var_local (tree var
, omp_context
*ctx
)
1166 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1167 insert_decl_map (&ctx
->cb
, var
, new_var
);
1171 /* Adjust the replacement for DECL in CTX for the new context. This means
1172 copying the DECL_VALUE_EXPR, and fixing up the type. */
1175 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1177 tree new_decl
, size
;
1179 new_decl
= lookup_decl (decl
, ctx
);
1181 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1183 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1184 && DECL_HAS_VALUE_EXPR_P (decl
))
1186 tree ve
= DECL_VALUE_EXPR (decl
);
1187 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1188 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1189 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1192 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1194 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1195 if (size
== error_mark_node
)
1196 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1197 DECL_SIZE (new_decl
) = size
;
1199 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1200 if (size
== error_mark_node
)
1201 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1202 DECL_SIZE_UNIT (new_decl
) = size
;
1206 /* The callback for remap_decl. Search all containing contexts for a
1207 mapping of the variable; this avoids having to duplicate the splay
1208 tree ahead of time. We know a mapping doesn't already exist in the
1209 given context. Create new mappings to implement default semantics. */
1212 omp_copy_decl (tree var
, copy_body_data
*cb
)
1214 omp_context
*ctx
= (omp_context
*) cb
;
1217 if (TREE_CODE (var
) == LABEL_DECL
)
1219 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1220 DECL_CONTEXT (new_var
) = current_function_decl
;
1221 insert_decl_map (&ctx
->cb
, var
, new_var
);
1225 while (!is_taskreg_ctx (ctx
))
1230 new_var
= maybe_lookup_decl (var
, ctx
);
1235 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1238 return error_mark_node
;
1242 /* Debugging dumps for parallel regions. */
1243 void dump_omp_region (FILE *, struct omp_region
*, int);
1244 void debug_omp_region (struct omp_region
*);
1245 void debug_all_omp_regions (void);
1247 /* Dump the parallel region tree rooted at REGION. */
1250 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1252 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1253 gimple_code_name
[region
->type
]);
1256 dump_omp_region (file
, region
->inner
, indent
+ 4);
1260 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1261 region
->cont
->index
);
1265 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1266 region
->exit
->index
);
1268 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1271 dump_omp_region (file
, region
->next
, indent
);
1275 debug_omp_region (struct omp_region
*region
)
1277 dump_omp_region (stderr
, region
, 0);
1281 debug_all_omp_regions (void)
1283 dump_omp_region (stderr
, root_omp_region
, 0);
1287 /* Create a new parallel region starting at STMT inside region PARENT. */
1289 static struct omp_region
*
1290 new_omp_region (basic_block bb
, enum gimple_code type
,
1291 struct omp_region
*parent
)
1293 struct omp_region
*region
= XCNEW (struct omp_region
);
1295 region
->outer
= parent
;
1297 region
->type
= type
;
1301 /* This is a nested region. Add it to the list of inner
1302 regions in PARENT. */
1303 region
->next
= parent
->inner
;
1304 parent
->inner
= region
;
1308 /* This is a toplevel region. Add it to the list of toplevel
1309 regions in ROOT_OMP_REGION. */
1310 region
->next
= root_omp_region
;
1311 root_omp_region
= region
;
1317 /* Release the memory associated with the region tree rooted at REGION. */
1320 free_omp_region_1 (struct omp_region
*region
)
1322 struct omp_region
*i
, *n
;
1324 for (i
= region
->inner
; i
; i
= n
)
1327 free_omp_region_1 (i
);
1333 /* Release the memory for the entire omp region tree. */
1336 free_omp_regions (void)
1338 struct omp_region
*r
, *n
;
1339 for (r
= root_omp_region
; r
; r
= n
)
1342 free_omp_region_1 (r
);
1344 root_omp_region
= NULL
;
1348 /* Create a new context, with OUTER_CTX being the surrounding context. */
1350 static omp_context
*
1351 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1353 omp_context
*ctx
= XCNEW (omp_context
);
1355 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1356 (splay_tree_value
) ctx
);
1361 ctx
->outer
= outer_ctx
;
1362 ctx
->cb
= outer_ctx
->cb
;
1363 ctx
->cb
.block
= NULL
;
1364 ctx
->depth
= outer_ctx
->depth
+ 1;
1368 ctx
->cb
.src_fn
= current_function_decl
;
1369 ctx
->cb
.dst_fn
= current_function_decl
;
1370 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1371 gcc_checking_assert (ctx
->cb
.src_node
);
1372 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1373 ctx
->cb
.src_cfun
= cfun
;
1374 ctx
->cb
.copy_decl
= omp_copy_decl
;
1375 ctx
->cb
.eh_lp_nr
= 0;
1376 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1380 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1385 static gimple_seq
maybe_catch_exception (gimple_seq
);
1387 /* Finalize task copyfn. */
1390 finalize_task_copyfn (gimple task_stmt
)
1392 struct function
*child_cfun
;
1394 gimple_seq seq
= NULL
, new_seq
;
1397 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1398 if (child_fn
== NULL_TREE
)
1401 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1402 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1404 push_cfun (child_cfun
);
1405 bind
= gimplify_body (child_fn
, false);
1406 gimple_seq_add_stmt (&seq
, bind
);
1407 new_seq
= maybe_catch_exception (seq
);
1410 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1412 gimple_seq_add_stmt (&seq
, bind
);
1414 gimple_set_body (child_fn
, seq
);
1417 /* Inform the callgraph about the new function. */
1418 cgraph_node::add_new_function (child_fn
, false);
1421 /* Destroy a omp_context data structures. Called through the splay tree
1422 value delete callback. */
1425 delete_omp_context (splay_tree_value value
)
1427 omp_context
*ctx
= (omp_context
*) value
;
1429 delete ctx
->cb
.decl_map
;
1432 splay_tree_delete (ctx
->field_map
);
1433 if (ctx
->sfield_map
)
1434 splay_tree_delete (ctx
->sfield_map
);
1436 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1437 it produces corrupt debug information. */
1438 if (ctx
->record_type
)
1441 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1442 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1444 if (ctx
->srecord_type
)
1447 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1448 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1451 if (is_task_ctx (ctx
))
1452 finalize_task_copyfn (ctx
->stmt
);
1457 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1461 fixup_child_record_type (omp_context
*ctx
)
1463 tree f
, type
= ctx
->record_type
;
1465 /* ??? It isn't sufficient to just call remap_type here, because
1466 variably_modified_type_p doesn't work the way we expect for
1467 record types. Testing each field for whether it needs remapping
1468 and creating a new record by hand works, however. */
1469 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1470 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1474 tree name
, new_fields
= NULL
;
1476 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1477 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1478 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1479 TYPE_DECL
, name
, type
);
1480 TYPE_NAME (type
) = name
;
1482 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1484 tree new_f
= copy_node (f
);
1485 DECL_CONTEXT (new_f
) = type
;
1486 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1487 DECL_CHAIN (new_f
) = new_fields
;
1488 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1489 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1491 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1495 /* Arrange to be able to look up the receiver field
1496 given the sender field. */
1497 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1498 (splay_tree_value
) new_f
);
1500 TYPE_FIELDS (type
) = nreverse (new_fields
);
1504 TREE_TYPE (ctx
->receiver_decl
) = build_pointer_type (type
);
1507 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1508 specified by CLAUSES. */
1511 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1514 bool scan_array_reductions
= false;
1516 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1520 switch (OMP_CLAUSE_CODE (c
))
1522 case OMP_CLAUSE_PRIVATE
:
1523 decl
= OMP_CLAUSE_DECL (c
);
1524 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1526 else if (!is_variable_sized (decl
))
1527 install_var_local (decl
, ctx
);
1530 case OMP_CLAUSE_SHARED
:
1531 decl
= OMP_CLAUSE_DECL (c
);
1532 /* Ignore shared directives in teams construct. */
1533 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1535 /* Global variables don't need to be copied,
1536 the receiver side will use them directly. */
1537 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1538 if (is_global_var (odecl
))
1540 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1543 gcc_assert (is_taskreg_ctx (ctx
));
1544 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1545 || !is_variable_sized (decl
));
1546 /* Global variables don't need to be copied,
1547 the receiver side will use them directly. */
1548 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1550 by_ref
= use_pointer_for_field (decl
, ctx
);
1551 if (! TREE_READONLY (decl
)
1552 || TREE_ADDRESSABLE (decl
)
1554 || is_reference (decl
))
1556 install_var_field (decl
, by_ref
, 3, ctx
);
1557 install_var_local (decl
, ctx
);
1560 /* We don't need to copy const scalar vars back. */
1561 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1564 case OMP_CLAUSE_LASTPRIVATE
:
1565 /* Let the corresponding firstprivate clause create
1567 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1571 case OMP_CLAUSE_FIRSTPRIVATE
:
1572 case OMP_CLAUSE_REDUCTION
:
1573 case OMP_CLAUSE_LINEAR
:
1574 decl
= OMP_CLAUSE_DECL (c
);
1576 if (is_variable_sized (decl
))
1578 if (is_task_ctx (ctx
))
1579 install_var_field (decl
, false, 1, ctx
);
1582 else if (is_taskreg_ctx (ctx
))
1585 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1586 by_ref
= use_pointer_for_field (decl
, NULL
);
1588 if (is_task_ctx (ctx
)
1589 && (global
|| by_ref
|| is_reference (decl
)))
1591 install_var_field (decl
, false, 1, ctx
);
1593 install_var_field (decl
, by_ref
, 2, ctx
);
1596 install_var_field (decl
, by_ref
, 3, ctx
);
1598 install_var_local (decl
, ctx
);
1601 case OMP_CLAUSE__LOOPTEMP_
:
1602 gcc_assert (is_parallel_ctx (ctx
));
1603 decl
= OMP_CLAUSE_DECL (c
);
1604 install_var_field (decl
, false, 3, ctx
);
1605 install_var_local (decl
, ctx
);
1608 case OMP_CLAUSE_COPYPRIVATE
:
1609 case OMP_CLAUSE_COPYIN
:
1610 decl
= OMP_CLAUSE_DECL (c
);
1611 by_ref
= use_pointer_for_field (decl
, NULL
);
1612 install_var_field (decl
, by_ref
, 3, ctx
);
1615 case OMP_CLAUSE_DEFAULT
:
1616 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1619 case OMP_CLAUSE_FINAL
:
1621 case OMP_CLAUSE_NUM_THREADS
:
1622 case OMP_CLAUSE_NUM_TEAMS
:
1623 case OMP_CLAUSE_THREAD_LIMIT
:
1624 case OMP_CLAUSE_DEVICE
:
1625 case OMP_CLAUSE_SCHEDULE
:
1626 case OMP_CLAUSE_DIST_SCHEDULE
:
1627 case OMP_CLAUSE_DEPEND
:
1628 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1630 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1634 case OMP_CLAUSE_FROM
:
1635 case OMP_CLAUSE_MAP
:
1637 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1638 decl
= OMP_CLAUSE_DECL (c
);
1639 /* Global variables with "omp declare target" attribute
1640 don't need to be copied, the receiver side will use them
1642 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1644 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1645 && lookup_attribute ("omp declare target",
1646 DECL_ATTRIBUTES (decl
)))
1648 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1649 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
)
1651 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1652 #pragma omp target data, there is nothing to map for
1654 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
1655 && !POINTER_TYPE_P (TREE_TYPE (decl
)))
1660 if (DECL_SIZE (decl
)
1661 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1663 tree decl2
= DECL_VALUE_EXPR (decl
);
1664 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1665 decl2
= TREE_OPERAND (decl2
, 0);
1666 gcc_assert (DECL_P (decl2
));
1667 install_var_field (decl2
, true, 3, ctx
);
1668 install_var_local (decl2
, ctx
);
1669 install_var_local (decl
, ctx
);
1673 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1674 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1675 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1676 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1677 install_var_field (decl
, true, 7, ctx
);
1679 install_var_field (decl
, true, 3, ctx
);
1680 if (gimple_omp_target_kind (ctx
->stmt
)
1681 == GF_OMP_TARGET_KIND_REGION
)
1682 install_var_local (decl
, ctx
);
1687 tree base
= get_base_address (decl
);
1688 tree nc
= OMP_CLAUSE_CHAIN (c
);
1691 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1692 && OMP_CLAUSE_DECL (nc
) == base
1693 && OMP_CLAUSE_MAP_KIND (nc
) == OMP_CLAUSE_MAP_POINTER
1694 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1696 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1697 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1703 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1704 decl
= OMP_CLAUSE_DECL (c
);
1706 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1707 (splay_tree_key
) decl
));
1709 = build_decl (OMP_CLAUSE_LOCATION (c
),
1710 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1711 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1712 insert_field_into_struct (ctx
->record_type
, field
);
1713 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1714 (splay_tree_value
) field
);
1719 case OMP_CLAUSE_NOWAIT
:
1720 case OMP_CLAUSE_ORDERED
:
1721 case OMP_CLAUSE_COLLAPSE
:
1722 case OMP_CLAUSE_UNTIED
:
1723 case OMP_CLAUSE_MERGEABLE
:
1724 case OMP_CLAUSE_PROC_BIND
:
1725 case OMP_CLAUSE_SAFELEN
:
1728 case OMP_CLAUSE_ALIGNED
:
1729 decl
= OMP_CLAUSE_DECL (c
);
1730 if (is_global_var (decl
)
1731 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1732 install_var_local (decl
, ctx
);
1740 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1742 switch (OMP_CLAUSE_CODE (c
))
1744 case OMP_CLAUSE_LASTPRIVATE
:
1745 /* Let the corresponding firstprivate clause create
1747 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1748 scan_array_reductions
= true;
1749 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1753 case OMP_CLAUSE_PRIVATE
:
1754 case OMP_CLAUSE_FIRSTPRIVATE
:
1755 case OMP_CLAUSE_REDUCTION
:
1756 case OMP_CLAUSE_LINEAR
:
1757 decl
= OMP_CLAUSE_DECL (c
);
1758 if (is_variable_sized (decl
))
1759 install_var_local (decl
, ctx
);
1760 fixup_remapped_decl (decl
, ctx
,
1761 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1762 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1763 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1764 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1765 scan_array_reductions
= true;
1766 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1767 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1768 scan_array_reductions
= true;
1771 case OMP_CLAUSE_SHARED
:
1772 /* Ignore shared directives in teams construct. */
1773 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1775 decl
= OMP_CLAUSE_DECL (c
);
1776 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1777 fixup_remapped_decl (decl
, ctx
, false);
1780 case OMP_CLAUSE_MAP
:
1781 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
)
1783 decl
= OMP_CLAUSE_DECL (c
);
1785 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1786 && lookup_attribute ("omp declare target",
1787 DECL_ATTRIBUTES (decl
)))
1791 if (OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1792 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1793 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1795 tree new_decl
= lookup_decl (decl
, ctx
);
1796 TREE_TYPE (new_decl
)
1797 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1799 else if (DECL_SIZE (decl
)
1800 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1802 tree decl2
= DECL_VALUE_EXPR (decl
);
1803 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1804 decl2
= TREE_OPERAND (decl2
, 0);
1805 gcc_assert (DECL_P (decl2
));
1806 fixup_remapped_decl (decl2
, ctx
, false);
1807 fixup_remapped_decl (decl
, ctx
, true);
1810 fixup_remapped_decl (decl
, ctx
, false);
1814 case OMP_CLAUSE_COPYPRIVATE
:
1815 case OMP_CLAUSE_COPYIN
:
1816 case OMP_CLAUSE_DEFAULT
:
1818 case OMP_CLAUSE_NUM_THREADS
:
1819 case OMP_CLAUSE_NUM_TEAMS
:
1820 case OMP_CLAUSE_THREAD_LIMIT
:
1821 case OMP_CLAUSE_DEVICE
:
1822 case OMP_CLAUSE_SCHEDULE
:
1823 case OMP_CLAUSE_DIST_SCHEDULE
:
1824 case OMP_CLAUSE_NOWAIT
:
1825 case OMP_CLAUSE_ORDERED
:
1826 case OMP_CLAUSE_COLLAPSE
:
1827 case OMP_CLAUSE_UNTIED
:
1828 case OMP_CLAUSE_FINAL
:
1829 case OMP_CLAUSE_MERGEABLE
:
1830 case OMP_CLAUSE_PROC_BIND
:
1831 case OMP_CLAUSE_SAFELEN
:
1832 case OMP_CLAUSE_ALIGNED
:
1833 case OMP_CLAUSE_DEPEND
:
1834 case OMP_CLAUSE__LOOPTEMP_
:
1836 case OMP_CLAUSE_FROM
:
1837 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1845 if (scan_array_reductions
)
1846 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1847 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1848 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1850 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
1851 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
1853 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
1854 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1855 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
1856 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1857 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1858 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
1861 /* Create a new name for omp child function. Returns an identifier. If
1862 IS_CILK_FOR is true then the suffix for the child function is
1866 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
1869 return clone_function_name (current_function_decl
, "_cilk_for_fn");
1870 return clone_function_name (current_function_decl
,
1871 task_copy
? "_omp_cpyfn" : "_omp_fn");
1874 /* Returns the type of the induction variable for the child function for
1875 _Cilk_for and the types for _high and _low variables based on TYPE. */
1878 cilk_for_check_loop_diff_type (tree type
)
1880 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
1882 if (TYPE_UNSIGNED (type
))
1883 return uint32_type_node
;
1885 return integer_type_node
;
1889 if (TYPE_UNSIGNED (type
))
1890 return uint64_type_node
;
1892 return long_long_integer_type_node
;
1896 /* Build a decl for the omp child function. It'll not contain a body
1897 yet, just the bare decl. */
1900 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
1902 tree decl
, type
, name
, t
;
1905 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
1906 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
1907 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
1908 tree cilk_var_type
= NULL_TREE
;
1910 name
= create_omp_child_function_name (task_copy
,
1911 cilk_for_count
!= NULL_TREE
);
1913 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1914 ptr_type_node
, NULL_TREE
);
1915 else if (cilk_for_count
)
1917 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
1918 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
1919 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1920 cilk_var_type
, cilk_var_type
, NULL_TREE
);
1923 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
1925 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
1928 ctx
->cb
.dst_fn
= decl
;
1930 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
1932 TREE_STATIC (decl
) = 1;
1933 TREE_USED (decl
) = 1;
1934 DECL_ARTIFICIAL (decl
) = 1;
1935 DECL_IGNORED_P (decl
) = 0;
1936 TREE_PUBLIC (decl
) = 0;
1937 DECL_UNINLINABLE (decl
) = 1;
1938 DECL_EXTERNAL (decl
) = 0;
1939 DECL_CONTEXT (decl
) = NULL_TREE
;
1940 DECL_INITIAL (decl
) = make_node (BLOCK
);
1941 bool target_p
= false;
1942 if (lookup_attribute ("omp declare target",
1943 DECL_ATTRIBUTES (current_function_decl
)))
1948 for (octx
= ctx
; octx
; octx
= octx
->outer
)
1949 if (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
1950 && gimple_omp_target_kind (octx
->stmt
)
1951 == GF_OMP_TARGET_KIND_REGION
)
1958 DECL_ATTRIBUTES (decl
)
1959 = tree_cons (get_identifier ("omp declare target"),
1960 NULL_TREE
, DECL_ATTRIBUTES (decl
));
1962 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1963 RESULT_DECL
, NULL_TREE
, void_type_node
);
1964 DECL_ARTIFICIAL (t
) = 1;
1965 DECL_IGNORED_P (t
) = 1;
1966 DECL_CONTEXT (t
) = decl
;
1967 DECL_RESULT (decl
) = t
;
1969 /* _Cilk_for's child function requires two extra parameters called
1970 __low and __high that are set the by Cilk runtime when it calls this
1974 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1975 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
1976 DECL_ARTIFICIAL (t
) = 1;
1977 DECL_NAMELESS (t
) = 1;
1978 DECL_ARG_TYPE (t
) = ptr_type_node
;
1979 DECL_CONTEXT (t
) = current_function_decl
;
1981 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1982 DECL_ARGUMENTS (decl
) = t
;
1984 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1985 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
1986 DECL_ARTIFICIAL (t
) = 1;
1987 DECL_NAMELESS (t
) = 1;
1988 DECL_ARG_TYPE (t
) = ptr_type_node
;
1989 DECL_CONTEXT (t
) = current_function_decl
;
1991 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1992 DECL_ARGUMENTS (decl
) = t
;
1995 tree data_name
= get_identifier (".omp_data_i");
1996 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
1998 DECL_ARTIFICIAL (t
) = 1;
1999 DECL_NAMELESS (t
) = 1;
2000 DECL_ARG_TYPE (t
) = ptr_type_node
;
2001 DECL_CONTEXT (t
) = current_function_decl
;
2004 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2005 DECL_ARGUMENTS (decl
) = t
;
2007 ctx
->receiver_decl
= t
;
2010 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2011 PARM_DECL
, get_identifier (".omp_data_o"),
2013 DECL_ARTIFICIAL (t
) = 1;
2014 DECL_NAMELESS (t
) = 1;
2015 DECL_ARG_TYPE (t
) = ptr_type_node
;
2016 DECL_CONTEXT (t
) = current_function_decl
;
2018 TREE_ADDRESSABLE (t
) = 1;
2019 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2020 DECL_ARGUMENTS (decl
) = t
;
2023 /* Allocate memory for the function structure. The call to
2024 allocate_struct_function clobbers CFUN, so we need to restore
2026 push_struct_function (decl
);
2027 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2031 /* Callback for walk_gimple_seq. Check if combined parallel
2032 contains gimple_omp_for_combined_into_p OMP_FOR. */
2035 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2036 bool *handled_ops_p
,
2037 struct walk_stmt_info
*wi
)
2039 gimple stmt
= gsi_stmt (*gsi_p
);
2041 *handled_ops_p
= true;
2042 switch (gimple_code (stmt
))
2046 case GIMPLE_OMP_FOR
:
2047 if (gimple_omp_for_combined_into_p (stmt
)
2048 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
2051 return integer_zero_node
;
2060 /* Scan an OpenMP parallel directive. */
2063 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2067 gimple stmt
= gsi_stmt (*gsi
);
2069 /* Ignore parallel directives with empty bodies, unless there
2070 are copyin clauses. */
2072 && empty_body_p (gimple_omp_body (stmt
))
2073 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2074 OMP_CLAUSE_COPYIN
) == NULL
)
2076 gsi_replace (gsi
, gimple_build_nop (), false);
2080 if (gimple_omp_parallel_combined_p (stmt
))
2083 struct walk_stmt_info wi
;
2085 memset (&wi
, 0, sizeof (wi
));
2087 walk_gimple_seq (gimple_omp_body (stmt
),
2088 find_combined_for
, NULL
, &wi
);
2089 for_stmt
= (gimple
) wi
.info
;
2092 struct omp_for_data fd
;
2093 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2094 /* We need two temporaries with fd.loop.v type (istart/iend)
2095 and then (fd.collapse - 1) temporaries with the same
2096 type for count2 ... countN-1 vars if not constant. */
2097 size_t count
= 2, i
;
2098 tree type
= fd
.iter_type
;
2100 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2101 count
+= fd
.collapse
- 1;
2102 for (i
= 0; i
< count
; i
++)
2104 tree temp
= create_tmp_var (type
, NULL
);
2105 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2106 OMP_CLAUSE__LOOPTEMP_
);
2107 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2108 OMP_CLAUSE_DECL (c
) = temp
;
2109 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2110 gimple_omp_parallel_set_clauses (stmt
, c
);
2115 ctx
= new_omp_context (stmt
, outer_ctx
);
2116 taskreg_contexts
.safe_push (ctx
);
2117 if (taskreg_nesting_level
> 1)
2118 ctx
->is_nested
= true;
2119 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2120 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2121 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2122 name
= create_tmp_var_name (".omp_data_s");
2123 name
= build_decl (gimple_location (stmt
),
2124 TYPE_DECL
, name
, ctx
->record_type
);
2125 DECL_ARTIFICIAL (name
) = 1;
2126 DECL_NAMELESS (name
) = 1;
2127 TYPE_NAME (ctx
->record_type
) = name
;
2128 create_omp_child_function (ctx
, false);
2129 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2131 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2132 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2134 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2135 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2138 /* Scan an OpenMP task directive. */
2141 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2145 gimple stmt
= gsi_stmt (*gsi
);
2147 /* Ignore task directives with empty bodies. */
2149 && empty_body_p (gimple_omp_body (stmt
)))
2151 gsi_replace (gsi
, gimple_build_nop (), false);
2155 ctx
= new_omp_context (stmt
, outer_ctx
);
2156 taskreg_contexts
.safe_push (ctx
);
2157 if (taskreg_nesting_level
> 1)
2158 ctx
->is_nested
= true;
2159 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2160 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2161 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2162 name
= create_tmp_var_name (".omp_data_s");
2163 name
= build_decl (gimple_location (stmt
),
2164 TYPE_DECL
, name
, ctx
->record_type
);
2165 DECL_ARTIFICIAL (name
) = 1;
2166 DECL_NAMELESS (name
) = 1;
2167 TYPE_NAME (ctx
->record_type
) = name
;
2168 create_omp_child_function (ctx
, false);
2169 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2171 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2173 if (ctx
->srecord_type
)
2175 name
= create_tmp_var_name (".omp_data_a");
2176 name
= build_decl (gimple_location (stmt
),
2177 TYPE_DECL
, name
, ctx
->srecord_type
);
2178 DECL_ARTIFICIAL (name
) = 1;
2179 DECL_NAMELESS (name
) = 1;
2180 TYPE_NAME (ctx
->srecord_type
) = name
;
2181 create_omp_child_function (ctx
, true);
2184 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2186 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2188 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2189 t
= build_int_cst (long_integer_type_node
, 0);
2190 gimple_omp_task_set_arg_size (stmt
, t
);
2191 t
= build_int_cst (long_integer_type_node
, 1);
2192 gimple_omp_task_set_arg_align (stmt
, t
);
2197 /* If any decls have been made addressable during scan_omp,
2198 adjust their fields if needed, and layout record types
2199 of parallel/task constructs. */
2202 finish_taskreg_scan (omp_context
*ctx
)
2204 if (ctx
->record_type
== NULL_TREE
)
2207 /* If any task_shared_vars were needed, verify all
2208 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2209 statements if use_pointer_for_field hasn't changed
2210 because of that. If it did, update field types now. */
2211 if (task_shared_vars
)
2215 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2216 c
; c
= OMP_CLAUSE_CHAIN (c
))
2217 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
2219 tree decl
= OMP_CLAUSE_DECL (c
);
2221 /* Global variables don't need to be copied,
2222 the receiver side will use them directly. */
2223 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2225 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2226 || !use_pointer_for_field (decl
, ctx
))
2228 tree field
= lookup_field (decl
, ctx
);
2229 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2230 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2232 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2233 TREE_THIS_VOLATILE (field
) = 0;
2234 DECL_USER_ALIGN (field
) = 0;
2235 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2236 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2237 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2238 if (ctx
->srecord_type
)
2240 tree sfield
= lookup_sfield (decl
, ctx
);
2241 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2242 TREE_THIS_VOLATILE (sfield
) = 0;
2243 DECL_USER_ALIGN (sfield
) = 0;
2244 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2245 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2246 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2251 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2253 layout_type (ctx
->record_type
);
2254 fixup_child_record_type (ctx
);
2258 location_t loc
= gimple_location (ctx
->stmt
);
2259 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2260 /* Move VLA fields to the end. */
2261 p
= &TYPE_FIELDS (ctx
->record_type
);
2263 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2264 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2267 *p
= TREE_CHAIN (*p
);
2268 TREE_CHAIN (*q
) = NULL_TREE
;
2269 q
= &TREE_CHAIN (*q
);
2272 p
= &DECL_CHAIN (*p
);
2274 layout_type (ctx
->record_type
);
2275 fixup_child_record_type (ctx
);
2276 if (ctx
->srecord_type
)
2277 layout_type (ctx
->srecord_type
);
2278 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2279 TYPE_SIZE_UNIT (ctx
->record_type
));
2280 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2281 t
= build_int_cst (long_integer_type_node
,
2282 TYPE_ALIGN_UNIT (ctx
->record_type
));
2283 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2288 /* Scan an OpenMP loop directive. */
2291 scan_omp_for (gimple stmt
, omp_context
*outer_ctx
)
2296 ctx
= new_omp_context (stmt
, outer_ctx
);
2298 scan_sharing_clauses (gimple_omp_for_clauses (stmt
), ctx
);
2300 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2301 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2303 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2304 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2305 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2306 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2308 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2311 /* Scan an OpenMP sections directive. */
2314 scan_omp_sections (gimple stmt
, omp_context
*outer_ctx
)
2318 ctx
= new_omp_context (stmt
, outer_ctx
);
2319 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2320 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2323 /* Scan an OpenMP single directive. */
2326 scan_omp_single (gimple stmt
, omp_context
*outer_ctx
)
2331 ctx
= new_omp_context (stmt
, outer_ctx
);
2332 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2333 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2334 name
= create_tmp_var_name (".omp_copy_s");
2335 name
= build_decl (gimple_location (stmt
),
2336 TYPE_DECL
, name
, ctx
->record_type
);
2337 TYPE_NAME (ctx
->record_type
) = name
;
2339 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2340 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2342 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2343 ctx
->record_type
= NULL
;
2345 layout_type (ctx
->record_type
);
2348 /* Scan an OpenMP target{, data, update} directive. */
2351 scan_omp_target (gimple stmt
, omp_context
*outer_ctx
)
2355 int kind
= gimple_omp_target_kind (stmt
);
2357 ctx
= new_omp_context (stmt
, outer_ctx
);
2358 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2359 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2360 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2361 name
= create_tmp_var_name (".omp_data_t");
2362 name
= build_decl (gimple_location (stmt
),
2363 TYPE_DECL
, name
, ctx
->record_type
);
2364 DECL_ARTIFICIAL (name
) = 1;
2365 DECL_NAMELESS (name
) = 1;
2366 TYPE_NAME (ctx
->record_type
) = name
;
2367 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2369 create_omp_child_function (ctx
, false);
2370 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2373 scan_sharing_clauses (gimple_omp_target_clauses (stmt
), ctx
);
2374 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2376 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2377 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2380 TYPE_FIELDS (ctx
->record_type
)
2381 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2382 #ifdef ENABLE_CHECKING
2384 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2385 for (field
= TYPE_FIELDS (ctx
->record_type
);
2387 field
= DECL_CHAIN (field
))
2388 gcc_assert (DECL_ALIGN (field
) == align
);
2390 layout_type (ctx
->record_type
);
2391 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2392 fixup_child_record_type (ctx
);
2396 /* Scan an OpenMP teams directive. */
2399 scan_omp_teams (gimple stmt
, omp_context
*outer_ctx
)
2401 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2402 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2403 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2406 /* Check OpenMP nesting restrictions. */
2408 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2412 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2413 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2415 error_at (gimple_location (stmt
),
2416 "OpenMP constructs may not be nested inside simd region");
2419 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2421 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2422 || (gimple_omp_for_kind (stmt
)
2423 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2424 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2426 error_at (gimple_location (stmt
),
2427 "only distribute or parallel constructs are allowed to "
2428 "be closely nested inside teams construct");
2433 switch (gimple_code (stmt
))
2435 case GIMPLE_OMP_FOR
:
2436 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2438 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2440 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2442 error_at (gimple_location (stmt
),
2443 "distribute construct must be closely nested inside "
2451 if (is_gimple_call (stmt
)
2452 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2453 == BUILT_IN_GOMP_CANCEL
2454 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2455 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2457 const char *bad
= NULL
;
2458 const char *kind
= NULL
;
2461 error_at (gimple_location (stmt
), "orphaned %qs construct",
2462 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2463 == BUILT_IN_GOMP_CANCEL
2464 ? "#pragma omp cancel"
2465 : "#pragma omp cancellation point");
2468 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2469 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2473 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2474 bad
= "#pragma omp parallel";
2475 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2476 == BUILT_IN_GOMP_CANCEL
2477 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2478 ctx
->cancellable
= true;
2482 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2483 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2484 bad
= "#pragma omp for";
2485 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2486 == BUILT_IN_GOMP_CANCEL
2487 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2489 ctx
->cancellable
= true;
2490 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2492 warning_at (gimple_location (stmt
), 0,
2493 "%<#pragma omp cancel for%> inside "
2494 "%<nowait%> for construct");
2495 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2496 OMP_CLAUSE_ORDERED
))
2497 warning_at (gimple_location (stmt
), 0,
2498 "%<#pragma omp cancel for%> inside "
2499 "%<ordered%> for construct");
2504 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2505 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2506 bad
= "#pragma omp sections";
2507 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2508 == BUILT_IN_GOMP_CANCEL
2509 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2511 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2513 ctx
->cancellable
= true;
2514 if (find_omp_clause (gimple_omp_sections_clauses
2517 warning_at (gimple_location (stmt
), 0,
2518 "%<#pragma omp cancel sections%> inside "
2519 "%<nowait%> sections construct");
2523 gcc_assert (ctx
->outer
2524 && gimple_code (ctx
->outer
->stmt
)
2525 == GIMPLE_OMP_SECTIONS
);
2526 ctx
->outer
->cancellable
= true;
2527 if (find_omp_clause (gimple_omp_sections_clauses
2530 warning_at (gimple_location (stmt
), 0,
2531 "%<#pragma omp cancel sections%> inside "
2532 "%<nowait%> sections construct");
2538 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2539 bad
= "#pragma omp task";
2541 ctx
->cancellable
= true;
2545 error_at (gimple_location (stmt
), "invalid arguments");
2550 error_at (gimple_location (stmt
),
2551 "%<%s %s%> construct not closely nested inside of %qs",
2552 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2553 == BUILT_IN_GOMP_CANCEL
2554 ? "#pragma omp cancel"
2555 : "#pragma omp cancellation point", kind
, bad
);
2560 case GIMPLE_OMP_SECTIONS
:
2561 case GIMPLE_OMP_SINGLE
:
2562 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2563 switch (gimple_code (ctx
->stmt
))
2565 case GIMPLE_OMP_FOR
:
2566 case GIMPLE_OMP_SECTIONS
:
2567 case GIMPLE_OMP_SINGLE
:
2568 case GIMPLE_OMP_ORDERED
:
2569 case GIMPLE_OMP_MASTER
:
2570 case GIMPLE_OMP_TASK
:
2571 case GIMPLE_OMP_CRITICAL
:
2572 if (is_gimple_call (stmt
))
2574 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2575 != BUILT_IN_GOMP_BARRIER
)
2577 error_at (gimple_location (stmt
),
2578 "barrier region may not be closely nested inside "
2579 "of work-sharing, critical, ordered, master or "
2580 "explicit task region");
2583 error_at (gimple_location (stmt
),
2584 "work-sharing region may not be closely nested inside "
2585 "of work-sharing, critical, ordered, master or explicit "
2588 case GIMPLE_OMP_PARALLEL
:
2594 case GIMPLE_OMP_MASTER
:
2595 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2596 switch (gimple_code (ctx
->stmt
))
2598 case GIMPLE_OMP_FOR
:
2599 case GIMPLE_OMP_SECTIONS
:
2600 case GIMPLE_OMP_SINGLE
:
2601 case GIMPLE_OMP_TASK
:
2602 error_at (gimple_location (stmt
),
2603 "master region may not be closely nested inside "
2604 "of work-sharing or explicit task region");
2606 case GIMPLE_OMP_PARALLEL
:
2612 case GIMPLE_OMP_ORDERED
:
2613 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2614 switch (gimple_code (ctx
->stmt
))
2616 case GIMPLE_OMP_CRITICAL
:
2617 case GIMPLE_OMP_TASK
:
2618 error_at (gimple_location (stmt
),
2619 "ordered region may not be closely nested inside "
2620 "of critical or explicit task region");
2622 case GIMPLE_OMP_FOR
:
2623 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2624 OMP_CLAUSE_ORDERED
) == NULL
)
2626 error_at (gimple_location (stmt
),
2627 "ordered region must be closely nested inside "
2628 "a loop region with an ordered clause");
2632 case GIMPLE_OMP_PARALLEL
:
2633 error_at (gimple_location (stmt
),
2634 "ordered region must be closely nested inside "
2635 "a loop region with an ordered clause");
2641 case GIMPLE_OMP_CRITICAL
:
2642 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2643 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_CRITICAL
2644 && (gimple_omp_critical_name (stmt
)
2645 == gimple_omp_critical_name (ctx
->stmt
)))
2647 error_at (gimple_location (stmt
),
2648 "critical region may not be nested inside a critical "
2649 "region with the same name");
2653 case GIMPLE_OMP_TEAMS
:
2655 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2656 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2658 error_at (gimple_location (stmt
),
2659 "teams construct not closely nested inside of target "
2664 case GIMPLE_OMP_TARGET
:
2665 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2666 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
2667 && gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_REGION
)
2670 switch (gimple_omp_target_kind (stmt
))
2672 case GF_OMP_TARGET_KIND_REGION
: name
= "target"; break;
2673 case GF_OMP_TARGET_KIND_DATA
: name
= "target data"; break;
2674 case GF_OMP_TARGET_KIND_UPDATE
: name
= "target update"; break;
2675 default: gcc_unreachable ();
2677 warning_at (gimple_location (stmt
), 0,
2678 "%s construct inside of target region", name
);
2688 /* Helper function scan_omp.
2690 Callback for walk_tree or operators in walk_gimple_stmt used to
2691 scan for OpenMP directives in TP. */
2694 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
2696 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
2697 omp_context
*ctx
= (omp_context
*) wi
->info
;
2700 switch (TREE_CODE (t
))
2707 *tp
= remap_decl (t
, &ctx
->cb
);
2711 if (ctx
&& TYPE_P (t
))
2712 *tp
= remap_type (t
, &ctx
->cb
);
2713 else if (!DECL_P (t
))
2718 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
2719 if (tem
!= TREE_TYPE (t
))
2721 if (TREE_CODE (t
) == INTEGER_CST
)
2722 *tp
= wide_int_to_tree (tem
, t
);
2724 TREE_TYPE (t
) = tem
;
2734 /* Return true if FNDECL is a setjmp or a longjmp. */
2737 setjmp_or_longjmp_p (const_tree fndecl
)
2739 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
2740 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
2741 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
2744 tree declname
= DECL_NAME (fndecl
);
2747 const char *name
= IDENTIFIER_POINTER (declname
);
2748 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
2752 /* Helper function for scan_omp.
2754 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2755 the current statement in GSI. */
2758 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
2759 struct walk_stmt_info
*wi
)
2761 gimple stmt
= gsi_stmt (*gsi
);
2762 omp_context
*ctx
= (omp_context
*) wi
->info
;
2764 if (gimple_has_location (stmt
))
2765 input_location
= gimple_location (stmt
);
2767 /* Check the OpenMP nesting restrictions. */
2768 bool remove
= false;
2769 if (is_gimple_omp (stmt
))
2770 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2771 else if (is_gimple_call (stmt
))
2773 tree fndecl
= gimple_call_fndecl (stmt
);
2776 if (setjmp_or_longjmp_p (fndecl
)
2778 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2779 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2782 error_at (gimple_location (stmt
),
2783 "setjmp/longjmp inside simd construct");
2785 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
2786 switch (DECL_FUNCTION_CODE (fndecl
))
2788 case BUILT_IN_GOMP_BARRIER
:
2789 case BUILT_IN_GOMP_CANCEL
:
2790 case BUILT_IN_GOMP_CANCELLATION_POINT
:
2791 case BUILT_IN_GOMP_TASKYIELD
:
2792 case BUILT_IN_GOMP_TASKWAIT
:
2793 case BUILT_IN_GOMP_TASKGROUP_START
:
2794 case BUILT_IN_GOMP_TASKGROUP_END
:
2795 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2804 stmt
= gimple_build_nop ();
2805 gsi_replace (gsi
, stmt
, false);
2808 *handled_ops_p
= true;
2810 switch (gimple_code (stmt
))
2812 case GIMPLE_OMP_PARALLEL
:
2813 taskreg_nesting_level
++;
2814 scan_omp_parallel (gsi
, ctx
);
2815 taskreg_nesting_level
--;
2818 case GIMPLE_OMP_TASK
:
2819 taskreg_nesting_level
++;
2820 scan_omp_task (gsi
, ctx
);
2821 taskreg_nesting_level
--;
2824 case GIMPLE_OMP_FOR
:
2825 scan_omp_for (stmt
, ctx
);
2828 case GIMPLE_OMP_SECTIONS
:
2829 scan_omp_sections (stmt
, ctx
);
2832 case GIMPLE_OMP_SINGLE
:
2833 scan_omp_single (stmt
, ctx
);
2836 case GIMPLE_OMP_SECTION
:
2837 case GIMPLE_OMP_MASTER
:
2838 case GIMPLE_OMP_TASKGROUP
:
2839 case GIMPLE_OMP_ORDERED
:
2840 case GIMPLE_OMP_CRITICAL
:
2841 ctx
= new_omp_context (stmt
, ctx
);
2842 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2845 case GIMPLE_OMP_TARGET
:
2846 scan_omp_target (stmt
, ctx
);
2849 case GIMPLE_OMP_TEAMS
:
2850 scan_omp_teams (stmt
, ctx
);
2857 *handled_ops_p
= false;
2859 for (var
= gimple_bind_vars (stmt
); var
; var
= DECL_CHAIN (var
))
2860 insert_decl_map (&ctx
->cb
, var
, var
);
2864 *handled_ops_p
= false;
2872 /* Scan all the statements starting at the current statement. CTX
2873 contains context information about the OpenMP directives and
2874 clauses found during the scan. */
2877 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
2879 location_t saved_location
;
2880 struct walk_stmt_info wi
;
2882 memset (&wi
, 0, sizeof (wi
));
2884 wi
.want_locations
= true;
2886 saved_location
= input_location
;
2887 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
2888 input_location
= saved_location
;
2891 /* Re-gimplification and code generation routines. */
2893 /* Build a call to GOMP_barrier. */
2896 build_omp_barrier (tree lhs
)
2898 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
2899 : BUILT_IN_GOMP_BARRIER
);
2900 gimple g
= gimple_build_call (fndecl
, 0);
2902 gimple_call_set_lhs (g
, lhs
);
2906 /* If a context was created for STMT when it was scanned, return it. */
2908 static omp_context
*
2909 maybe_lookup_ctx (gimple stmt
)
2912 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
2913 return n
? (omp_context
*) n
->value
: NULL
;
2917 /* Find the mapping for DECL in CTX or the immediately enclosing
2918 context that has a mapping for DECL.
2920 If CTX is a nested parallel directive, we may have to use the decl
2921 mappings created in CTX's parent context. Suppose that we have the
2922 following parallel nesting (variable UIDs showed for clarity):
2925 #omp parallel shared(iD.1562) -> outer parallel
2926 iD.1562 = iD.1562 + 1;
2928 #omp parallel shared (iD.1562) -> inner parallel
2929 iD.1562 = iD.1562 - 1;
2931 Each parallel structure will create a distinct .omp_data_s structure
2932 for copying iD.1562 in/out of the directive:
2934 outer parallel .omp_data_s.1.i -> iD.1562
2935 inner parallel .omp_data_s.2.i -> iD.1562
2937 A shared variable mapping will produce a copy-out operation before
2938 the parallel directive and a copy-in operation after it. So, in
2939 this case we would have:
2942 .omp_data_o.1.i = iD.1562;
2943 #omp parallel shared(iD.1562) -> outer parallel
2944 .omp_data_i.1 = &.omp_data_o.1
2945 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2947 .omp_data_o.2.i = iD.1562; -> **
2948 #omp parallel shared(iD.1562) -> inner parallel
2949 .omp_data_i.2 = &.omp_data_o.2
2950 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2953 ** This is a problem. The symbol iD.1562 cannot be referenced
2954 inside the body of the outer parallel region. But since we are
2955 emitting this copy operation while expanding the inner parallel
2956 directive, we need to access the CTX structure of the outer
2957 parallel directive to get the correct mapping:
2959 .omp_data_o.2.i = .omp_data_i.1->i
2961 Since there may be other workshare or parallel directives enclosing
2962 the parallel directive, it may be necessary to walk up the context
2963 parent chain. This is not a problem in general because nested
2964 parallelism happens only rarely. */
2967 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2972 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2973 t
= maybe_lookup_decl (decl
, up
);
2975 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
2977 return t
? t
: decl
;
2981 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2982 in outer contexts. */
2985 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2990 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2991 t
= maybe_lookup_decl (decl
, up
);
2993 return t
? t
: decl
;
2997 /* Construct the initialization value for reduction CLAUSE. */
3000 omp_reduction_init (tree clause
, tree type
)
3002 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
3003 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
3010 case TRUTH_ORIF_EXPR
:
3011 case TRUTH_XOR_EXPR
:
3013 return build_zero_cst (type
);
3016 case TRUTH_AND_EXPR
:
3017 case TRUTH_ANDIF_EXPR
:
3019 return fold_convert_loc (loc
, type
, integer_one_node
);
3022 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3025 if (SCALAR_FLOAT_TYPE_P (type
))
3027 REAL_VALUE_TYPE max
, min
;
3028 if (HONOR_INFINITIES (TYPE_MODE (type
)))
3031 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3034 real_maxval (&min
, 1, TYPE_MODE (type
));
3035 return build_real (type
, min
);
3039 gcc_assert (INTEGRAL_TYPE_P (type
));
3040 return TYPE_MIN_VALUE (type
);
3044 if (SCALAR_FLOAT_TYPE_P (type
))
3046 REAL_VALUE_TYPE max
;
3047 if (HONOR_INFINITIES (TYPE_MODE (type
)))
3050 real_maxval (&max
, 0, TYPE_MODE (type
));
3051 return build_real (type
, max
);
3055 gcc_assert (INTEGRAL_TYPE_P (type
));
3056 return TYPE_MAX_VALUE (type
);
3064 /* Return alignment to be assumed for var in CLAUSE, which should be
3065 OMP_CLAUSE_ALIGNED. */
3068 omp_clause_aligned_alignment (tree clause
)
3070 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3071 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3073 /* Otherwise return implementation defined alignment. */
3074 unsigned int al
= 1;
3075 machine_mode mode
, vmode
;
3076 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3078 vs
= 1 << floor_log2 (vs
);
3079 static enum mode_class classes
[]
3080 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3081 for (int i
= 0; i
< 4; i
+= 2)
3082 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3084 mode
= GET_MODE_WIDER_MODE (mode
))
3086 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3087 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3090 && GET_MODE_SIZE (vmode
) < vs
3091 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3092 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3094 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3095 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3097 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3098 / GET_MODE_SIZE (mode
));
3099 if (TYPE_MODE (type
) != vmode
)
3101 if (TYPE_ALIGN_UNIT (type
) > al
)
3102 al
= TYPE_ALIGN_UNIT (type
);
3104 return build_int_cst (integer_type_node
, al
);
3107 /* Return maximum possible vectorization factor for the target. */
3114 || !flag_tree_loop_optimize
3115 || (!flag_tree_loop_vectorize
3116 && (global_options_set
.x_flag_tree_loop_vectorize
3117 || global_options_set
.x_flag_tree_vectorize
)))
3120 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3123 vs
= 1 << floor_log2 (vs
);
3126 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
3127 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
3128 return GET_MODE_NUNITS (vqimode
);
3132 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3136 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
3137 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
3141 max_vf
= omp_max_vf ();
3144 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3145 OMP_CLAUSE_SAFELEN
);
3146 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3148 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3150 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3154 idx
= create_tmp_var (unsigned_type_node
, NULL
);
3155 lane
= create_tmp_var (unsigned_type_node
, NULL
);
3161 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3162 tree avar
= create_tmp_var_raw (atype
, NULL
);
3163 if (TREE_ADDRESSABLE (new_var
))
3164 TREE_ADDRESSABLE (avar
) = 1;
3165 DECL_ATTRIBUTES (avar
)
3166 = tree_cons (get_identifier ("omp simd array"), NULL
,
3167 DECL_ATTRIBUTES (avar
));
3168 gimple_add_tmp_var (avar
);
3169 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3170 NULL_TREE
, NULL_TREE
);
3171 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3172 NULL_TREE
, NULL_TREE
);
3173 if (DECL_P (new_var
))
3175 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3176 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3181 /* Helper function of lower_rec_input_clauses. For a reference
3182 in simd reduction, add an underlying variable it will reference. */
3185 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3187 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3188 if (TREE_CONSTANT (z
))
3190 const char *name
= NULL
;
3191 if (DECL_NAME (new_vard
))
3192 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3194 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3195 gimple_add_tmp_var (z
);
3196 TREE_ADDRESSABLE (z
) = 1;
3197 z
= build_fold_addr_expr_loc (loc
, z
);
3198 gimplify_assign (new_vard
, z
, ilist
);
3202 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3203 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3204 private variables. Initialization statements go in ILIST, while calls
3205 to destructors go in DLIST. */
3208 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3209 omp_context
*ctx
, struct omp_for_data
*fd
)
3211 tree c
, dtor
, copyin_seq
, x
, ptr
;
3212 bool copyin_by_ref
= false;
3213 bool lastprivate_firstprivate
= false;
3214 bool reduction_omp_orig_ref
= false;
3216 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3217 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3219 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3220 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3221 gimple_seq llist
[2] = { NULL
, NULL
};
3225 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3226 with data sharing clauses referencing variable sized vars. That
3227 is unnecessarily hard to support and very unlikely to result in
3228 vectorized code anyway. */
3230 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3231 switch (OMP_CLAUSE_CODE (c
))
3233 case OMP_CLAUSE_LINEAR
:
3234 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3237 case OMP_CLAUSE_REDUCTION
:
3238 case OMP_CLAUSE_PRIVATE
:
3239 case OMP_CLAUSE_FIRSTPRIVATE
:
3240 case OMP_CLAUSE_LASTPRIVATE
:
3241 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3248 /* Do all the fixed sized types in the first pass, and the variable sized
3249 types in the second pass. This makes sure that the scalar arguments to
3250 the variable sized types are processed before we use them in the
3251 variable sized operations. */
3252 for (pass
= 0; pass
< 2; ++pass
)
3254 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3256 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3259 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3263 case OMP_CLAUSE_PRIVATE
:
3264 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3267 case OMP_CLAUSE_SHARED
:
3268 /* Ignore shared directives in teams construct. */
3269 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3271 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3273 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3276 case OMP_CLAUSE_FIRSTPRIVATE
:
3277 case OMP_CLAUSE_COPYIN
:
3278 case OMP_CLAUSE_LINEAR
:
3280 case OMP_CLAUSE_REDUCTION
:
3281 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3282 reduction_omp_orig_ref
= true;
3284 case OMP_CLAUSE__LOOPTEMP_
:
3285 /* Handle _looptemp_ clauses only on parallel. */
3289 case OMP_CLAUSE_LASTPRIVATE
:
3290 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3292 lastprivate_firstprivate
= true;
3296 /* Even without corresponding firstprivate, if
3297 decl is Fortran allocatable, it needs outer var
3300 && lang_hooks
.decls
.omp_private_outer_ref
3301 (OMP_CLAUSE_DECL (c
)))
3302 lastprivate_firstprivate
= true;
3304 case OMP_CLAUSE_ALIGNED
:
3307 var
= OMP_CLAUSE_DECL (c
);
3308 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3309 && !is_global_var (var
))
3311 new_var
= maybe_lookup_decl (var
, ctx
);
3312 if (new_var
== NULL_TREE
)
3313 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3314 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3315 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3316 omp_clause_aligned_alignment (c
));
3317 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3318 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3319 gimplify_and_add (x
, ilist
);
3321 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3322 && is_global_var (var
))
3324 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3325 new_var
= lookup_decl (var
, ctx
);
3326 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3327 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3328 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3329 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3330 omp_clause_aligned_alignment (c
));
3331 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3332 x
= create_tmp_var (ptype
, NULL
);
3333 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3334 gimplify_and_add (t
, ilist
);
3335 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3336 SET_DECL_VALUE_EXPR (new_var
, t
);
3337 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3344 new_var
= var
= OMP_CLAUSE_DECL (c
);
3345 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3346 new_var
= lookup_decl (var
, ctx
);
3348 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3353 else if (is_variable_sized (var
))
3355 /* For variable sized types, we need to allocate the
3356 actual storage here. Call alloca and store the
3357 result in the pointer decl that we created elsewhere. */
3361 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3366 ptr
= DECL_VALUE_EXPR (new_var
);
3367 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3368 ptr
= TREE_OPERAND (ptr
, 0);
3369 gcc_assert (DECL_P (ptr
));
3370 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3372 /* void *tmp = __builtin_alloca */
3373 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3374 stmt
= gimple_build_call (atmp
, 1, x
);
3375 tmp
= create_tmp_var_raw (ptr_type_node
, NULL
);
3376 gimple_add_tmp_var (tmp
);
3377 gimple_call_set_lhs (stmt
, tmp
);
3379 gimple_seq_add_stmt (ilist
, stmt
);
3381 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3382 gimplify_assign (ptr
, x
, ilist
);
3385 else if (is_reference (var
))
3387 /* For references that are being privatized for Fortran,
3388 allocate new backing storage for the new pointer
3389 variable. This allows us to avoid changing all the
3390 code that expects a pointer to something that expects
3391 a direct variable. */
3395 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3396 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3398 x
= build_receiver_ref (var
, false, ctx
);
3399 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3401 else if (TREE_CONSTANT (x
))
3403 /* For reduction in SIMD loop, defer adding the
3404 initialization of the reference, because if we decide
3405 to use SIMD array for it, the initilization could cause
3407 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3411 const char *name
= NULL
;
3412 if (DECL_NAME (var
))
3413 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3415 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3417 gimple_add_tmp_var (x
);
3418 TREE_ADDRESSABLE (x
) = 1;
3419 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3424 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3425 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3430 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3431 gimplify_assign (new_var
, x
, ilist
);
3434 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3436 else if (c_kind
== OMP_CLAUSE_REDUCTION
3437 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3445 switch (OMP_CLAUSE_CODE (c
))
3447 case OMP_CLAUSE_SHARED
:
3448 /* Ignore shared directives in teams construct. */
3449 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3451 /* Shared global vars are just accessed directly. */
3452 if (is_global_var (new_var
))
3454 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3455 needs to be delayed until after fixup_child_record_type so
3456 that we get the correct type during the dereference. */
3457 by_ref
= use_pointer_for_field (var
, ctx
);
3458 x
= build_receiver_ref (var
, by_ref
, ctx
);
3459 SET_DECL_VALUE_EXPR (new_var
, x
);
3460 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3462 /* ??? If VAR is not passed by reference, and the variable
3463 hasn't been initialized yet, then we'll get a warning for
3464 the store into the omp_data_s structure. Ideally, we'd be
3465 able to notice this and not store anything at all, but
3466 we're generating code too early. Suppress the warning. */
3468 TREE_NO_WARNING (var
) = 1;
3471 case OMP_CLAUSE_LASTPRIVATE
:
3472 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3476 case OMP_CLAUSE_PRIVATE
:
3477 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3478 x
= build_outer_var_ref (var
, ctx
);
3479 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3481 if (is_task_ctx (ctx
))
3482 x
= build_receiver_ref (var
, false, ctx
);
3484 x
= build_outer_var_ref (var
, ctx
);
3490 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3493 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3494 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3495 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3496 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3497 idx
, lane
, ivar
, lvar
))
3500 x
= lang_hooks
.decls
.omp_clause_default_ctor
3501 (c
, unshare_expr (ivar
), x
);
3503 gimplify_and_add (x
, &llist
[0]);
3506 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3509 gimple_seq tseq
= NULL
;
3512 gimplify_stmt (&dtor
, &tseq
);
3513 gimple_seq_add_seq (&llist
[1], tseq
);
3520 gimplify_and_add (nx
, ilist
);
3524 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3527 gimple_seq tseq
= NULL
;
3530 gimplify_stmt (&dtor
, &tseq
);
3531 gimple_seq_add_seq (dlist
, tseq
);
3535 case OMP_CLAUSE_LINEAR
:
3536 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3537 goto do_firstprivate
;
3538 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3541 x
= build_outer_var_ref (var
, ctx
);
3544 case OMP_CLAUSE_FIRSTPRIVATE
:
3545 if (is_task_ctx (ctx
))
3547 if (is_reference (var
) || is_variable_sized (var
))
3549 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3551 || use_pointer_for_field (var
, NULL
))
3553 x
= build_receiver_ref (var
, false, ctx
);
3554 SET_DECL_VALUE_EXPR (new_var
, x
);
3555 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3560 x
= build_outer_var_ref (var
, ctx
);
3563 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3564 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3566 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3567 tree stept
= TREE_TYPE (t
);
3568 tree ct
= find_omp_clause (clauses
,
3569 OMP_CLAUSE__LOOPTEMP_
);
3571 tree l
= OMP_CLAUSE_DECL (ct
);
3572 tree n1
= fd
->loop
.n1
;
3573 tree step
= fd
->loop
.step
;
3574 tree itype
= TREE_TYPE (l
);
3575 if (POINTER_TYPE_P (itype
))
3576 itype
= signed_type_for (itype
);
3577 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3578 if (TYPE_UNSIGNED (itype
)
3579 && fd
->loop
.cond_code
== GT_EXPR
)
3580 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3581 fold_build1 (NEGATE_EXPR
, itype
, l
),
3582 fold_build1 (NEGATE_EXPR
,
3585 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3586 t
= fold_build2 (MULT_EXPR
, stept
,
3587 fold_convert (stept
, l
), t
);
3589 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3591 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3593 gimplify_and_add (x
, ilist
);
3597 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3598 x
= fold_build2 (POINTER_PLUS_EXPR
,
3599 TREE_TYPE (x
), x
, t
);
3601 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3604 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3605 || TREE_ADDRESSABLE (new_var
))
3606 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3607 idx
, lane
, ivar
, lvar
))
3609 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
3611 tree iv
= create_tmp_var (TREE_TYPE (new_var
), NULL
);
3612 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
3613 gimplify_and_add (x
, ilist
);
3614 gimple_stmt_iterator gsi
3615 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3617 = gimple_build_assign (unshare_expr (lvar
), iv
);
3618 gsi_insert_before_without_update (&gsi
, g
,
3620 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3621 enum tree_code code
= PLUS_EXPR
;
3622 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
3623 code
= POINTER_PLUS_EXPR
;
3624 g
= gimple_build_assign_with_ops (code
, iv
, iv
, t
);
3625 gsi_insert_before_without_update (&gsi
, g
,
3629 x
= lang_hooks
.decls
.omp_clause_copy_ctor
3630 (c
, unshare_expr (ivar
), x
);
3631 gimplify_and_add (x
, &llist
[0]);
3632 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3635 gimple_seq tseq
= NULL
;
3638 gimplify_stmt (&dtor
, &tseq
);
3639 gimple_seq_add_seq (&llist
[1], tseq
);
3644 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
3645 gimplify_and_add (x
, ilist
);
3648 case OMP_CLAUSE__LOOPTEMP_
:
3649 gcc_assert (is_parallel_ctx (ctx
));
3650 x
= build_outer_var_ref (var
, ctx
);
3651 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3652 gimplify_and_add (x
, ilist
);
3655 case OMP_CLAUSE_COPYIN
:
3656 by_ref
= use_pointer_for_field (var
, NULL
);
3657 x
= build_receiver_ref (var
, by_ref
, ctx
);
3658 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
3659 append_to_statement_list (x
, ©in_seq
);
3660 copyin_by_ref
|= by_ref
;
3663 case OMP_CLAUSE_REDUCTION
:
3664 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3666 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3668 x
= build_outer_var_ref (var
, ctx
);
3670 if (is_reference (var
)
3671 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
3673 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3674 SET_DECL_VALUE_EXPR (placeholder
, x
);
3675 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3676 tree new_vard
= new_var
;
3677 if (is_reference (var
))
3679 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3680 new_vard
= TREE_OPERAND (new_var
, 0);
3681 gcc_assert (DECL_P (new_vard
));
3684 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3685 idx
, lane
, ivar
, lvar
))
3687 if (new_vard
== new_var
)
3689 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
3690 SET_DECL_VALUE_EXPR (new_var
, ivar
);
3694 SET_DECL_VALUE_EXPR (new_vard
,
3695 build_fold_addr_expr (ivar
));
3696 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3698 x
= lang_hooks
.decls
.omp_clause_default_ctor
3699 (c
, unshare_expr (ivar
),
3700 build_outer_var_ref (var
, ctx
));
3702 gimplify_and_add (x
, &llist
[0]);
3703 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3705 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3706 lower_omp (&tseq
, ctx
);
3707 gimple_seq_add_seq (&llist
[0], tseq
);
3709 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3710 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3711 lower_omp (&tseq
, ctx
);
3712 gimple_seq_add_seq (&llist
[1], tseq
);
3713 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3714 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3715 if (new_vard
== new_var
)
3716 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3718 SET_DECL_VALUE_EXPR (new_vard
,
3719 build_fold_addr_expr (lvar
));
3720 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3725 gimplify_stmt (&dtor
, &tseq
);
3726 gimple_seq_add_seq (&llist
[1], tseq
);
3730 /* If this is a reference to constant size reduction var
3731 with placeholder, we haven't emitted the initializer
3732 for it because it is undesirable if SIMD arrays are used.
3733 But if they aren't used, we need to emit the deferred
3734 initialization now. */
3735 else if (is_reference (var
) && is_simd
)
3736 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3737 x
= lang_hooks
.decls
.omp_clause_default_ctor
3738 (c
, unshare_expr (new_var
),
3739 build_outer_var_ref (var
, ctx
));
3741 gimplify_and_add (x
, ilist
);
3742 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3744 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3745 lower_omp (&tseq
, ctx
);
3746 gimple_seq_add_seq (ilist
, tseq
);
3748 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3751 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3752 lower_omp (&tseq
, ctx
);
3753 gimple_seq_add_seq (dlist
, tseq
);
3754 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3756 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3761 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
3762 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
3763 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3765 /* reduction(-:var) sums up the partial results, so it
3766 acts identically to reduction(+:var). */
3767 if (code
== MINUS_EXPR
)
3770 tree new_vard
= new_var
;
3771 if (is_simd
&& is_reference (var
))
3773 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3774 new_vard
= TREE_OPERAND (new_var
, 0);
3775 gcc_assert (DECL_P (new_vard
));
3778 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3779 idx
, lane
, ivar
, lvar
))
3781 tree ref
= build_outer_var_ref (var
, ctx
);
3783 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
3785 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
3786 ref
= build_outer_var_ref (var
, ctx
);
3787 gimplify_assign (ref
, x
, &llist
[1]);
3789 if (new_vard
!= new_var
)
3791 SET_DECL_VALUE_EXPR (new_vard
,
3792 build_fold_addr_expr (lvar
));
3793 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3798 if (is_reference (var
) && is_simd
)
3799 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3800 gimplify_assign (new_var
, x
, ilist
);
3803 tree ref
= build_outer_var_ref (var
, ctx
);
3805 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3806 ref
= build_outer_var_ref (var
, ctx
);
3807 gimplify_assign (ref
, x
, dlist
);
3821 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
3822 /* Don't want uninit warnings on simduid, it is always uninitialized,
3823 but we use it not for the value, but for the DECL_UID only. */
3824 TREE_NO_WARNING (uid
) = 1;
3826 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
3827 gimple_call_set_lhs (g
, lane
);
3828 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3829 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
3830 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
3831 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
3832 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3833 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3834 g
= gimple_build_assign_with_ops (INTEGER_CST
, lane
,
3835 build_int_cst (unsigned_type_node
, 0),
3837 gimple_seq_add_stmt (ilist
, g
);
3838 for (int i
= 0; i
< 2; i
++)
3841 tree vf
= create_tmp_var (unsigned_type_node
, NULL
);
3842 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
3843 gimple_call_set_lhs (g
, vf
);
3844 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
3845 gimple_seq_add_stmt (seq
, g
);
3846 tree t
= build_int_cst (unsigned_type_node
, 0);
3847 g
= gimple_build_assign_with_ops (INTEGER_CST
, idx
, t
, NULL_TREE
);
3848 gimple_seq_add_stmt (seq
, g
);
3849 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
3850 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
3851 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
3852 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
3853 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
3854 gimple_seq_add_seq (seq
, llist
[i
]);
3855 t
= build_int_cst (unsigned_type_node
, 1);
3856 g
= gimple_build_assign_with_ops (PLUS_EXPR
, idx
, idx
, t
);
3857 gimple_seq_add_stmt (seq
, g
);
3858 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
3859 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
3860 gimple_seq_add_stmt (seq
, g
);
3861 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
3865 /* The copyin sequence is not to be executed by the main thread, since
3866 that would result in self-copies. Perhaps not visible to scalars,
3867 but it certainly is to C++ operator=. */
3870 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
3872 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
3873 build_int_cst (TREE_TYPE (x
), 0));
3874 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
3875 gimplify_and_add (x
, ilist
);
3878 /* If any copyin variable is passed by reference, we must ensure the
3879 master thread doesn't modify it before it is copied over in all
3880 threads. Similarly for variables in both firstprivate and
3881 lastprivate clauses we need to ensure the lastprivate copying
3882 happens after firstprivate copying in all threads. And similarly
3883 for UDRs if initializer expression refers to omp_orig. */
3884 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
3886 /* Don't add any barrier for #pragma omp simd or
3887 #pragma omp distribute. */
3888 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3889 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
3890 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
3893 /* If max_vf is non-zero, then we can use only a vectorization factor
3894 up to the max_vf we chose. So stick it into the safelen clause. */
3897 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3898 OMP_CLAUSE_SAFELEN
);
3900 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
3901 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3904 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
3905 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
3907 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3908 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3914 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3915 both parallel and workshare constructs. PREDICATE may be NULL if it's
3919 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
3922 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
3923 bool par_clauses
= false;
3924 tree simduid
= NULL
, lastlane
= NULL
;
3926 /* Early exit if there are no lastprivate or linear clauses. */
3927 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
3928 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
3929 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
3930 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
3932 if (clauses
== NULL
)
3934 /* If this was a workshare clause, see if it had been combined
3935 with its parallel. In that case, look for the clauses on the
3936 parallel statement itself. */
3937 if (is_parallel_ctx (ctx
))
3941 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
3944 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
3945 OMP_CLAUSE_LASTPRIVATE
);
3946 if (clauses
== NULL
)
3954 tree label_true
, arm1
, arm2
;
3956 label
= create_artificial_label (UNKNOWN_LOCATION
);
3957 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
3958 arm1
= TREE_OPERAND (predicate
, 0);
3959 arm2
= TREE_OPERAND (predicate
, 1);
3960 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3961 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3962 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
3964 gimple_seq_add_stmt (stmt_list
, stmt
);
3965 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
3968 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3969 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3971 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
3973 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
3976 for (c
= clauses
; c
;)
3979 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3981 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
3982 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3983 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
3985 var
= OMP_CLAUSE_DECL (c
);
3986 new_var
= lookup_decl (var
, ctx
);
3988 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
3990 tree val
= DECL_VALUE_EXPR (new_var
);
3991 if (TREE_CODE (val
) == ARRAY_REF
3992 && VAR_P (TREE_OPERAND (val
, 0))
3993 && lookup_attribute ("omp simd array",
3994 DECL_ATTRIBUTES (TREE_OPERAND (val
,
3997 if (lastlane
== NULL
)
3999 lastlane
= create_tmp_var (unsigned_type_node
, NULL
);
4001 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
4003 TREE_OPERAND (val
, 1));
4004 gimple_call_set_lhs (g
, lastlane
);
4005 gimple_seq_add_stmt (stmt_list
, g
);
4007 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
4008 TREE_OPERAND (val
, 0), lastlane
,
4009 NULL_TREE
, NULL_TREE
);
4013 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4014 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
4016 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
4017 gimple_seq_add_seq (stmt_list
,
4018 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
4019 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
4021 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4022 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
4024 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
4025 gimple_seq_add_seq (stmt_list
,
4026 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
4027 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
4030 x
= build_outer_var_ref (var
, ctx
);
4031 if (is_reference (var
))
4032 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4033 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
4034 gimplify_and_add (x
, stmt_list
);
4036 c
= OMP_CLAUSE_CHAIN (c
);
4037 if (c
== NULL
&& !par_clauses
)
4039 /* If this was a workshare clause, see if it had been combined
4040 with its parallel. In that case, continue looking for the
4041 clauses also on the parallel statement itself. */
4042 if (is_parallel_ctx (ctx
))
4046 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4049 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4050 OMP_CLAUSE_LASTPRIVATE
);
4056 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
4060 /* Generate code to implement the REDUCTION clauses. */
4063 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
4065 gimple_seq sub_seq
= NULL
;
4070 /* SIMD reductions are handled in lower_rec_input_clauses. */
4071 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4072 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4075 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4076 update in that case, otherwise use a lock. */
4077 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
4078 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
4080 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4082 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4092 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4094 tree var
, ref
, new_var
;
4095 enum tree_code code
;
4096 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4098 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
4101 var
= OMP_CLAUSE_DECL (c
);
4102 new_var
= lookup_decl (var
, ctx
);
4103 if (is_reference (var
))
4104 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4105 ref
= build_outer_var_ref (var
, ctx
);
4106 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4108 /* reduction(-:var) sums up the partial results, so it acts
4109 identically to reduction(+:var). */
4110 if (code
== MINUS_EXPR
)
4115 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
4117 addr
= save_expr (addr
);
4118 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
4119 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
4120 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
4121 gimplify_and_add (x
, stmt_seqp
);
4125 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4127 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4129 if (is_reference (var
)
4130 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4132 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
4133 SET_DECL_VALUE_EXPR (placeholder
, ref
);
4134 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4135 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
4136 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
4137 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4138 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
4142 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4143 ref
= build_outer_var_ref (var
, ctx
);
4144 gimplify_assign (ref
, x
, &sub_seq
);
4148 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4150 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4152 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4154 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4156 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4160 /* Generate code to implement the COPYPRIVATE clauses. */
4163 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4168 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4170 tree var
, new_var
, ref
, x
;
4172 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4174 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4177 var
= OMP_CLAUSE_DECL (c
);
4178 by_ref
= use_pointer_for_field (var
, NULL
);
4180 ref
= build_sender_ref (var
, ctx
);
4181 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4184 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4185 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4187 gimplify_assign (ref
, x
, slist
);
4189 ref
= build_receiver_ref (var
, false, ctx
);
4192 ref
= fold_convert_loc (clause_loc
,
4193 build_pointer_type (TREE_TYPE (new_var
)),
4195 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4197 if (is_reference (var
))
4199 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4200 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4201 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4203 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4204 gimplify_and_add (x
, rlist
);
4209 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4210 and REDUCTION from the sender (aka parent) side. */
4213 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4218 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4220 tree val
, ref
, x
, var
;
4221 bool by_ref
, do_in
= false, do_out
= false;
4222 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4224 switch (OMP_CLAUSE_CODE (c
))
4226 case OMP_CLAUSE_PRIVATE
:
4227 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4230 case OMP_CLAUSE_FIRSTPRIVATE
:
4231 case OMP_CLAUSE_COPYIN
:
4232 case OMP_CLAUSE_LASTPRIVATE
:
4233 case OMP_CLAUSE_REDUCTION
:
4234 case OMP_CLAUSE__LOOPTEMP_
:
4240 val
= OMP_CLAUSE_DECL (c
);
4241 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4243 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4244 && is_global_var (var
))
4246 if (is_variable_sized (val
))
4248 by_ref
= use_pointer_for_field (val
, NULL
);
4250 switch (OMP_CLAUSE_CODE (c
))
4252 case OMP_CLAUSE_PRIVATE
:
4253 case OMP_CLAUSE_FIRSTPRIVATE
:
4254 case OMP_CLAUSE_COPYIN
:
4255 case OMP_CLAUSE__LOOPTEMP_
:
4259 case OMP_CLAUSE_LASTPRIVATE
:
4260 if (by_ref
|| is_reference (val
))
4262 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4269 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4274 case OMP_CLAUSE_REDUCTION
:
4276 do_out
= !(by_ref
|| is_reference (val
));
4285 ref
= build_sender_ref (val
, ctx
);
4286 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4287 gimplify_assign (ref
, x
, ilist
);
4288 if (is_task_ctx (ctx
))
4289 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4294 ref
= build_sender_ref (val
, ctx
);
4295 gimplify_assign (var
, ref
, olist
);
4300 /* Generate code to implement SHARED from the sender (aka parent)
4301 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4302 list things that got automatically shared. */
4305 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4307 tree var
, ovar
, nvar
, f
, x
, record_type
;
4309 if (ctx
->record_type
== NULL
)
4312 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4313 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4315 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4316 nvar
= maybe_lookup_decl (ovar
, ctx
);
4317 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4320 /* If CTX is a nested parallel directive. Find the immediately
4321 enclosing parallel or workshare construct that contains a
4322 mapping for OVAR. */
4323 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4325 if (use_pointer_for_field (ovar
, ctx
))
4327 x
= build_sender_ref (ovar
, ctx
);
4328 var
= build_fold_addr_expr (var
);
4329 gimplify_assign (x
, var
, ilist
);
4333 x
= build_sender_ref (ovar
, ctx
);
4334 gimplify_assign (x
, var
, ilist
);
4336 if (!TREE_READONLY (var
)
4337 /* We don't need to receive a new reference to a result
4338 or parm decl. In fact we may not store to it as we will
4339 invalidate any pending RSO and generate wrong gimple
4341 && !((TREE_CODE (var
) == RESULT_DECL
4342 || TREE_CODE (var
) == PARM_DECL
)
4343 && DECL_BY_REFERENCE (var
)))
4345 x
= build_sender_ref (ovar
, ctx
);
4346 gimplify_assign (var
, x
, olist
);
4353 /* A convenience function to build an empty GIMPLE_COND with just the
4357 gimple_build_cond_empty (tree cond
)
4359 enum tree_code pred_code
;
4362 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4363 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4367 /* Build the function calls to GOMP_parallel_start etc to actually
4368 generate the parallel operation. REGION is the parallel region
4369 being expanded. BB is the block where to insert the code. WS_ARGS
4370 will be set if this is a call to a combined parallel+workshare
4371 construct, it contains the list of additional arguments needed by
4372 the workshare construct. */
4375 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4376 gimple entry_stmt
, vec
<tree
, va_gc
> *ws_args
)
4378 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4379 gimple_stmt_iterator gsi
;
4381 enum built_in_function start_ix
;
4383 location_t clause_loc
;
4384 vec
<tree
, va_gc
> *args
;
4386 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4388 /* Determine what flavor of GOMP_parallel we will be
4390 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4391 if (is_combined_parallel (region
))
4393 switch (region
->inner
->type
)
4395 case GIMPLE_OMP_FOR
:
4396 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4397 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4398 + (region
->inner
->sched_kind
4399 == OMP_CLAUSE_SCHEDULE_RUNTIME
4400 ? 3 : region
->inner
->sched_kind
));
4401 start_ix
= (enum built_in_function
)start_ix2
;
4403 case GIMPLE_OMP_SECTIONS
:
4404 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4411 /* By default, the value of NUM_THREADS is zero (selected at run time)
4412 and there is no conditional. */
4414 val
= build_int_cst (unsigned_type_node
, 0);
4415 flags
= build_int_cst (unsigned_type_node
, 0);
4417 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4419 cond
= OMP_CLAUSE_IF_EXPR (c
);
4421 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4424 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4425 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4428 clause_loc
= gimple_location (entry_stmt
);
4430 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4432 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4434 /* Ensure 'val' is of the correct type. */
4435 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4437 /* If we found the clause 'if (cond)', build either
4438 (cond != 0) or (cond ? val : 1u). */
4441 cond
= gimple_boolify (cond
);
4443 if (integer_zerop (val
))
4444 val
= fold_build2_loc (clause_loc
,
4445 EQ_EXPR
, unsigned_type_node
, cond
,
4446 build_int_cst (TREE_TYPE (cond
), 0));
4449 basic_block cond_bb
, then_bb
, else_bb
;
4450 edge e
, e_then
, e_else
;
4451 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4453 tmp_var
= create_tmp_var (TREE_TYPE (val
), NULL
);
4454 if (gimple_in_ssa_p (cfun
))
4456 tmp_then
= make_ssa_name (tmp_var
, NULL
);
4457 tmp_else
= make_ssa_name (tmp_var
, NULL
);
4458 tmp_join
= make_ssa_name (tmp_var
, NULL
);
4467 e
= split_block (bb
, NULL
);
4472 then_bb
= create_empty_bb (cond_bb
);
4473 else_bb
= create_empty_bb (then_bb
);
4474 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4475 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4477 stmt
= gimple_build_cond_empty (cond
);
4478 gsi
= gsi_start_bb (cond_bb
);
4479 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4481 gsi
= gsi_start_bb (then_bb
);
4482 stmt
= gimple_build_assign (tmp_then
, val
);
4483 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4485 gsi
= gsi_start_bb (else_bb
);
4486 stmt
= gimple_build_assign
4487 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4488 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4490 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4491 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4492 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4493 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4494 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4495 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4497 if (gimple_in_ssa_p (cfun
))
4499 gimple phi
= create_phi_node (tmp_join
, bb
);
4500 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4501 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4507 gsi
= gsi_start_bb (bb
);
4508 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4509 false, GSI_CONTINUE_LINKING
);
4512 gsi
= gsi_last_bb (bb
);
4513 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4515 t1
= null_pointer_node
;
4517 t1
= build_fold_addr_expr (t
);
4518 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4520 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4521 args
->quick_push (t2
);
4522 args
->quick_push (t1
);
4523 args
->quick_push (val
);
4525 args
->splice (*ws_args
);
4526 args
->quick_push (flags
);
4528 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4529 builtin_decl_explicit (start_ix
), args
);
4531 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4532 false, GSI_CONTINUE_LINKING
);
4535 /* Insert a function call whose name is FUNC_NAME with the information from
4536 ENTRY_STMT into the basic_block BB. */
4539 expand_cilk_for_call (basic_block bb
, gimple entry_stmt
,
4540 vec
<tree
, va_gc
> *ws_args
)
4543 gimple_stmt_iterator gsi
;
4544 vec
<tree
, va_gc
> *args
;
4546 gcc_assert (vec_safe_length (ws_args
) == 2);
4547 tree func_name
= (*ws_args
)[0];
4548 tree grain
= (*ws_args
)[1];
4550 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4551 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
4552 gcc_assert (count
!= NULL_TREE
);
4553 count
= OMP_CLAUSE_OPERAND (count
, 0);
4555 gsi
= gsi_last_bb (bb
);
4556 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4558 t1
= null_pointer_node
;
4560 t1
= build_fold_addr_expr (t
);
4561 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4563 vec_alloc (args
, 4);
4564 args
->quick_push (t2
);
4565 args
->quick_push (t1
);
4566 args
->quick_push (count
);
4567 args
->quick_push (grain
);
4568 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
4570 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
4571 GSI_CONTINUE_LINKING
);
4574 /* Build the function call to GOMP_task to actually
4575 generate the task operation. BB is the block where to insert the code. */
4578 expand_task_call (basic_block bb
, gimple entry_stmt
)
4580 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
4581 gimple_stmt_iterator gsi
;
4582 location_t loc
= gimple_location (entry_stmt
);
4584 clauses
= gimple_omp_task_clauses (entry_stmt
);
4586 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4588 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
4590 cond
= boolean_true_node
;
4592 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
4593 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
4594 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
4595 flags
= build_int_cst (unsigned_type_node
,
4596 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
4598 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
4601 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
4602 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
4603 build_int_cst (unsigned_type_node
, 2),
4604 build_int_cst (unsigned_type_node
, 0));
4605 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
4608 depend
= OMP_CLAUSE_DECL (depend
);
4610 depend
= build_int_cst (ptr_type_node
, 0);
4612 gsi
= gsi_last_bb (bb
);
4613 t
= gimple_omp_task_data_arg (entry_stmt
);
4615 t2
= null_pointer_node
;
4617 t2
= build_fold_addr_expr_loc (loc
, t
);
4618 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
4619 t
= gimple_omp_task_copy_fn (entry_stmt
);
4621 t3
= null_pointer_node
;
4623 t3
= build_fold_addr_expr_loc (loc
, t
);
4625 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
4627 gimple_omp_task_arg_size (entry_stmt
),
4628 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
4631 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4632 false, GSI_CONTINUE_LINKING
);
4636 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4637 catch handler and return it. This prevents programs from violating the
4638 structured block semantics with throws. */
4641 maybe_catch_exception (gimple_seq body
)
4646 if (!flag_exceptions
)
4649 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
4650 decl
= lang_hooks
.eh_protect_cleanup_actions ();
4652 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
4654 g
= gimple_build_eh_must_not_throw (decl
);
4655 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
4658 return gimple_seq_alloc_with_stmt (g
);
4661 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4664 vec2chain (vec
<tree
, va_gc
> *v
)
4666 tree chain
= NULL_TREE
, t
;
4669 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
4671 DECL_CHAIN (t
) = chain
;
4679 /* Remove barriers in REGION->EXIT's block. Note that this is only
4680 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4681 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4682 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4686 remove_exit_barrier (struct omp_region
*region
)
4688 gimple_stmt_iterator gsi
;
4689 basic_block exit_bb
;
4693 int any_addressable_vars
= -1;
4695 exit_bb
= region
->exit
;
4697 /* If the parallel region doesn't return, we don't have REGION->EXIT
4702 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4703 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4704 statements that can appear in between are extremely limited -- no
4705 memory operations at all. Here, we allow nothing at all, so the
4706 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4707 gsi
= gsi_last_bb (exit_bb
);
4708 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
4710 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
4713 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
4715 gsi
= gsi_last_bb (e
->src
);
4716 if (gsi_end_p (gsi
))
4718 stmt
= gsi_stmt (gsi
);
4719 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
4720 && !gimple_omp_return_nowait_p (stmt
))
4722 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4723 in many cases. If there could be tasks queued, the barrier
4724 might be needed to let the tasks run before some local
4725 variable of the parallel that the task uses as shared
4726 runs out of scope. The task can be spawned either
4727 from within current function (this would be easy to check)
4728 or from some function it calls and gets passed an address
4729 of such a variable. */
4730 if (any_addressable_vars
< 0)
4732 gimple parallel_stmt
= last_stmt (region
->entry
);
4733 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
4734 tree local_decls
, block
, decl
;
4737 any_addressable_vars
= 0;
4738 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
4739 if (TREE_ADDRESSABLE (decl
))
4741 any_addressable_vars
= 1;
4744 for (block
= gimple_block (stmt
);
4745 !any_addressable_vars
4747 && TREE_CODE (block
) == BLOCK
;
4748 block
= BLOCK_SUPERCONTEXT (block
))
4750 for (local_decls
= BLOCK_VARS (block
);
4752 local_decls
= DECL_CHAIN (local_decls
))
4753 if (TREE_ADDRESSABLE (local_decls
))
4755 any_addressable_vars
= 1;
4758 if (block
== gimple_block (parallel_stmt
))
4762 if (!any_addressable_vars
)
4763 gimple_omp_return_set_nowait (stmt
);
4769 remove_exit_barriers (struct omp_region
*region
)
4771 if (region
->type
== GIMPLE_OMP_PARALLEL
)
4772 remove_exit_barrier (region
);
4776 region
= region
->inner
;
4777 remove_exit_barriers (region
);
4778 while (region
->next
)
4780 region
= region
->next
;
4781 remove_exit_barriers (region
);
4786 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4787 calls. These can't be declared as const functions, but
4788 within one parallel body they are constant, so they can be
4789 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4790 which are declared const. Similarly for task body, except
4791 that in untied task omp_get_thread_num () can change at any task
4792 scheduling point. */
4795 optimize_omp_library_calls (gimple entry_stmt
)
4798 gimple_stmt_iterator gsi
;
4799 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4800 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
4801 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4802 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
4803 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
4804 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
4805 OMP_CLAUSE_UNTIED
) != NULL
);
4807 FOR_EACH_BB_FN (bb
, cfun
)
4808 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4810 gimple call
= gsi_stmt (gsi
);
4813 if (is_gimple_call (call
)
4814 && (decl
= gimple_call_fndecl (call
))
4815 && DECL_EXTERNAL (decl
)
4816 && TREE_PUBLIC (decl
)
4817 && DECL_INITIAL (decl
) == NULL
)
4821 if (DECL_NAME (decl
) == thr_num_id
)
4823 /* In #pragma omp task untied omp_get_thread_num () can change
4824 during the execution of the task region. */
4827 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4829 else if (DECL_NAME (decl
) == num_thr_id
)
4830 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4834 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
4835 || gimple_call_num_args (call
) != 0)
4838 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
4841 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
4842 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
4843 TREE_TYPE (TREE_TYPE (built_in
))))
4846 gimple_call_set_fndecl (call
, built_in
);
4851 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4855 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
4859 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4860 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
4863 if (TREE_CODE (t
) == ADDR_EXPR
)
4864 recompute_tree_invariant_for_addr_expr (t
);
4866 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
4870 /* Prepend TO = FROM assignment before *GSI_P. */
4873 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
4875 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
4876 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
4877 true, GSI_SAME_STMT
);
4878 gimple stmt
= gimple_build_assign (to
, from
);
4879 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
4880 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
4881 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
4883 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
4884 gimple_regimplify_operands (stmt
, &gsi
);
4888 /* Expand the OpenMP parallel or task directive starting at REGION. */
4891 expand_omp_taskreg (struct omp_region
*region
)
4893 basic_block entry_bb
, exit_bb
, new_bb
;
4894 struct function
*child_cfun
;
4895 tree child_fn
, block
, t
;
4896 gimple_stmt_iterator gsi
;
4897 gimple entry_stmt
, stmt
;
4899 vec
<tree
, va_gc
> *ws_args
;
4901 entry_stmt
= last_stmt (region
->entry
);
4902 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
4903 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
4905 entry_bb
= region
->entry
;
4906 exit_bb
= region
->exit
;
4910 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
4911 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
4912 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
4915 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4916 and the inner statement contains the name of the built-in function
4918 ws_args
= region
->inner
->ws_args
;
4919 else if (is_combined_parallel (region
))
4920 ws_args
= region
->ws_args
;
4924 if (child_cfun
->cfg
)
4926 /* Due to inlining, it may happen that we have already outlined
4927 the region, in which case all we need to do is make the
4928 sub-graph unreachable and emit the parallel call. */
4929 edge entry_succ_e
, exit_succ_e
;
4931 entry_succ_e
= single_succ_edge (entry_bb
);
4933 gsi
= gsi_last_bb (entry_bb
);
4934 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
4935 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
4936 gsi_remove (&gsi
, true);
4941 exit_succ_e
= single_succ_edge (exit_bb
);
4942 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
4944 remove_edge_and_dominated_blocks (entry_succ_e
);
4948 unsigned srcidx
, dstidx
, num
;
4950 /* If the parallel region needs data sent from the parent
4951 function, then the very first statement (except possible
4952 tree profile counter updates) of the parallel body
4953 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4954 &.OMP_DATA_O is passed as an argument to the child function,
4955 we need to replace it with the argument as seen by the child
4958 In most cases, this will end up being the identity assignment
4959 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4960 a function call that has been inlined, the original PARM_DECL
4961 .OMP_DATA_I may have been converted into a different local
4962 variable. In which case, we need to keep the assignment. */
4963 if (gimple_omp_taskreg_data_arg (entry_stmt
))
4965 basic_block entry_succ_bb
= single_succ (entry_bb
);
4967 gimple parcopy_stmt
= NULL
;
4969 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
4973 gcc_assert (!gsi_end_p (gsi
));
4974 stmt
= gsi_stmt (gsi
);
4975 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
4978 if (gimple_num_ops (stmt
) == 2)
4980 tree arg
= gimple_assign_rhs1 (stmt
);
4982 /* We're ignore the subcode because we're
4983 effectively doing a STRIP_NOPS. */
4985 if (TREE_CODE (arg
) == ADDR_EXPR
4986 && TREE_OPERAND (arg
, 0)
4987 == gimple_omp_taskreg_data_arg (entry_stmt
))
4989 parcopy_stmt
= stmt
;
4995 gcc_assert (parcopy_stmt
!= NULL
);
4996 arg
= DECL_ARGUMENTS (child_fn
);
4998 if (!gimple_in_ssa_p (cfun
))
5000 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
5001 gsi_remove (&gsi
, true);
5004 /* ?? Is setting the subcode really necessary ?? */
5005 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
5006 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
5011 /* If we are in ssa form, we must load the value from the default
5012 definition of the argument. That should not be defined now,
5013 since the argument is not used uninitialized. */
5014 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
5015 narg
= make_ssa_name (arg
, gimple_build_nop ());
5016 set_ssa_default_def (cfun
, arg
, narg
);
5017 /* ?? Is setting the subcode really necessary ?? */
5018 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
5019 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
5020 update_stmt (parcopy_stmt
);
5024 /* Declare local variables needed in CHILD_CFUN. */
5025 block
= DECL_INITIAL (child_fn
);
5026 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
5027 /* The gimplifier could record temporaries in parallel/task block
5028 rather than in containing function's local_decls chain,
5029 which would mean cgraph missed finalizing them. Do it now. */
5030 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
5031 if (TREE_CODE (t
) == VAR_DECL
5033 && !DECL_EXTERNAL (t
))
5034 varpool_node::finalize_decl (t
);
5035 DECL_SAVED_TREE (child_fn
) = NULL
;
5036 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5037 gimple_set_body (child_fn
, NULL
);
5038 TREE_USED (block
) = 1;
5040 /* Reset DECL_CONTEXT on function arguments. */
5041 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
5042 DECL_CONTEXT (t
) = child_fn
;
5044 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5045 so that it can be moved to the child function. */
5046 gsi
= gsi_last_bb (entry_bb
);
5047 stmt
= gsi_stmt (gsi
);
5048 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
5049 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
5050 gsi_remove (&gsi
, true);
5051 e
= split_block (entry_bb
, stmt
);
5053 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5055 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5058 gsi
= gsi_last_bb (exit_bb
);
5059 gcc_assert (!gsi_end_p (gsi
)
5060 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5061 stmt
= gimple_build_return (NULL
);
5062 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5063 gsi_remove (&gsi
, true);
5066 /* Move the parallel region into CHILD_CFUN. */
5068 if (gimple_in_ssa_p (cfun
))
5070 init_tree_ssa (child_cfun
);
5071 init_ssa_operands (child_cfun
);
5072 child_cfun
->gimple_df
->in_ssa_p
= true;
5076 block
= gimple_block (entry_stmt
);
5078 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
5080 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
5081 /* When the OMP expansion process cannot guarantee an up-to-date
5082 loop tree arrange for the child function to fixup loops. */
5083 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5084 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
5086 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5087 num
= vec_safe_length (child_cfun
->local_decls
);
5088 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
5090 t
= (*child_cfun
->local_decls
)[srcidx
];
5091 if (DECL_CONTEXT (t
) == cfun
->decl
)
5093 if (srcidx
!= dstidx
)
5094 (*child_cfun
->local_decls
)[dstidx
] = t
;
5098 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
5100 /* Inform the callgraph about the new function. */
5101 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
5102 cgraph_node::add_new_function (child_fn
, true);
5104 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5105 fixed in a following pass. */
5106 push_cfun (child_cfun
);
5108 optimize_omp_library_calls (entry_stmt
);
5109 cgraph_edge::rebuild_edges ();
5111 /* Some EH regions might become dead, see PR34608. If
5112 pass_cleanup_cfg isn't the first pass to happen with the
5113 new child, these dead EH edges might cause problems.
5114 Clean them up now. */
5115 if (flag_exceptions
)
5118 bool changed
= false;
5120 FOR_EACH_BB_FN (bb
, cfun
)
5121 changed
|= gimple_purge_dead_eh_edges (bb
);
5123 cleanup_tree_cfg ();
5125 if (gimple_in_ssa_p (cfun
))
5126 update_ssa (TODO_update_ssa
);
5130 /* Emit a library call to launch the children threads. */
5132 expand_cilk_for_call (new_bb
, entry_stmt
, ws_args
);
5133 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5134 expand_parallel_call (region
, new_bb
, entry_stmt
, ws_args
);
5136 expand_task_call (new_bb
, entry_stmt
);
5137 if (gimple_in_ssa_p (cfun
))
5138 update_ssa (TODO_update_ssa_only_virtuals
);
5142 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5143 of the combined collapse > 1 loop constructs, generate code like:
5144 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5149 count3 = (adj + N32 - N31) / STEP3;
5150 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5155 count2 = (adj + N22 - N21) / STEP2;
5156 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5161 count1 = (adj + N12 - N11) / STEP1;
5162 count = count1 * count2 * count3;
5163 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5165 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5166 of the combined loop constructs, just initialize COUNTS array
5167 from the _looptemp_ clauses. */
5169 /* NOTE: It *could* be better to moosh all of the BBs together,
5170 creating one larger BB with all the computation and the unexpected
5171 jump at the end. I.e.
5173 bool zero3, zero2, zero1, zero;
5176 count3 = (N32 - N31) /[cl] STEP3;
5178 count2 = (N22 - N21) /[cl] STEP2;
5180 count1 = (N12 - N11) /[cl] STEP1;
5181 zero = zero3 || zero2 || zero1;
5182 count = count1 * count2 * count3;
5183 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5185 After all, we expect the zero=false, and thus we expect to have to
5186 evaluate all of the comparison expressions, so short-circuiting
5187 oughtn't be a win. Since the condition isn't protecting a
5188 denominator, we're not concerned about divide-by-zero, so we can
5189 fully evaluate count even if a numerator turned out to be wrong.
5191 It seems like putting this all together would create much better
5192 scheduling opportunities, and less pressure on the chip's branch
5196 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5197 basic_block
&entry_bb
, tree
*counts
,
5198 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5199 basic_block
&l2_dom_bb
)
5201 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5206 /* Collapsed loops need work for expansion into SSA form. */
5207 gcc_assert (!gimple_in_ssa_p (cfun
));
5209 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5210 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5212 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5213 isn't supposed to be handled, as the inner loop doesn't
5215 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5216 OMP_CLAUSE__LOOPTEMP_
);
5217 gcc_assert (innerc
);
5218 for (i
= 0; i
< fd
->collapse
; i
++)
5220 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5221 OMP_CLAUSE__LOOPTEMP_
);
5222 gcc_assert (innerc
);
5224 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5226 counts
[0] = NULL_TREE
;
5231 for (i
= 0; i
< fd
->collapse
; i
++)
5233 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5235 if (SSA_VAR_P (fd
->loop
.n2
)
5236 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5237 fold_convert (itype
, fd
->loops
[i
].n1
),
5238 fold_convert (itype
, fd
->loops
[i
].n2
)))
5239 == NULL_TREE
|| !integer_onep (t
)))
5242 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5243 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5244 true, GSI_SAME_STMT
);
5245 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5246 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5247 true, GSI_SAME_STMT
);
5248 stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5249 NULL_TREE
, NULL_TREE
);
5250 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5251 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
5252 expand_omp_regimplify_p
, NULL
, NULL
)
5253 || walk_tree (gimple_cond_rhs_ptr (stmt
),
5254 expand_omp_regimplify_p
, NULL
, NULL
))
5256 *gsi
= gsi_for_stmt (stmt
);
5257 gimple_regimplify_operands (stmt
, gsi
);
5259 e
= split_block (entry_bb
, stmt
);
5260 if (zero_iter_bb
== NULL
)
5262 first_zero_iter
= i
;
5263 zero_iter_bb
= create_empty_bb (entry_bb
);
5264 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5265 *gsi
= gsi_after_labels (zero_iter_bb
);
5266 stmt
= gimple_build_assign (fd
->loop
.n2
,
5267 build_zero_cst (type
));
5268 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5269 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5272 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5273 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5274 e
->flags
= EDGE_TRUE_VALUE
;
5275 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5276 if (l2_dom_bb
== NULL
)
5277 l2_dom_bb
= entry_bb
;
5279 *gsi
= gsi_last_bb (entry_bb
);
5282 if (POINTER_TYPE_P (itype
))
5283 itype
= signed_type_for (itype
);
5284 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5286 t
= fold_build2 (PLUS_EXPR
, itype
,
5287 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5288 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5289 fold_convert (itype
, fd
->loops
[i
].n2
));
5290 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5291 fold_convert (itype
, fd
->loops
[i
].n1
));
5292 /* ?? We could probably use CEIL_DIV_EXPR instead of
5293 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5294 generate the same code in the end because generically we
5295 don't know that the values involved must be negative for
5297 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5298 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5299 fold_build1 (NEGATE_EXPR
, itype
, t
),
5300 fold_build1 (NEGATE_EXPR
, itype
,
5301 fold_convert (itype
,
5302 fd
->loops
[i
].step
)));
5304 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5305 fold_convert (itype
, fd
->loops
[i
].step
));
5306 t
= fold_convert (type
, t
);
5307 if (TREE_CODE (t
) == INTEGER_CST
)
5311 counts
[i
] = create_tmp_reg (type
, ".count");
5312 expand_omp_build_assign (gsi
, counts
[i
], t
);
5314 if (SSA_VAR_P (fd
->loop
.n2
))
5319 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5320 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5326 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5328 V3 = N31 + (T % count3) * STEP3;
5330 V2 = N21 + (T % count2) * STEP2;
5332 V1 = N11 + T * STEP1;
5333 if this loop doesn't have an inner loop construct combined with it.
5334 If it does have an inner loop construct combined with it and the
5335 iteration count isn't known constant, store values from counts array
5336 into its _looptemp_ temporaries instead. */
5339 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5340 tree
*counts
, gimple inner_stmt
, tree startvar
)
5343 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5345 /* If fd->loop.n2 is constant, then no propagation of the counts
5346 is needed, they are constant. */
5347 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5350 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5351 ? gimple_omp_parallel_clauses (inner_stmt
)
5352 : gimple_omp_for_clauses (inner_stmt
);
5353 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5354 isn't supposed to be handled, as the inner loop doesn't
5356 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5357 gcc_assert (innerc
);
5358 for (i
= 0; i
< fd
->collapse
; i
++)
5360 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5361 OMP_CLAUSE__LOOPTEMP_
);
5362 gcc_assert (innerc
);
5365 tree tem
= OMP_CLAUSE_DECL (innerc
);
5366 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5367 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5368 false, GSI_CONTINUE_LINKING
);
5369 gimple stmt
= gimple_build_assign (tem
, t
);
5370 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5376 tree type
= TREE_TYPE (fd
->loop
.v
);
5377 tree tem
= create_tmp_reg (type
, ".tem");
5378 gimple stmt
= gimple_build_assign (tem
, startvar
);
5379 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5381 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5383 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5385 if (POINTER_TYPE_P (vtype
))
5386 itype
= signed_type_for (vtype
);
5388 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5391 t
= fold_convert (itype
, t
);
5392 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5393 fold_convert (itype
, fd
->loops
[i
].step
));
5394 if (POINTER_TYPE_P (vtype
))
5395 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5397 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5398 t
= force_gimple_operand_gsi (gsi
, t
,
5399 DECL_P (fd
->loops
[i
].v
)
5400 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5402 GSI_CONTINUE_LINKING
);
5403 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5404 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5407 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5408 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5409 false, GSI_CONTINUE_LINKING
);
5410 stmt
= gimple_build_assign (tem
, t
);
5411 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5417 /* Helper function for expand_omp_for_*. Generate code like:
5420 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5424 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5431 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5432 basic_block body_bb
)
5434 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5436 gimple_stmt_iterator gsi
;
5442 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5444 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5446 bb
= create_empty_bb (last_bb
);
5447 add_bb_to_loop (bb
, last_bb
->loop_father
);
5448 gsi
= gsi_start_bb (bb
);
5450 if (i
< fd
->collapse
- 1)
5452 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5453 e
->probability
= REG_BR_PROB_BASE
/ 8;
5455 t
= fd
->loops
[i
+ 1].n1
;
5456 t
= force_gimple_operand_gsi (&gsi
, t
,
5457 DECL_P (fd
->loops
[i
+ 1].v
)
5458 && TREE_ADDRESSABLE (fd
->loops
[i
5461 GSI_CONTINUE_LINKING
);
5462 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5463 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5468 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5470 if (POINTER_TYPE_P (vtype
))
5471 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5473 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5474 t
= force_gimple_operand_gsi (&gsi
, t
,
5475 DECL_P (fd
->loops
[i
].v
)
5476 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5477 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5478 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5479 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5483 t
= fd
->loops
[i
].n2
;
5484 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5485 false, GSI_CONTINUE_LINKING
);
5486 tree v
= fd
->loops
[i
].v
;
5487 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5488 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5489 false, GSI_CONTINUE_LINKING
);
5490 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5491 stmt
= gimple_build_cond_empty (t
);
5492 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5493 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5494 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5497 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5505 /* A subroutine of expand_omp_for. Generate code for a parallel
5506 loop with any schedule. Given parameters:
5508 for (V = N1; V cond N2; V += STEP) BODY;
5510 where COND is "<" or ">", we generate pseudocode
5512 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5513 if (more) goto L0; else goto L3;
5520 if (V cond iend) goto L1; else goto L2;
5522 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5525 If this is a combined omp parallel loop, instead of the call to
5526 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5527 If this is gimple_omp_for_combined_p loop, then instead of assigning
5528 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5529 inner GIMPLE_OMP_FOR and V += STEP; and
5530 if (V cond iend) goto L1; else goto L2; are removed.
5532 For collapsed loops, given parameters:
5534 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5535 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5536 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5539 we generate pseudocode
5541 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5546 count3 = (adj + N32 - N31) / STEP3;
5547 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5552 count2 = (adj + N22 - N21) / STEP2;
5553 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5558 count1 = (adj + N12 - N11) / STEP1;
5559 count = count1 * count2 * count3;
5564 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5565 if (more) goto L0; else goto L3;
5569 V3 = N31 + (T % count3) * STEP3;
5571 V2 = N21 + (T % count2) * STEP2;
5573 V1 = N11 + T * STEP1;
5578 if (V < iend) goto L10; else goto L2;
5581 if (V3 cond3 N32) goto L1; else goto L11;
5585 if (V2 cond2 N22) goto L1; else goto L12;
5591 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5597 expand_omp_for_generic (struct omp_region
*region
,
5598 struct omp_for_data
*fd
,
5599 enum built_in_function start_fn
,
5600 enum built_in_function next_fn
,
5603 tree type
, istart0
, iend0
, iend
;
5604 tree t
, vmain
, vback
, bias
= NULL_TREE
;
5605 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
5606 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
5607 gimple_stmt_iterator gsi
;
5609 bool in_combined_parallel
= is_combined_parallel (region
);
5610 bool broken_loop
= region
->cont
== NULL
;
5612 tree
*counts
= NULL
;
5615 gcc_assert (!broken_loop
|| !in_combined_parallel
);
5616 gcc_assert (fd
->iter_type
== long_integer_type_node
5617 || !in_combined_parallel
);
5619 type
= TREE_TYPE (fd
->loop
.v
);
5620 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
5621 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
5622 TREE_ADDRESSABLE (istart0
) = 1;
5623 TREE_ADDRESSABLE (iend0
) = 1;
5625 /* See if we need to bias by LLONG_MIN. */
5626 if (fd
->iter_type
== long_long_unsigned_type_node
5627 && TREE_CODE (type
) == INTEGER_TYPE
5628 && !TYPE_UNSIGNED (type
))
5632 if (fd
->loop
.cond_code
== LT_EXPR
)
5635 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5639 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5642 if (TREE_CODE (n1
) != INTEGER_CST
5643 || TREE_CODE (n2
) != INTEGER_CST
5644 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
5645 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
5648 entry_bb
= region
->entry
;
5649 cont_bb
= region
->cont
;
5651 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5652 gcc_assert (broken_loop
5653 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
5654 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
5655 l1_bb
= single_succ (l0_bb
);
5658 l2_bb
= create_empty_bb (cont_bb
);
5659 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
5660 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5664 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5665 exit_bb
= region
->exit
;
5667 gsi
= gsi_last_bb (entry_bb
);
5669 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5670 if (fd
->collapse
> 1)
5672 int first_zero_iter
= -1;
5673 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
5675 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5676 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5677 zero_iter_bb
, first_zero_iter
,
5682 /* Some counts[i] vars might be uninitialized if
5683 some loop has zero iterations. But the body shouldn't
5684 be executed in that case, so just avoid uninit warnings. */
5685 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
5686 if (SSA_VAR_P (counts
[i
]))
5687 TREE_NO_WARNING (counts
[i
]) = 1;
5689 e
= split_block (entry_bb
, gsi_stmt (gsi
));
5691 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
5692 gsi
= gsi_last_bb (entry_bb
);
5693 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
5694 get_immediate_dominator (CDI_DOMINATORS
,
5698 if (in_combined_parallel
)
5700 /* In a combined parallel loop, emit a call to
5701 GOMP_loop_foo_next. */
5702 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5703 build_fold_addr_expr (istart0
),
5704 build_fold_addr_expr (iend0
));
5708 tree t0
, t1
, t2
, t3
, t4
;
5709 /* If this is not a combined parallel loop, emit a call to
5710 GOMP_loop_foo_start in ENTRY_BB. */
5711 t4
= build_fold_addr_expr (iend0
);
5712 t3
= build_fold_addr_expr (istart0
);
5713 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
5716 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5718 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5719 OMP_CLAUSE__LOOPTEMP_
);
5720 gcc_assert (innerc
);
5721 t0
= OMP_CLAUSE_DECL (innerc
);
5722 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5723 OMP_CLAUSE__LOOPTEMP_
);
5724 gcc_assert (innerc
);
5725 t1
= OMP_CLAUSE_DECL (innerc
);
5727 if (POINTER_TYPE_P (TREE_TYPE (t0
))
5728 && TYPE_PRECISION (TREE_TYPE (t0
))
5729 != TYPE_PRECISION (fd
->iter_type
))
5731 /* Avoid casting pointers to integer of a different size. */
5732 tree itype
= signed_type_for (type
);
5733 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
5734 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
5738 t1
= fold_convert (fd
->iter_type
, t1
);
5739 t0
= fold_convert (fd
->iter_type
, t0
);
5743 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
5744 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
5746 if (fd
->iter_type
== long_integer_type_node
)
5750 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5751 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5752 6, t0
, t1
, t2
, t
, t3
, t4
);
5755 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5756 5, t0
, t1
, t2
, t3
, t4
);
5764 /* The GOMP_loop_ull_*start functions have additional boolean
5765 argument, true for < loops and false for > loops.
5766 In Fortran, the C bool type can be different from
5767 boolean_type_node. */
5768 bfn_decl
= builtin_decl_explicit (start_fn
);
5769 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
5770 t5
= build_int_cst (c_bool_type
,
5771 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
5774 tree bfn_decl
= builtin_decl_explicit (start_fn
);
5775 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5776 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
5779 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5780 6, t5
, t0
, t1
, t2
, t3
, t4
);
5783 if (TREE_TYPE (t
) != boolean_type_node
)
5784 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5785 t
, build_int_cst (TREE_TYPE (t
), 0));
5786 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5787 true, GSI_SAME_STMT
);
5788 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5790 /* Remove the GIMPLE_OMP_FOR statement. */
5791 gsi_remove (&gsi
, true);
5793 /* Iteration setup for sequential loop goes in L0_BB. */
5794 tree startvar
= fd
->loop
.v
;
5795 tree endvar
= NULL_TREE
;
5797 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5799 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
5800 && gimple_omp_for_kind (inner_stmt
)
5801 == GF_OMP_FOR_KIND_SIMD
);
5802 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
5803 OMP_CLAUSE__LOOPTEMP_
);
5804 gcc_assert (innerc
);
5805 startvar
= OMP_CLAUSE_DECL (innerc
);
5806 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5807 OMP_CLAUSE__LOOPTEMP_
);
5808 gcc_assert (innerc
);
5809 endvar
= OMP_CLAUSE_DECL (innerc
);
5812 gsi
= gsi_start_bb (l0_bb
);
5815 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5816 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5817 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5818 t
= fold_convert (TREE_TYPE (startvar
), t
);
5819 t
= force_gimple_operand_gsi (&gsi
, t
,
5821 && TREE_ADDRESSABLE (startvar
),
5822 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5823 stmt
= gimple_build_assign (startvar
, t
);
5824 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5828 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5829 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5830 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5831 t
= fold_convert (TREE_TYPE (startvar
), t
);
5832 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5833 false, GSI_CONTINUE_LINKING
);
5836 stmt
= gimple_build_assign (endvar
, iend
);
5837 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5838 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
5839 stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
5841 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, iend
,
5843 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5845 if (fd
->collapse
> 1)
5846 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
5850 /* Code to control the increment and predicate for the sequential
5851 loop goes in the CONT_BB. */
5852 gsi
= gsi_last_bb (cont_bb
);
5853 stmt
= gsi_stmt (gsi
);
5854 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
5855 vmain
= gimple_omp_continue_control_use (stmt
);
5856 vback
= gimple_omp_continue_control_def (stmt
);
5858 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5860 if (POINTER_TYPE_P (type
))
5861 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
5863 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
5864 t
= force_gimple_operand_gsi (&gsi
, t
,
5866 && TREE_ADDRESSABLE (vback
),
5867 NULL_TREE
, true, GSI_SAME_STMT
);
5868 stmt
= gimple_build_assign (vback
, t
);
5869 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5871 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
5872 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
5874 stmt
= gimple_build_cond_empty (t
);
5875 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5878 /* Remove GIMPLE_OMP_CONTINUE. */
5879 gsi_remove (&gsi
, true);
5881 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
5882 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
5884 /* Emit code to get the next parallel iteration in L2_BB. */
5885 gsi
= gsi_start_bb (l2_bb
);
5887 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5888 build_fold_addr_expr (istart0
),
5889 build_fold_addr_expr (iend0
));
5890 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5891 false, GSI_CONTINUE_LINKING
);
5892 if (TREE_TYPE (t
) != boolean_type_node
)
5893 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5894 t
, build_int_cst (TREE_TYPE (t
), 0));
5895 stmt
= gimple_build_cond_empty (t
);
5896 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5899 /* Add the loop cleanup function. */
5900 gsi
= gsi_last_bb (exit_bb
);
5901 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
5902 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
5903 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5904 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
5906 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
5907 stmt
= gimple_build_call (t
, 0);
5908 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5909 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
5910 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5911 gsi_remove (&gsi
, true);
5913 /* Connect the new blocks. */
5914 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
5915 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
5921 e
= find_edge (cont_bb
, l3_bb
);
5922 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
5924 phis
= phi_nodes (l3_bb
);
5925 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5927 gimple phi
= gsi_stmt (gsi
);
5928 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
5929 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
5933 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
5934 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
5935 e
= find_edge (cont_bb
, l1_bb
);
5936 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5941 else if (fd
->collapse
> 1)
5944 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
5947 e
->flags
= EDGE_TRUE_VALUE
;
5950 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5951 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
5955 e
= find_edge (cont_bb
, l2_bb
);
5956 e
->flags
= EDGE_FALLTHRU
;
5958 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
5960 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
5961 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
5962 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
5963 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
5964 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
5965 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
5966 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
5967 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
5969 struct loop
*outer_loop
= alloc_loop ();
5970 outer_loop
->header
= l0_bb
;
5971 outer_loop
->latch
= l2_bb
;
5972 add_loop (outer_loop
, l0_bb
->loop_father
);
5974 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5976 struct loop
*loop
= alloc_loop ();
5977 loop
->header
= l1_bb
;
5978 /* The loop may have multiple latches. */
5979 add_loop (loop
, outer_loop
);
5985 /* A subroutine of expand_omp_for. Generate code for a parallel
5986 loop with static schedule and no specified chunk size. Given
5989 for (V = N1; V cond N2; V += STEP) BODY;
5991 where COND is "<" or ">", we generate pseudocode
5993 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5998 if ((__typeof (V)) -1 > 0 && cond is >)
5999 n = -(adj + N2 - N1) / -STEP;
6001 n = (adj + N2 - N1) / STEP;
6004 if (threadid < tt) goto L3; else goto L4;
6009 s0 = q * threadid + tt;
6012 if (s0 >= e0) goto L2; else goto L0;
6018 if (V cond e) goto L1;
6023 expand_omp_for_static_nochunk (struct omp_region
*region
,
6024 struct omp_for_data
*fd
,
6027 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
6028 tree type
, itype
, vmain
, vback
;
6029 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
6030 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
6032 gimple_stmt_iterator gsi
;
6035 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6036 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6037 bool broken_loop
= region
->cont
== NULL
;
6038 tree
*counts
= NULL
;
6041 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6042 if (POINTER_TYPE_P (type
))
6043 itype
= signed_type_for (type
);
6045 entry_bb
= region
->entry
;
6046 cont_bb
= region
->cont
;
6047 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6048 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6049 gcc_assert (broken_loop
6050 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
6051 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6052 body_bb
= single_succ (seq_start_bb
);
6055 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6056 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6058 exit_bb
= region
->exit
;
6060 /* Iteration space partitioning goes in ENTRY_BB. */
6061 gsi
= gsi_last_bb (entry_bb
);
6062 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6064 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6066 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6067 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6070 if (fd
->collapse
> 1)
6072 int first_zero_iter
= -1;
6073 basic_block l2_dom_bb
= NULL
;
6075 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6076 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6077 fin_bb
, first_zero_iter
,
6081 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6082 t
= integer_one_node
;
6084 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6085 fold_convert (type
, fd
->loop
.n1
),
6086 fold_convert (type
, fd
->loop
.n2
));
6087 if (fd
->collapse
== 1
6088 && TYPE_UNSIGNED (type
)
6089 && (t
== NULL_TREE
|| !integer_onep (t
)))
6091 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6092 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6093 true, GSI_SAME_STMT
);
6094 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6095 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6096 true, GSI_SAME_STMT
);
6097 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6098 NULL_TREE
, NULL_TREE
);
6099 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6100 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
6101 expand_omp_regimplify_p
, NULL
, NULL
)
6102 || walk_tree (gimple_cond_rhs_ptr (stmt
),
6103 expand_omp_regimplify_p
, NULL
, NULL
))
6105 gsi
= gsi_for_stmt (stmt
);
6106 gimple_regimplify_operands (stmt
, &gsi
);
6108 ep
= split_block (entry_bb
, stmt
);
6109 ep
->flags
= EDGE_TRUE_VALUE
;
6110 entry_bb
= ep
->dest
;
6111 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6112 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6113 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6114 if (gimple_in_ssa_p (cfun
))
6116 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6117 for (gsi
= gsi_start_phis (fin_bb
);
6118 !gsi_end_p (gsi
); gsi_next (&gsi
))
6120 gimple phi
= gsi_stmt (gsi
);
6121 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6122 ep
, UNKNOWN_LOCATION
);
6125 gsi
= gsi_last_bb (entry_bb
);
6128 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6129 t
= fold_convert (itype
, t
);
6130 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6131 true, GSI_SAME_STMT
);
6133 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6134 t
= fold_convert (itype
, t
);
6135 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6136 true, GSI_SAME_STMT
);
6140 step
= fd
->loop
.step
;
6141 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6143 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6144 OMP_CLAUSE__LOOPTEMP_
);
6145 gcc_assert (innerc
);
6146 n1
= OMP_CLAUSE_DECL (innerc
);
6147 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6148 OMP_CLAUSE__LOOPTEMP_
);
6149 gcc_assert (innerc
);
6150 n2
= OMP_CLAUSE_DECL (innerc
);
6152 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6153 true, NULL_TREE
, true, GSI_SAME_STMT
);
6154 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6155 true, NULL_TREE
, true, GSI_SAME_STMT
);
6156 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6157 true, NULL_TREE
, true, GSI_SAME_STMT
);
6159 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6160 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6161 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6162 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6163 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6164 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6165 fold_build1 (NEGATE_EXPR
, itype
, t
),
6166 fold_build1 (NEGATE_EXPR
, itype
, step
));
6168 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6169 t
= fold_convert (itype
, t
);
6170 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6172 q
= create_tmp_reg (itype
, "q");
6173 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
6174 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6175 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
6177 tt
= create_tmp_reg (itype
, "tt");
6178 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
6179 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6180 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
6182 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
6183 stmt
= gimple_build_cond_empty (t
);
6184 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6186 second_bb
= split_block (entry_bb
, stmt
)->dest
;
6187 gsi
= gsi_last_bb (second_bb
);
6188 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6190 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
6192 stmt
= gimple_build_assign_with_ops (PLUS_EXPR
, q
, q
,
6193 build_int_cst (itype
, 1));
6194 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6196 third_bb
= split_block (second_bb
, stmt
)->dest
;
6197 gsi
= gsi_last_bb (third_bb
);
6198 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6200 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6201 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6202 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6204 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6205 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6207 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6208 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6210 /* Remove the GIMPLE_OMP_FOR statement. */
6211 gsi_remove (&gsi
, true);
6213 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6214 gsi
= gsi_start_bb (seq_start_bb
);
6216 tree startvar
= fd
->loop
.v
;
6217 tree endvar
= NULL_TREE
;
6219 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6221 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6222 ? gimple_omp_parallel_clauses (inner_stmt
)
6223 : gimple_omp_for_clauses (inner_stmt
);
6224 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6225 gcc_assert (innerc
);
6226 startvar
= OMP_CLAUSE_DECL (innerc
);
6227 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6228 OMP_CLAUSE__LOOPTEMP_
);
6229 gcc_assert (innerc
);
6230 endvar
= OMP_CLAUSE_DECL (innerc
);
6232 t
= fold_convert (itype
, s0
);
6233 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6234 if (POINTER_TYPE_P (type
))
6235 t
= fold_build_pointer_plus (n1
, t
);
6237 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6238 t
= fold_convert (TREE_TYPE (startvar
), t
);
6239 t
= force_gimple_operand_gsi (&gsi
, t
,
6241 && TREE_ADDRESSABLE (startvar
),
6242 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6243 stmt
= gimple_build_assign (startvar
, t
);
6244 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6246 t
= fold_convert (itype
, e0
);
6247 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6248 if (POINTER_TYPE_P (type
))
6249 t
= fold_build_pointer_plus (n1
, t
);
6251 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6252 t
= fold_convert (TREE_TYPE (startvar
), t
);
6253 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6254 false, GSI_CONTINUE_LINKING
);
6257 stmt
= gimple_build_assign (endvar
, e
);
6258 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6259 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6260 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6262 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6264 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6266 if (fd
->collapse
> 1)
6267 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6271 /* The code controlling the sequential loop replaces the
6272 GIMPLE_OMP_CONTINUE. */
6273 gsi
= gsi_last_bb (cont_bb
);
6274 stmt
= gsi_stmt (gsi
);
6275 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6276 vmain
= gimple_omp_continue_control_use (stmt
);
6277 vback
= gimple_omp_continue_control_def (stmt
);
6279 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6281 if (POINTER_TYPE_P (type
))
6282 t
= fold_build_pointer_plus (vmain
, step
);
6284 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6285 t
= force_gimple_operand_gsi (&gsi
, t
,
6287 && TREE_ADDRESSABLE (vback
),
6288 NULL_TREE
, true, GSI_SAME_STMT
);
6289 stmt
= gimple_build_assign (vback
, t
);
6290 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6292 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6293 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6295 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6298 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6299 gsi_remove (&gsi
, true);
6301 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6302 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6305 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6306 gsi
= gsi_last_bb (exit_bb
);
6307 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6309 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6310 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6312 gsi_remove (&gsi
, true);
6314 /* Connect all the blocks. */
6315 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6316 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6317 ep
= find_edge (entry_bb
, second_bb
);
6318 ep
->flags
= EDGE_TRUE_VALUE
;
6319 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6320 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6321 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6325 ep
= find_edge (cont_bb
, body_bb
);
6326 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6331 else if (fd
->collapse
> 1)
6334 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6337 ep
->flags
= EDGE_TRUE_VALUE
;
6338 find_edge (cont_bb
, fin_bb
)->flags
6339 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6342 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6343 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6344 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6346 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6347 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6348 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6349 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6351 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6353 struct loop
*loop
= alloc_loop ();
6354 loop
->header
= body_bb
;
6355 if (collapse_bb
== NULL
)
6356 loop
->latch
= cont_bb
;
6357 add_loop (loop
, body_bb
->loop_father
);
6362 /* A subroutine of expand_omp_for. Generate code for a parallel
6363 loop with static schedule and a specified chunk size. Given
6366 for (V = N1; V cond N2; V += STEP) BODY;
6368 where COND is "<" or ">", we generate pseudocode
6370 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6375 if ((__typeof (V)) -1 > 0 && cond is >)
6376 n = -(adj + N2 - N1) / -STEP;
6378 n = (adj + N2 - N1) / STEP;
6380 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6381 here so that V is defined
6382 if the loop is not entered
6384 s0 = (trip * nthreads + threadid) * CHUNK;
6385 e0 = min(s0 + CHUNK, n);
6386 if (s0 < n) goto L1; else goto L4;
6393 if (V cond e) goto L2; else goto L3;
6401 expand_omp_for_static_chunk (struct omp_region
*region
,
6402 struct omp_for_data
*fd
, gimple inner_stmt
)
6404 tree n
, s0
, e0
, e
, t
;
6405 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6406 tree type
, itype
, vmain
, vback
, vextra
;
6407 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6408 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6409 gimple_stmt_iterator gsi
;
6412 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6413 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6414 bool broken_loop
= region
->cont
== NULL
;
6415 tree
*counts
= NULL
;
6418 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6419 if (POINTER_TYPE_P (type
))
6420 itype
= signed_type_for (type
);
6422 entry_bb
= region
->entry
;
6423 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6425 iter_part_bb
= se
->dest
;
6426 cont_bb
= region
->cont
;
6427 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6428 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6429 gcc_assert (broken_loop
6430 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6431 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6432 body_bb
= single_succ (seq_start_bb
);
6435 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6436 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6437 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6439 exit_bb
= region
->exit
;
6441 /* Trip and adjustment setup goes in ENTRY_BB. */
6442 gsi
= gsi_last_bb (entry_bb
);
6443 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6445 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6447 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6448 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6451 if (fd
->collapse
> 1)
6453 int first_zero_iter
= -1;
6454 basic_block l2_dom_bb
= NULL
;
6456 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6457 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6458 fin_bb
, first_zero_iter
,
6462 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6463 t
= integer_one_node
;
6465 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6466 fold_convert (type
, fd
->loop
.n1
),
6467 fold_convert (type
, fd
->loop
.n2
));
6468 if (fd
->collapse
== 1
6469 && TYPE_UNSIGNED (type
)
6470 && (t
== NULL_TREE
|| !integer_onep (t
)))
6472 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6473 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6474 true, GSI_SAME_STMT
);
6475 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6476 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6477 true, GSI_SAME_STMT
);
6478 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6479 NULL_TREE
, NULL_TREE
);
6480 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6481 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
6482 expand_omp_regimplify_p
, NULL
, NULL
)
6483 || walk_tree (gimple_cond_rhs_ptr (stmt
),
6484 expand_omp_regimplify_p
, NULL
, NULL
))
6486 gsi
= gsi_for_stmt (stmt
);
6487 gimple_regimplify_operands (stmt
, &gsi
);
6489 se
= split_block (entry_bb
, stmt
);
6490 se
->flags
= EDGE_TRUE_VALUE
;
6491 entry_bb
= se
->dest
;
6492 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6493 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6494 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6495 if (gimple_in_ssa_p (cfun
))
6497 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6498 for (gsi
= gsi_start_phis (fin_bb
);
6499 !gsi_end_p (gsi
); gsi_next (&gsi
))
6501 gimple phi
= gsi_stmt (gsi
);
6502 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6503 se
, UNKNOWN_LOCATION
);
6506 gsi
= gsi_last_bb (entry_bb
);
6509 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6510 t
= fold_convert (itype
, t
);
6511 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6512 true, GSI_SAME_STMT
);
6514 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6515 t
= fold_convert (itype
, t
);
6516 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6517 true, GSI_SAME_STMT
);
6521 step
= fd
->loop
.step
;
6522 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6524 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6525 OMP_CLAUSE__LOOPTEMP_
);
6526 gcc_assert (innerc
);
6527 n1
= OMP_CLAUSE_DECL (innerc
);
6528 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6529 OMP_CLAUSE__LOOPTEMP_
);
6530 gcc_assert (innerc
);
6531 n2
= OMP_CLAUSE_DECL (innerc
);
6533 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6534 true, NULL_TREE
, true, GSI_SAME_STMT
);
6535 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6536 true, NULL_TREE
, true, GSI_SAME_STMT
);
6537 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6538 true, NULL_TREE
, true, GSI_SAME_STMT
);
6540 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
6541 true, NULL_TREE
, true, GSI_SAME_STMT
);
6543 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6544 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6545 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6546 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6547 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6548 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6549 fold_build1 (NEGATE_EXPR
, itype
, t
),
6550 fold_build1 (NEGATE_EXPR
, itype
, step
));
6552 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6553 t
= fold_convert (itype
, t
);
6554 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6555 true, GSI_SAME_STMT
);
6557 trip_var
= create_tmp_reg (itype
, ".trip");
6558 if (gimple_in_ssa_p (cfun
))
6560 trip_init
= make_ssa_name (trip_var
, NULL
);
6561 trip_main
= make_ssa_name (trip_var
, NULL
);
6562 trip_back
= make_ssa_name (trip_var
, NULL
);
6566 trip_init
= trip_var
;
6567 trip_main
= trip_var
;
6568 trip_back
= trip_var
;
6571 stmt
= gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
6572 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6574 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
6575 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6576 if (POINTER_TYPE_P (type
))
6577 t
= fold_build_pointer_plus (n1
, t
);
6579 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6580 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6581 true, GSI_SAME_STMT
);
6583 /* Remove the GIMPLE_OMP_FOR. */
6584 gsi_remove (&gsi
, true);
6586 /* Iteration space partitioning goes in ITER_PART_BB. */
6587 gsi
= gsi_last_bb (iter_part_bb
);
6589 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
6590 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
6591 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
6592 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6593 false, GSI_CONTINUE_LINKING
);
6595 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
6596 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
6597 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6598 false, GSI_CONTINUE_LINKING
);
6600 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
6601 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
6603 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6604 gsi
= gsi_start_bb (seq_start_bb
);
6606 tree startvar
= fd
->loop
.v
;
6607 tree endvar
= NULL_TREE
;
6609 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6611 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6612 ? gimple_omp_parallel_clauses (inner_stmt
)
6613 : gimple_omp_for_clauses (inner_stmt
);
6614 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6615 gcc_assert (innerc
);
6616 startvar
= OMP_CLAUSE_DECL (innerc
);
6617 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6618 OMP_CLAUSE__LOOPTEMP_
);
6619 gcc_assert (innerc
);
6620 endvar
= OMP_CLAUSE_DECL (innerc
);
6623 t
= fold_convert (itype
, s0
);
6624 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6625 if (POINTER_TYPE_P (type
))
6626 t
= fold_build_pointer_plus (n1
, t
);
6628 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6629 t
= fold_convert (TREE_TYPE (startvar
), t
);
6630 t
= force_gimple_operand_gsi (&gsi
, t
,
6632 && TREE_ADDRESSABLE (startvar
),
6633 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6634 stmt
= gimple_build_assign (startvar
, t
);
6635 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6637 t
= fold_convert (itype
, e0
);
6638 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6639 if (POINTER_TYPE_P (type
))
6640 t
= fold_build_pointer_plus (n1
, t
);
6642 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6643 t
= fold_convert (TREE_TYPE (startvar
), t
);
6644 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6645 false, GSI_CONTINUE_LINKING
);
6648 stmt
= gimple_build_assign (endvar
, e
);
6649 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6650 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6651 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6653 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6655 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6657 if (fd
->collapse
> 1)
6658 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6662 /* The code controlling the sequential loop goes in CONT_BB,
6663 replacing the GIMPLE_OMP_CONTINUE. */
6664 gsi
= gsi_last_bb (cont_bb
);
6665 stmt
= gsi_stmt (gsi
);
6666 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6667 vmain
= gimple_omp_continue_control_use (stmt
);
6668 vback
= gimple_omp_continue_control_def (stmt
);
6670 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6672 if (POINTER_TYPE_P (type
))
6673 t
= fold_build_pointer_plus (vmain
, step
);
6675 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6676 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
6677 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6678 true, GSI_SAME_STMT
);
6679 stmt
= gimple_build_assign (vback
, t
);
6680 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6682 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6683 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6685 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6688 /* Remove GIMPLE_OMP_CONTINUE. */
6689 gsi_remove (&gsi
, true);
6691 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6692 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6694 /* Trip update code goes into TRIP_UPDATE_BB. */
6695 gsi
= gsi_start_bb (trip_update_bb
);
6697 t
= build_int_cst (itype
, 1);
6698 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
6699 stmt
= gimple_build_assign (trip_back
, t
);
6700 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6703 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6704 gsi
= gsi_last_bb (exit_bb
);
6705 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6707 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6708 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6710 gsi_remove (&gsi
, true);
6712 /* Connect the new blocks. */
6713 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
6714 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
6718 se
= find_edge (cont_bb
, body_bb
);
6719 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6724 else if (fd
->collapse
> 1)
6727 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6730 se
->flags
= EDGE_TRUE_VALUE
;
6731 find_edge (cont_bb
, trip_update_bb
)->flags
6732 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6734 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
6737 if (gimple_in_ssa_p (cfun
))
6739 gimple_stmt_iterator psi
;
6745 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
6747 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6748 remove arguments of the phi nodes in fin_bb. We need to create
6749 appropriate phi nodes in iter_part_bb instead. */
6750 se
= single_pred_edge (fin_bb
);
6751 re
= single_succ_edge (trip_update_bb
);
6752 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
6753 ene
= single_succ_edge (entry_bb
);
6755 psi
= gsi_start_phis (fin_bb
);
6756 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
6757 gsi_next (&psi
), ++i
)
6760 source_location locus
;
6762 phi
= gsi_stmt (psi
);
6763 t
= gimple_phi_result (phi
);
6764 gcc_assert (t
== redirect_edge_var_map_result (vm
));
6765 nphi
= create_phi_node (t
, iter_part_bb
);
6767 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
6768 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
6770 /* A special case -- fd->loop.v is not yet computed in
6771 iter_part_bb, we need to use vextra instead. */
6772 if (t
== fd
->loop
.v
)
6774 add_phi_arg (nphi
, t
, ene
, locus
);
6775 locus
= redirect_edge_var_map_location (vm
);
6776 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
6778 gcc_assert (!gsi_end_p (psi
) && i
== head
->length ());
6779 redirect_edge_var_map_clear (re
);
6782 psi
= gsi_start_phis (fin_bb
);
6783 if (gsi_end_p (psi
))
6785 remove_phi_node (&psi
, false);
6788 /* Make phi node for trip. */
6789 phi
= create_phi_node (trip_main
, iter_part_bb
);
6790 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
6792 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
6797 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
6798 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
6799 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
6800 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6801 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6802 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
6803 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
6804 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6805 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6809 struct loop
*trip_loop
= alloc_loop ();
6810 trip_loop
->header
= iter_part_bb
;
6811 trip_loop
->latch
= trip_update_bb
;
6812 add_loop (trip_loop
, iter_part_bb
->loop_father
);
6814 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6816 struct loop
*loop
= alloc_loop ();
6817 loop
->header
= body_bb
;
6818 if (collapse_bb
== NULL
)
6819 loop
->latch
= cont_bb
;
6820 add_loop (loop
, trip_loop
);
6825 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6827 for (V = N1; V cond N2; V += STEP) BODY;
6829 where COND is "<" or ">" or "!=", we generate pseudocode
6831 for (ind_var = low; ind_var < high; ind_var++)
6833 V = n1 + (ind_var * STEP)
6838 In the above pseudocode, low and high are function parameters of the
6839 child function. In the function below, we are inserting a temp.
6840 variable that will be making a call to two OMP functions that will not be
6841 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6842 with _Cilk_for). These functions are replaced with low and high
6843 by the function that handles taskreg. */
6847 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
6849 bool broken_loop
= region
->cont
== NULL
;
6850 basic_block entry_bb
= region
->entry
;
6851 basic_block cont_bb
= region
->cont
;
6853 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6854 gcc_assert (broken_loop
6855 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6856 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
6857 basic_block l1_bb
, l2_bb
;
6861 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
6862 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6863 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
6864 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6868 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
6869 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
6870 l2_bb
= single_succ (l1_bb
);
6872 basic_block exit_bb
= region
->exit
;
6873 basic_block l2_dom_bb
= NULL
;
6875 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
6877 /* Below statements until the "tree high_val = ..." are pseudo statements
6878 used to pass information to be used by expand_omp_taskreg.
6879 low_val and high_val will be replaced by the __low and __high
6880 parameter from the child function.
6882 The call_exprs part is a place-holder, it is mainly used
6883 to distinctly identify to the top-level part that this is
6884 where we should put low and high (reasoning given in header
6888 = gimple_omp_parallel_child_fn (last_stmt (region
->outer
->entry
));
6889 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
6890 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
6892 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
6894 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
6897 gcc_assert (low_val
&& high_val
);
6899 tree type
= TREE_TYPE (low_val
);
6900 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
6901 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6903 /* Not needed in SSA form right now. */
6904 gcc_assert (!gimple_in_ssa_p (cfun
));
6905 if (l2_dom_bb
== NULL
)
6911 gimple stmt
= gimple_build_assign (ind_var
, n1
);
6913 /* Replace the GIMPLE_OMP_FOR statement. */
6914 gsi_replace (&gsi
, stmt
, true);
6918 /* Code to control the increment goes in the CONT_BB. */
6919 gsi
= gsi_last_bb (cont_bb
);
6920 stmt
= gsi_stmt (gsi
);
6921 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6922 stmt
= gimple_build_assign_with_ops (PLUS_EXPR
, ind_var
, ind_var
,
6923 build_one_cst (type
));
6925 /* Replace GIMPLE_OMP_CONTINUE. */
6926 gsi_replace (&gsi
, stmt
, true);
6929 /* Emit the condition in L1_BB. */
6930 gsi
= gsi_after_labels (l1_bb
);
6931 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
6932 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
6934 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
6935 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
6936 fd
->loop
.n1
, fold_convert (sizetype
, t
));
6938 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
6939 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
6940 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
6941 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
6943 /* The condition is always '<' since the runtime will fill in the low
6945 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
6946 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6948 /* Remove GIMPLE_OMP_RETURN. */
6949 gsi
= gsi_last_bb (exit_bb
);
6950 gsi_remove (&gsi
, true);
6952 /* Connect the new blocks. */
6953 remove_edge (FALLTHRU_EDGE (entry_bb
));
6958 remove_edge (BRANCH_EDGE (entry_bb
));
6959 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
6961 e
= BRANCH_EDGE (l1_bb
);
6962 ne
= FALLTHRU_EDGE (l1_bb
);
6963 e
->flags
= EDGE_TRUE_VALUE
;
6967 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6969 ne
= single_succ_edge (l1_bb
);
6970 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6973 ne
->flags
= EDGE_FALSE_VALUE
;
6974 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6975 ne
->probability
= REG_BR_PROB_BASE
/ 8;
6977 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
6978 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
6979 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
6983 struct loop
*loop
= alloc_loop ();
6984 loop
->header
= l1_bb
;
6985 loop
->latch
= cont_bb
;
6986 add_loop (loop
, l1_bb
->loop_father
);
6987 loop
->safelen
= INT_MAX
;
6990 /* Pick the correct library function based on the precision of the
6991 induction variable type. */
6992 tree lib_fun
= NULL_TREE
;
6993 if (TYPE_PRECISION (type
) == 32)
6994 lib_fun
= cilk_for_32_fndecl
;
6995 else if (TYPE_PRECISION (type
) == 64)
6996 lib_fun
= cilk_for_64_fndecl
;
7000 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
7002 /* WS_ARGS contains the library function flavor to call:
7003 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7004 user-defined grain value. If the user does not define one, then zero
7005 is passed in by the parser. */
7006 vec_alloc (region
->ws_args
, 2);
7007 region
->ws_args
->quick_push (lib_fun
);
7008 region
->ws_args
->quick_push (fd
->chunk_size
);
7011 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7012 loop. Given parameters:
7014 for (V = N1; V cond N2; V += STEP) BODY;
7016 where COND is "<" or ">", we generate pseudocode
7024 if (V cond N2) goto L0; else goto L2;
7027 For collapsed loops, given parameters:
7029 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7030 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7031 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7034 we generate pseudocode
7040 count3 = (adj + N32 - N31) / STEP3;
7045 count2 = (adj + N22 - N21) / STEP2;
7050 count1 = (adj + N12 - N11) / STEP1;
7051 count = count1 * count2 * count3;
7061 V2 += (V3 cond3 N32) ? 0 : STEP2;
7062 V3 = (V3 cond3 N32) ? V3 : N31;
7063 V1 += (V2 cond2 N22) ? 0 : STEP1;
7064 V2 = (V2 cond2 N22) ? V2 : N21;
7066 if (V < count) goto L0; else goto L2;
7072 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
7075 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
7076 gimple_stmt_iterator gsi
;
7078 bool broken_loop
= region
->cont
== NULL
;
7080 tree
*counts
= NULL
;
7082 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7083 OMP_CLAUSE_SAFELEN
);
7084 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7085 OMP_CLAUSE__SIMDUID_
);
7088 type
= TREE_TYPE (fd
->loop
.v
);
7089 entry_bb
= region
->entry
;
7090 cont_bb
= region
->cont
;
7091 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7092 gcc_assert (broken_loop
7093 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7094 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7097 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7098 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7099 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7100 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7104 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7105 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7106 l2_bb
= single_succ (l1_bb
);
7108 exit_bb
= region
->exit
;
7111 gsi
= gsi_last_bb (entry_bb
);
7113 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7114 /* Not needed in SSA form right now. */
7115 gcc_assert (!gimple_in_ssa_p (cfun
));
7116 if (fd
->collapse
> 1)
7118 int first_zero_iter
= -1;
7119 basic_block zero_iter_bb
= l2_bb
;
7121 counts
= XALLOCAVEC (tree
, fd
->collapse
);
7122 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7123 zero_iter_bb
, first_zero_iter
,
7126 if (l2_dom_bb
== NULL
)
7131 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7133 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7134 OMP_CLAUSE__LOOPTEMP_
);
7135 gcc_assert (innerc
);
7136 n1
= OMP_CLAUSE_DECL (innerc
);
7137 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7138 OMP_CLAUSE__LOOPTEMP_
);
7139 gcc_assert (innerc
);
7140 n2
= OMP_CLAUSE_DECL (innerc
);
7141 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7142 fold_convert (type
, n1
));
7143 if (fd
->collapse
> 1)
7146 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
7152 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7153 fold_convert (type
, fd
->loop
.n1
));
7154 if (fd
->collapse
> 1)
7155 for (i
= 0; i
< fd
->collapse
; i
++)
7157 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7158 if (POINTER_TYPE_P (itype
))
7159 itype
= signed_type_for (itype
);
7160 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
7161 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7165 /* Remove the GIMPLE_OMP_FOR statement. */
7166 gsi_remove (&gsi
, true);
7170 /* Code to control the increment goes in the CONT_BB. */
7171 gsi
= gsi_last_bb (cont_bb
);
7172 stmt
= gsi_stmt (gsi
);
7173 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7175 if (POINTER_TYPE_P (type
))
7176 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
7178 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
7179 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7181 if (fd
->collapse
> 1)
7183 i
= fd
->collapse
- 1;
7184 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7186 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
7187 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
7191 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
7193 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7196 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7198 for (i
= fd
->collapse
- 1; i
> 0; i
--)
7200 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7201 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
7202 if (POINTER_TYPE_P (itype2
))
7203 itype2
= signed_type_for (itype2
);
7204 t
= build3 (COND_EXPR
, itype2
,
7205 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7207 fold_convert (itype
, fd
->loops
[i
].n2
)),
7208 build_int_cst (itype2
, 0),
7209 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
7210 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
7211 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
7213 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
7214 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
7216 t
= build3 (COND_EXPR
, itype
,
7217 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7219 fold_convert (itype
, fd
->loops
[i
].n2
)),
7221 fold_convert (itype
, fd
->loops
[i
].n1
));
7222 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7226 /* Remove GIMPLE_OMP_CONTINUE. */
7227 gsi_remove (&gsi
, true);
7230 /* Emit the condition in L1_BB. */
7231 gsi
= gsi_start_bb (l1_bb
);
7233 t
= fold_convert (type
, n2
);
7234 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7235 false, GSI_CONTINUE_LINKING
);
7236 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
7237 stmt
= gimple_build_cond_empty (t
);
7238 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7239 if (walk_tree (gimple_cond_lhs_ptr (stmt
), expand_omp_regimplify_p
,
7241 || walk_tree (gimple_cond_rhs_ptr (stmt
), expand_omp_regimplify_p
,
7244 gsi
= gsi_for_stmt (stmt
);
7245 gimple_regimplify_operands (stmt
, &gsi
);
7248 /* Remove GIMPLE_OMP_RETURN. */
7249 gsi
= gsi_last_bb (exit_bb
);
7250 gsi_remove (&gsi
, true);
7252 /* Connect the new blocks. */
7253 remove_edge (FALLTHRU_EDGE (entry_bb
));
7257 remove_edge (BRANCH_EDGE (entry_bb
));
7258 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7260 e
= BRANCH_EDGE (l1_bb
);
7261 ne
= FALLTHRU_EDGE (l1_bb
);
7262 e
->flags
= EDGE_TRUE_VALUE
;
7266 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7268 ne
= single_succ_edge (l1_bb
);
7269 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7272 ne
->flags
= EDGE_FALSE_VALUE
;
7273 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7274 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7276 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7277 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7278 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7282 struct loop
*loop
= alloc_loop ();
7283 loop
->header
= l1_bb
;
7284 loop
->latch
= cont_bb
;
7285 add_loop (loop
, l1_bb
->loop_father
);
7286 if (safelen
== NULL_TREE
)
7287 loop
->safelen
= INT_MAX
;
7290 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
7291 if (TREE_CODE (safelen
) != INTEGER_CST
)
7293 else if (!tree_fits_uhwi_p (safelen
)
7294 || tree_to_uhwi (safelen
) > INT_MAX
)
7295 loop
->safelen
= INT_MAX
;
7297 loop
->safelen
= tree_to_uhwi (safelen
);
7298 if (loop
->safelen
== 1)
7303 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
7304 cfun
->has_simduid_loops
= true;
7306 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7308 if ((flag_tree_loop_vectorize
7309 || (!global_options_set
.x_flag_tree_loop_vectorize
7310 && !global_options_set
.x_flag_tree_vectorize
))
7311 && flag_tree_loop_optimize
7312 && loop
->safelen
> 1)
7314 loop
->force_vectorize
= true;
7315 cfun
->has_force_vectorize_loops
= true;
7321 /* Expand the OpenMP loop defined by REGION. */
7324 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
7326 struct omp_for_data fd
;
7327 struct omp_for_data_loop
*loops
;
7330 = (struct omp_for_data_loop
*)
7331 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
7332 * sizeof (struct omp_for_data_loop
));
7333 extract_omp_for_data (last_stmt (region
->entry
), &fd
, loops
);
7334 region
->sched_kind
= fd
.sched_kind
;
7336 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
7337 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7338 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7341 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
7342 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7343 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7346 /* If there isn't a continue then this is a degerate case where
7347 the introduction of abnormal edges during lowering will prevent
7348 original loops from being detected. Fix that up. */
7349 loops_state_set (LOOPS_NEED_FIXUP
);
7351 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
7352 expand_omp_simd (region
, &fd
);
7353 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
7354 expand_cilk_for (region
, &fd
);
7355 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
7356 && !fd
.have_ordered
)
7358 if (fd
.chunk_size
== NULL
)
7359 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
7361 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
7365 int fn_index
, start_ix
, next_ix
;
7367 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
7368 == GF_OMP_FOR_KIND_FOR
);
7369 if (fd
.chunk_size
== NULL
7370 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
7371 fd
.chunk_size
= integer_zero_node
;
7372 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
7373 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
7374 ? 3 : fd
.sched_kind
;
7375 fn_index
+= fd
.have_ordered
* 4;
7376 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
7377 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
7378 if (fd
.iter_type
== long_long_unsigned_type_node
)
7380 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7381 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
7382 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7383 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7385 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7386 (enum built_in_function
) next_ix
, inner_stmt
);
7389 if (gimple_in_ssa_p (cfun
))
7390 update_ssa (TODO_update_ssa_only_virtuals
);
7394 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7396 v = GOMP_sections_start (n);
7413 v = GOMP_sections_next ();
7418 If this is a combined parallel sections, replace the call to
7419 GOMP_sections_start with call to GOMP_sections_next. */
7422 expand_omp_sections (struct omp_region
*region
)
7424 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7426 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7427 gimple_stmt_iterator si
, switch_si
;
7428 gimple sections_stmt
, stmt
, cont
;
7431 struct omp_region
*inner
;
7433 bool exit_reachable
= region
->cont
!= NULL
;
7435 gcc_assert (region
->exit
!= NULL
);
7436 entry_bb
= region
->entry
;
7437 l0_bb
= single_succ (entry_bb
);
7438 l1_bb
= region
->cont
;
7439 l2_bb
= region
->exit
;
7440 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7441 l2
= gimple_block_label (l2_bb
);
7444 /* This can happen if there are reductions. */
7445 len
= EDGE_COUNT (l0_bb
->succs
);
7446 gcc_assert (len
> 0);
7447 e
= EDGE_SUCC (l0_bb
, len
- 1);
7448 si
= gsi_last_bb (e
->dest
);
7451 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7452 l2
= gimple_block_label (e
->dest
);
7454 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7456 si
= gsi_last_bb (e
->dest
);
7458 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7460 l2
= gimple_block_label (e
->dest
);
7466 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7468 default_bb
= create_empty_bb (l0_bb
);
7470 /* We will build a switch() with enough cases for all the
7471 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7472 and a default case to abort if something goes wrong. */
7473 len
= EDGE_COUNT (l0_bb
->succs
);
7475 /* Use vec::quick_push on label_vec throughout, since we know the size
7477 auto_vec
<tree
> label_vec (len
);
7479 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7480 GIMPLE_OMP_SECTIONS statement. */
7481 si
= gsi_last_bb (entry_bb
);
7482 sections_stmt
= gsi_stmt (si
);
7483 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
7484 vin
= gimple_omp_sections_control (sections_stmt
);
7485 if (!is_combined_parallel (region
))
7487 /* If we are not inside a combined parallel+sections region,
7488 call GOMP_sections_start. */
7489 t
= build_int_cst (unsigned_type_node
, len
- 1);
7490 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
7491 stmt
= gimple_build_call (u
, 1, t
);
7495 /* Otherwise, call GOMP_sections_next. */
7496 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7497 stmt
= gimple_build_call (u
, 0);
7499 gimple_call_set_lhs (stmt
, vin
);
7500 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7501 gsi_remove (&si
, true);
7503 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7505 switch_si
= gsi_last_bb (l0_bb
);
7506 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
7509 cont
= last_stmt (l1_bb
);
7510 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
7511 vmain
= gimple_omp_continue_control_use (cont
);
7512 vnext
= gimple_omp_continue_control_def (cont
);
7520 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
7521 label_vec
.quick_push (t
);
7524 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7525 for (inner
= region
->inner
, casei
= 1;
7527 inner
= inner
->next
, i
++, casei
++)
7529 basic_block s_entry_bb
, s_exit_bb
;
7531 /* Skip optional reduction region. */
7532 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
7539 s_entry_bb
= inner
->entry
;
7540 s_exit_bb
= inner
->exit
;
7542 t
= gimple_block_label (s_entry_bb
);
7543 u
= build_int_cst (unsigned_type_node
, casei
);
7544 u
= build_case_label (u
, NULL
, t
);
7545 label_vec
.quick_push (u
);
7547 si
= gsi_last_bb (s_entry_bb
);
7548 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
7549 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
7550 gsi_remove (&si
, true);
7551 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
7553 if (s_exit_bb
== NULL
)
7556 si
= gsi_last_bb (s_exit_bb
);
7557 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7558 gsi_remove (&si
, true);
7560 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
7563 /* Error handling code goes in DEFAULT_BB. */
7564 t
= gimple_block_label (default_bb
);
7565 u
= build_case_label (NULL
, NULL
, t
);
7566 make_edge (l0_bb
, default_bb
, 0);
7567 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
7569 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
7570 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
7571 gsi_remove (&switch_si
, true);
7573 si
= gsi_start_bb (default_bb
);
7574 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
7575 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
7581 /* Code to get the next section goes in L1_BB. */
7582 si
= gsi_last_bb (l1_bb
);
7583 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
7585 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7586 stmt
= gimple_build_call (bfn_decl
, 0);
7587 gimple_call_set_lhs (stmt
, vnext
);
7588 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7589 gsi_remove (&si
, true);
7591 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
7594 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7595 si
= gsi_last_bb (l2_bb
);
7596 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
7597 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
7598 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
7599 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
7601 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
7602 stmt
= gimple_build_call (t
, 0);
7603 if (gimple_omp_return_lhs (gsi_stmt (si
)))
7604 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
7605 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7606 gsi_remove (&si
, true);
7608 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
7612 /* Expand code for an OpenMP single directive. We've already expanded
7613 much of the code, here we simply place the GOMP_barrier call. */
7616 expand_omp_single (struct omp_region
*region
)
7618 basic_block entry_bb
, exit_bb
;
7619 gimple_stmt_iterator si
;
7621 entry_bb
= region
->entry
;
7622 exit_bb
= region
->exit
;
7624 si
= gsi_last_bb (entry_bb
);
7625 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
7626 gsi_remove (&si
, true);
7627 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7629 si
= gsi_last_bb (exit_bb
);
7630 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
7632 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
7633 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
7635 gsi_remove (&si
, true);
7636 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7640 /* Generic expansion for OpenMP synchronization directives: master,
7641 ordered and critical. All we need to do here is remove the entry
7642 and exit markers for REGION. */
7645 expand_omp_synch (struct omp_region
*region
)
7647 basic_block entry_bb
, exit_bb
;
7648 gimple_stmt_iterator si
;
7650 entry_bb
= region
->entry
;
7651 exit_bb
= region
->exit
;
7653 si
= gsi_last_bb (entry_bb
);
7654 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
7655 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
7656 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
7657 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
7658 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
7659 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
7660 gsi_remove (&si
, true);
7661 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7665 si
= gsi_last_bb (exit_bb
);
7666 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7667 gsi_remove (&si
, true);
7668 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7672 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7673 operation as a normal volatile load. */
7676 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
7677 tree loaded_val
, int index
)
7679 enum built_in_function tmpbase
;
7680 gimple_stmt_iterator gsi
;
7681 basic_block store_bb
;
7684 tree decl
, call
, type
, itype
;
7686 gsi
= gsi_last_bb (load_bb
);
7687 stmt
= gsi_stmt (gsi
);
7688 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7689 loc
= gimple_location (stmt
);
7691 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7692 is smaller than word size, then expand_atomic_load assumes that the load
7693 is atomic. We could avoid the builtin entirely in this case. */
7695 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7696 decl
= builtin_decl_explicit (tmpbase
);
7697 if (decl
== NULL_TREE
)
7700 type
= TREE_TYPE (loaded_val
);
7701 itype
= TREE_TYPE (TREE_TYPE (decl
));
7703 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
7704 build_int_cst (NULL
,
7705 gimple_omp_atomic_seq_cst_p (stmt
)
7707 : MEMMODEL_RELAXED
));
7708 if (!useless_type_conversion_p (type
, itype
))
7709 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7710 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7712 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7713 gsi_remove (&gsi
, true);
7715 store_bb
= single_succ (load_bb
);
7716 gsi
= gsi_last_bb (store_bb
);
7717 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7718 gsi_remove (&gsi
, true);
7720 if (gimple_in_ssa_p (cfun
))
7721 update_ssa (TODO_update_ssa_no_phi
);
7726 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7727 operation as a normal volatile store. */
7730 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
7731 tree loaded_val
, tree stored_val
, int index
)
7733 enum built_in_function tmpbase
;
7734 gimple_stmt_iterator gsi
;
7735 basic_block store_bb
= single_succ (load_bb
);
7738 tree decl
, call
, type
, itype
;
7742 gsi
= gsi_last_bb (load_bb
);
7743 stmt
= gsi_stmt (gsi
);
7744 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7746 /* If the load value is needed, then this isn't a store but an exchange. */
7747 exchange
= gimple_omp_atomic_need_value_p (stmt
);
7749 gsi
= gsi_last_bb (store_bb
);
7750 stmt
= gsi_stmt (gsi
);
7751 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
7752 loc
= gimple_location (stmt
);
7754 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7755 is smaller than word size, then expand_atomic_store assumes that the store
7756 is atomic. We could avoid the builtin entirely in this case. */
7758 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
7759 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
7760 decl
= builtin_decl_explicit (tmpbase
);
7761 if (decl
== NULL_TREE
)
7764 type
= TREE_TYPE (stored_val
);
7766 /* Dig out the type of the function's second argument. */
7767 itype
= TREE_TYPE (decl
);
7768 itype
= TYPE_ARG_TYPES (itype
);
7769 itype
= TREE_CHAIN (itype
);
7770 itype
= TREE_VALUE (itype
);
7771 imode
= TYPE_MODE (itype
);
7773 if (exchange
&& !can_atomic_exchange_p (imode
, true))
7776 if (!useless_type_conversion_p (itype
, type
))
7777 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
7778 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
7779 build_int_cst (NULL
,
7780 gimple_omp_atomic_seq_cst_p (stmt
)
7782 : MEMMODEL_RELAXED
));
7785 if (!useless_type_conversion_p (type
, itype
))
7786 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7787 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7790 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7791 gsi_remove (&gsi
, true);
7793 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7794 gsi
= gsi_last_bb (load_bb
);
7795 gsi_remove (&gsi
, true);
7797 if (gimple_in_ssa_p (cfun
))
7798 update_ssa (TODO_update_ssa_no_phi
);
7803 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7804 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7805 size of the data type, and thus usable to find the index of the builtin
7806 decl. Returns false if the expression is not of the proper form. */
7809 expand_omp_atomic_fetch_op (basic_block load_bb
,
7810 tree addr
, tree loaded_val
,
7811 tree stored_val
, int index
)
7813 enum built_in_function oldbase
, newbase
, tmpbase
;
7814 tree decl
, itype
, call
;
7816 basic_block store_bb
= single_succ (load_bb
);
7817 gimple_stmt_iterator gsi
;
7820 enum tree_code code
;
7821 bool need_old
, need_new
;
7825 /* We expect to find the following sequences:
7828 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7831 val = tmp OP something; (or: something OP tmp)
7832 GIMPLE_OMP_STORE (val)
7834 ???FIXME: Allow a more flexible sequence.
7835 Perhaps use data flow to pick the statements.
7839 gsi
= gsi_after_labels (store_bb
);
7840 stmt
= gsi_stmt (gsi
);
7841 loc
= gimple_location (stmt
);
7842 if (!is_gimple_assign (stmt
))
7845 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
7847 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
7848 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
7849 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
7850 gcc_checking_assert (!need_old
|| !need_new
);
7852 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
7855 /* Check for one of the supported fetch-op operations. */
7856 code
= gimple_assign_rhs_code (stmt
);
7860 case POINTER_PLUS_EXPR
:
7861 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
7862 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
7865 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
7866 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
7869 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
7870 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
7873 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
7874 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
7877 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
7878 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
7884 /* Make sure the expression is of the proper form. */
7885 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
7886 rhs
= gimple_assign_rhs2 (stmt
);
7887 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
7888 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
7889 rhs
= gimple_assign_rhs1 (stmt
);
7893 tmpbase
= ((enum built_in_function
)
7894 ((need_new
? newbase
: oldbase
) + index
+ 1));
7895 decl
= builtin_decl_explicit (tmpbase
);
7896 if (decl
== NULL_TREE
)
7898 itype
= TREE_TYPE (TREE_TYPE (decl
));
7899 imode
= TYPE_MODE (itype
);
7901 /* We could test all of the various optabs involved, but the fact of the
7902 matter is that (with the exception of i486 vs i586 and xadd) all targets
7903 that support any atomic operaton optab also implements compare-and-swap.
7904 Let optabs.c take care of expanding any compare-and-swap loop. */
7905 if (!can_compare_and_swap_p (imode
, true))
7908 gsi
= gsi_last_bb (load_bb
);
7909 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7911 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7912 It only requires that the operation happen atomically. Thus we can
7913 use the RELAXED memory model. */
7914 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
7915 fold_convert_loc (loc
, itype
, rhs
),
7916 build_int_cst (NULL
,
7917 seq_cst
? MEMMODEL_SEQ_CST
7918 : MEMMODEL_RELAXED
));
7920 if (need_old
|| need_new
)
7922 lhs
= need_old
? loaded_val
: stored_val
;
7923 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
7924 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
7927 call
= fold_convert_loc (loc
, void_type_node
, call
);
7928 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7929 gsi_remove (&gsi
, true);
7931 gsi
= gsi_last_bb (store_bb
);
7932 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7933 gsi_remove (&gsi
, true);
7934 gsi
= gsi_last_bb (store_bb
);
7935 gsi_remove (&gsi
, true);
7937 if (gimple_in_ssa_p (cfun
))
7938 update_ssa (TODO_update_ssa_no_phi
);
7943 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7947 newval = rhs; // with oldval replacing *addr in rhs
7948 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7949 if (oldval != newval)
7952 INDEX is log2 of the size of the data type, and thus usable to find the
7953 index of the builtin decl. */
7956 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
7957 tree addr
, tree loaded_val
, tree stored_val
,
7960 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
7961 tree type
, itype
, cmpxchg
, iaddr
;
7962 gimple_stmt_iterator si
;
7963 basic_block loop_header
= single_succ (load_bb
);
7966 enum built_in_function fncode
;
7968 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7969 order to use the RELAXED memory model effectively. */
7970 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7972 cmpxchg
= builtin_decl_explicit (fncode
);
7973 if (cmpxchg
== NULL_TREE
)
7975 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
7976 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
7978 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
7981 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7982 si
= gsi_last_bb (load_bb
);
7983 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7985 /* For floating-point values, we'll need to view-convert them to integers
7986 so that we can perform the atomic compare and swap. Simplify the
7987 following code by always setting up the "i"ntegral variables. */
7988 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
7992 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
7995 = force_gimple_operand_gsi (&si
,
7996 fold_convert (TREE_TYPE (iaddr
), addr
),
7997 false, NULL_TREE
, true, GSI_SAME_STMT
);
7998 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
7999 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8000 loadedi
= create_tmp_var (itype
, NULL
);
8001 if (gimple_in_ssa_p (cfun
))
8002 loadedi
= make_ssa_name (loadedi
, NULL
);
8007 loadedi
= loaded_val
;
8010 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8011 tree loaddecl
= builtin_decl_explicit (fncode
);
8014 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
8015 build_call_expr (loaddecl
, 2, iaddr
,
8016 build_int_cst (NULL_TREE
,
8017 MEMMODEL_RELAXED
)));
8019 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
8020 build_int_cst (TREE_TYPE (iaddr
), 0));
8023 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
8026 /* Move the value to the LOADEDI temporary. */
8027 if (gimple_in_ssa_p (cfun
))
8029 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
8030 phi
= create_phi_node (loadedi
, loop_header
);
8031 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
8035 gsi_insert_before (&si
,
8036 gimple_build_assign (loadedi
, initial
),
8038 if (loadedi
!= loaded_val
)
8040 gimple_stmt_iterator gsi2
;
8043 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
8044 gsi2
= gsi_start_bb (loop_header
);
8045 if (gimple_in_ssa_p (cfun
))
8048 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8049 true, GSI_SAME_STMT
);
8050 stmt
= gimple_build_assign (loaded_val
, x
);
8051 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
8055 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
8056 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8057 true, GSI_SAME_STMT
);
8060 gsi_remove (&si
, true);
8062 si
= gsi_last_bb (store_bb
);
8063 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8066 storedi
= stored_val
;
8069 force_gimple_operand_gsi (&si
,
8070 build1 (VIEW_CONVERT_EXPR
, itype
,
8071 stored_val
), true, NULL_TREE
, true,
8074 /* Build the compare&swap statement. */
8075 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
8076 new_storedi
= force_gimple_operand_gsi (&si
,
8077 fold_convert (TREE_TYPE (loadedi
),
8080 true, GSI_SAME_STMT
);
8082 if (gimple_in_ssa_p (cfun
))
8086 old_vali
= create_tmp_var (TREE_TYPE (loadedi
), NULL
);
8087 stmt
= gimple_build_assign (old_vali
, loadedi
);
8088 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8090 stmt
= gimple_build_assign (loadedi
, new_storedi
);
8091 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8094 /* Note that we always perform the comparison as an integer, even for
8095 floating point. This allows the atomic operation to properly
8096 succeed even with NaNs and -0.0. */
8097 stmt
= gimple_build_cond_empty
8098 (build2 (NE_EXPR
, boolean_type_node
,
8099 new_storedi
, old_vali
));
8100 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8103 e
= single_succ_edge (store_bb
);
8104 e
->flags
&= ~EDGE_FALLTHRU
;
8105 e
->flags
|= EDGE_FALSE_VALUE
;
8107 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
8109 /* Copy the new value to loadedi (we already did that before the condition
8110 if we are not in SSA). */
8111 if (gimple_in_ssa_p (cfun
))
8113 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
8114 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
8117 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8118 gsi_remove (&si
, true);
8120 struct loop
*loop
= alloc_loop ();
8121 loop
->header
= loop_header
;
8122 loop
->latch
= store_bb
;
8123 add_loop (loop
, loop_header
->loop_father
);
8125 if (gimple_in_ssa_p (cfun
))
8126 update_ssa (TODO_update_ssa_no_phi
);
8131 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8133 GOMP_atomic_start ();
8137 The result is not globally atomic, but works so long as all parallel
8138 references are within #pragma omp atomic directives. According to
8139 responses received from omp@openmp.org, appears to be within spec.
8140 Which makes sense, since that's how several other compilers handle
8141 this situation as well.
8142 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8143 expanding. STORED_VAL is the operand of the matching
8144 GIMPLE_OMP_ATOMIC_STORE.
8147 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8151 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8156 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
8157 tree addr
, tree loaded_val
, tree stored_val
)
8159 gimple_stmt_iterator si
;
8163 si
= gsi_last_bb (load_bb
);
8164 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8166 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
8167 t
= build_call_expr (t
, 0);
8168 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8170 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
8171 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8172 gsi_remove (&si
, true);
8174 si
= gsi_last_bb (store_bb
);
8175 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8177 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
8179 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8181 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
8182 t
= build_call_expr (t
, 0);
8183 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8184 gsi_remove (&si
, true);
8186 if (gimple_in_ssa_p (cfun
))
8187 update_ssa (TODO_update_ssa_no_phi
);
8191 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8192 using expand_omp_atomic_fetch_op. If it failed, we try to
8193 call expand_omp_atomic_pipeline, and if it fails too, the
8194 ultimate fallback is wrapping the operation in a mutex
8195 (expand_omp_atomic_mutex). REGION is the atomic region built
8196 by build_omp_regions_1(). */
8199 expand_omp_atomic (struct omp_region
*region
)
8201 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
8202 gimple load
= last_stmt (load_bb
), store
= last_stmt (store_bb
);
8203 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
8204 tree addr
= gimple_omp_atomic_load_rhs (load
);
8205 tree stored_val
= gimple_omp_atomic_store_val (store
);
8206 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8207 HOST_WIDE_INT index
;
8209 /* Make sure the type is one of the supported sizes. */
8210 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
8211 index
= exact_log2 (index
);
8212 if (index
>= 0 && index
<= 4)
8214 unsigned int align
= TYPE_ALIGN_UNIT (type
);
8216 /* __sync builtins require strict data alignment. */
8217 if (exact_log2 (align
) >= index
)
8220 if (loaded_val
== stored_val
8221 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8222 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8223 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8224 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
8228 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8229 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8230 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8231 && store_bb
== single_succ (load_bb
)
8232 && first_stmt (store_bb
) == store
8233 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
8237 /* When possible, use specialized atomic update functions. */
8238 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
8239 && store_bb
== single_succ (load_bb
)
8240 && expand_omp_atomic_fetch_op (load_bb
, addr
,
8241 loaded_val
, stored_val
, index
))
8244 /* If we don't have specialized __sync builtins, try and implement
8245 as a compare and swap loop. */
8246 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
8247 loaded_val
, stored_val
, index
))
8252 /* The ultimate fallback is wrapping the operation in a mutex. */
8253 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
8257 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8260 expand_omp_target (struct omp_region
*region
)
8262 basic_block entry_bb
, exit_bb
, new_bb
;
8263 struct function
*child_cfun
= NULL
;
8264 tree child_fn
= NULL_TREE
, block
, t
;
8265 gimple_stmt_iterator gsi
;
8266 gimple entry_stmt
, stmt
;
8269 entry_stmt
= last_stmt (region
->entry
);
8270 new_bb
= region
->entry
;
8271 int kind
= gimple_omp_target_kind (entry_stmt
);
8272 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8274 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
8275 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
8278 entry_bb
= region
->entry
;
8279 exit_bb
= region
->exit
;
8281 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8283 unsigned srcidx
, dstidx
, num
;
8285 /* If the target region needs data sent from the parent
8286 function, then the very first statement (except possible
8287 tree profile counter updates) of the parallel body
8288 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8289 &.OMP_DATA_O is passed as an argument to the child function,
8290 we need to replace it with the argument as seen by the child
8293 In most cases, this will end up being the identity assignment
8294 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8295 a function call that has been inlined, the original PARM_DECL
8296 .OMP_DATA_I may have been converted into a different local
8297 variable. In which case, we need to keep the assignment. */
8298 if (gimple_omp_target_data_arg (entry_stmt
))
8300 basic_block entry_succ_bb
= single_succ (entry_bb
);
8301 gimple_stmt_iterator gsi
;
8303 gimple tgtcopy_stmt
= NULL
;
8305 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt
), 0);
8307 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
8309 gcc_assert (!gsi_end_p (gsi
));
8310 stmt
= gsi_stmt (gsi
);
8311 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
8314 if (gimple_num_ops (stmt
) == 2)
8316 tree arg
= gimple_assign_rhs1 (stmt
);
8318 /* We're ignoring the subcode because we're
8319 effectively doing a STRIP_NOPS. */
8321 if (TREE_CODE (arg
) == ADDR_EXPR
8322 && TREE_OPERAND (arg
, 0) == sender
)
8324 tgtcopy_stmt
= stmt
;
8330 gcc_assert (tgtcopy_stmt
!= NULL
);
8331 arg
= DECL_ARGUMENTS (child_fn
);
8333 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
8334 gsi_remove (&gsi
, true);
8337 /* Declare local variables needed in CHILD_CFUN. */
8338 block
= DECL_INITIAL (child_fn
);
8339 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
8340 /* The gimplifier could record temporaries in target block
8341 rather than in containing function's local_decls chain,
8342 which would mean cgraph missed finalizing them. Do it now. */
8343 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
8344 if (TREE_CODE (t
) == VAR_DECL
8346 && !DECL_EXTERNAL (t
))
8347 varpool_node::finalize_decl (t
);
8348 DECL_SAVED_TREE (child_fn
) = NULL
;
8349 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8350 gimple_set_body (child_fn
, NULL
);
8351 TREE_USED (block
) = 1;
8353 /* Reset DECL_CONTEXT on function arguments. */
8354 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
8355 DECL_CONTEXT (t
) = child_fn
;
8357 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8358 so that it can be moved to the child function. */
8359 gsi
= gsi_last_bb (entry_bb
);
8360 stmt
= gsi_stmt (gsi
);
8361 gcc_assert (stmt
&& gimple_code (stmt
) == GIMPLE_OMP_TARGET
8362 && gimple_omp_target_kind (stmt
)
8363 == GF_OMP_TARGET_KIND_REGION
);
8364 gsi_remove (&gsi
, true);
8365 e
= split_block (entry_bb
, stmt
);
8367 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8369 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8372 gsi
= gsi_last_bb (exit_bb
);
8373 gcc_assert (!gsi_end_p (gsi
)
8374 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
8375 stmt
= gimple_build_return (NULL
);
8376 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
8377 gsi_remove (&gsi
, true);
8380 /* Move the target region into CHILD_CFUN. */
8382 block
= gimple_block (entry_stmt
);
8384 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
8386 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
8387 /* When the OMP expansion process cannot guarantee an up-to-date
8388 loop tree arrange for the child function to fixup loops. */
8389 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
8390 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
8392 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8393 num
= vec_safe_length (child_cfun
->local_decls
);
8394 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
8396 t
= (*child_cfun
->local_decls
)[srcidx
];
8397 if (DECL_CONTEXT (t
) == cfun
->decl
)
8399 if (srcidx
!= dstidx
)
8400 (*child_cfun
->local_decls
)[dstidx
] = t
;
8404 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
8406 /* Inform the callgraph about the new function. */
8407 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
8408 cgraph_node::add_new_function (child_fn
, true);
8410 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8411 fixed in a following pass. */
8412 push_cfun (child_cfun
);
8413 cgraph_edge::rebuild_edges ();
8415 /* Some EH regions might become dead, see PR34608. If
8416 pass_cleanup_cfg isn't the first pass to happen with the
8417 new child, these dead EH edges might cause problems.
8418 Clean them up now. */
8419 if (flag_exceptions
)
8422 bool changed
= false;
8424 FOR_EACH_BB_FN (bb
, cfun
)
8425 changed
|= gimple_purge_dead_eh_edges (bb
);
8427 cleanup_tree_cfg ();
8432 /* Emit a library call to launch the target region, or do data
8434 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
8435 enum built_in_function start_ix
;
8436 location_t clause_loc
;
8438 clauses
= gimple_omp_target_clauses (entry_stmt
);
8440 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8441 start_ix
= BUILT_IN_GOMP_TARGET
;
8442 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
8443 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
8445 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
8447 /* By default, the value of DEVICE is -1 (let runtime library choose)
8448 and there is no conditional. */
8450 device
= build_int_cst (integer_type_node
, -1);
8452 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
8454 cond
= OMP_CLAUSE_IF_EXPR (c
);
8456 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
8459 device
= OMP_CLAUSE_DEVICE_ID (c
);
8460 clause_loc
= OMP_CLAUSE_LOCATION (c
);
8463 clause_loc
= gimple_location (entry_stmt
);
8465 /* Ensure 'device' is of the correct type. */
8466 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
8468 /* If we found the clause 'if (cond)', build
8469 (cond ? device : -2). */
8472 cond
= gimple_boolify (cond
);
8474 basic_block cond_bb
, then_bb
, else_bb
;
8478 tmp_var
= create_tmp_var (TREE_TYPE (device
), NULL
);
8479 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8481 gsi
= gsi_last_bb (new_bb
);
8483 e
= split_block (new_bb
, gsi_stmt (gsi
));
8486 e
= split_block (new_bb
, NULL
);
8491 then_bb
= create_empty_bb (cond_bb
);
8492 else_bb
= create_empty_bb (then_bb
);
8493 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
8494 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
8496 stmt
= gimple_build_cond_empty (cond
);
8497 gsi
= gsi_last_bb (cond_bb
);
8498 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8500 gsi
= gsi_start_bb (then_bb
);
8501 stmt
= gimple_build_assign (tmp_var
, device
);
8502 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8504 gsi
= gsi_start_bb (else_bb
);
8505 stmt
= gimple_build_assign (tmp_var
,
8506 build_int_cst (integer_type_node
, -2));
8507 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8509 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
8510 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
8511 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
8512 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
8513 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
8514 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
8519 gsi
= gsi_last_bb (new_bb
);
8520 t
= gimple_omp_target_data_arg (entry_stmt
);
8523 t1
= size_zero_node
;
8524 t2
= build_zero_cst (ptr_type_node
);
8530 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
8531 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
8532 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
8533 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
8534 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
8538 /* FIXME: This will be address of
8539 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8540 symbol, as soon as the linker plugin is able to create it for us. */
8541 tree openmp_target
= build_zero_cst (ptr_type_node
);
8542 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8544 tree fnaddr
= build_fold_addr_expr (child_fn
);
8545 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 7,
8546 device
, fnaddr
, openmp_target
, t1
, t2
, t3
, t4
);
8549 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 6,
8550 device
, openmp_target
, t1
, t2
, t3
, t4
);
8551 gimple_set_location (g
, gimple_location (entry_stmt
));
8552 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
8553 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8556 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
8557 gsi_remove (&gsi
, true);
8559 if (kind
== GF_OMP_TARGET_KIND_DATA
&& region
->exit
)
8561 gsi
= gsi_last_bb (region
->exit
);
8563 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
8564 gsi_remove (&gsi
, true);
8569 /* Expand the parallel region tree rooted at REGION. Expansion
8570 proceeds in depth-first order. Innermost regions are expanded
8571 first. This way, parallel regions that require a new function to
8572 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8573 internal dependencies in their body. */
8576 expand_omp (struct omp_region
*region
)
8580 location_t saved_location
;
8581 gimple inner_stmt
= NULL
;
8583 /* First, determine whether this is a combined parallel+workshare
8585 if (region
->type
== GIMPLE_OMP_PARALLEL
)
8586 determine_parallel_type (region
);
8588 if (region
->type
== GIMPLE_OMP_FOR
8589 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
8590 inner_stmt
= last_stmt (region
->inner
->entry
);
8593 expand_omp (region
->inner
);
8595 saved_location
= input_location
;
8596 if (gimple_has_location (last_stmt (region
->entry
)))
8597 input_location
= gimple_location (last_stmt (region
->entry
));
8599 switch (region
->type
)
8601 case GIMPLE_OMP_PARALLEL
:
8602 case GIMPLE_OMP_TASK
:
8603 expand_omp_taskreg (region
);
8606 case GIMPLE_OMP_FOR
:
8607 expand_omp_for (region
, inner_stmt
);
8610 case GIMPLE_OMP_SECTIONS
:
8611 expand_omp_sections (region
);
8614 case GIMPLE_OMP_SECTION
:
8615 /* Individual omp sections are handled together with their
8616 parent GIMPLE_OMP_SECTIONS region. */
8619 case GIMPLE_OMP_SINGLE
:
8620 expand_omp_single (region
);
8623 case GIMPLE_OMP_MASTER
:
8624 case GIMPLE_OMP_TASKGROUP
:
8625 case GIMPLE_OMP_ORDERED
:
8626 case GIMPLE_OMP_CRITICAL
:
8627 case GIMPLE_OMP_TEAMS
:
8628 expand_omp_synch (region
);
8631 case GIMPLE_OMP_ATOMIC_LOAD
:
8632 expand_omp_atomic (region
);
8635 case GIMPLE_OMP_TARGET
:
8636 expand_omp_target (region
);
8643 input_location
= saved_location
;
8644 region
= region
->next
;
8649 /* Helper for build_omp_regions. Scan the dominator tree starting at
8650 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8651 true, the function ends once a single tree is built (otherwise, whole
8652 forest of OMP constructs may be built). */
8655 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
8658 gimple_stmt_iterator gsi
;
8662 gsi
= gsi_last_bb (bb
);
8663 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
8665 struct omp_region
*region
;
8666 enum gimple_code code
;
8668 stmt
= gsi_stmt (gsi
);
8669 code
= gimple_code (stmt
);
8670 if (code
== GIMPLE_OMP_RETURN
)
8672 /* STMT is the return point out of region PARENT. Mark it
8673 as the exit point and make PARENT the immediately
8674 enclosing region. */
8675 gcc_assert (parent
);
8678 parent
= parent
->outer
;
8680 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
8682 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8683 GIMPLE_OMP_RETURN, but matches with
8684 GIMPLE_OMP_ATOMIC_LOAD. */
8685 gcc_assert (parent
);
8686 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
8689 parent
= parent
->outer
;
8692 else if (code
== GIMPLE_OMP_CONTINUE
)
8694 gcc_assert (parent
);
8697 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
8699 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8700 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8703 else if (code
== GIMPLE_OMP_TARGET
8704 && gimple_omp_target_kind (stmt
) == GF_OMP_TARGET_KIND_UPDATE
)
8705 new_omp_region (bb
, code
, parent
);
8708 /* Otherwise, this directive becomes the parent for a new
8710 region
= new_omp_region (bb
, code
, parent
);
8715 if (single_tree
&& !parent
)
8718 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
8720 son
= next_dom_son (CDI_DOMINATORS
, son
))
8721 build_omp_regions_1 (son
, parent
, single_tree
);
8724 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8728 build_omp_regions_root (basic_block root
)
8730 gcc_assert (root_omp_region
== NULL
);
8731 build_omp_regions_1 (root
, NULL
, true);
8732 gcc_assert (root_omp_region
!= NULL
);
8735 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8738 omp_expand_local (basic_block head
)
8740 build_omp_regions_root (head
);
8741 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
8743 fprintf (dump_file
, "\nOMP region tree\n\n");
8744 dump_omp_region (dump_file
, root_omp_region
, 0);
8745 fprintf (dump_file
, "\n");
8748 remove_exit_barriers (root_omp_region
);
8749 expand_omp (root_omp_region
);
8751 free_omp_regions ();
8754 /* Scan the CFG and build a tree of OMP regions. Return the root of
8755 the OMP region tree. */
8758 build_omp_regions (void)
8760 gcc_assert (root_omp_region
== NULL
);
8761 calculate_dominance_info (CDI_DOMINATORS
);
8762 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
8765 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8768 execute_expand_omp (void)
8770 build_omp_regions ();
8772 if (!root_omp_region
)
8777 fprintf (dump_file
, "\nOMP region tree\n\n");
8778 dump_omp_region (dump_file
, root_omp_region
, 0);
8779 fprintf (dump_file
, "\n");
8782 remove_exit_barriers (root_omp_region
);
8784 expand_omp (root_omp_region
);
8786 cleanup_tree_cfg ();
8788 free_omp_regions ();
8793 /* OMP expansion -- the default pass, run before creation of SSA form. */
8797 const pass_data pass_data_expand_omp
=
8799 GIMPLE_PASS
, /* type */
8800 "ompexp", /* name */
8801 OPTGROUP_NONE
, /* optinfo_flags */
8802 TV_NONE
, /* tv_id */
8803 PROP_gimple_any
, /* properties_required */
8804 0, /* properties_provided */
8805 0, /* properties_destroyed */
8806 0, /* todo_flags_start */
8807 0, /* todo_flags_finish */
8810 class pass_expand_omp
: public gimple_opt_pass
8813 pass_expand_omp (gcc::context
*ctxt
)
8814 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
8817 /* opt_pass methods: */
8818 virtual bool gate (function
*)
8820 return ((flag_openmp
!= 0 || flag_openmp_simd
!= 0
8821 || flag_cilkplus
!= 0) && !seen_error ());
8824 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
8826 }; // class pass_expand_omp
8831 make_pass_expand_omp (gcc::context
*ctxt
)
8833 return new pass_expand_omp (ctxt
);
8836 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8838 /* If ctx is a worksharing context inside of a cancellable parallel
8839 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8840 and conditional branch to parallel's cancel_label to handle
8841 cancellation in the implicit barrier. */
8844 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
8846 gimple omp_return
= gimple_seq_last_stmt (*body
);
8847 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
8848 if (gimple_omp_return_nowait_p (omp_return
))
8851 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
8852 && ctx
->outer
->cancellable
)
8854 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
8855 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
8856 tree lhs
= create_tmp_var (c_bool_type
, NULL
);
8857 gimple_omp_return_set_lhs (omp_return
, lhs
);
8858 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
8859 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
8860 fold_convert (c_bool_type
,
8861 boolean_false_node
),
8862 ctx
->outer
->cancel_label
, fallthru_label
);
8863 gimple_seq_add_stmt (body
, g
);
8864 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
8868 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8869 CTX is the enclosing OMP context for the current statement. */
8872 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8874 tree block
, control
;
8875 gimple_stmt_iterator tgsi
;
8876 gimple stmt
, new_stmt
, bind
, t
;
8877 gimple_seq ilist
, dlist
, olist
, new_body
;
8879 stmt
= gsi_stmt (*gsi_p
);
8881 push_gimplify_context ();
8885 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
8886 &ilist
, &dlist
, ctx
, NULL
);
8888 new_body
= gimple_omp_body (stmt
);
8889 gimple_omp_set_body (stmt
, NULL
);
8890 tgsi
= gsi_start (new_body
);
8891 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
8896 sec_start
= gsi_stmt (tgsi
);
8897 sctx
= maybe_lookup_ctx (sec_start
);
8900 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
8901 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
8902 GSI_CONTINUE_LINKING
);
8903 gimple_omp_set_body (sec_start
, NULL
);
8905 if (gsi_one_before_end_p (tgsi
))
8907 gimple_seq l
= NULL
;
8908 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
8910 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
8911 gimple_omp_section_set_last (sec_start
);
8914 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
8915 GSI_CONTINUE_LINKING
);
8918 block
= make_node (BLOCK
);
8919 bind
= gimple_build_bind (NULL
, new_body
, block
);
8922 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
8924 block
= make_node (BLOCK
);
8925 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
8926 gsi_replace (gsi_p
, new_stmt
, true);
8928 pop_gimplify_context (new_stmt
);
8929 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
8930 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8931 if (BLOCK_VARS (block
))
8932 TREE_USED (block
) = 1;
8935 gimple_seq_add_seq (&new_body
, ilist
);
8936 gimple_seq_add_stmt (&new_body
, stmt
);
8937 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
8938 gimple_seq_add_stmt (&new_body
, bind
);
8940 control
= create_tmp_var (unsigned_type_node
, ".section");
8941 t
= gimple_build_omp_continue (control
, control
);
8942 gimple_omp_sections_set_control (stmt
, control
);
8943 gimple_seq_add_stmt (&new_body
, t
);
8945 gimple_seq_add_seq (&new_body
, olist
);
8946 if (ctx
->cancellable
)
8947 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
8948 gimple_seq_add_seq (&new_body
, dlist
);
8950 new_body
= maybe_catch_exception (new_body
);
8952 t
= gimple_build_omp_return
8953 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
8954 OMP_CLAUSE_NOWAIT
));
8955 gimple_seq_add_stmt (&new_body
, t
);
8956 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
8958 gimple_bind_set_body (new_stmt
, new_body
);
8962 /* A subroutine of lower_omp_single. Expand the simple form of
8963 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8965 if (GOMP_single_start ())
8967 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8969 FIXME. It may be better to delay expanding the logic of this until
8970 pass_expand_omp. The expanded logic may make the job more difficult
8971 to a synchronization analysis pass. */
8974 lower_omp_single_simple (gimple single_stmt
, gimple_seq
*pre_p
)
8976 location_t loc
= gimple_location (single_stmt
);
8977 tree tlabel
= create_artificial_label (loc
);
8978 tree flabel
= create_artificial_label (loc
);
8982 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
8983 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)), NULL
);
8984 call
= gimple_build_call (decl
, 0);
8985 gimple_call_set_lhs (call
, lhs
);
8986 gimple_seq_add_stmt (pre_p
, call
);
8988 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
8989 fold_convert_loc (loc
, TREE_TYPE (lhs
),
8992 gimple_seq_add_stmt (pre_p
, cond
);
8993 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
8994 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
8995 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
8999 /* A subroutine of lower_omp_single. Expand the simple form of
9000 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9002 #pragma omp single copyprivate (a, b, c)
9004 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9007 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9013 GOMP_single_copy_end (©out);
9024 FIXME. It may be better to delay expanding the logic of this until
9025 pass_expand_omp. The expanded logic may make the job more difficult
9026 to a synchronization analysis pass. */
9029 lower_omp_single_copy (gimple single_stmt
, gimple_seq
*pre_p
, omp_context
*ctx
)
9031 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
9032 gimple_seq copyin_seq
;
9033 location_t loc
= gimple_location (single_stmt
);
9035 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
9037 ptr_type
= build_pointer_type (ctx
->record_type
);
9038 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
9040 l0
= create_artificial_label (loc
);
9041 l1
= create_artificial_label (loc
);
9042 l2
= create_artificial_label (loc
);
9044 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
9045 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
9046 t
= fold_convert_loc (loc
, ptr_type
, t
);
9047 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
9049 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
9050 build_int_cst (ptr_type
, 0));
9051 t
= build3 (COND_EXPR
, void_type_node
, t
,
9052 build_and_jump (&l0
), build_and_jump (&l1
));
9053 gimplify_and_add (t
, pre_p
);
9055 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
9057 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
9060 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
9063 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9064 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
9065 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
9066 gimplify_and_add (t
, pre_p
);
9068 t
= build_and_jump (&l2
);
9069 gimplify_and_add (t
, pre_p
);
9071 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
9073 gimple_seq_add_seq (pre_p
, copyin_seq
);
9075 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
9079 /* Expand code for an OpenMP single directive. */
9082 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9085 gimple t
, bind
, single_stmt
= gsi_stmt (*gsi_p
);
9086 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
9088 push_gimplify_context ();
9090 block
= make_node (BLOCK
);
9091 bind
= gimple_build_bind (NULL
, NULL
, block
);
9092 gsi_replace (gsi_p
, bind
, true);
9095 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
9096 &bind_body
, &dlist
, ctx
, NULL
);
9097 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
9099 gimple_seq_add_stmt (&bind_body
, single_stmt
);
9101 if (ctx
->record_type
)
9102 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
9104 lower_omp_single_simple (single_stmt
, &bind_body
);
9106 gimple_omp_set_body (single_stmt
, NULL
);
9108 gimple_seq_add_seq (&bind_body
, dlist
);
9110 bind_body
= maybe_catch_exception (bind_body
);
9112 t
= gimple_build_omp_return
9113 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
9114 OMP_CLAUSE_NOWAIT
));
9115 gimple_seq_add_stmt (&bind_body_tail
, t
);
9116 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
9117 if (ctx
->record_type
)
9119 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
9120 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
9121 TREE_THIS_VOLATILE (clobber
) = 1;
9122 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
9123 clobber
), GSI_SAME_STMT
);
9125 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
9126 gimple_bind_set_body (bind
, bind_body
);
9128 pop_gimplify_context (bind
);
9130 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9131 BLOCK_VARS (block
) = ctx
->block_vars
;
9132 if (BLOCK_VARS (block
))
9133 TREE_USED (block
) = 1;
9137 /* Expand code for an OpenMP master directive. */
9140 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9142 tree block
, lab
= NULL
, x
, bfn_decl
;
9143 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
9144 location_t loc
= gimple_location (stmt
);
9147 push_gimplify_context ();
9149 block
= make_node (BLOCK
);
9150 bind
= gimple_build_bind (NULL
, NULL
, block
);
9151 gsi_replace (gsi_p
, bind
, true);
9152 gimple_bind_add_stmt (bind
, stmt
);
9154 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
9155 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
9156 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
9157 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
9159 gimplify_and_add (x
, &tseq
);
9160 gimple_bind_add_seq (bind
, tseq
);
9162 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9163 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9164 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9165 gimple_omp_set_body (stmt
, NULL
);
9167 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
9169 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9171 pop_gimplify_context (bind
);
9173 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9174 BLOCK_VARS (block
) = ctx
->block_vars
;
9178 /* Expand code for an OpenMP taskgroup directive. */
9181 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9183 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
9184 tree block
= make_node (BLOCK
);
9186 bind
= gimple_build_bind (NULL
, NULL
, block
);
9187 gsi_replace (gsi_p
, bind
, true);
9188 gimple_bind_add_stmt (bind
, stmt
);
9190 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
9192 gimple_bind_add_stmt (bind
, x
);
9194 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9195 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9196 gimple_omp_set_body (stmt
, NULL
);
9198 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9200 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9201 BLOCK_VARS (block
) = ctx
->block_vars
;
9205 /* Expand code for an OpenMP ordered directive. */
9208 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9211 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
9213 push_gimplify_context ();
9215 block
= make_node (BLOCK
);
9216 bind
= gimple_build_bind (NULL
, NULL
, block
);
9217 gsi_replace (gsi_p
, bind
, true);
9218 gimple_bind_add_stmt (bind
, stmt
);
9220 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
9222 gimple_bind_add_stmt (bind
, x
);
9224 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9225 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9226 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9227 gimple_omp_set_body (stmt
, NULL
);
9229 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
9230 gimple_bind_add_stmt (bind
, x
);
9232 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9234 pop_gimplify_context (bind
);
9236 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9237 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
9241 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9242 substitution of a couple of function calls. But in the NAMED case,
9243 requires that languages coordinate a symbol name. It is therefore
9244 best put here in common code. */
9246 static GTY((param1_is (tree
), param2_is (tree
)))
9247 splay_tree critical_name_mutexes
;
9250 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9253 tree name
, lock
, unlock
;
9254 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
9255 location_t loc
= gimple_location (stmt
);
9258 name
= gimple_omp_critical_name (stmt
);
9264 if (!critical_name_mutexes
)
9265 critical_name_mutexes
9266 = splay_tree_new_ggc (splay_tree_compare_pointers
,
9267 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s
,
9268 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s
);
9270 n
= splay_tree_lookup (critical_name_mutexes
, (splay_tree_key
) name
);
9275 decl
= create_tmp_var_raw (ptr_type_node
, NULL
);
9277 new_str
= ACONCAT ((".gomp_critical_user_",
9278 IDENTIFIER_POINTER (name
), NULL
));
9279 DECL_NAME (decl
) = get_identifier (new_str
);
9280 TREE_PUBLIC (decl
) = 1;
9281 TREE_STATIC (decl
) = 1;
9282 DECL_COMMON (decl
) = 1;
9283 DECL_ARTIFICIAL (decl
) = 1;
9284 DECL_IGNORED_P (decl
) = 1;
9285 varpool_node::finalize_decl (decl
);
9287 splay_tree_insert (critical_name_mutexes
, (splay_tree_key
) name
,
9288 (splay_tree_value
) decl
);
9291 decl
= (tree
) n
->value
;
9293 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
9294 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
9296 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
9297 unlock
= build_call_expr_loc (loc
, unlock
, 1,
9298 build_fold_addr_expr_loc (loc
, decl
));
9302 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
9303 lock
= build_call_expr_loc (loc
, lock
, 0);
9305 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
9306 unlock
= build_call_expr_loc (loc
, unlock
, 0);
9309 push_gimplify_context ();
9311 block
= make_node (BLOCK
);
9312 bind
= gimple_build_bind (NULL
, NULL
, block
);
9313 gsi_replace (gsi_p
, bind
, true);
9314 gimple_bind_add_stmt (bind
, stmt
);
9316 tbody
= gimple_bind_body (bind
);
9317 gimplify_and_add (lock
, &tbody
);
9318 gimple_bind_set_body (bind
, tbody
);
9320 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9321 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9322 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9323 gimple_omp_set_body (stmt
, NULL
);
9325 tbody
= gimple_bind_body (bind
);
9326 gimplify_and_add (unlock
, &tbody
);
9327 gimple_bind_set_body (bind
, tbody
);
9329 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9331 pop_gimplify_context (bind
);
9332 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9333 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
9337 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9338 for a lastprivate clause. Given a loop control predicate of (V
9339 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9340 is appended to *DLIST, iterator initialization is appended to
9344 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
9345 gimple_seq
*dlist
, struct omp_context
*ctx
)
9347 tree clauses
, cond
, vinit
;
9348 enum tree_code cond_code
;
9351 cond_code
= fd
->loop
.cond_code
;
9352 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
9354 /* When possible, use a strict equality expression. This can let VRP
9355 type optimizations deduce the value and remove a copy. */
9356 if (tree_fits_shwi_p (fd
->loop
.step
))
9358 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
9359 if (step
== 1 || step
== -1)
9360 cond_code
= EQ_EXPR
;
9363 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, fd
->loop
.n2
);
9365 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
9367 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
9368 if (!gimple_seq_empty_p (stmts
))
9370 gimple_seq_add_seq (&stmts
, *dlist
);
9373 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9374 vinit
= fd
->loop
.n1
;
9375 if (cond_code
== EQ_EXPR
9376 && tree_fits_shwi_p (fd
->loop
.n2
)
9377 && ! integer_zerop (fd
->loop
.n2
))
9378 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
9380 vinit
= unshare_expr (vinit
);
9382 /* Initialize the iterator variable, so that threads that don't execute
9383 any iterations don't execute the lastprivate clauses by accident. */
9384 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
9389 /* Lower code for an OpenMP loop directive. */
9392 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9395 struct omp_for_data fd
, *fdp
= NULL
;
9396 gimple stmt
= gsi_stmt (*gsi_p
), new_stmt
;
9397 gimple_seq omp_for_body
, body
, dlist
;
9400 push_gimplify_context ();
9402 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
9404 block
= make_node (BLOCK
);
9405 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
9406 /* Replace at gsi right away, so that 'stmt' is no member
9407 of a sequence anymore as we're going to add to to a different
9409 gsi_replace (gsi_p
, new_stmt
, true);
9411 /* Move declaration of temporaries in the loop body before we make
9413 omp_for_body
= gimple_omp_body (stmt
);
9414 if (!gimple_seq_empty_p (omp_for_body
)
9415 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
9417 gimple inner_bind
= gimple_seq_first_stmt (omp_for_body
);
9418 tree vars
= gimple_bind_vars (inner_bind
);
9419 gimple_bind_append_vars (new_stmt
, vars
);
9420 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9421 keep them on the inner_bind and it's block. */
9422 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
9423 if (gimple_bind_block (inner_bind
))
9424 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
9427 if (gimple_omp_for_combined_into_p (stmt
))
9429 extract_omp_for_data (stmt
, &fd
, NULL
);
9432 /* We need two temporaries with fd.loop.v type (istart/iend)
9433 and then (fd.collapse - 1) temporaries with the same
9434 type for count2 ... countN-1 vars if not constant. */
9436 tree type
= fd
.iter_type
;
9438 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
9439 count
+= fd
.collapse
- 1;
9440 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
9441 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
9445 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
9446 OMP_CLAUSE__LOOPTEMP_
);
9447 for (i
= 0; i
< count
; i
++)
9452 gcc_assert (outerc
);
9453 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
9454 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
9455 OMP_CLAUSE__LOOPTEMP_
);
9459 temp
= create_tmp_var (type
, NULL
);
9460 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
9462 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
9463 OMP_CLAUSE_DECL (*pc
) = temp
;
9464 pc
= &OMP_CLAUSE_CHAIN (*pc
);
9469 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9472 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
9474 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
9476 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9478 /* Lower the header expressions. At this point, we can assume that
9479 the header is of the form:
9481 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9483 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9484 using the .omp_data_s mapping, if needed. */
9485 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
9487 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
9488 if (!is_gimple_min_invariant (*rhs_p
))
9489 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9491 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
9492 if (!is_gimple_min_invariant (*rhs_p
))
9493 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9495 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
9496 if (!is_gimple_min_invariant (*rhs_p
))
9497 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9500 /* Once lowered, extract the bounds and clauses. */
9501 extract_omp_for_data (stmt
, &fd
, NULL
);
9503 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
9505 gimple_seq_add_stmt (&body
, stmt
);
9506 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
9508 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
9511 /* After the loop, add exit clauses. */
9512 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
9514 if (ctx
->cancellable
)
9515 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
9517 gimple_seq_add_seq (&body
, dlist
);
9519 body
= maybe_catch_exception (body
);
9521 /* Region exit marker goes at the end of the loop body. */
9522 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
9523 maybe_add_implicit_barrier_cancel (ctx
, &body
);
9524 pop_gimplify_context (new_stmt
);
9526 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
9527 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
9528 if (BLOCK_VARS (block
))
9529 TREE_USED (block
) = 1;
9531 gimple_bind_set_body (new_stmt
, body
);
9532 gimple_omp_set_body (stmt
, NULL
);
9533 gimple_omp_for_set_pre_body (stmt
, NULL
);
9536 /* Callback for walk_stmts. Check if the current statement only contains
9537 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9540 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
9541 bool *handled_ops_p
,
9542 struct walk_stmt_info
*wi
)
9544 int *info
= (int *) wi
->info
;
9545 gimple stmt
= gsi_stmt (*gsi_p
);
9547 *handled_ops_p
= true;
9548 switch (gimple_code (stmt
))
9552 case GIMPLE_OMP_FOR
:
9553 case GIMPLE_OMP_SECTIONS
:
9554 *info
= *info
== 0 ? 1 : -1;
9563 struct omp_taskcopy_context
9565 /* This field must be at the beginning, as we do "inheritance": Some
9566 callback functions for tree-inline.c (e.g., omp_copy_decl)
9567 receive a copy_body_data pointer that is up-casted to an
9568 omp_context pointer. */
9574 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
9576 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
9578 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
9579 return create_tmp_var (TREE_TYPE (var
), NULL
);
9585 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
9587 tree name
, new_fields
= NULL
, type
, f
;
9589 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
9590 name
= DECL_NAME (TYPE_NAME (orig_type
));
9591 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
9592 TYPE_DECL
, name
, type
);
9593 TYPE_NAME (type
) = name
;
9595 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
9597 tree new_f
= copy_node (f
);
9598 DECL_CONTEXT (new_f
) = type
;
9599 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
9600 TREE_CHAIN (new_f
) = new_fields
;
9601 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9602 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9603 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
9606 tcctx
->cb
.decl_map
->put (f
, new_f
);
9608 TYPE_FIELDS (type
) = nreverse (new_fields
);
9613 /* Create task copyfn. */
9616 create_task_copyfn (gimple task_stmt
, omp_context
*ctx
)
9618 struct function
*child_cfun
;
9619 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
9620 tree record_type
, srecord_type
, bind
, list
;
9621 bool record_needs_remap
= false, srecord_needs_remap
= false;
9623 struct omp_taskcopy_context tcctx
;
9624 location_t loc
= gimple_location (task_stmt
);
9626 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
9627 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
9628 gcc_assert (child_cfun
->cfg
== NULL
);
9629 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
9631 /* Reset DECL_CONTEXT on function arguments. */
9632 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
9633 DECL_CONTEXT (t
) = child_fn
;
9635 /* Populate the function. */
9636 push_gimplify_context ();
9637 push_cfun (child_cfun
);
9639 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
9640 TREE_SIDE_EFFECTS (bind
) = 1;
9642 DECL_SAVED_TREE (child_fn
) = bind
;
9643 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
9645 /* Remap src and dst argument types if needed. */
9646 record_type
= ctx
->record_type
;
9647 srecord_type
= ctx
->srecord_type
;
9648 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
9649 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9651 record_needs_remap
= true;
9654 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
9655 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9657 srecord_needs_remap
= true;
9661 if (record_needs_remap
|| srecord_needs_remap
)
9663 memset (&tcctx
, '\0', sizeof (tcctx
));
9664 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
9665 tcctx
.cb
.dst_fn
= child_fn
;
9666 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
9667 gcc_checking_assert (tcctx
.cb
.src_node
);
9668 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
9669 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
9670 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
9671 tcctx
.cb
.eh_lp_nr
= 0;
9672 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
9673 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
9676 if (record_needs_remap
)
9677 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
9678 if (srecord_needs_remap
)
9679 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
9682 tcctx
.cb
.decl_map
= NULL
;
9684 arg
= DECL_ARGUMENTS (child_fn
);
9685 TREE_TYPE (arg
) = build_pointer_type (record_type
);
9686 sarg
= DECL_CHAIN (arg
);
9687 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
9689 /* First pass: initialize temporaries used in record_type and srecord_type
9690 sizes and field offsets. */
9691 if (tcctx
.cb
.decl_map
)
9692 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9693 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9697 decl
= OMP_CLAUSE_DECL (c
);
9698 p
= tcctx
.cb
.decl_map
->get (decl
);
9701 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9702 sf
= (tree
) n
->value
;
9703 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9704 src
= build_simple_mem_ref_loc (loc
, sarg
);
9705 src
= omp_build_component_ref (src
, sf
);
9706 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
9707 append_to_statement_list (t
, &list
);
9710 /* Second pass: copy shared var pointers and copy construct non-VLA
9711 firstprivate vars. */
9712 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9713 switch (OMP_CLAUSE_CODE (c
))
9715 case OMP_CLAUSE_SHARED
:
9716 decl
= OMP_CLAUSE_DECL (c
);
9717 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9720 f
= (tree
) n
->value
;
9721 if (tcctx
.cb
.decl_map
)
9722 f
= *tcctx
.cb
.decl_map
->get (f
);
9723 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9724 sf
= (tree
) n
->value
;
9725 if (tcctx
.cb
.decl_map
)
9726 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9727 src
= build_simple_mem_ref_loc (loc
, sarg
);
9728 src
= omp_build_component_ref (src
, sf
);
9729 dst
= build_simple_mem_ref_loc (loc
, arg
);
9730 dst
= omp_build_component_ref (dst
, f
);
9731 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9732 append_to_statement_list (t
, &list
);
9734 case OMP_CLAUSE_FIRSTPRIVATE
:
9735 decl
= OMP_CLAUSE_DECL (c
);
9736 if (is_variable_sized (decl
))
9738 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9741 f
= (tree
) n
->value
;
9742 if (tcctx
.cb
.decl_map
)
9743 f
= *tcctx
.cb
.decl_map
->get (f
);
9744 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9747 sf
= (tree
) n
->value
;
9748 if (tcctx
.cb
.decl_map
)
9749 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9750 src
= build_simple_mem_ref_loc (loc
, sarg
);
9751 src
= omp_build_component_ref (src
, sf
);
9752 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
9753 src
= build_simple_mem_ref_loc (loc
, src
);
9757 dst
= build_simple_mem_ref_loc (loc
, arg
);
9758 dst
= omp_build_component_ref (dst
, f
);
9759 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9760 append_to_statement_list (t
, &list
);
9762 case OMP_CLAUSE_PRIVATE
:
9763 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
9765 decl
= OMP_CLAUSE_DECL (c
);
9766 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9767 f
= (tree
) n
->value
;
9768 if (tcctx
.cb
.decl_map
)
9769 f
= *tcctx
.cb
.decl_map
->get (f
);
9770 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9773 sf
= (tree
) n
->value
;
9774 if (tcctx
.cb
.decl_map
)
9775 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9776 src
= build_simple_mem_ref_loc (loc
, sarg
);
9777 src
= omp_build_component_ref (src
, sf
);
9778 if (use_pointer_for_field (decl
, NULL
))
9779 src
= build_simple_mem_ref_loc (loc
, src
);
9783 dst
= build_simple_mem_ref_loc (loc
, arg
);
9784 dst
= omp_build_component_ref (dst
, f
);
9785 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9786 append_to_statement_list (t
, &list
);
9792 /* Last pass: handle VLA firstprivates. */
9793 if (tcctx
.cb
.decl_map
)
9794 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9795 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9799 decl
= OMP_CLAUSE_DECL (c
);
9800 if (!is_variable_sized (decl
))
9802 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9805 f
= (tree
) n
->value
;
9806 f
= *tcctx
.cb
.decl_map
->get (f
);
9807 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
9808 ind
= DECL_VALUE_EXPR (decl
);
9809 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
9810 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
9811 n
= splay_tree_lookup (ctx
->sfield_map
,
9812 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9813 sf
= (tree
) n
->value
;
9814 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9815 src
= build_simple_mem_ref_loc (loc
, sarg
);
9816 src
= omp_build_component_ref (src
, sf
);
9817 src
= build_simple_mem_ref_loc (loc
, src
);
9818 dst
= build_simple_mem_ref_loc (loc
, arg
);
9819 dst
= omp_build_component_ref (dst
, f
);
9820 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9821 append_to_statement_list (t
, &list
);
9822 n
= splay_tree_lookup (ctx
->field_map
,
9823 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9824 df
= (tree
) n
->value
;
9825 df
= *tcctx
.cb
.decl_map
->get (df
);
9826 ptr
= build_simple_mem_ref_loc (loc
, arg
);
9827 ptr
= omp_build_component_ref (ptr
, df
);
9828 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
9829 build_fold_addr_expr_loc (loc
, dst
));
9830 append_to_statement_list (t
, &list
);
9833 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
9834 append_to_statement_list (t
, &list
);
9836 if (tcctx
.cb
.decl_map
)
9837 delete tcctx
.cb
.decl_map
;
9838 pop_gimplify_context (NULL
);
9839 BIND_EXPR_BODY (bind
) = list
;
9844 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
9848 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
9850 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
9852 gcc_assert (clauses
);
9853 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9854 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
9855 switch (OMP_CLAUSE_DEPEND_KIND (c
))
9857 case OMP_CLAUSE_DEPEND_IN
:
9860 case OMP_CLAUSE_DEPEND_OUT
:
9861 case OMP_CLAUSE_DEPEND_INOUT
:
9867 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
9868 tree array
= create_tmp_var (type
, NULL
);
9869 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
9871 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
9872 gimple_seq_add_stmt (iseq
, g
);
9873 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
9875 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
9876 gimple_seq_add_stmt (iseq
, g
);
9877 for (i
= 0; i
< 2; i
++)
9879 if ((i
? n_in
: n_out
) == 0)
9881 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9882 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
9883 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
9885 tree t
= OMP_CLAUSE_DECL (c
);
9886 t
= fold_convert (ptr_type_node
, t
);
9887 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
9888 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
9889 NULL_TREE
, NULL_TREE
);
9890 g
= gimple_build_assign (r
, t
);
9891 gimple_seq_add_stmt (iseq
, g
);
9894 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
9895 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
9896 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
9897 OMP_CLAUSE_CHAIN (c
) = *p
;
9899 tree clobber
= build_constructor (type
, NULL
);
9900 TREE_THIS_VOLATILE (clobber
) = 1;
9901 g
= gimple_build_assign (array
, clobber
);
9902 gimple_seq_add_stmt (oseq
, g
);
9905 /* Lower the OpenMP parallel or task directive in the current statement
9906 in GSI_P. CTX holds context information for the directive. */
9909 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9913 gimple stmt
= gsi_stmt (*gsi_p
);
9914 gimple par_bind
, bind
, dep_bind
= NULL
;
9915 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
9916 location_t loc
= gimple_location (stmt
);
9918 clauses
= gimple_omp_taskreg_clauses (stmt
);
9919 par_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
9920 par_body
= gimple_bind_body (par_bind
);
9921 child_fn
= ctx
->cb
.dst_fn
;
9922 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
9923 && !gimple_omp_parallel_combined_p (stmt
))
9925 struct walk_stmt_info wi
;
9928 memset (&wi
, 0, sizeof (wi
));
9931 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
9933 gimple_omp_parallel_set_combined_p (stmt
, true);
9935 gimple_seq dep_ilist
= NULL
;
9936 gimple_seq dep_olist
= NULL
;
9937 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
9938 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
9940 push_gimplify_context ();
9941 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
9942 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
9945 if (ctx
->srecord_type
)
9946 create_task_copyfn (stmt
, ctx
);
9948 push_gimplify_context ();
9953 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
9954 lower_omp (&par_body
, ctx
);
9955 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
9956 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
9958 /* Declare all the variables created by mapping and the variables
9959 declared in the scope of the parallel body. */
9960 record_vars_into (ctx
->block_vars
, child_fn
);
9961 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
9963 if (ctx
->record_type
)
9966 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
9967 : ctx
->record_type
, ".omp_data_o");
9968 DECL_NAMELESS (ctx
->sender_decl
) = 1;
9969 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
9970 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
9975 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
9976 lower_send_shared_vars (&ilist
, &olist
, ctx
);
9978 if (ctx
->record_type
)
9980 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
9981 TREE_THIS_VOLATILE (clobber
) = 1;
9982 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
9986 /* Once all the expansions are done, sequence all the different
9987 fragments inside gimple_omp_body. */
9991 if (ctx
->record_type
)
9993 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9994 /* fixup_child_record_type might have changed receiver_decl's type. */
9995 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
9996 gimple_seq_add_stmt (&new_body
,
9997 gimple_build_assign (ctx
->receiver_decl
, t
));
10000 gimple_seq_add_seq (&new_body
, par_ilist
);
10001 gimple_seq_add_seq (&new_body
, par_body
);
10002 gimple_seq_add_seq (&new_body
, par_rlist
);
10003 if (ctx
->cancellable
)
10004 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
10005 gimple_seq_add_seq (&new_body
, par_olist
);
10006 new_body
= maybe_catch_exception (new_body
);
10007 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
10008 gimple_omp_set_body (stmt
, new_body
);
10010 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
10011 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
10012 gimple_bind_add_seq (bind
, ilist
);
10013 gimple_bind_add_stmt (bind
, stmt
);
10014 gimple_bind_add_seq (bind
, olist
);
10016 pop_gimplify_context (NULL
);
10020 gimple_bind_add_seq (dep_bind
, dep_ilist
);
10021 gimple_bind_add_stmt (dep_bind
, bind
);
10022 gimple_bind_add_seq (dep_bind
, dep_olist
);
10023 pop_gimplify_context (dep_bind
);
10027 /* Lower the OpenMP target directive in the current statement
10028 in GSI_P. CTX holds context information for the directive. */
10031 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10034 tree child_fn
, t
, c
;
10035 gimple stmt
= gsi_stmt (*gsi_p
);
10036 gimple tgt_bind
= NULL
, bind
;
10037 gimple_seq tgt_body
= NULL
, olist
, ilist
, new_body
;
10038 location_t loc
= gimple_location (stmt
);
10039 int kind
= gimple_omp_target_kind (stmt
);
10040 unsigned int map_cnt
= 0;
10042 clauses
= gimple_omp_target_clauses (stmt
);
10043 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10045 tgt_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
10046 tgt_body
= gimple_bind_body (tgt_bind
);
10048 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10049 tgt_body
= gimple_omp_body (stmt
);
10050 child_fn
= ctx
->cb
.dst_fn
;
10052 push_gimplify_context ();
10054 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
10055 switch (OMP_CLAUSE_CODE (c
))
10061 case OMP_CLAUSE_MAP
:
10062 case OMP_CLAUSE_TO
:
10063 case OMP_CLAUSE_FROM
:
10064 var
= OMP_CLAUSE_DECL (c
);
10067 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
10068 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
10073 if (DECL_SIZE (var
)
10074 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
10076 tree var2
= DECL_VALUE_EXPR (var
);
10077 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
10078 var2
= TREE_OPERAND (var2
, 0);
10079 gcc_assert (DECL_P (var2
));
10083 if (!maybe_lookup_field (var
, ctx
))
10086 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10088 x
= build_receiver_ref (var
, true, ctx
);
10089 tree new_var
= lookup_decl (var
, ctx
);
10090 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10091 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
10092 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
10093 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
10094 x
= build_simple_mem_ref (x
);
10095 SET_DECL_VALUE_EXPR (new_var
, x
);
10096 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
10101 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10103 target_nesting_level
++;
10104 lower_omp (&tgt_body
, ctx
);
10105 target_nesting_level
--;
10107 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10108 lower_omp (&tgt_body
, ctx
);
10110 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10112 /* Declare all the variables created by mapping and the variables
10113 declared in the scope of the target body. */
10114 record_vars_into (ctx
->block_vars
, child_fn
);
10115 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
10120 if (ctx
->record_type
)
10123 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
10124 DECL_NAMELESS (ctx
->sender_decl
) = 1;
10125 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
10126 t
= make_tree_vec (3);
10127 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
10128 TREE_VEC_ELT (t
, 1)
10129 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
10130 ".omp_data_sizes");
10131 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
10132 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
10133 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
10134 TREE_VEC_ELT (t
, 2)
10135 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node
,
10137 ".omp_data_kinds");
10138 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
10139 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
10140 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
10141 gimple_omp_target_set_data_arg (stmt
, t
);
10143 vec
<constructor_elt
, va_gc
> *vsize
;
10144 vec
<constructor_elt
, va_gc
> *vkind
;
10145 vec_alloc (vsize
, map_cnt
);
10146 vec_alloc (vkind
, map_cnt
);
10147 unsigned int map_idx
= 0;
10149 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
10150 switch (OMP_CLAUSE_CODE (c
))
10156 case OMP_CLAUSE_MAP
:
10157 case OMP_CLAUSE_TO
:
10158 case OMP_CLAUSE_FROM
:
10160 ovar
= OMP_CLAUSE_DECL (c
);
10161 if (!DECL_P (ovar
))
10163 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10164 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
10166 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
10167 == get_base_address (ovar
));
10168 nc
= OMP_CLAUSE_CHAIN (c
);
10169 ovar
= OMP_CLAUSE_DECL (nc
);
10173 tree x
= build_sender_ref (ovar
, ctx
);
10175 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
10176 gimplify_assign (x
, v
, &ilist
);
10182 if (DECL_SIZE (ovar
)
10183 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
10185 tree ovar2
= DECL_VALUE_EXPR (ovar
);
10186 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
10187 ovar2
= TREE_OPERAND (ovar2
, 0);
10188 gcc_assert (DECL_P (ovar2
));
10191 if (!maybe_lookup_field (ovar
, ctx
))
10195 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
10196 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
10197 talign
= DECL_ALIGN_UNIT (ovar
);
10200 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
10201 tree x
= build_sender_ref (ovar
, ctx
);
10202 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10203 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
10204 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
10205 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
10207 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
10209 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)), NULL
);
10210 mark_addressable (avar
);
10211 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
10212 talign
= DECL_ALIGN_UNIT (avar
);
10213 avar
= build_fold_addr_expr (avar
);
10214 gimplify_assign (x
, avar
, &ilist
);
10216 else if (is_gimple_reg (var
))
10218 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
10219 tree avar
= create_tmp_var (TREE_TYPE (var
), NULL
);
10220 mark_addressable (avar
);
10221 if (OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_ALLOC
10222 && OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_FROM
)
10223 gimplify_assign (avar
, var
, &ilist
);
10224 avar
= build_fold_addr_expr (avar
);
10225 gimplify_assign (x
, avar
, &ilist
);
10226 if ((OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_FROM
10227 || OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_TOFROM
)
10228 && !TYPE_READONLY (TREE_TYPE (var
)))
10230 x
= build_sender_ref (ovar
, ctx
);
10231 x
= build_simple_mem_ref (x
);
10232 gimplify_assign (var
, x
, &olist
);
10237 var
= build_fold_addr_expr (var
);
10238 gimplify_assign (x
, var
, &ilist
);
10241 tree s
= OMP_CLAUSE_SIZE (c
);
10242 if (s
== NULL_TREE
)
10243 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
10244 s
= fold_convert (size_type_node
, s
);
10245 tree purpose
= size_int (map_idx
++);
10246 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
10247 if (TREE_CODE (s
) != INTEGER_CST
)
10248 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
10250 unsigned char tkind
= 0;
10251 switch (OMP_CLAUSE_CODE (c
))
10253 case OMP_CLAUSE_MAP
:
10254 tkind
= OMP_CLAUSE_MAP_KIND (c
);
10256 case OMP_CLAUSE_TO
:
10257 tkind
= OMP_CLAUSE_MAP_TO
;
10259 case OMP_CLAUSE_FROM
:
10260 tkind
= OMP_CLAUSE_MAP_FROM
;
10263 gcc_unreachable ();
10265 talign
= ceil_log2 (talign
);
10266 tkind
|= talign
<< 3;
10267 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
10268 build_int_cst (unsigned_char_type_node
,
10274 gcc_assert (map_idx
== map_cnt
);
10276 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
10277 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
10278 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
10279 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
10280 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
10282 gimple_seq initlist
= NULL
;
10283 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
10284 TREE_VEC_ELT (t
, 1)),
10285 &initlist
, true, NULL_TREE
);
10286 gimple_seq_add_seq (&ilist
, initlist
);
10288 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
10290 TREE_THIS_VOLATILE (clobber
) = 1;
10291 gimple_seq_add_stmt (&olist
,
10292 gimple_build_assign (TREE_VEC_ELT (t
, 1),
10296 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
10297 TREE_THIS_VOLATILE (clobber
) = 1;
10298 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
10302 /* Once all the expansions are done, sequence all the different
10303 fragments inside gimple_omp_body. */
10307 if (ctx
->record_type
&& kind
== GF_OMP_TARGET_KIND_REGION
)
10309 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10310 /* fixup_child_record_type might have changed receiver_decl's type. */
10311 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
10312 gimple_seq_add_stmt (&new_body
,
10313 gimple_build_assign (ctx
->receiver_decl
, t
));
10316 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10318 gimple_seq_add_seq (&new_body
, tgt_body
);
10319 new_body
= maybe_catch_exception (new_body
);
10321 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10322 new_body
= tgt_body
;
10323 if (kind
!= GF_OMP_TARGET_KIND_UPDATE
)
10325 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
10326 gimple_omp_set_body (stmt
, new_body
);
10329 bind
= gimple_build_bind (NULL
, NULL
,
10330 tgt_bind
? gimple_bind_block (tgt_bind
)
10332 gsi_replace (gsi_p
, bind
, true);
10333 gimple_bind_add_seq (bind
, ilist
);
10334 gimple_bind_add_stmt (bind
, stmt
);
10335 gimple_bind_add_seq (bind
, olist
);
10337 pop_gimplify_context (NULL
);
10340 /* Expand code for an OpenMP teams directive. */
10343 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10345 gimple teams_stmt
= gsi_stmt (*gsi_p
);
10346 push_gimplify_context ();
10348 tree block
= make_node (BLOCK
);
10349 gimple bind
= gimple_build_bind (NULL
, NULL
, block
);
10350 gsi_replace (gsi_p
, bind
, true);
10351 gimple_seq bind_body
= NULL
;
10352 gimple_seq dlist
= NULL
;
10353 gimple_seq olist
= NULL
;
10355 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
10356 OMP_CLAUSE_NUM_TEAMS
);
10357 if (num_teams
== NULL_TREE
)
10358 num_teams
= build_int_cst (unsigned_type_node
, 0);
10361 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
10362 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
10363 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
10365 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
10366 OMP_CLAUSE_THREAD_LIMIT
);
10367 if (thread_limit
== NULL_TREE
)
10368 thread_limit
= build_int_cst (unsigned_type_node
, 0);
10371 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
10372 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
10373 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
10377 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
10378 &bind_body
, &dlist
, ctx
, NULL
);
10379 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
10380 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
10381 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
10383 location_t loc
= gimple_location (teams_stmt
);
10384 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
10385 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
10386 gimple_set_location (call
, loc
);
10387 gimple_seq_add_stmt (&bind_body
, call
);
10389 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
10390 gimple_omp_set_body (teams_stmt
, NULL
);
10391 gimple_seq_add_seq (&bind_body
, olist
);
10392 gimple_seq_add_seq (&bind_body
, dlist
);
10393 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
10394 gimple_bind_set_body (bind
, bind_body
);
10396 pop_gimplify_context (bind
);
10398 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10399 BLOCK_VARS (block
) = ctx
->block_vars
;
10400 if (BLOCK_VARS (block
))
10401 TREE_USED (block
) = 1;
10405 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10406 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10407 of OpenMP context, but with task_shared_vars set. */
10410 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
10415 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10416 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
10419 if (task_shared_vars
10421 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
10424 /* If a global variable has been privatized, TREE_CONSTANT on
10425 ADDR_EXPR might be wrong. */
10426 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
10427 recompute_tree_invariant_for_addr_expr (t
);
10429 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
10434 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10436 gimple stmt
= gsi_stmt (*gsi_p
);
10437 struct walk_stmt_info wi
;
10439 if (gimple_has_location (stmt
))
10440 input_location
= gimple_location (stmt
);
10442 if (task_shared_vars
)
10443 memset (&wi
, '\0', sizeof (wi
));
10445 /* If we have issued syntax errors, avoid doing any heavy lifting.
10446 Just replace the OpenMP directives with a NOP to avoid
10447 confusing RTL expansion. */
10448 if (seen_error () && is_gimple_omp (stmt
))
10450 gsi_replace (gsi_p
, gimple_build_nop (), true);
10454 switch (gimple_code (stmt
))
10457 if ((ctx
|| task_shared_vars
)
10458 && (walk_tree (gimple_cond_lhs_ptr (stmt
), lower_omp_regimplify_p
,
10459 ctx
? NULL
: &wi
, NULL
)
10460 || walk_tree (gimple_cond_rhs_ptr (stmt
), lower_omp_regimplify_p
,
10461 ctx
? NULL
: &wi
, NULL
)))
10462 gimple_regimplify_operands (stmt
, gsi_p
);
10465 lower_omp (gimple_catch_handler_ptr (stmt
), ctx
);
10467 case GIMPLE_EH_FILTER
:
10468 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
10471 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
10472 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
10474 case GIMPLE_TRANSACTION
:
10475 lower_omp (gimple_transaction_body_ptr (stmt
), ctx
);
10478 lower_omp (gimple_bind_body_ptr (stmt
), ctx
);
10480 case GIMPLE_OMP_PARALLEL
:
10481 case GIMPLE_OMP_TASK
:
10482 ctx
= maybe_lookup_ctx (stmt
);
10484 if (ctx
->cancellable
)
10485 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10486 lower_omp_taskreg (gsi_p
, ctx
);
10488 case GIMPLE_OMP_FOR
:
10489 ctx
= maybe_lookup_ctx (stmt
);
10491 if (ctx
->cancellable
)
10492 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10493 lower_omp_for (gsi_p
, ctx
);
10495 case GIMPLE_OMP_SECTIONS
:
10496 ctx
= maybe_lookup_ctx (stmt
);
10498 if (ctx
->cancellable
)
10499 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10500 lower_omp_sections (gsi_p
, ctx
);
10502 case GIMPLE_OMP_SINGLE
:
10503 ctx
= maybe_lookup_ctx (stmt
);
10505 lower_omp_single (gsi_p
, ctx
);
10507 case GIMPLE_OMP_MASTER
:
10508 ctx
= maybe_lookup_ctx (stmt
);
10510 lower_omp_master (gsi_p
, ctx
);
10512 case GIMPLE_OMP_TASKGROUP
:
10513 ctx
= maybe_lookup_ctx (stmt
);
10515 lower_omp_taskgroup (gsi_p
, ctx
);
10517 case GIMPLE_OMP_ORDERED
:
10518 ctx
= maybe_lookup_ctx (stmt
);
10520 lower_omp_ordered (gsi_p
, ctx
);
10522 case GIMPLE_OMP_CRITICAL
:
10523 ctx
= maybe_lookup_ctx (stmt
);
10525 lower_omp_critical (gsi_p
, ctx
);
10527 case GIMPLE_OMP_ATOMIC_LOAD
:
10528 if ((ctx
|| task_shared_vars
)
10529 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt
),
10530 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
10531 gimple_regimplify_operands (stmt
, gsi_p
);
10533 case GIMPLE_OMP_TARGET
:
10534 ctx
= maybe_lookup_ctx (stmt
);
10536 lower_omp_target (gsi_p
, ctx
);
10538 case GIMPLE_OMP_TEAMS
:
10539 ctx
= maybe_lookup_ctx (stmt
);
10541 lower_omp_teams (gsi_p
, ctx
);
10545 fndecl
= gimple_call_fndecl (stmt
);
10547 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
10548 switch (DECL_FUNCTION_CODE (fndecl
))
10550 case BUILT_IN_GOMP_BARRIER
:
10554 case BUILT_IN_GOMP_CANCEL
:
10555 case BUILT_IN_GOMP_CANCELLATION_POINT
:
10558 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
10559 cctx
= cctx
->outer
;
10560 gcc_assert (gimple_call_lhs (stmt
) == NULL_TREE
);
10561 if (!cctx
->cancellable
)
10563 if (DECL_FUNCTION_CODE (fndecl
)
10564 == BUILT_IN_GOMP_CANCELLATION_POINT
)
10566 stmt
= gimple_build_nop ();
10567 gsi_replace (gsi_p
, stmt
, false);
10571 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
10573 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
10574 gimple_call_set_fndecl (stmt
, fndecl
);
10575 gimple_call_set_fntype (stmt
, TREE_TYPE (fndecl
));
10578 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)), NULL
);
10579 gimple_call_set_lhs (stmt
, lhs
);
10580 tree fallthru_label
;
10581 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
10583 g
= gimple_build_label (fallthru_label
);
10584 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10585 g
= gimple_build_cond (NE_EXPR
, lhs
,
10586 fold_convert (TREE_TYPE (lhs
),
10587 boolean_false_node
),
10588 cctx
->cancel_label
, fallthru_label
);
10589 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10596 if ((ctx
|| task_shared_vars
)
10597 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
10600 /* Just remove clobbers, this should happen only if we have
10601 "privatized" local addressable variables in SIMD regions,
10602 the clobber isn't needed in that case and gimplifying address
10603 of the ARRAY_REF into a pointer and creating MEM_REF based
10604 clobber would create worse code than we get with the clobber
10606 if (gimple_clobber_p (stmt
))
10608 gsi_replace (gsi_p
, gimple_build_nop (), true);
10611 gimple_regimplify_operands (stmt
, gsi_p
);
10618 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
10620 location_t saved_location
= input_location
;
10621 gimple_stmt_iterator gsi
;
10622 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10623 lower_omp_1 (&gsi
, ctx
);
10624 /* During gimplification, we have not always invoked fold_stmt
10625 (gimplify.c:maybe_fold_stmt); call it now. */
10626 if (target_nesting_level
)
10627 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10629 input_location
= saved_location
;
10632 /* Main entry point. */
10634 static unsigned int
10635 execute_lower_omp (void)
10641 /* This pass always runs, to provide PROP_gimple_lomp.
10642 But there is nothing to do unless -fopenmp is given. */
10643 if (flag_openmp
== 0 && flag_openmp_simd
== 0 && flag_cilkplus
== 0)
10646 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
10647 delete_omp_context
);
10649 body
= gimple_body (current_function_decl
);
10650 scan_omp (&body
, NULL
);
10651 gcc_assert (taskreg_nesting_level
== 0);
10652 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
10653 finish_taskreg_scan (ctx
);
10654 taskreg_contexts
.release ();
10656 if (all_contexts
->root
)
10658 if (task_shared_vars
)
10659 push_gimplify_context ();
10660 lower_omp (&body
, NULL
);
10661 if (task_shared_vars
)
10662 pop_gimplify_context (NULL
);
10667 splay_tree_delete (all_contexts
);
10668 all_contexts
= NULL
;
10670 BITMAP_FREE (task_shared_vars
);
10676 const pass_data pass_data_lower_omp
=
10678 GIMPLE_PASS
, /* type */
10679 "omplower", /* name */
10680 OPTGROUP_NONE
, /* optinfo_flags */
10681 TV_NONE
, /* tv_id */
10682 PROP_gimple_any
, /* properties_required */
10683 PROP_gimple_lomp
, /* properties_provided */
10684 0, /* properties_destroyed */
10685 0, /* todo_flags_start */
10686 0, /* todo_flags_finish */
10689 class pass_lower_omp
: public gimple_opt_pass
10692 pass_lower_omp (gcc::context
*ctxt
)
10693 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
10696 /* opt_pass methods: */
10697 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
10699 }; // class pass_lower_omp
10701 } // anon namespace
10704 make_pass_lower_omp (gcc::context
*ctxt
)
10706 return new pass_lower_omp (ctxt
);
10709 /* The following is a utility to diagnose OpenMP structured block violations.
10710 It is not part of the "omplower" pass, as that's invoked too late. It
10711 should be invoked by the respective front ends after gimplification. */
10713 static splay_tree all_labels
;
10715 /* Check for mismatched contexts and generate an error if needed. Return
10716 true if an error is detected. */
10719 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
10720 gimple branch_ctx
, gimple label_ctx
)
10722 if (label_ctx
== branch_ctx
)
10727 Previously we kept track of the label's entire context in diagnose_sb_[12]
10728 so we could traverse it and issue a correct "exit" or "enter" error
10729 message upon a structured block violation.
10731 We built the context by building a list with tree_cons'ing, but there is
10732 no easy counterpart in gimple tuples. It seems like far too much work
10733 for issuing exit/enter error messages. If someone really misses the
10734 distinct error message... patches welcome.
10738 /* Try to avoid confusing the user by producing and error message
10739 with correct "exit" or "enter" verbiage. We prefer "exit"
10740 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10741 if (branch_ctx
== NULL
)
10747 if (TREE_VALUE (label_ctx
) == branch_ctx
)
10752 label_ctx
= TREE_CHAIN (label_ctx
);
10757 error ("invalid exit from OpenMP structured block");
10759 error ("invalid entry to OpenMP structured block");
10762 bool cilkplus_block
= false;
10766 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
10767 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
10769 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
10770 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
10771 cilkplus_block
= true;
10774 /* If it's obvious we have an invalid entry, be specific about the error. */
10775 if (branch_ctx
== NULL
)
10777 if (cilkplus_block
)
10778 error ("invalid entry to Cilk Plus structured block");
10780 error ("invalid entry to OpenMP structured block");
10784 /* Otherwise, be vague and lazy, but efficient. */
10785 if (cilkplus_block
)
10786 error ("invalid branch to/from a Cilk Plus structured block");
10788 error ("invalid branch to/from an OpenMP structured block");
10791 gsi_replace (gsi_p
, gimple_build_nop (), false);
10795 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10796 where each label is found. */
10799 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10800 struct walk_stmt_info
*wi
)
10802 gimple context
= (gimple
) wi
->info
;
10803 gimple inner_context
;
10804 gimple stmt
= gsi_stmt (*gsi_p
);
10806 *handled_ops_p
= true;
10808 switch (gimple_code (stmt
))
10812 case GIMPLE_OMP_PARALLEL
:
10813 case GIMPLE_OMP_TASK
:
10814 case GIMPLE_OMP_SECTIONS
:
10815 case GIMPLE_OMP_SINGLE
:
10816 case GIMPLE_OMP_SECTION
:
10817 case GIMPLE_OMP_MASTER
:
10818 case GIMPLE_OMP_ORDERED
:
10819 case GIMPLE_OMP_CRITICAL
:
10820 case GIMPLE_OMP_TARGET
:
10821 case GIMPLE_OMP_TEAMS
:
10822 case GIMPLE_OMP_TASKGROUP
:
10823 /* The minimal context here is just the current OMP construct. */
10824 inner_context
= stmt
;
10825 wi
->info
= inner_context
;
10826 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10827 wi
->info
= context
;
10830 case GIMPLE_OMP_FOR
:
10831 inner_context
= stmt
;
10832 wi
->info
= inner_context
;
10833 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10835 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
10836 diagnose_sb_1
, NULL
, wi
);
10837 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10838 wi
->info
= context
;
10842 splay_tree_insert (all_labels
, (splay_tree_key
) gimple_label_label (stmt
),
10843 (splay_tree_value
) context
);
10853 /* Pass 2: Check each branch and see if its context differs from that of
10854 the destination label's context. */
10857 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10858 struct walk_stmt_info
*wi
)
10860 gimple context
= (gimple
) wi
->info
;
10862 gimple stmt
= gsi_stmt (*gsi_p
);
10864 *handled_ops_p
= true;
10866 switch (gimple_code (stmt
))
10870 case GIMPLE_OMP_PARALLEL
:
10871 case GIMPLE_OMP_TASK
:
10872 case GIMPLE_OMP_SECTIONS
:
10873 case GIMPLE_OMP_SINGLE
:
10874 case GIMPLE_OMP_SECTION
:
10875 case GIMPLE_OMP_MASTER
:
10876 case GIMPLE_OMP_ORDERED
:
10877 case GIMPLE_OMP_CRITICAL
:
10878 case GIMPLE_OMP_TARGET
:
10879 case GIMPLE_OMP_TEAMS
:
10880 case GIMPLE_OMP_TASKGROUP
:
10882 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10883 wi
->info
= context
;
10886 case GIMPLE_OMP_FOR
:
10888 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10890 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
10891 diagnose_sb_2
, NULL
, wi
);
10892 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10893 wi
->info
= context
;
10898 tree lab
= gimple_cond_true_label (stmt
);
10901 n
= splay_tree_lookup (all_labels
,
10902 (splay_tree_key
) lab
);
10903 diagnose_sb_0 (gsi_p
, context
,
10904 n
? (gimple
) n
->value
: NULL
);
10906 lab
= gimple_cond_false_label (stmt
);
10909 n
= splay_tree_lookup (all_labels
,
10910 (splay_tree_key
) lab
);
10911 diagnose_sb_0 (gsi_p
, context
,
10912 n
? (gimple
) n
->value
: NULL
);
10919 tree lab
= gimple_goto_dest (stmt
);
10920 if (TREE_CODE (lab
) != LABEL_DECL
)
10923 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10924 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
10928 case GIMPLE_SWITCH
:
10931 for (i
= 0; i
< gimple_switch_num_labels (stmt
); ++i
)
10933 tree lab
= CASE_LABEL (gimple_switch_label (stmt
, i
));
10934 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10935 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
10941 case GIMPLE_RETURN
:
10942 diagnose_sb_0 (gsi_p
, context
, NULL
);
10952 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10955 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
10958 gimple last
= last_stmt (bb
);
10959 enum gimple_code code
= gimple_code (last
);
10960 struct omp_region
*cur_region
= *region
;
10961 bool fallthru
= false;
10965 case GIMPLE_OMP_PARALLEL
:
10966 case GIMPLE_OMP_TASK
:
10967 case GIMPLE_OMP_FOR
:
10968 case GIMPLE_OMP_SINGLE
:
10969 case GIMPLE_OMP_TEAMS
:
10970 case GIMPLE_OMP_MASTER
:
10971 case GIMPLE_OMP_TASKGROUP
:
10972 case GIMPLE_OMP_ORDERED
:
10973 case GIMPLE_OMP_CRITICAL
:
10974 case GIMPLE_OMP_SECTION
:
10975 cur_region
= new_omp_region (bb
, code
, cur_region
);
10979 case GIMPLE_OMP_TARGET
:
10980 cur_region
= new_omp_region (bb
, code
, cur_region
);
10982 if (gimple_omp_target_kind (last
) == GF_OMP_TARGET_KIND_UPDATE
)
10983 cur_region
= cur_region
->outer
;
10986 case GIMPLE_OMP_SECTIONS
:
10987 cur_region
= new_omp_region (bb
, code
, cur_region
);
10991 case GIMPLE_OMP_SECTIONS_SWITCH
:
10995 case GIMPLE_OMP_ATOMIC_LOAD
:
10996 case GIMPLE_OMP_ATOMIC_STORE
:
11000 case GIMPLE_OMP_RETURN
:
11001 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11002 somewhere other than the next block. This will be
11004 cur_region
->exit
= bb
;
11005 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
11006 cur_region
= cur_region
->outer
;
11009 case GIMPLE_OMP_CONTINUE
:
11010 cur_region
->cont
= bb
;
11011 switch (cur_region
->type
)
11013 case GIMPLE_OMP_FOR
:
11014 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11015 succs edges as abnormal to prevent splitting
11017 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
11018 /* Make the loopback edge. */
11019 make_edge (bb
, single_succ (cur_region
->entry
),
11022 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11023 corresponds to the case that the body of the loop
11024 is not executed at all. */
11025 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
11026 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
11030 case GIMPLE_OMP_SECTIONS
:
11031 /* Wire up the edges into and out of the nested sections. */
11033 basic_block switch_bb
= single_succ (cur_region
->entry
);
11035 struct omp_region
*i
;
11036 for (i
= cur_region
->inner
; i
; i
= i
->next
)
11038 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
11039 make_edge (switch_bb
, i
->entry
, 0);
11040 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
11043 /* Make the loopback edge to the block with
11044 GIMPLE_OMP_SECTIONS_SWITCH. */
11045 make_edge (bb
, switch_bb
, 0);
11047 /* Make the edge from the switch to exit. */
11048 make_edge (switch_bb
, bb
->next_bb
, 0);
11054 gcc_unreachable ();
11059 gcc_unreachable ();
11062 if (*region
!= cur_region
)
11064 *region
= cur_region
;
11066 *region_idx
= cur_region
->entry
->index
;
11074 static unsigned int
11075 diagnose_omp_structured_block_errors (void)
11077 struct walk_stmt_info wi
;
11078 gimple_seq body
= gimple_body (current_function_decl
);
11080 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
11082 memset (&wi
, 0, sizeof (wi
));
11083 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
11085 memset (&wi
, 0, sizeof (wi
));
11086 wi
.want_locations
= true;
11087 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
11089 gimple_set_body (current_function_decl
, body
);
11091 splay_tree_delete (all_labels
);
11099 const pass_data pass_data_diagnose_omp_blocks
=
11101 GIMPLE_PASS
, /* type */
11102 "*diagnose_omp_blocks", /* name */
11103 OPTGROUP_NONE
, /* optinfo_flags */
11104 TV_NONE
, /* tv_id */
11105 PROP_gimple_any
, /* properties_required */
11106 0, /* properties_provided */
11107 0, /* properties_destroyed */
11108 0, /* todo_flags_start */
11109 0, /* todo_flags_finish */
11112 class pass_diagnose_omp_blocks
: public gimple_opt_pass
11115 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
11116 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
11119 /* opt_pass methods: */
11120 virtual bool gate (function
*) { return flag_openmp
|| flag_cilkplus
; }
11121 virtual unsigned int execute (function
*)
11123 return diagnose_omp_structured_block_errors ();
11126 }; // class pass_diagnose_omp_blocks
11128 } // anon namespace
11131 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
11133 return new pass_diagnose_omp_blocks (ctxt
);
11136 /* SIMD clone supporting code. */
11138 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11139 of arguments to reserve space for. */
11141 static struct cgraph_simd_clone
*
11142 simd_clone_struct_alloc (int nargs
)
11144 struct cgraph_simd_clone
*clone_info
;
11145 size_t len
= (sizeof (struct cgraph_simd_clone
)
11146 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
11147 clone_info
= (struct cgraph_simd_clone
*)
11148 ggc_internal_cleared_alloc (len
);
11152 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11155 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
11156 struct cgraph_simd_clone
*from
)
11158 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
11159 + ((from
->nargs
- from
->inbranch
)
11160 * sizeof (struct cgraph_simd_clone_arg
))));
11163 /* Return vector of parameter types of function FNDECL. This uses
11164 TYPE_ARG_TYPES if available, otherwise falls back to types of
11165 DECL_ARGUMENTS types. */
11168 simd_clone_vector_of_formal_parm_types (tree fndecl
)
11170 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
11171 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
11172 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
11175 FOR_EACH_VEC_ELT (args
, i
, arg
)
11176 args
[i
] = TREE_TYPE (args
[i
]);
11180 /* Given a simd function in NODE, extract the simd specific
11181 information from the OMP clauses passed in CLAUSES, and return
11182 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11183 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11184 otherwise set to FALSE. */
11186 static struct cgraph_simd_clone
*
11187 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
11188 bool *inbranch_specified
)
11190 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11193 *inbranch_specified
= false;
11195 n
= args
.length ();
11196 if (n
> 0 && args
.last () == void_type_node
)
11199 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11200 be cloned have a distinctive artificial label in addition to "omp
11204 && lookup_attribute ("cilk simd function",
11205 DECL_ATTRIBUTES (node
->decl
)));
11207 /* Allocate one more than needed just in case this is an in-branch
11208 clone which will require a mask argument. */
11209 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
11210 clone_info
->nargs
= n
;
11211 clone_info
->cilk_elemental
= cilk_clone
;
11218 clauses
= TREE_VALUE (clauses
);
11219 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
11222 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
11224 switch (OMP_CLAUSE_CODE (t
))
11226 case OMP_CLAUSE_INBRANCH
:
11227 clone_info
->inbranch
= 1;
11228 *inbranch_specified
= true;
11230 case OMP_CLAUSE_NOTINBRANCH
:
11231 clone_info
->inbranch
= 0;
11232 *inbranch_specified
= true;
11234 case OMP_CLAUSE_SIMDLEN
:
11235 clone_info
->simdlen
11236 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
11238 case OMP_CLAUSE_LINEAR
:
11240 tree decl
= OMP_CLAUSE_DECL (t
);
11241 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
11242 int argno
= TREE_INT_CST_LOW (decl
);
11243 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
11245 clone_info
->args
[argno
].arg_type
11246 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
11247 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
11248 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
11249 && clone_info
->args
[argno
].linear_step
< n
);
11253 if (POINTER_TYPE_P (args
[argno
]))
11254 step
= fold_convert (ssizetype
, step
);
11255 if (!tree_fits_shwi_p (step
))
11257 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
11258 "ignoring large linear step");
11262 else if (integer_zerop (step
))
11264 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
11265 "ignoring zero linear step");
11271 clone_info
->args
[argno
].arg_type
11272 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
11273 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
11278 case OMP_CLAUSE_UNIFORM
:
11280 tree decl
= OMP_CLAUSE_DECL (t
);
11281 int argno
= tree_to_uhwi (decl
);
11282 clone_info
->args
[argno
].arg_type
11283 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
11286 case OMP_CLAUSE_ALIGNED
:
11288 tree decl
= OMP_CLAUSE_DECL (t
);
11289 int argno
= tree_to_uhwi (decl
);
11290 clone_info
->args
[argno
].alignment
11291 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
11302 /* Given a SIMD clone in NODE, calculate the characteristic data
11303 type and return the coresponding type. The characteristic data
11304 type is computed as described in the Intel Vector ABI. */
11307 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
11308 struct cgraph_simd_clone
*clone_info
)
11310 tree type
= integer_type_node
;
11311 tree fndecl
= node
->decl
;
11313 /* a) For non-void function, the characteristic data type is the
11315 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
11316 type
= TREE_TYPE (TREE_TYPE (fndecl
));
11318 /* b) If the function has any non-uniform, non-linear parameters,
11319 then the characteristic data type is the type of the first
11323 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
11324 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
11325 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
11333 /* c) If the characteristic data type determined by a) or b) above
11334 is struct, union, or class type which is pass-by-value (except
11335 for the type that maps to the built-in complex data type), the
11336 characteristic data type is int. */
11337 if (RECORD_OR_UNION_TYPE_P (type
)
11338 && !aggregate_value_p (type
, NULL
)
11339 && TREE_CODE (type
) != COMPLEX_TYPE
)
11340 return integer_type_node
;
11342 /* d) If none of the above three classes is applicable, the
11343 characteristic data type is int. */
11347 /* e) For Intel Xeon Phi native and offload compilation, if the
11348 resulting characteristic data type is 8-bit or 16-bit integer
11349 data type, the characteristic data type is int. */
11350 /* Well, we don't handle Xeon Phi yet. */
11354 simd_clone_mangle (struct cgraph_node
*node
,
11355 struct cgraph_simd_clone
*clone_info
)
11357 char vecsize_mangle
= clone_info
->vecsize_mangle
;
11358 char mask
= clone_info
->inbranch
? 'M' : 'N';
11359 unsigned int simdlen
= clone_info
->simdlen
;
11363 gcc_assert (vecsize_mangle
&& simdlen
);
11365 pp_string (&pp
, "_ZGV");
11366 pp_character (&pp
, vecsize_mangle
);
11367 pp_character (&pp
, mask
);
11368 pp_decimal_int (&pp
, simdlen
);
11370 for (n
= 0; n
< clone_info
->nargs
; ++n
)
11372 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
11374 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
11375 pp_character (&pp
, 'u');
11376 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
11378 gcc_assert (arg
.linear_step
!= 0);
11379 pp_character (&pp
, 'l');
11380 if (arg
.linear_step
> 1)
11381 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
11382 else if (arg
.linear_step
< 0)
11384 pp_character (&pp
, 'n');
11385 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
11389 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
11391 pp_character (&pp
, 's');
11392 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
11395 pp_character (&pp
, 'v');
11398 pp_character (&pp
, 'a');
11399 pp_decimal_int (&pp
, arg
.alignment
);
11403 pp_underscore (&pp
);
11405 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
)));
11406 const char *str
= pp_formatted_text (&pp
);
11408 /* If there already is a SIMD clone with the same mangled name, don't
11409 add another one. This can happen e.g. for
11410 #pragma omp declare simd
11411 #pragma omp declare simd simdlen(8)
11412 int foo (int, int);
11413 if the simdlen is assumed to be 8 for the first one, etc. */
11414 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
11415 clone
= clone
->simdclone
->next_clone
)
11416 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
11420 return get_identifier (str
);
11423 /* Create a simd clone of OLD_NODE and return it. */
11425 static struct cgraph_node
*
11426 simd_clone_create (struct cgraph_node
*old_node
)
11428 struct cgraph_node
*new_node
;
11429 if (old_node
->definition
)
11431 if (!old_node
->has_gimple_body_p ())
11433 old_node
->get_body ();
11434 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
11440 tree old_decl
= old_node
->decl
;
11441 tree new_decl
= copy_node (old_node
->decl
);
11442 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
11443 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
11444 SET_DECL_RTL (new_decl
, NULL
);
11445 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
11446 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
11447 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
11448 symtab
->call_cgraph_insertion_hooks (new_node
);
11450 if (new_node
== NULL
)
11453 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
11455 /* The function cgraph_function_versioning () will force the new
11456 symbol local. Undo this, and inherit external visability from
11458 new_node
->local
.local
= old_node
->local
.local
;
11459 new_node
->externally_visible
= old_node
->externally_visible
;
11464 /* Adjust the return type of the given function to its appropriate
11465 vector counterpart. Returns a simd array to be used throughout the
11466 function as a return value. */
11469 simd_clone_adjust_return_type (struct cgraph_node
*node
)
11471 tree fndecl
= node
->decl
;
11472 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
11473 unsigned int veclen
;
11476 /* Adjust the function return type. */
11477 if (orig_rettype
== void_type_node
)
11479 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
11480 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
)))
11481 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
))))
11482 veclen
= node
->simdclone
->vecsize_int
;
11484 veclen
= node
->simdclone
->vecsize_float
;
11485 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl
))));
11486 if (veclen
> node
->simdclone
->simdlen
)
11487 veclen
= node
->simdclone
->simdlen
;
11488 if (veclen
== node
->simdclone
->simdlen
)
11489 TREE_TYPE (TREE_TYPE (fndecl
))
11490 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)),
11491 node
->simdclone
->simdlen
);
11494 t
= build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)), veclen
);
11495 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
11496 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
11498 if (!node
->definition
)
11501 t
= DECL_RESULT (fndecl
);
11502 /* Adjust the DECL_RESULT. */
11503 gcc_assert (TREE_TYPE (t
) != void_type_node
);
11504 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
11507 tree atype
= build_array_type_nelts (orig_rettype
,
11508 node
->simdclone
->simdlen
);
11509 if (veclen
!= node
->simdclone
->simdlen
)
11510 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
11512 /* Set up a SIMD array to use as the return value. */
11513 tree retval
= create_tmp_var_raw (atype
, "retval");
11514 gimple_add_tmp_var (retval
);
11518 /* Each vector argument has a corresponding array to be used locally
11519 as part of the eventual loop. Create such temporary array and
11522 PREFIX is the prefix to be used for the temporary.
11524 TYPE is the inner element type.
11526 SIMDLEN is the number of elements. */
11529 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
11531 tree atype
= build_array_type_nelts (type
, simdlen
);
11532 tree avar
= create_tmp_var_raw (atype
, prefix
);
11533 gimple_add_tmp_var (avar
);
11537 /* Modify the function argument types to their corresponding vector
11538 counterparts if appropriate. Also, create one array for each simd
11539 argument to be used locally when using the function arguments as
11542 NODE is the function whose arguments are to be adjusted.
11544 Returns an adjustment vector that will be filled describing how the
11545 argument types will be adjusted. */
11547 static ipa_parm_adjustment_vec
11548 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
11551 ipa_parm_adjustment_vec adjustments
;
11553 if (node
->definition
)
11554 args
= ipa_get_vector_of_formal_parms (node
->decl
);
11556 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11557 adjustments
.create (args
.length ());
11558 unsigned i
, j
, veclen
;
11559 struct ipa_parm_adjustment adj
;
11560 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
11562 memset (&adj
, 0, sizeof (adj
));
11563 tree parm
= args
[i
];
11564 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
11565 adj
.base_index
= i
;
11568 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
11569 node
->simdclone
->args
[i
].orig_type
= parm_type
;
11571 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
11573 /* No adjustment necessary for scalar arguments. */
11574 adj
.op
= IPA_PARM_OP_COPY
;
11578 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
11579 veclen
= node
->simdclone
->vecsize_int
;
11581 veclen
= node
->simdclone
->vecsize_float
;
11582 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
11583 if (veclen
> node
->simdclone
->simdlen
)
11584 veclen
= node
->simdclone
->simdlen
;
11585 adj
.arg_prefix
= "simd";
11586 adj
.type
= build_vector_type (parm_type
, veclen
);
11587 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
11588 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11590 adjustments
.safe_push (adj
);
11593 memset (&adj
, 0, sizeof (adj
));
11594 adj
.op
= IPA_PARM_OP_NEW
;
11595 adj
.arg_prefix
= "simd";
11596 adj
.base_index
= i
;
11597 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
11601 if (node
->definition
)
11602 node
->simdclone
->args
[i
].simd_array
11603 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
11604 parm_type
, node
->simdclone
->simdlen
);
11606 adjustments
.safe_push (adj
);
11609 if (node
->simdclone
->inbranch
)
11612 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
11615 memset (&adj
, 0, sizeof (adj
));
11616 adj
.op
= IPA_PARM_OP_NEW
;
11617 adj
.arg_prefix
= "mask";
11619 adj
.base_index
= i
;
11620 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
11621 veclen
= node
->simdclone
->vecsize_int
;
11623 veclen
= node
->simdclone
->vecsize_float
;
11624 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
11625 if (veclen
> node
->simdclone
->simdlen
)
11626 veclen
= node
->simdclone
->simdlen
;
11627 adj
.type
= build_vector_type (base_type
, veclen
);
11628 adjustments
.safe_push (adj
);
11630 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11631 adjustments
.safe_push (adj
);
11633 /* We have previously allocated one extra entry for the mask. Use
11635 struct cgraph_simd_clone
*sc
= node
->simdclone
;
11637 if (node
->definition
)
11639 sc
->args
[i
].orig_arg
11640 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
11641 sc
->args
[i
].simd_array
11642 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
11644 sc
->args
[i
].orig_type
= base_type
;
11645 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
11648 if (node
->definition
)
11649 ipa_modify_formal_parameters (node
->decl
, adjustments
);
11652 tree new_arg_types
= NULL_TREE
, new_reversed
;
11653 bool last_parm_void
= false;
11654 if (args
.length () > 0 && args
.last () == void_type_node
)
11655 last_parm_void
= true;
11657 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
11658 j
= adjustments
.length ();
11659 for (i
= 0; i
< j
; i
++)
11661 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
11663 if (adj
->op
== IPA_PARM_OP_COPY
)
11664 ptype
= args
[adj
->base_index
];
11667 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
11669 new_reversed
= nreverse (new_arg_types
);
11670 if (last_parm_void
)
11673 TREE_CHAIN (new_arg_types
) = void_list_node
;
11675 new_reversed
= void_list_node
;
11678 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
11679 TYPE_ARG_TYPES (new_type
) = new_reversed
;
11680 TREE_TYPE (node
->decl
) = new_type
;
11682 adjustments
.release ();
11685 return adjustments
;
11688 /* Initialize and copy the function arguments in NODE to their
11689 corresponding local simd arrays. Returns a fresh gimple_seq with
11690 the instruction sequence generated. */
11693 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
11694 ipa_parm_adjustment_vec adjustments
)
11696 gimple_seq seq
= NULL
;
11697 unsigned i
= 0, j
= 0, k
;
11699 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
11701 arg
= DECL_CHAIN (arg
), i
++, j
++)
11703 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
11706 node
->simdclone
->args
[i
].vector_arg
= arg
;
11708 tree array
= node
->simdclone
->args
[i
].simd_array
;
11709 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
11711 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11712 tree ptr
= build_fold_addr_expr (array
);
11713 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11714 build_int_cst (ptype
, 0));
11715 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11716 gimplify_and_add (t
, &seq
);
11720 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
11721 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11722 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
11724 tree ptr
= build_fold_addr_expr (array
);
11728 arg
= DECL_CHAIN (arg
);
11732 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
11733 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11734 build_int_cst (ptype
, k
* elemsize
));
11735 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11736 gimplify_and_add (t
, &seq
);
11743 /* Callback info for ipa_simd_modify_stmt_ops below. */
11745 struct modify_stmt_info
{
11746 ipa_parm_adjustment_vec adjustments
;
11748 /* True if the parent statement was modified by
11749 ipa_simd_modify_stmt_ops. */
11753 /* Callback for walk_gimple_op.
11755 Adjust operands from a given statement as specified in the
11756 adjustments vector in the callback data. */
11759 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
11761 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
11762 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
11763 tree
*orig_tp
= tp
;
11764 if (TREE_CODE (*tp
) == ADDR_EXPR
)
11765 tp
= &TREE_OPERAND (*tp
, 0);
11766 struct ipa_parm_adjustment
*cand
= NULL
;
11767 if (TREE_CODE (*tp
) == PARM_DECL
)
11768 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
11772 *walk_subtrees
= 0;
11775 tree repl
= NULL_TREE
;
11777 repl
= unshare_expr (cand
->new_decl
);
11782 *walk_subtrees
= 0;
11783 bool modified
= info
->modified
;
11784 info
->modified
= false;
11785 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
11786 if (!info
->modified
)
11788 info
->modified
= modified
;
11791 info
->modified
= modified
;
11800 repl
= build_fold_addr_expr (repl
);
11802 if (is_gimple_debug (info
->stmt
))
11804 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
11805 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
11806 DECL_ARTIFICIAL (vexpr
) = 1;
11807 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
11808 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
11813 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
),
11815 repl
= gimple_assign_lhs (stmt
);
11817 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
11818 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11821 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
11823 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
11829 info
->modified
= true;
11833 /* Traverse the function body and perform all modifications as
11834 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11835 modified such that the replacement/reduction value will now be an
11836 offset into the corresponding simd_array.
11838 This function will replace all function argument uses with their
11839 corresponding simd array elements, and ajust the return values
11843 ipa_simd_modify_function_body (struct cgraph_node
*node
,
11844 ipa_parm_adjustment_vec adjustments
,
11845 tree retval_array
, tree iter
)
11848 unsigned int i
, j
, l
;
11850 /* Re-use the adjustments array, but this time use it to replace
11851 every function argument use to an offset into the corresponding
11853 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
11855 if (!node
->simdclone
->args
[i
].vector_arg
)
11858 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
11859 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
11860 adjustments
[j
].new_decl
11861 = build4 (ARRAY_REF
,
11863 node
->simdclone
->args
[i
].simd_array
,
11865 NULL_TREE
, NULL_TREE
);
11866 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
11867 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
11868 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
11871 l
= adjustments
.length ();
11872 for (i
= 1; i
< num_ssa_names
; i
++)
11874 tree name
= ssa_name (i
);
11876 && SSA_NAME_VAR (name
)
11877 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
11879 for (j
= 0; j
< l
; j
++)
11880 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
11881 && adjustments
[j
].new_decl
)
11884 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
11887 = copy_var_decl (adjustments
[j
].base
,
11888 DECL_NAME (adjustments
[j
].base
),
11889 TREE_TYPE (adjustments
[j
].base
));
11890 adjustments
[j
].new_ssa_base
= base_var
;
11893 base_var
= adjustments
[j
].new_ssa_base
;
11894 if (SSA_NAME_IS_DEFAULT_DEF (name
))
11896 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11897 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
11898 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
11899 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
11900 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11901 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
11902 gimple stmt
= gimple_build_assign (name
, new_decl
);
11903 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11906 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11911 struct modify_stmt_info info
;
11912 info
.adjustments
= adjustments
;
11914 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
11916 gimple_stmt_iterator gsi
;
11918 gsi
= gsi_start_bb (bb
);
11919 while (!gsi_end_p (gsi
))
11921 gimple stmt
= gsi_stmt (gsi
);
11923 struct walk_stmt_info wi
;
11925 memset (&wi
, 0, sizeof (wi
));
11926 info
.modified
= false;
11928 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
11930 if (gimple_code (stmt
) == GIMPLE_RETURN
)
11932 tree retval
= gimple_return_retval (stmt
);
11935 gsi_remove (&gsi
, true);
11939 /* Replace `return foo' with `retval_array[iter] = foo'. */
11940 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
11941 retval_array
, iter
, NULL
, NULL
);
11942 stmt
= gimple_build_assign (ref
, retval
);
11943 gsi_replace (&gsi
, stmt
, true);
11944 info
.modified
= true;
11949 update_stmt (stmt
);
11950 if (maybe_clean_eh_stmt (stmt
))
11951 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
11958 /* Adjust the argument types in NODE to their appropriate vector
11962 simd_clone_adjust (struct cgraph_node
*node
)
11964 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
11966 targetm
.simd_clone
.adjust (node
);
11968 tree retval
= simd_clone_adjust_return_type (node
);
11969 ipa_parm_adjustment_vec adjustments
11970 = simd_clone_adjust_argument_types (node
);
11972 push_gimplify_context ();
11974 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
11976 /* Adjust all uses of vector arguments accordingly. Adjust all
11977 return values accordingly. */
11978 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
11979 tree iter1
= make_ssa_name (iter
, NULL
);
11980 tree iter2
= make_ssa_name (iter
, NULL
);
11981 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
11983 /* Initialize the iteration variable. */
11984 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11985 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
11986 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
11987 /* Insert the SIMD array and iv initialization at function
11989 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
11991 pop_gimplify_context (NULL
);
11993 /* Create a new BB right before the original exit BB, to hold the
11994 iteration increment and the condition/branch. */
11995 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
11996 basic_block incr_bb
= create_empty_bb (orig_exit
);
11997 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
11998 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11999 flag. Set it now to be a FALLTHRU_EDGE. */
12000 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
12001 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
12002 for (unsigned i
= 0;
12003 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
12005 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
12006 redirect_edge_succ (e
, incr_bb
);
12008 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
12009 e
->probability
= REG_BR_PROB_BASE
;
12010 gsi
= gsi_last_bb (incr_bb
);
12011 gimple g
= gimple_build_assign_with_ops (PLUS_EXPR
, iter2
, iter1
,
12012 build_int_cst (unsigned_type_node
,
12014 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12016 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12017 struct loop
*loop
= alloc_loop ();
12018 cfun
->has_force_vectorize_loops
= true;
12019 loop
->safelen
= node
->simdclone
->simdlen
;
12020 loop
->force_vectorize
= true;
12021 loop
->header
= body_bb
;
12023 /* Branch around the body if the mask applies. */
12024 if (node
->simdclone
->inbranch
)
12026 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
12028 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
12029 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)), NULL
);
12030 tree aref
= build4 (ARRAY_REF
,
12031 TREE_TYPE (TREE_TYPE (mask_array
)),
12034 g
= gimple_build_assign (mask
, aref
);
12035 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12036 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
12037 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
12039 aref
= build1 (VIEW_CONVERT_EXPR
,
12040 build_nonstandard_integer_type (bitsize
, 0), mask
);
12041 mask
= make_ssa_name (TREE_TYPE (aref
), NULL
);
12042 g
= gimple_build_assign (mask
, aref
);
12043 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12046 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
12048 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12049 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
12050 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
12053 /* Generate the condition. */
12054 g
= gimple_build_cond (LT_EXPR
,
12056 build_int_cst (unsigned_type_node
,
12057 node
->simdclone
->simdlen
),
12059 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12060 e
= split_block (incr_bb
, gsi_stmt (gsi
));
12061 basic_block latch_bb
= e
->dest
;
12062 basic_block new_exit_bb
;
12063 new_exit_bb
= split_block (latch_bb
, NULL
)->dest
;
12064 loop
->latch
= latch_bb
;
12066 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
12068 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
12069 /* The successor of incr_bb is already pointing to latch_bb; just
12071 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12072 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
12074 gimple phi
= create_phi_node (iter1
, body_bb
);
12075 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
12076 edge latch_edge
= single_succ_edge (latch_bb
);
12077 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
12079 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
12081 /* Generate the new return. */
12082 gsi
= gsi_last_bb (new_exit_bb
);
12084 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
12085 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
12086 retval
= TREE_OPERAND (retval
, 0);
12089 retval
= build1 (VIEW_CONVERT_EXPR
,
12090 TREE_TYPE (TREE_TYPE (node
->decl
)),
12092 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
12093 false, GSI_CONTINUE_LINKING
);
12095 g
= gimple_build_return (retval
);
12096 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12098 /* Handle aligned clauses by replacing default defs of the aligned
12099 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12100 lhs. Handle linear by adding PHIs. */
12101 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
12102 if (node
->simdclone
->args
[i
].alignment
12103 && node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
12104 && (node
->simdclone
->args
[i
].alignment
12105 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
12106 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
12109 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
12110 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
12111 tree def
= ssa_default_def (cfun
, orig_arg
);
12112 if (def
&& !has_zero_uses (def
))
12114 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
12115 gimple_seq seq
= NULL
;
12116 bool need_cvt
= false;
12118 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
12120 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
12123 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
, NULL
);
12124 gimple_call_set_lhs (g
, t
);
12125 gimple_seq_add_stmt_without_update (&seq
, g
);
12128 t
= make_ssa_name (orig_arg
, NULL
);
12129 g
= gimple_build_assign_with_ops (NOP_EXPR
, t
,
12130 gimple_call_lhs (g
),
12132 gimple_seq_add_stmt_without_update (&seq
, g
);
12134 gsi_insert_seq_on_edge_immediate
12135 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
12137 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
12138 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
12140 node
->create_edge (cgraph_node::get_create (fn
),
12141 call
, entry_bb
->count
, freq
);
12143 imm_use_iterator iter
;
12144 use_operand_p use_p
;
12146 tree repl
= gimple_get_lhs (g
);
12147 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
12148 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
12151 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
12152 SET_USE (use_p
, repl
);
12155 else if (node
->simdclone
->args
[i
].arg_type
12156 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
12158 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
12159 tree def
= ssa_default_def (cfun
, orig_arg
);
12160 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12161 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
12162 if (def
&& !has_zero_uses (def
))
12164 iter1
= make_ssa_name (orig_arg
, NULL
);
12165 iter2
= make_ssa_name (orig_arg
, NULL
);
12166 phi
= create_phi_node (iter1
, body_bb
);
12167 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
12168 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
12169 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12170 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
12171 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12172 ? TREE_TYPE (orig_arg
) : sizetype
;
12174 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
12175 g
= gimple_build_assign_with_ops (code
, iter2
, iter1
, addcst
);
12176 gsi
= gsi_last_bb (incr_bb
);
12177 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
12179 imm_use_iterator iter
;
12180 use_operand_p use_p
;
12182 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
12183 if (use_stmt
== phi
)
12186 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
12187 SET_USE (use_p
, iter1
);
12191 calculate_dominance_info (CDI_DOMINATORS
);
12192 add_loop (loop
, loop
->header
->loop_father
);
12193 update_ssa (TODO_update_ssa
);
12198 /* If the function in NODE is tagged as an elemental SIMD function,
12199 create the appropriate SIMD clones. */
12202 expand_simd_clones (struct cgraph_node
*node
)
12204 tree attr
= lookup_attribute ("omp declare simd",
12205 DECL_ATTRIBUTES (node
->decl
));
12206 if (attr
== NULL_TREE
12207 || node
->global
.inlined_to
12208 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
12212 #pragma omp declare simd
12214 in C, there we don't know the argument types at all. */
12215 if (!node
->definition
12216 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
12221 /* Start with parsing the "omp declare simd" attribute(s). */
12222 bool inbranch_clause_specified
;
12223 struct cgraph_simd_clone
*clone_info
12224 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
12225 &inbranch_clause_specified
);
12226 if (clone_info
== NULL
)
12229 int orig_simdlen
= clone_info
->simdlen
;
12230 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
12231 /* The target can return 0 (no simd clones should be created),
12232 1 (just one ISA of simd clones should be created) or higher
12233 count of ISA variants. In that case, clone_info is initialized
12234 for the first ISA variant. */
12236 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
12241 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12242 also create one inbranch and one !inbranch clone of it. */
12243 for (int i
= 0; i
< count
* 2; i
++)
12245 struct cgraph_simd_clone
*clone
= clone_info
;
12246 if (inbranch_clause_specified
&& (i
& 1) != 0)
12251 clone
= simd_clone_struct_alloc (clone_info
->nargs
12253 simd_clone_struct_copy (clone
, clone_info
);
12254 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12255 and simd_clone_adjust_argument_types did to the first
12257 clone
->nargs
-= clone_info
->inbranch
;
12258 clone
->simdlen
= orig_simdlen
;
12259 /* And call the target hook again to get the right ISA. */
12260 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
12264 clone
->inbranch
= 1;
12267 /* simd_clone_mangle might fail if such a clone has been created
12269 tree id
= simd_clone_mangle (node
, clone
);
12270 if (id
== NULL_TREE
)
12273 /* Only when we are sure we want to create the clone actually
12274 clone the function (or definitions) or create another
12275 extern FUNCTION_DECL (for prototypes without definitions). */
12276 struct cgraph_node
*n
= simd_clone_create (node
);
12280 n
->simdclone
= clone
;
12281 clone
->origin
= node
;
12282 clone
->next_clone
= NULL
;
12283 if (node
->simd_clones
== NULL
)
12285 clone
->prev_clone
= n
;
12286 node
->simd_clones
= n
;
12290 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
12291 clone
->prev_clone
->simdclone
->next_clone
= n
;
12292 node
->simd_clones
->simdclone
->prev_clone
= n
;
12294 symtab
->change_decl_assembler_name (n
->decl
, id
);
12295 /* And finally adjust the return type, parameters and for
12296 definitions also function body. */
12297 if (node
->definition
)
12298 simd_clone_adjust (n
);
12301 simd_clone_adjust_return_type (n
);
12302 simd_clone_adjust_argument_types (n
);
12306 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
12309 /* Entry point for IPA simd clone creation pass. */
12311 static unsigned int
12312 ipa_omp_simd_clone (void)
12314 struct cgraph_node
*node
;
12315 FOR_EACH_FUNCTION (node
)
12316 expand_simd_clones (node
);
12322 const pass_data pass_data_omp_simd_clone
=
12324 SIMPLE_IPA_PASS
, /* type */
12325 "simdclone", /* name */
12326 OPTGROUP_NONE
, /* optinfo_flags */
12327 TV_NONE
, /* tv_id */
12328 ( PROP_ssa
| PROP_cfg
), /* properties_required */
12329 0, /* properties_provided */
12330 0, /* properties_destroyed */
12331 0, /* todo_flags_start */
12332 0, /* todo_flags_finish */
12335 class pass_omp_simd_clone
: public simple_ipa_opt_pass
12338 pass_omp_simd_clone(gcc::context
*ctxt
)
12339 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
12342 /* opt_pass methods: */
12343 virtual bool gate (function
*);
12344 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
12348 pass_omp_simd_clone::gate (function
*)
12350 return ((flag_openmp
|| flag_openmp_simd
12352 || (in_lto_p
&& !flag_wpa
))
12353 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
12356 } // anon namespace
12358 simple_ipa_opt_pass
*
12359 make_pass_omp_simd_clone (gcc::context
*ctxt
)
12361 return new pass_omp_simd_clone (ctxt
);
12364 #include "gt-omp-low.h"