1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
26 #include "coretypes.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
32 #include "basic-block.h"
33 #include "tree-ssa-alias.h"
34 #include "internal-fn.h"
35 #include "gimple-fold.h"
36 #include "gimple-expr.h"
40 #include "gimple-iterator.h"
41 #include "gimplify-me.h"
42 #include "gimple-walk.h"
43 #include "tree-iterator.h"
44 #include "tree-inline.h"
45 #include "langhooks.h"
46 #include "diagnostic-core.h"
47 #include "gimple-ssa.h"
50 #include "tree-phinodes.h"
51 #include "ssa-iterators.h"
52 #include "tree-ssanames.h"
53 #include "tree-into-ssa.h"
60 #include "tree-pass.h"
62 #include "splay-tree.h"
67 #include "gimple-low.h"
68 #include "tree-cfgcleanup.h"
69 #include "pretty-print.h"
71 #include "tree-nested.h"
76 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
77 phases. The first phase scans the function looking for OMP statements
78 and then for variables that must be replaced to satisfy data sharing
79 clauses. The second phase expands code for the constructs, as well as
80 re-gimplifying things when variables have been replaced with complex
83 Final code generation is done by pass_expand_omp. The flowgraph is
84 scanned for parallel regions which are then moved to a new
85 function, to be invoked by the thread library. */
87 /* Parallel region information. Every parallel and workshare
88 directive is enclosed between two markers, the OMP_* directive
89 and a corresponding OMP_RETURN statement. */
93 /* The enclosing region. */
94 struct omp_region
*outer
;
96 /* First child region. */
97 struct omp_region
*inner
;
99 /* Next peer region. */
100 struct omp_region
*next
;
102 /* Block containing the omp directive as its last stmt. */
105 /* Block containing the OMP_RETURN as its last stmt. */
108 /* Block containing the OMP_CONTINUE as its last stmt. */
111 /* If this is a combined parallel+workshare region, this is a list
112 of additional arguments needed by the combined parallel+workshare
114 vec
<tree
, va_gc
> *ws_args
;
116 /* The code for the omp directive of this region. */
117 enum gimple_code type
;
119 /* Schedule kind, only used for OMP_FOR type regions. */
120 enum omp_clause_schedule_kind sched_kind
;
122 /* True if this is a combined parallel+workshare region. */
123 bool is_combined_parallel
;
126 /* Context structure. Used to store information about each parallel
127 directive in the code. */
129 typedef struct omp_context
131 /* This field must be at the beginning, as we do "inheritance": Some
132 callback functions for tree-inline.c (e.g., omp_copy_decl)
133 receive a copy_body_data pointer that is up-casted to an
134 omp_context pointer. */
137 /* The tree of contexts corresponding to the encountered constructs. */
138 struct omp_context
*outer
;
141 /* Map variables to fields in a structure that allows communication
142 between sending and receiving threads. */
143 splay_tree field_map
;
148 /* These are used just by task contexts, if task firstprivate fn is
149 needed. srecord_type is used to communicate from the thread
150 that encountered the task construct to task firstprivate fn,
151 record_type is allocated by GOMP_task, initialized by task firstprivate
152 fn and passed to the task body fn. */
153 splay_tree sfield_map
;
156 /* A chain of variables to add to the top-level block surrounding the
157 construct. In the case of a parallel, this is in the child function. */
160 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
161 barriers should jump to during omplower pass. */
164 /* What to do with variables with implicitly determined sharing
166 enum omp_clause_default_kind default_kind
;
168 /* Nesting depth of this context. Used to beautify error messages re
169 invalid gotos. The outermost ctx is depth 1, with depth 0 being
170 reserved for the main body of the function. */
173 /* True if this parallel directive is nested within another. */
176 /* True if this construct can be cancelled. */
181 struct omp_for_data_loop
183 tree v
, n1
, n2
, step
;
184 enum tree_code cond_code
;
187 /* A structure describing the main elements of a parallel loop. */
191 struct omp_for_data_loop loop
;
196 bool have_nowait
, have_ordered
;
197 enum omp_clause_schedule_kind sched_kind
;
198 struct omp_for_data_loop
*loops
;
202 static splay_tree all_contexts
;
203 static int taskreg_nesting_level
;
204 static int target_nesting_level
;
205 static struct omp_region
*root_omp_region
;
206 static bitmap task_shared_vars
;
207 static vec
<omp_context
*> taskreg_contexts
;
209 static void scan_omp (gimple_seq
*, omp_context
*);
210 static tree
scan_omp_1_op (tree
*, int *, void *);
212 #define WALK_SUBSTMTS \
216 case GIMPLE_EH_FILTER: \
217 case GIMPLE_TRANSACTION: \
218 /* The sub-statements for these should be walked. */ \
219 *handled_ops_p = false; \
222 /* Convenience function for calling scan_omp_1_op on tree operands. */
225 scan_omp_op (tree
*tp
, omp_context
*ctx
)
227 struct walk_stmt_info wi
;
229 memset (&wi
, 0, sizeof (wi
));
231 wi
.want_locations
= true;
233 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
236 static void lower_omp (gimple_seq
*, omp_context
*);
237 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
238 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
240 /* Find an OpenMP clause of type KIND within CLAUSES. */
243 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
245 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
246 if (OMP_CLAUSE_CODE (clauses
) == kind
)
252 /* Return true if CTX is for an omp parallel. */
255 is_parallel_ctx (omp_context
*ctx
)
257 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
261 /* Return true if CTX is for an omp task. */
264 is_task_ctx (omp_context
*ctx
)
266 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
270 /* Return true if CTX is for an omp parallel or omp task. */
273 is_taskreg_ctx (omp_context
*ctx
)
275 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
276 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
280 /* Return true if REGION is a combined parallel+workshare region. */
283 is_combined_parallel (struct omp_region
*region
)
285 return region
->is_combined_parallel
;
289 /* Extract the header elements of parallel loop FOR_STMT and store
293 extract_omp_for_data (gimple for_stmt
, struct omp_for_data
*fd
,
294 struct omp_for_data_loop
*loops
)
296 tree t
, var
, *collapse_iter
, *collapse_count
;
297 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
298 struct omp_for_data_loop
*loop
;
300 struct omp_for_data_loop dummy_loop
;
301 location_t loc
= gimple_location (for_stmt
);
302 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
303 bool distribute
= gimple_omp_for_kind (for_stmt
)
304 == GF_OMP_FOR_KIND_DISTRIBUTE
;
306 fd
->for_stmt
= for_stmt
;
308 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
309 if (fd
->collapse
> 1)
312 fd
->loops
= &fd
->loop
;
314 fd
->have_nowait
= distribute
|| simd
;
315 fd
->have_ordered
= false;
316 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
317 fd
->chunk_size
= NULL_TREE
;
318 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
319 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
320 collapse_iter
= NULL
;
321 collapse_count
= NULL
;
323 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
324 switch (OMP_CLAUSE_CODE (t
))
326 case OMP_CLAUSE_NOWAIT
:
327 fd
->have_nowait
= true;
329 case OMP_CLAUSE_ORDERED
:
330 fd
->have_ordered
= true;
332 case OMP_CLAUSE_SCHEDULE
:
333 gcc_assert (!distribute
);
334 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
335 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
337 case OMP_CLAUSE_DIST_SCHEDULE
:
338 gcc_assert (distribute
);
339 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
341 case OMP_CLAUSE_COLLAPSE
:
342 if (fd
->collapse
> 1)
344 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
345 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
352 /* FIXME: for now map schedule(auto) to schedule(static).
353 There should be analysis to determine whether all iterations
354 are approximately the same amount of work (then schedule(static)
355 is best) or if it varies (then schedule(dynamic,N) is better). */
356 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
358 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
359 gcc_assert (fd
->chunk_size
== NULL
);
361 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
362 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
363 gcc_assert (fd
->chunk_size
== NULL
);
364 else if (fd
->chunk_size
== NULL
)
366 /* We only need to compute a default chunk size for ordered
367 static loops and dynamic loops. */
368 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
370 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
371 ? integer_zero_node
: integer_one_node
;
374 for (i
= 0; i
< fd
->collapse
; i
++)
376 if (fd
->collapse
== 1)
378 else if (loops
!= NULL
)
383 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
384 gcc_assert (SSA_VAR_P (loop
->v
));
385 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
386 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
387 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
388 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
390 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
391 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
392 switch (loop
->cond_code
)
398 gcc_assert (gimple_omp_for_kind (for_stmt
)
399 == GF_OMP_FOR_KIND_CILKSIMD
400 || (gimple_omp_for_kind (for_stmt
)
401 == GF_OMP_FOR_KIND_CILKFOR
));
404 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
405 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
407 loop
->n2
= fold_build2_loc (loc
,
408 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
409 build_int_cst (TREE_TYPE (loop
->n2
), 1));
410 loop
->cond_code
= LT_EXPR
;
413 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
414 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
416 loop
->n2
= fold_build2_loc (loc
,
417 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
418 build_int_cst (TREE_TYPE (loop
->n2
), 1));
419 loop
->cond_code
= GT_EXPR
;
425 t
= gimple_omp_for_incr (for_stmt
, i
);
426 gcc_assert (TREE_OPERAND (t
, 0) == var
);
427 switch (TREE_CODE (t
))
430 loop
->step
= TREE_OPERAND (t
, 1);
432 case POINTER_PLUS_EXPR
:
433 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
436 loop
->step
= TREE_OPERAND (t
, 1);
437 loop
->step
= fold_build1_loc (loc
,
438 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
446 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
447 && !fd
->have_ordered
))
449 if (fd
->collapse
== 1)
450 iter_type
= TREE_TYPE (loop
->v
);
452 || TYPE_PRECISION (iter_type
)
453 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
455 = build_nonstandard_integer_type
456 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
458 else if (iter_type
!= long_long_unsigned_type_node
)
460 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
461 iter_type
= long_long_unsigned_type_node
;
462 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
463 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
464 >= TYPE_PRECISION (iter_type
))
468 if (loop
->cond_code
== LT_EXPR
)
469 n
= fold_build2_loc (loc
,
470 PLUS_EXPR
, TREE_TYPE (loop
->v
),
471 loop
->n2
, loop
->step
);
474 if (TREE_CODE (n
) != INTEGER_CST
475 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
476 iter_type
= long_long_unsigned_type_node
;
478 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
479 > TYPE_PRECISION (iter_type
))
483 if (loop
->cond_code
== LT_EXPR
)
486 n2
= fold_build2_loc (loc
,
487 PLUS_EXPR
, TREE_TYPE (loop
->v
),
488 loop
->n2
, loop
->step
);
492 n1
= fold_build2_loc (loc
,
493 MINUS_EXPR
, TREE_TYPE (loop
->v
),
494 loop
->n2
, loop
->step
);
497 if (TREE_CODE (n1
) != INTEGER_CST
498 || TREE_CODE (n2
) != INTEGER_CST
499 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
500 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
501 iter_type
= long_long_unsigned_type_node
;
505 if (collapse_count
&& *collapse_count
== NULL
)
507 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
508 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
509 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
510 if (t
&& integer_zerop (t
))
511 count
= build_zero_cst (long_long_unsigned_type_node
);
512 else if ((i
== 0 || count
!= NULL_TREE
)
513 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
514 && TREE_CONSTANT (loop
->n1
)
515 && TREE_CONSTANT (loop
->n2
)
516 && TREE_CODE (loop
->step
) == INTEGER_CST
)
518 tree itype
= TREE_TYPE (loop
->v
);
520 if (POINTER_TYPE_P (itype
))
521 itype
= signed_type_for (itype
);
522 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
523 t
= fold_build2_loc (loc
,
525 fold_convert_loc (loc
, itype
, loop
->step
), t
);
526 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
527 fold_convert_loc (loc
, itype
, loop
->n2
));
528 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
529 fold_convert_loc (loc
, itype
, loop
->n1
));
530 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
531 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
532 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
533 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
534 fold_convert_loc (loc
, itype
,
537 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
538 fold_convert_loc (loc
, itype
, loop
->step
));
539 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
540 if (count
!= NULL_TREE
)
541 count
= fold_build2_loc (loc
,
542 MULT_EXPR
, long_long_unsigned_type_node
,
546 if (TREE_CODE (count
) != INTEGER_CST
)
549 else if (count
&& !integer_zerop (count
))
556 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
557 || fd
->have_ordered
))
559 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
560 iter_type
= long_long_unsigned_type_node
;
562 iter_type
= long_integer_type_node
;
564 else if (collapse_iter
&& *collapse_iter
!= NULL
)
565 iter_type
= TREE_TYPE (*collapse_iter
);
566 fd
->iter_type
= iter_type
;
567 if (collapse_iter
&& *collapse_iter
== NULL
)
568 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
569 if (collapse_count
&& *collapse_count
== NULL
)
572 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
574 *collapse_count
= create_tmp_var (iter_type
, ".count");
577 if (fd
->collapse
> 1)
579 fd
->loop
.v
= *collapse_iter
;
580 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
581 fd
->loop
.n2
= *collapse_count
;
582 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
583 fd
->loop
.cond_code
= LT_EXPR
;
588 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
589 is the immediate dominator of PAR_ENTRY_BB, return true if there
590 are no data dependencies that would prevent expanding the parallel
591 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
593 When expanding a combined parallel+workshare region, the call to
594 the child function may need additional arguments in the case of
595 GIMPLE_OMP_FOR regions. In some cases, these arguments are
596 computed out of variables passed in from the parent to the child
597 via 'struct .omp_data_s'. For instance:
599 #pragma omp parallel for schedule (guided, i * 4)
604 # BLOCK 2 (PAR_ENTRY_BB)
606 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
608 # BLOCK 3 (WS_ENTRY_BB)
609 .omp_data_i = &.omp_data_o;
610 D.1667 = .omp_data_i->i;
612 #pragma omp for schedule (guided, D.1598)
614 When we outline the parallel region, the call to the child function
615 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
616 that value is computed *after* the call site. So, in principle we
617 cannot do the transformation.
619 To see whether the code in WS_ENTRY_BB blocks the combined
620 parallel+workshare call, we collect all the variables used in the
621 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
622 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
625 FIXME. If we had the SSA form built at this point, we could merely
626 hoist the code in block 3 into block 2 and be done with it. But at
627 this point we don't have dataflow information and though we could
628 hack something up here, it is really not worth the aggravation. */
631 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
633 struct omp_for_data fd
;
634 gimple ws_stmt
= last_stmt (ws_entry_bb
);
636 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
639 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
641 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
643 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
645 if (fd
.iter_type
!= long_integer_type_node
)
648 /* FIXME. We give up too easily here. If any of these arguments
649 are not constants, they will likely involve variables that have
650 been mapped into fields of .omp_data_s for sharing with the child
651 function. With appropriate data flow, it would be possible to
653 if (!is_gimple_min_invariant (fd
.loop
.n1
)
654 || !is_gimple_min_invariant (fd
.loop
.n2
)
655 || !is_gimple_min_invariant (fd
.loop
.step
)
656 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
663 /* Collect additional arguments needed to emit a combined
664 parallel+workshare call. WS_STMT is the workshare directive being
667 static vec
<tree
, va_gc
> *
668 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
671 location_t loc
= gimple_location (ws_stmt
);
672 vec
<tree
, va_gc
> *ws_args
;
674 if (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
)
676 struct omp_for_data fd
;
679 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
683 if (gimple_omp_for_combined_into_p (ws_stmt
))
686 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
687 OMP_CLAUSE__LOOPTEMP_
);
689 n1
= OMP_CLAUSE_DECL (innerc
);
690 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
691 OMP_CLAUSE__LOOPTEMP_
);
693 n2
= OMP_CLAUSE_DECL (innerc
);
696 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
698 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
699 ws_args
->quick_push (t
);
701 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
702 ws_args
->quick_push (t
);
704 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
705 ws_args
->quick_push (t
);
709 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
710 ws_args
->quick_push (t
);
715 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
717 /* Number of sections is equal to the number of edges from the
718 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
719 the exit of the sections region. */
720 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
721 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
722 vec_alloc (ws_args
, 1);
723 ws_args
->quick_push (t
);
731 /* Discover whether REGION is a combined parallel+workshare region. */
734 determine_parallel_type (struct omp_region
*region
)
736 basic_block par_entry_bb
, par_exit_bb
;
737 basic_block ws_entry_bb
, ws_exit_bb
;
739 if (region
== NULL
|| region
->inner
== NULL
740 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
741 || region
->inner
->cont
== NULL
)
744 /* We only support parallel+for and parallel+sections. */
745 if (region
->type
!= GIMPLE_OMP_PARALLEL
746 || (region
->inner
->type
!= GIMPLE_OMP_FOR
747 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
750 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
751 WS_EXIT_BB -> PAR_EXIT_BB. */
752 par_entry_bb
= region
->entry
;
753 par_exit_bb
= region
->exit
;
754 ws_entry_bb
= region
->inner
->entry
;
755 ws_exit_bb
= region
->inner
->exit
;
757 if (single_succ (par_entry_bb
) == ws_entry_bb
758 && single_succ (ws_exit_bb
) == par_exit_bb
759 && workshare_safe_to_combine_p (ws_entry_bb
)
760 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
761 || (last_and_only_stmt (ws_entry_bb
)
762 && last_and_only_stmt (par_exit_bb
))))
764 gimple par_stmt
= last_stmt (par_entry_bb
);
765 gimple ws_stmt
= last_stmt (ws_entry_bb
);
767 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
769 /* If this is a combined parallel loop, we need to determine
770 whether or not to use the combined library calls. There
771 are two cases where we do not apply the transformation:
772 static loops and any kind of ordered loop. In the first
773 case, we already open code the loop so there is no need
774 to do anything else. In the latter case, the combined
775 parallel loop call would still need extra synchronization
776 to implement ordered semantics, so there would not be any
777 gain in using the combined call. */
778 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
779 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
781 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
782 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
784 region
->is_combined_parallel
= false;
785 region
->inner
->is_combined_parallel
= false;
790 region
->is_combined_parallel
= true;
791 region
->inner
->is_combined_parallel
= true;
792 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
797 /* Return true if EXPR is variable sized. */
800 is_variable_sized (const_tree expr
)
802 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
805 /* Return true if DECL is a reference type. */
808 is_reference (tree decl
)
810 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
813 /* Lookup variables in the decl or field splay trees. The "maybe" form
814 allows for the variable form to not have been entered, otherwise we
815 assert that the variable must have been entered. */
818 lookup_decl (tree var
, omp_context
*ctx
)
820 tree
*n
= ctx
->cb
.decl_map
->get (var
);
825 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
827 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
828 return n
? *n
: NULL_TREE
;
832 lookup_field (tree var
, omp_context
*ctx
)
835 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
836 return (tree
) n
->value
;
840 lookup_sfield (tree var
, omp_context
*ctx
)
843 n
= splay_tree_lookup (ctx
->sfield_map
844 ? ctx
->sfield_map
: ctx
->field_map
,
845 (splay_tree_key
) var
);
846 return (tree
) n
->value
;
850 maybe_lookup_field (tree var
, omp_context
*ctx
)
853 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
854 return n
? (tree
) n
->value
: NULL_TREE
;
857 /* Return true if DECL should be copied by pointer. SHARED_CTX is
858 the parallel context if DECL is to be shared. */
861 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
863 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
866 /* We can only use copy-in/copy-out semantics for shared variables
867 when we know the value is not accessible from an outer scope. */
870 /* ??? Trivially accessible from anywhere. But why would we even
871 be passing an address in this case? Should we simply assert
872 this to be false, or should we have a cleanup pass that removes
873 these from the list of mappings? */
874 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
877 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
878 without analyzing the expression whether or not its location
879 is accessible to anyone else. In the case of nested parallel
880 regions it certainly may be. */
881 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
884 /* Do not use copy-in/copy-out for variables that have their
886 if (TREE_ADDRESSABLE (decl
))
889 /* lower_send_shared_vars only uses copy-in, but not copy-out
891 if (TREE_READONLY (decl
)
892 || ((TREE_CODE (decl
) == RESULT_DECL
893 || TREE_CODE (decl
) == PARM_DECL
)
894 && DECL_BY_REFERENCE (decl
)))
897 /* Disallow copy-in/out in nested parallel if
898 decl is shared in outer parallel, otherwise
899 each thread could store the shared variable
900 in its own copy-in location, making the
901 variable no longer really shared. */
902 if (shared_ctx
->is_nested
)
906 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
907 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
914 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
915 c
; c
= OMP_CLAUSE_CHAIN (c
))
916 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
917 && OMP_CLAUSE_DECL (c
) == decl
)
921 goto maybe_mark_addressable_and_ret
;
925 /* For tasks avoid using copy-in/out. As tasks can be
926 deferred or executed in different thread, when GOMP_task
927 returns, the task hasn't necessarily terminated. */
928 if (is_task_ctx (shared_ctx
))
931 maybe_mark_addressable_and_ret
:
932 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
933 if (is_gimple_reg (outer
))
935 /* Taking address of OUTER in lower_send_shared_vars
936 might need regimplification of everything that uses the
938 if (!task_shared_vars
)
939 task_shared_vars
= BITMAP_ALLOC (NULL
);
940 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
941 TREE_ADDRESSABLE (outer
) = 1;
950 /* Construct a new automatic decl similar to VAR. */
953 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
955 tree copy
= copy_var_decl (var
, name
, type
);
957 DECL_CONTEXT (copy
) = current_function_decl
;
958 DECL_CHAIN (copy
) = ctx
->block_vars
;
959 ctx
->block_vars
= copy
;
965 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
967 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
970 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
973 omp_build_component_ref (tree obj
, tree field
)
975 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
976 if (TREE_THIS_VOLATILE (field
))
977 TREE_THIS_VOLATILE (ret
) |= 1;
978 if (TREE_READONLY (field
))
979 TREE_READONLY (ret
) |= 1;
983 /* Build tree nodes to access the field for VAR on the receiver side. */
986 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
988 tree x
, field
= lookup_field (var
, ctx
);
990 /* If the receiver record type was remapped in the child function,
991 remap the field into the new record type. */
992 x
= maybe_lookup_field (field
, ctx
);
996 x
= build_simple_mem_ref (ctx
->receiver_decl
);
997 x
= omp_build_component_ref (x
, field
);
999 x
= build_simple_mem_ref (x
);
1004 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1005 of a parallel, this is a component reference; for workshare constructs
1006 this is some variable. */
1009 build_outer_var_ref (tree var
, omp_context
*ctx
)
1013 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1015 else if (is_variable_sized (var
))
1017 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1018 x
= build_outer_var_ref (x
, ctx
);
1019 x
= build_simple_mem_ref (x
);
1021 else if (is_taskreg_ctx (ctx
))
1023 bool by_ref
= use_pointer_for_field (var
, NULL
);
1024 x
= build_receiver_ref (var
, by_ref
, ctx
);
1026 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1027 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1029 /* #pragma omp simd isn't a worksharing construct, and can reference even
1030 private vars in its linear etc. clauses. */
1032 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1033 x
= lookup_decl (var
, ctx
->outer
);
1034 else if (ctx
->outer
)
1035 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1039 else if (ctx
->outer
)
1040 x
= lookup_decl (var
, ctx
->outer
);
1041 else if (is_reference (var
))
1042 /* This can happen with orphaned constructs. If var is reference, it is
1043 possible it is shared and as such valid. */
1048 if (is_reference (var
))
1049 x
= build_simple_mem_ref (x
);
1054 /* Build tree nodes to access the field for VAR on the sender side. */
1057 build_sender_ref (tree var
, omp_context
*ctx
)
1059 tree field
= lookup_sfield (var
, ctx
);
1060 return omp_build_component_ref (ctx
->sender_decl
, field
);
1063 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1066 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1068 tree field
, type
, sfield
= NULL_TREE
;
1070 gcc_assert ((mask
& 1) == 0
1071 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1072 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1073 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1075 type
= TREE_TYPE (var
);
1078 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1079 type
= build_pointer_type (build_pointer_type (type
));
1082 type
= build_pointer_type (type
);
1083 else if ((mask
& 3) == 1 && is_reference (var
))
1084 type
= TREE_TYPE (type
);
1086 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1087 FIELD_DECL
, DECL_NAME (var
), type
);
1089 /* Remember what variable this field was created for. This does have a
1090 side effect of making dwarf2out ignore this member, so for helpful
1091 debugging we clear it later in delete_omp_context. */
1092 DECL_ABSTRACT_ORIGIN (field
) = var
;
1093 if (type
== TREE_TYPE (var
))
1095 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1096 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1097 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1100 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1102 if ((mask
& 3) == 3)
1104 insert_field_into_struct (ctx
->record_type
, field
);
1105 if (ctx
->srecord_type
)
1107 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1108 FIELD_DECL
, DECL_NAME (var
), type
);
1109 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1110 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1111 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1112 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1113 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1118 if (ctx
->srecord_type
== NULL_TREE
)
1122 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1123 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1124 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1126 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1127 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1128 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1129 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1130 splay_tree_insert (ctx
->sfield_map
,
1131 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1132 (splay_tree_value
) sfield
);
1136 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1137 : ctx
->srecord_type
, field
);
1141 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1142 (splay_tree_value
) field
);
1143 if ((mask
& 2) && ctx
->sfield_map
)
1144 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1145 (splay_tree_value
) sfield
);
1149 install_var_local (tree var
, omp_context
*ctx
)
1151 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1152 insert_decl_map (&ctx
->cb
, var
, new_var
);
1156 /* Adjust the replacement for DECL in CTX for the new context. This means
1157 copying the DECL_VALUE_EXPR, and fixing up the type. */
1160 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1162 tree new_decl
, size
;
1164 new_decl
= lookup_decl (decl
, ctx
);
1166 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1168 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1169 && DECL_HAS_VALUE_EXPR_P (decl
))
1171 tree ve
= DECL_VALUE_EXPR (decl
);
1172 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1173 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1174 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1177 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1179 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1180 if (size
== error_mark_node
)
1181 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1182 DECL_SIZE (new_decl
) = size
;
1184 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1185 if (size
== error_mark_node
)
1186 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1187 DECL_SIZE_UNIT (new_decl
) = size
;
1191 /* The callback for remap_decl. Search all containing contexts for a
1192 mapping of the variable; this avoids having to duplicate the splay
1193 tree ahead of time. We know a mapping doesn't already exist in the
1194 given context. Create new mappings to implement default semantics. */
1197 omp_copy_decl (tree var
, copy_body_data
*cb
)
1199 omp_context
*ctx
= (omp_context
*) cb
;
1202 if (TREE_CODE (var
) == LABEL_DECL
)
1204 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1205 DECL_CONTEXT (new_var
) = current_function_decl
;
1206 insert_decl_map (&ctx
->cb
, var
, new_var
);
1210 while (!is_taskreg_ctx (ctx
))
1215 new_var
= maybe_lookup_decl (var
, ctx
);
1220 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1223 return error_mark_node
;
1227 /* Debugging dumps for parallel regions. */
1228 void dump_omp_region (FILE *, struct omp_region
*, int);
1229 void debug_omp_region (struct omp_region
*);
1230 void debug_all_omp_regions (void);
1232 /* Dump the parallel region tree rooted at REGION. */
1235 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1237 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1238 gimple_code_name
[region
->type
]);
1241 dump_omp_region (file
, region
->inner
, indent
+ 4);
1245 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1246 region
->cont
->index
);
1250 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1251 region
->exit
->index
);
1253 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1256 dump_omp_region (file
, region
->next
, indent
);
1260 debug_omp_region (struct omp_region
*region
)
1262 dump_omp_region (stderr
, region
, 0);
1266 debug_all_omp_regions (void)
1268 dump_omp_region (stderr
, root_omp_region
, 0);
1272 /* Create a new parallel region starting at STMT inside region PARENT. */
1274 static struct omp_region
*
1275 new_omp_region (basic_block bb
, enum gimple_code type
,
1276 struct omp_region
*parent
)
1278 struct omp_region
*region
= XCNEW (struct omp_region
);
1280 region
->outer
= parent
;
1282 region
->type
= type
;
1286 /* This is a nested region. Add it to the list of inner
1287 regions in PARENT. */
1288 region
->next
= parent
->inner
;
1289 parent
->inner
= region
;
1293 /* This is a toplevel region. Add it to the list of toplevel
1294 regions in ROOT_OMP_REGION. */
1295 region
->next
= root_omp_region
;
1296 root_omp_region
= region
;
1302 /* Release the memory associated with the region tree rooted at REGION. */
1305 free_omp_region_1 (struct omp_region
*region
)
1307 struct omp_region
*i
, *n
;
1309 for (i
= region
->inner
; i
; i
= n
)
1312 free_omp_region_1 (i
);
1318 /* Release the memory for the entire omp region tree. */
1321 free_omp_regions (void)
1323 struct omp_region
*r
, *n
;
1324 for (r
= root_omp_region
; r
; r
= n
)
1327 free_omp_region_1 (r
);
1329 root_omp_region
= NULL
;
1333 /* Create a new context, with OUTER_CTX being the surrounding context. */
1335 static omp_context
*
1336 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1338 omp_context
*ctx
= XCNEW (omp_context
);
1340 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1341 (splay_tree_value
) ctx
);
1346 ctx
->outer
= outer_ctx
;
1347 ctx
->cb
= outer_ctx
->cb
;
1348 ctx
->cb
.block
= NULL
;
1349 ctx
->depth
= outer_ctx
->depth
+ 1;
1353 ctx
->cb
.src_fn
= current_function_decl
;
1354 ctx
->cb
.dst_fn
= current_function_decl
;
1355 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1356 gcc_checking_assert (ctx
->cb
.src_node
);
1357 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1358 ctx
->cb
.src_cfun
= cfun
;
1359 ctx
->cb
.copy_decl
= omp_copy_decl
;
1360 ctx
->cb
.eh_lp_nr
= 0;
1361 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1365 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1370 static gimple_seq
maybe_catch_exception (gimple_seq
);
1372 /* Finalize task copyfn. */
1375 finalize_task_copyfn (gimple task_stmt
)
1377 struct function
*child_cfun
;
1379 gimple_seq seq
= NULL
, new_seq
;
1382 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1383 if (child_fn
== NULL_TREE
)
1386 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1387 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1389 push_cfun (child_cfun
);
1390 bind
= gimplify_body (child_fn
, false);
1391 gimple_seq_add_stmt (&seq
, bind
);
1392 new_seq
= maybe_catch_exception (seq
);
1395 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1397 gimple_seq_add_stmt (&seq
, bind
);
1399 gimple_set_body (child_fn
, seq
);
1402 /* Inform the callgraph about the new function. */
1403 cgraph_node::add_new_function (child_fn
, false);
1406 /* Destroy a omp_context data structures. Called through the splay tree
1407 value delete callback. */
1410 delete_omp_context (splay_tree_value value
)
1412 omp_context
*ctx
= (omp_context
*) value
;
1414 delete ctx
->cb
.decl_map
;
1417 splay_tree_delete (ctx
->field_map
);
1418 if (ctx
->sfield_map
)
1419 splay_tree_delete (ctx
->sfield_map
);
1421 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1422 it produces corrupt debug information. */
1423 if (ctx
->record_type
)
1426 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1427 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1429 if (ctx
->srecord_type
)
1432 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1433 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1436 if (is_task_ctx (ctx
))
1437 finalize_task_copyfn (ctx
->stmt
);
1442 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1446 fixup_child_record_type (omp_context
*ctx
)
1448 tree f
, type
= ctx
->record_type
;
1450 /* ??? It isn't sufficient to just call remap_type here, because
1451 variably_modified_type_p doesn't work the way we expect for
1452 record types. Testing each field for whether it needs remapping
1453 and creating a new record by hand works, however. */
1454 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1455 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1459 tree name
, new_fields
= NULL
;
1461 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1462 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1463 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1464 TYPE_DECL
, name
, type
);
1465 TYPE_NAME (type
) = name
;
1467 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1469 tree new_f
= copy_node (f
);
1470 DECL_CONTEXT (new_f
) = type
;
1471 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1472 DECL_CHAIN (new_f
) = new_fields
;
1473 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1474 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1476 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1480 /* Arrange to be able to look up the receiver field
1481 given the sender field. */
1482 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1483 (splay_tree_value
) new_f
);
1485 TYPE_FIELDS (type
) = nreverse (new_fields
);
1489 TREE_TYPE (ctx
->receiver_decl
) = build_pointer_type (type
);
1492 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1493 specified by CLAUSES. */
1496 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1499 bool scan_array_reductions
= false;
1501 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1505 switch (OMP_CLAUSE_CODE (c
))
1507 case OMP_CLAUSE_PRIVATE
:
1508 decl
= OMP_CLAUSE_DECL (c
);
1509 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1511 else if (!is_variable_sized (decl
))
1512 install_var_local (decl
, ctx
);
1515 case OMP_CLAUSE_SHARED
:
1516 decl
= OMP_CLAUSE_DECL (c
);
1517 /* Ignore shared directives in teams construct. */
1518 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1520 /* Global variables don't need to be copied,
1521 the receiver side will use them directly. */
1522 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1523 if (is_global_var (odecl
))
1525 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1528 gcc_assert (is_taskreg_ctx (ctx
));
1529 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1530 || !is_variable_sized (decl
));
1531 /* Global variables don't need to be copied,
1532 the receiver side will use them directly. */
1533 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1535 by_ref
= use_pointer_for_field (decl
, ctx
);
1536 if (! TREE_READONLY (decl
)
1537 || TREE_ADDRESSABLE (decl
)
1539 || is_reference (decl
))
1541 install_var_field (decl
, by_ref
, 3, ctx
);
1542 install_var_local (decl
, ctx
);
1545 /* We don't need to copy const scalar vars back. */
1546 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1549 case OMP_CLAUSE_LASTPRIVATE
:
1550 /* Let the corresponding firstprivate clause create
1552 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1556 case OMP_CLAUSE_FIRSTPRIVATE
:
1557 case OMP_CLAUSE_REDUCTION
:
1558 case OMP_CLAUSE_LINEAR
:
1559 decl
= OMP_CLAUSE_DECL (c
);
1561 if (is_variable_sized (decl
))
1563 if (is_task_ctx (ctx
))
1564 install_var_field (decl
, false, 1, ctx
);
1567 else if (is_taskreg_ctx (ctx
))
1570 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1571 by_ref
= use_pointer_for_field (decl
, NULL
);
1573 if (is_task_ctx (ctx
)
1574 && (global
|| by_ref
|| is_reference (decl
)))
1576 install_var_field (decl
, false, 1, ctx
);
1578 install_var_field (decl
, by_ref
, 2, ctx
);
1581 install_var_field (decl
, by_ref
, 3, ctx
);
1583 install_var_local (decl
, ctx
);
1586 case OMP_CLAUSE__LOOPTEMP_
:
1587 gcc_assert (is_parallel_ctx (ctx
));
1588 decl
= OMP_CLAUSE_DECL (c
);
1589 install_var_field (decl
, false, 3, ctx
);
1590 install_var_local (decl
, ctx
);
1593 case OMP_CLAUSE_COPYPRIVATE
:
1594 case OMP_CLAUSE_COPYIN
:
1595 decl
= OMP_CLAUSE_DECL (c
);
1596 by_ref
= use_pointer_for_field (decl
, NULL
);
1597 install_var_field (decl
, by_ref
, 3, ctx
);
1600 case OMP_CLAUSE_DEFAULT
:
1601 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1604 case OMP_CLAUSE_FINAL
:
1606 case OMP_CLAUSE_NUM_THREADS
:
1607 case OMP_CLAUSE_NUM_TEAMS
:
1608 case OMP_CLAUSE_THREAD_LIMIT
:
1609 case OMP_CLAUSE_DEVICE
:
1610 case OMP_CLAUSE_SCHEDULE
:
1611 case OMP_CLAUSE_DIST_SCHEDULE
:
1612 case OMP_CLAUSE_DEPEND
:
1613 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1615 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1619 case OMP_CLAUSE_FROM
:
1620 case OMP_CLAUSE_MAP
:
1622 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1623 decl
= OMP_CLAUSE_DECL (c
);
1624 /* Global variables with "omp declare target" attribute
1625 don't need to be copied, the receiver side will use them
1627 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1629 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1630 && lookup_attribute ("omp declare target",
1631 DECL_ATTRIBUTES (decl
)))
1633 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1634 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
)
1636 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1637 #pragma omp target data, there is nothing to map for
1639 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
1640 && !POINTER_TYPE_P (TREE_TYPE (decl
)))
1645 if (DECL_SIZE (decl
)
1646 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1648 tree decl2
= DECL_VALUE_EXPR (decl
);
1649 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1650 decl2
= TREE_OPERAND (decl2
, 0);
1651 gcc_assert (DECL_P (decl2
));
1652 install_var_field (decl2
, true, 3, ctx
);
1653 install_var_local (decl2
, ctx
);
1654 install_var_local (decl
, ctx
);
1658 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1659 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1660 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1661 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1662 install_var_field (decl
, true, 7, ctx
);
1664 install_var_field (decl
, true, 3, ctx
);
1665 if (gimple_omp_target_kind (ctx
->stmt
)
1666 == GF_OMP_TARGET_KIND_REGION
)
1667 install_var_local (decl
, ctx
);
1672 tree base
= get_base_address (decl
);
1673 tree nc
= OMP_CLAUSE_CHAIN (c
);
1676 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1677 && OMP_CLAUSE_DECL (nc
) == base
1678 && OMP_CLAUSE_MAP_KIND (nc
) == OMP_CLAUSE_MAP_POINTER
1679 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1681 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1682 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1688 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1689 decl
= OMP_CLAUSE_DECL (c
);
1691 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1692 (splay_tree_key
) decl
));
1694 = build_decl (OMP_CLAUSE_LOCATION (c
),
1695 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1696 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1697 insert_field_into_struct (ctx
->record_type
, field
);
1698 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1699 (splay_tree_value
) field
);
1704 case OMP_CLAUSE_NOWAIT
:
1705 case OMP_CLAUSE_ORDERED
:
1706 case OMP_CLAUSE_COLLAPSE
:
1707 case OMP_CLAUSE_UNTIED
:
1708 case OMP_CLAUSE_MERGEABLE
:
1709 case OMP_CLAUSE_PROC_BIND
:
1710 case OMP_CLAUSE_SAFELEN
:
1713 case OMP_CLAUSE_ALIGNED
:
1714 decl
= OMP_CLAUSE_DECL (c
);
1715 if (is_global_var (decl
)
1716 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1717 install_var_local (decl
, ctx
);
1725 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1727 switch (OMP_CLAUSE_CODE (c
))
1729 case OMP_CLAUSE_LASTPRIVATE
:
1730 /* Let the corresponding firstprivate clause create
1732 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1733 scan_array_reductions
= true;
1734 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1738 case OMP_CLAUSE_PRIVATE
:
1739 case OMP_CLAUSE_FIRSTPRIVATE
:
1740 case OMP_CLAUSE_REDUCTION
:
1741 case OMP_CLAUSE_LINEAR
:
1742 decl
= OMP_CLAUSE_DECL (c
);
1743 if (is_variable_sized (decl
))
1744 install_var_local (decl
, ctx
);
1745 fixup_remapped_decl (decl
, ctx
,
1746 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1747 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1748 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1749 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1750 scan_array_reductions
= true;
1751 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1752 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1753 scan_array_reductions
= true;
1756 case OMP_CLAUSE_SHARED
:
1757 /* Ignore shared directives in teams construct. */
1758 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1760 decl
= OMP_CLAUSE_DECL (c
);
1761 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1762 fixup_remapped_decl (decl
, ctx
, false);
1765 case OMP_CLAUSE_MAP
:
1766 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
)
1768 decl
= OMP_CLAUSE_DECL (c
);
1770 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1771 && lookup_attribute ("omp declare target",
1772 DECL_ATTRIBUTES (decl
)))
1776 if (OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1777 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1778 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1780 tree new_decl
= lookup_decl (decl
, ctx
);
1781 TREE_TYPE (new_decl
)
1782 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1784 else if (DECL_SIZE (decl
)
1785 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1787 tree decl2
= DECL_VALUE_EXPR (decl
);
1788 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1789 decl2
= TREE_OPERAND (decl2
, 0);
1790 gcc_assert (DECL_P (decl2
));
1791 fixup_remapped_decl (decl2
, ctx
, false);
1792 fixup_remapped_decl (decl
, ctx
, true);
1795 fixup_remapped_decl (decl
, ctx
, false);
1799 case OMP_CLAUSE_COPYPRIVATE
:
1800 case OMP_CLAUSE_COPYIN
:
1801 case OMP_CLAUSE_DEFAULT
:
1803 case OMP_CLAUSE_NUM_THREADS
:
1804 case OMP_CLAUSE_NUM_TEAMS
:
1805 case OMP_CLAUSE_THREAD_LIMIT
:
1806 case OMP_CLAUSE_DEVICE
:
1807 case OMP_CLAUSE_SCHEDULE
:
1808 case OMP_CLAUSE_DIST_SCHEDULE
:
1809 case OMP_CLAUSE_NOWAIT
:
1810 case OMP_CLAUSE_ORDERED
:
1811 case OMP_CLAUSE_COLLAPSE
:
1812 case OMP_CLAUSE_UNTIED
:
1813 case OMP_CLAUSE_FINAL
:
1814 case OMP_CLAUSE_MERGEABLE
:
1815 case OMP_CLAUSE_PROC_BIND
:
1816 case OMP_CLAUSE_SAFELEN
:
1817 case OMP_CLAUSE_ALIGNED
:
1818 case OMP_CLAUSE_DEPEND
:
1819 case OMP_CLAUSE__LOOPTEMP_
:
1821 case OMP_CLAUSE_FROM
:
1822 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1830 if (scan_array_reductions
)
1831 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1832 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1833 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1835 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
1836 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
1838 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
1839 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1840 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
1841 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1842 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1843 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
1846 /* Create a new name for omp child function. Returns an identifier. If
1847 IS_CILK_FOR is true then the suffix for the child function is
1851 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
1854 return clone_function_name (current_function_decl
, "_cilk_for_fn");
1855 return clone_function_name (current_function_decl
,
1856 task_copy
? "_omp_cpyfn" : "_omp_fn");
1859 /* Returns the type of the induction variable for the child function for
1860 _Cilk_for and the types for _high and _low variables based on TYPE. */
1863 cilk_for_check_loop_diff_type (tree type
)
1865 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
1867 if (TYPE_UNSIGNED (type
))
1868 return uint32_type_node
;
1870 return integer_type_node
;
1874 if (TYPE_UNSIGNED (type
))
1875 return uint64_type_node
;
1877 return long_long_integer_type_node
;
1881 /* Build a decl for the omp child function. It'll not contain a body
1882 yet, just the bare decl. */
1885 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
1887 tree decl
, type
, name
, t
;
1890 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
1891 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
1892 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
1893 tree cilk_var_type
= NULL_TREE
;
1895 name
= create_omp_child_function_name (task_copy
,
1896 cilk_for_count
!= NULL_TREE
);
1898 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1899 ptr_type_node
, NULL_TREE
);
1900 else if (cilk_for_count
)
1902 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
1903 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
1904 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1905 cilk_var_type
, cilk_var_type
, NULL_TREE
);
1908 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
1910 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
1913 ctx
->cb
.dst_fn
= decl
;
1915 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
1917 TREE_STATIC (decl
) = 1;
1918 TREE_USED (decl
) = 1;
1919 DECL_ARTIFICIAL (decl
) = 1;
1920 DECL_IGNORED_P (decl
) = 0;
1921 TREE_PUBLIC (decl
) = 0;
1922 DECL_UNINLINABLE (decl
) = 1;
1923 DECL_EXTERNAL (decl
) = 0;
1924 DECL_CONTEXT (decl
) = NULL_TREE
;
1925 DECL_INITIAL (decl
) = make_node (BLOCK
);
1926 bool target_p
= false;
1927 if (lookup_attribute ("omp declare target",
1928 DECL_ATTRIBUTES (current_function_decl
)))
1933 for (octx
= ctx
; octx
; octx
= octx
->outer
)
1934 if (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
1935 && gimple_omp_target_kind (octx
->stmt
)
1936 == GF_OMP_TARGET_KIND_REGION
)
1943 DECL_ATTRIBUTES (decl
)
1944 = tree_cons (get_identifier ("omp declare target"),
1945 NULL_TREE
, DECL_ATTRIBUTES (decl
));
1947 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1948 RESULT_DECL
, NULL_TREE
, void_type_node
);
1949 DECL_ARTIFICIAL (t
) = 1;
1950 DECL_IGNORED_P (t
) = 1;
1951 DECL_CONTEXT (t
) = decl
;
1952 DECL_RESULT (decl
) = t
;
1954 /* _Cilk_for's child function requires two extra parameters called
1955 __low and __high that are set the by Cilk runtime when it calls this
1959 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1960 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
1961 DECL_ARTIFICIAL (t
) = 1;
1962 DECL_NAMELESS (t
) = 1;
1963 DECL_ARG_TYPE (t
) = ptr_type_node
;
1964 DECL_CONTEXT (t
) = current_function_decl
;
1966 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1967 DECL_ARGUMENTS (decl
) = t
;
1969 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1970 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
1971 DECL_ARTIFICIAL (t
) = 1;
1972 DECL_NAMELESS (t
) = 1;
1973 DECL_ARG_TYPE (t
) = ptr_type_node
;
1974 DECL_CONTEXT (t
) = current_function_decl
;
1976 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1977 DECL_ARGUMENTS (decl
) = t
;
1980 tree data_name
= get_identifier (".omp_data_i");
1981 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
1983 DECL_ARTIFICIAL (t
) = 1;
1984 DECL_NAMELESS (t
) = 1;
1985 DECL_ARG_TYPE (t
) = ptr_type_node
;
1986 DECL_CONTEXT (t
) = current_function_decl
;
1989 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1990 DECL_ARGUMENTS (decl
) = t
;
1992 ctx
->receiver_decl
= t
;
1995 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1996 PARM_DECL
, get_identifier (".omp_data_o"),
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
;
2003 TREE_ADDRESSABLE (t
) = 1;
2004 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2005 DECL_ARGUMENTS (decl
) = t
;
2008 /* Allocate memory for the function structure. The call to
2009 allocate_struct_function clobbers CFUN, so we need to restore
2011 push_struct_function (decl
);
2012 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2016 /* Callback for walk_gimple_seq. Check if combined parallel
2017 contains gimple_omp_for_combined_into_p OMP_FOR. */
2020 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2021 bool *handled_ops_p
,
2022 struct walk_stmt_info
*wi
)
2024 gimple stmt
= gsi_stmt (*gsi_p
);
2026 *handled_ops_p
= true;
2027 switch (gimple_code (stmt
))
2031 case GIMPLE_OMP_FOR
:
2032 if (gimple_omp_for_combined_into_p (stmt
)
2033 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
2036 return integer_zero_node
;
2045 /* Scan an OpenMP parallel directive. */
2048 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2052 gimple stmt
= gsi_stmt (*gsi
);
2054 /* Ignore parallel directives with empty bodies, unless there
2055 are copyin clauses. */
2057 && empty_body_p (gimple_omp_body (stmt
))
2058 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2059 OMP_CLAUSE_COPYIN
) == NULL
)
2061 gsi_replace (gsi
, gimple_build_nop (), false);
2065 if (gimple_omp_parallel_combined_p (stmt
))
2068 struct walk_stmt_info wi
;
2070 memset (&wi
, 0, sizeof (wi
));
2072 walk_gimple_seq (gimple_omp_body (stmt
),
2073 find_combined_for
, NULL
, &wi
);
2074 for_stmt
= (gimple
) wi
.info
;
2077 struct omp_for_data fd
;
2078 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2079 /* We need two temporaries with fd.loop.v type (istart/iend)
2080 and then (fd.collapse - 1) temporaries with the same
2081 type for count2 ... countN-1 vars if not constant. */
2082 size_t count
= 2, i
;
2083 tree type
= fd
.iter_type
;
2085 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2086 count
+= fd
.collapse
- 1;
2087 for (i
= 0; i
< count
; i
++)
2089 tree temp
= create_tmp_var (type
, NULL
);
2090 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2091 OMP_CLAUSE__LOOPTEMP_
);
2092 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2093 OMP_CLAUSE_DECL (c
) = temp
;
2094 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2095 gimple_omp_parallel_set_clauses (stmt
, c
);
2100 ctx
= new_omp_context (stmt
, outer_ctx
);
2101 taskreg_contexts
.safe_push (ctx
);
2102 if (taskreg_nesting_level
> 1)
2103 ctx
->is_nested
= true;
2104 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2105 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2106 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2107 name
= create_tmp_var_name (".omp_data_s");
2108 name
= build_decl (gimple_location (stmt
),
2109 TYPE_DECL
, name
, ctx
->record_type
);
2110 DECL_ARTIFICIAL (name
) = 1;
2111 DECL_NAMELESS (name
) = 1;
2112 TYPE_NAME (ctx
->record_type
) = name
;
2113 create_omp_child_function (ctx
, false);
2114 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2116 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2117 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2119 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2120 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2123 /* Scan an OpenMP task directive. */
2126 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2130 gimple stmt
= gsi_stmt (*gsi
);
2132 /* Ignore task directives with empty bodies. */
2134 && empty_body_p (gimple_omp_body (stmt
)))
2136 gsi_replace (gsi
, gimple_build_nop (), false);
2140 ctx
= new_omp_context (stmt
, outer_ctx
);
2141 taskreg_contexts
.safe_push (ctx
);
2142 if (taskreg_nesting_level
> 1)
2143 ctx
->is_nested
= true;
2144 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2145 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2146 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2147 name
= create_tmp_var_name (".omp_data_s");
2148 name
= build_decl (gimple_location (stmt
),
2149 TYPE_DECL
, name
, ctx
->record_type
);
2150 DECL_ARTIFICIAL (name
) = 1;
2151 DECL_NAMELESS (name
) = 1;
2152 TYPE_NAME (ctx
->record_type
) = name
;
2153 create_omp_child_function (ctx
, false);
2154 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2156 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2158 if (ctx
->srecord_type
)
2160 name
= create_tmp_var_name (".omp_data_a");
2161 name
= build_decl (gimple_location (stmt
),
2162 TYPE_DECL
, name
, ctx
->srecord_type
);
2163 DECL_ARTIFICIAL (name
) = 1;
2164 DECL_NAMELESS (name
) = 1;
2165 TYPE_NAME (ctx
->srecord_type
) = name
;
2166 create_omp_child_function (ctx
, true);
2169 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2171 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2173 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2174 t
= build_int_cst (long_integer_type_node
, 0);
2175 gimple_omp_task_set_arg_size (stmt
, t
);
2176 t
= build_int_cst (long_integer_type_node
, 1);
2177 gimple_omp_task_set_arg_align (stmt
, t
);
2182 /* If any decls have been made addressable during scan_omp,
2183 adjust their fields if needed, and layout record types
2184 of parallel/task constructs. */
2187 finish_taskreg_scan (omp_context
*ctx
)
2189 if (ctx
->record_type
== NULL_TREE
)
2192 /* If any task_shared_vars were needed, verify all
2193 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2194 statements if use_pointer_for_field hasn't changed
2195 because of that. If it did, update field types now. */
2196 if (task_shared_vars
)
2200 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2201 c
; c
= OMP_CLAUSE_CHAIN (c
))
2202 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
2204 tree decl
= OMP_CLAUSE_DECL (c
);
2206 /* Global variables don't need to be copied,
2207 the receiver side will use them directly. */
2208 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2210 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2211 || !use_pointer_for_field (decl
, ctx
))
2213 tree field
= lookup_field (decl
, ctx
);
2214 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2215 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2217 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2218 TREE_THIS_VOLATILE (field
) = 0;
2219 DECL_USER_ALIGN (field
) = 0;
2220 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2221 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2222 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2223 if (ctx
->srecord_type
)
2225 tree sfield
= lookup_sfield (decl
, ctx
);
2226 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2227 TREE_THIS_VOLATILE (sfield
) = 0;
2228 DECL_USER_ALIGN (sfield
) = 0;
2229 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2230 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2231 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2236 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2238 layout_type (ctx
->record_type
);
2239 fixup_child_record_type (ctx
);
2243 location_t loc
= gimple_location (ctx
->stmt
);
2244 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2245 /* Move VLA fields to the end. */
2246 p
= &TYPE_FIELDS (ctx
->record_type
);
2248 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2249 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2252 *p
= TREE_CHAIN (*p
);
2253 TREE_CHAIN (*q
) = NULL_TREE
;
2254 q
= &TREE_CHAIN (*q
);
2257 p
= &DECL_CHAIN (*p
);
2259 layout_type (ctx
->record_type
);
2260 fixup_child_record_type (ctx
);
2261 if (ctx
->srecord_type
)
2262 layout_type (ctx
->srecord_type
);
2263 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2264 TYPE_SIZE_UNIT (ctx
->record_type
));
2265 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2266 t
= build_int_cst (long_integer_type_node
,
2267 TYPE_ALIGN_UNIT (ctx
->record_type
));
2268 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2273 /* Scan an OpenMP loop directive. */
2276 scan_omp_for (gimple stmt
, omp_context
*outer_ctx
)
2281 ctx
= new_omp_context (stmt
, outer_ctx
);
2283 scan_sharing_clauses (gimple_omp_for_clauses (stmt
), ctx
);
2285 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2286 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2288 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2289 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2290 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2291 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2293 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2296 /* Scan an OpenMP sections directive. */
2299 scan_omp_sections (gimple stmt
, omp_context
*outer_ctx
)
2303 ctx
= new_omp_context (stmt
, outer_ctx
);
2304 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2305 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2308 /* Scan an OpenMP single directive. */
2311 scan_omp_single (gimple stmt
, omp_context
*outer_ctx
)
2316 ctx
= new_omp_context (stmt
, outer_ctx
);
2317 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2318 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2319 name
= create_tmp_var_name (".omp_copy_s");
2320 name
= build_decl (gimple_location (stmt
),
2321 TYPE_DECL
, name
, ctx
->record_type
);
2322 TYPE_NAME (ctx
->record_type
) = name
;
2324 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2325 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2327 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2328 ctx
->record_type
= NULL
;
2330 layout_type (ctx
->record_type
);
2333 /* Scan an OpenMP target{, data, update} directive. */
2336 scan_omp_target (gimple stmt
, omp_context
*outer_ctx
)
2340 int kind
= gimple_omp_target_kind (stmt
);
2342 ctx
= new_omp_context (stmt
, outer_ctx
);
2343 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2344 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2345 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2346 name
= create_tmp_var_name (".omp_data_t");
2347 name
= build_decl (gimple_location (stmt
),
2348 TYPE_DECL
, name
, ctx
->record_type
);
2349 DECL_ARTIFICIAL (name
) = 1;
2350 DECL_NAMELESS (name
) = 1;
2351 TYPE_NAME (ctx
->record_type
) = name
;
2352 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2354 create_omp_child_function (ctx
, false);
2355 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2358 scan_sharing_clauses (gimple_omp_target_clauses (stmt
), ctx
);
2359 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2361 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2362 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2365 TYPE_FIELDS (ctx
->record_type
)
2366 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2367 #ifdef ENABLE_CHECKING
2369 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2370 for (field
= TYPE_FIELDS (ctx
->record_type
);
2372 field
= DECL_CHAIN (field
))
2373 gcc_assert (DECL_ALIGN (field
) == align
);
2375 layout_type (ctx
->record_type
);
2376 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2377 fixup_child_record_type (ctx
);
2381 /* Scan an OpenMP teams directive. */
2384 scan_omp_teams (gimple stmt
, omp_context
*outer_ctx
)
2386 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2387 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2388 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2391 /* Check OpenMP nesting restrictions. */
2393 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2397 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2398 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2400 error_at (gimple_location (stmt
),
2401 "OpenMP constructs may not be nested inside simd region");
2404 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2406 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2407 || (gimple_omp_for_kind (stmt
)
2408 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2409 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2411 error_at (gimple_location (stmt
),
2412 "only distribute or parallel constructs are allowed to "
2413 "be closely nested inside teams construct");
2418 switch (gimple_code (stmt
))
2420 case GIMPLE_OMP_FOR
:
2421 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2423 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2425 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2427 error_at (gimple_location (stmt
),
2428 "distribute construct must be closely nested inside "
2436 if (is_gimple_call (stmt
)
2437 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2438 == BUILT_IN_GOMP_CANCEL
2439 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2440 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2442 const char *bad
= NULL
;
2443 const char *kind
= NULL
;
2446 error_at (gimple_location (stmt
), "orphaned %qs construct",
2447 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2448 == BUILT_IN_GOMP_CANCEL
2449 ? "#pragma omp cancel"
2450 : "#pragma omp cancellation point");
2453 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2454 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2458 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2459 bad
= "#pragma omp parallel";
2460 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2461 == BUILT_IN_GOMP_CANCEL
2462 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2463 ctx
->cancellable
= true;
2467 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2468 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2469 bad
= "#pragma omp for";
2470 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2471 == BUILT_IN_GOMP_CANCEL
2472 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2474 ctx
->cancellable
= true;
2475 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2477 warning_at (gimple_location (stmt
), 0,
2478 "%<#pragma omp cancel for%> inside "
2479 "%<nowait%> for construct");
2480 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2481 OMP_CLAUSE_ORDERED
))
2482 warning_at (gimple_location (stmt
), 0,
2483 "%<#pragma omp cancel for%> inside "
2484 "%<ordered%> for construct");
2489 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2490 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2491 bad
= "#pragma omp sections";
2492 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2493 == BUILT_IN_GOMP_CANCEL
2494 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2496 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2498 ctx
->cancellable
= true;
2499 if (find_omp_clause (gimple_omp_sections_clauses
2502 warning_at (gimple_location (stmt
), 0,
2503 "%<#pragma omp cancel sections%> inside "
2504 "%<nowait%> sections construct");
2508 gcc_assert (ctx
->outer
2509 && gimple_code (ctx
->outer
->stmt
)
2510 == GIMPLE_OMP_SECTIONS
);
2511 ctx
->outer
->cancellable
= true;
2512 if (find_omp_clause (gimple_omp_sections_clauses
2515 warning_at (gimple_location (stmt
), 0,
2516 "%<#pragma omp cancel sections%> inside "
2517 "%<nowait%> sections construct");
2523 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2524 bad
= "#pragma omp task";
2526 ctx
->cancellable
= true;
2530 error_at (gimple_location (stmt
), "invalid arguments");
2535 error_at (gimple_location (stmt
),
2536 "%<%s %s%> construct not closely nested inside of %qs",
2537 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2538 == BUILT_IN_GOMP_CANCEL
2539 ? "#pragma omp cancel"
2540 : "#pragma omp cancellation point", kind
, bad
);
2545 case GIMPLE_OMP_SECTIONS
:
2546 case GIMPLE_OMP_SINGLE
:
2547 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2548 switch (gimple_code (ctx
->stmt
))
2550 case GIMPLE_OMP_FOR
:
2551 case GIMPLE_OMP_SECTIONS
:
2552 case GIMPLE_OMP_SINGLE
:
2553 case GIMPLE_OMP_ORDERED
:
2554 case GIMPLE_OMP_MASTER
:
2555 case GIMPLE_OMP_TASK
:
2556 case GIMPLE_OMP_CRITICAL
:
2557 if (is_gimple_call (stmt
))
2559 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2560 != BUILT_IN_GOMP_BARRIER
)
2562 error_at (gimple_location (stmt
),
2563 "barrier region may not be closely nested inside "
2564 "of work-sharing, critical, ordered, master or "
2565 "explicit task region");
2568 error_at (gimple_location (stmt
),
2569 "work-sharing region may not be closely nested inside "
2570 "of work-sharing, critical, ordered, master or explicit "
2573 case GIMPLE_OMP_PARALLEL
:
2579 case GIMPLE_OMP_MASTER
:
2580 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2581 switch (gimple_code (ctx
->stmt
))
2583 case GIMPLE_OMP_FOR
:
2584 case GIMPLE_OMP_SECTIONS
:
2585 case GIMPLE_OMP_SINGLE
:
2586 case GIMPLE_OMP_TASK
:
2587 error_at (gimple_location (stmt
),
2588 "master region may not be closely nested inside "
2589 "of work-sharing or explicit task region");
2591 case GIMPLE_OMP_PARALLEL
:
2597 case GIMPLE_OMP_ORDERED
:
2598 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2599 switch (gimple_code (ctx
->stmt
))
2601 case GIMPLE_OMP_CRITICAL
:
2602 case GIMPLE_OMP_TASK
:
2603 error_at (gimple_location (stmt
),
2604 "ordered region may not be closely nested inside "
2605 "of critical or explicit task region");
2607 case GIMPLE_OMP_FOR
:
2608 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2609 OMP_CLAUSE_ORDERED
) == NULL
)
2611 error_at (gimple_location (stmt
),
2612 "ordered region must be closely nested inside "
2613 "a loop region with an ordered clause");
2617 case GIMPLE_OMP_PARALLEL
:
2618 error_at (gimple_location (stmt
),
2619 "ordered region must be closely nested inside "
2620 "a loop region with an ordered clause");
2626 case GIMPLE_OMP_CRITICAL
:
2627 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2628 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_CRITICAL
2629 && (gimple_omp_critical_name (stmt
)
2630 == gimple_omp_critical_name (ctx
->stmt
)))
2632 error_at (gimple_location (stmt
),
2633 "critical region may not be nested inside a critical "
2634 "region with the same name");
2638 case GIMPLE_OMP_TEAMS
:
2640 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2641 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2643 error_at (gimple_location (stmt
),
2644 "teams construct not closely nested inside of target "
2649 case GIMPLE_OMP_TARGET
:
2650 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2651 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
2652 && gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_REGION
)
2655 switch (gimple_omp_target_kind (stmt
))
2657 case GF_OMP_TARGET_KIND_REGION
: name
= "target"; break;
2658 case GF_OMP_TARGET_KIND_DATA
: name
= "target data"; break;
2659 case GF_OMP_TARGET_KIND_UPDATE
: name
= "target update"; break;
2660 default: gcc_unreachable ();
2662 warning_at (gimple_location (stmt
), 0,
2663 "%s construct inside of target region", name
);
2673 /* Helper function scan_omp.
2675 Callback for walk_tree or operators in walk_gimple_stmt used to
2676 scan for OpenMP directives in TP. */
2679 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
2681 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
2682 omp_context
*ctx
= (omp_context
*) wi
->info
;
2685 switch (TREE_CODE (t
))
2692 *tp
= remap_decl (t
, &ctx
->cb
);
2696 if (ctx
&& TYPE_P (t
))
2697 *tp
= remap_type (t
, &ctx
->cb
);
2698 else if (!DECL_P (t
))
2703 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
2704 if (tem
!= TREE_TYPE (t
))
2706 if (TREE_CODE (t
) == INTEGER_CST
)
2707 *tp
= wide_int_to_tree (tem
, t
);
2709 TREE_TYPE (t
) = tem
;
2719 /* Return true if FNDECL is a setjmp or a longjmp. */
2722 setjmp_or_longjmp_p (const_tree fndecl
)
2724 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
2725 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
2726 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
2729 tree declname
= DECL_NAME (fndecl
);
2732 const char *name
= IDENTIFIER_POINTER (declname
);
2733 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
2737 /* Helper function for scan_omp.
2739 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2740 the current statement in GSI. */
2743 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
2744 struct walk_stmt_info
*wi
)
2746 gimple stmt
= gsi_stmt (*gsi
);
2747 omp_context
*ctx
= (omp_context
*) wi
->info
;
2749 if (gimple_has_location (stmt
))
2750 input_location
= gimple_location (stmt
);
2752 /* Check the OpenMP nesting restrictions. */
2753 bool remove
= false;
2754 if (is_gimple_omp (stmt
))
2755 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2756 else if (is_gimple_call (stmt
))
2758 tree fndecl
= gimple_call_fndecl (stmt
);
2761 if (setjmp_or_longjmp_p (fndecl
)
2763 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2764 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2767 error_at (gimple_location (stmt
),
2768 "setjmp/longjmp inside simd construct");
2770 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
2771 switch (DECL_FUNCTION_CODE (fndecl
))
2773 case BUILT_IN_GOMP_BARRIER
:
2774 case BUILT_IN_GOMP_CANCEL
:
2775 case BUILT_IN_GOMP_CANCELLATION_POINT
:
2776 case BUILT_IN_GOMP_TASKYIELD
:
2777 case BUILT_IN_GOMP_TASKWAIT
:
2778 case BUILT_IN_GOMP_TASKGROUP_START
:
2779 case BUILT_IN_GOMP_TASKGROUP_END
:
2780 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2789 stmt
= gimple_build_nop ();
2790 gsi_replace (gsi
, stmt
, false);
2793 *handled_ops_p
= true;
2795 switch (gimple_code (stmt
))
2797 case GIMPLE_OMP_PARALLEL
:
2798 taskreg_nesting_level
++;
2799 scan_omp_parallel (gsi
, ctx
);
2800 taskreg_nesting_level
--;
2803 case GIMPLE_OMP_TASK
:
2804 taskreg_nesting_level
++;
2805 scan_omp_task (gsi
, ctx
);
2806 taskreg_nesting_level
--;
2809 case GIMPLE_OMP_FOR
:
2810 scan_omp_for (stmt
, ctx
);
2813 case GIMPLE_OMP_SECTIONS
:
2814 scan_omp_sections (stmt
, ctx
);
2817 case GIMPLE_OMP_SINGLE
:
2818 scan_omp_single (stmt
, ctx
);
2821 case GIMPLE_OMP_SECTION
:
2822 case GIMPLE_OMP_MASTER
:
2823 case GIMPLE_OMP_TASKGROUP
:
2824 case GIMPLE_OMP_ORDERED
:
2825 case GIMPLE_OMP_CRITICAL
:
2826 ctx
= new_omp_context (stmt
, ctx
);
2827 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2830 case GIMPLE_OMP_TARGET
:
2831 scan_omp_target (stmt
, ctx
);
2834 case GIMPLE_OMP_TEAMS
:
2835 scan_omp_teams (stmt
, ctx
);
2842 *handled_ops_p
= false;
2844 for (var
= gimple_bind_vars (stmt
); var
; var
= DECL_CHAIN (var
))
2845 insert_decl_map (&ctx
->cb
, var
, var
);
2849 *handled_ops_p
= false;
2857 /* Scan all the statements starting at the current statement. CTX
2858 contains context information about the OpenMP directives and
2859 clauses found during the scan. */
2862 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
2864 location_t saved_location
;
2865 struct walk_stmt_info wi
;
2867 memset (&wi
, 0, sizeof (wi
));
2869 wi
.want_locations
= true;
2871 saved_location
= input_location
;
2872 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
2873 input_location
= saved_location
;
2876 /* Re-gimplification and code generation routines. */
2878 /* Build a call to GOMP_barrier. */
2881 build_omp_barrier (tree lhs
)
2883 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
2884 : BUILT_IN_GOMP_BARRIER
);
2885 gimple g
= gimple_build_call (fndecl
, 0);
2887 gimple_call_set_lhs (g
, lhs
);
2891 /* If a context was created for STMT when it was scanned, return it. */
2893 static omp_context
*
2894 maybe_lookup_ctx (gimple stmt
)
2897 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
2898 return n
? (omp_context
*) n
->value
: NULL
;
2902 /* Find the mapping for DECL in CTX or the immediately enclosing
2903 context that has a mapping for DECL.
2905 If CTX is a nested parallel directive, we may have to use the decl
2906 mappings created in CTX's parent context. Suppose that we have the
2907 following parallel nesting (variable UIDs showed for clarity):
2910 #omp parallel shared(iD.1562) -> outer parallel
2911 iD.1562 = iD.1562 + 1;
2913 #omp parallel shared (iD.1562) -> inner parallel
2914 iD.1562 = iD.1562 - 1;
2916 Each parallel structure will create a distinct .omp_data_s structure
2917 for copying iD.1562 in/out of the directive:
2919 outer parallel .omp_data_s.1.i -> iD.1562
2920 inner parallel .omp_data_s.2.i -> iD.1562
2922 A shared variable mapping will produce a copy-out operation before
2923 the parallel directive and a copy-in operation after it. So, in
2924 this case we would have:
2927 .omp_data_o.1.i = iD.1562;
2928 #omp parallel shared(iD.1562) -> outer parallel
2929 .omp_data_i.1 = &.omp_data_o.1
2930 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2932 .omp_data_o.2.i = iD.1562; -> **
2933 #omp parallel shared(iD.1562) -> inner parallel
2934 .omp_data_i.2 = &.omp_data_o.2
2935 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2938 ** This is a problem. The symbol iD.1562 cannot be referenced
2939 inside the body of the outer parallel region. But since we are
2940 emitting this copy operation while expanding the inner parallel
2941 directive, we need to access the CTX structure of the outer
2942 parallel directive to get the correct mapping:
2944 .omp_data_o.2.i = .omp_data_i.1->i
2946 Since there may be other workshare or parallel directives enclosing
2947 the parallel directive, it may be necessary to walk up the context
2948 parent chain. This is not a problem in general because nested
2949 parallelism happens only rarely. */
2952 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2957 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2958 t
= maybe_lookup_decl (decl
, up
);
2960 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
2962 return t
? t
: decl
;
2966 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2967 in outer contexts. */
2970 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2975 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2976 t
= maybe_lookup_decl (decl
, up
);
2978 return t
? t
: decl
;
2982 /* Construct the initialization value for reduction CLAUSE. */
2985 omp_reduction_init (tree clause
, tree type
)
2987 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
2988 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
2995 case TRUTH_ORIF_EXPR
:
2996 case TRUTH_XOR_EXPR
:
2998 return build_zero_cst (type
);
3001 case TRUTH_AND_EXPR
:
3002 case TRUTH_ANDIF_EXPR
:
3004 return fold_convert_loc (loc
, type
, integer_one_node
);
3007 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3010 if (SCALAR_FLOAT_TYPE_P (type
))
3012 REAL_VALUE_TYPE max
, min
;
3013 if (HONOR_INFINITIES (TYPE_MODE (type
)))
3016 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3019 real_maxval (&min
, 1, TYPE_MODE (type
));
3020 return build_real (type
, min
);
3024 gcc_assert (INTEGRAL_TYPE_P (type
));
3025 return TYPE_MIN_VALUE (type
);
3029 if (SCALAR_FLOAT_TYPE_P (type
))
3031 REAL_VALUE_TYPE max
;
3032 if (HONOR_INFINITIES (TYPE_MODE (type
)))
3035 real_maxval (&max
, 0, TYPE_MODE (type
));
3036 return build_real (type
, max
);
3040 gcc_assert (INTEGRAL_TYPE_P (type
));
3041 return TYPE_MAX_VALUE (type
);
3049 /* Return alignment to be assumed for var in CLAUSE, which should be
3050 OMP_CLAUSE_ALIGNED. */
3053 omp_clause_aligned_alignment (tree clause
)
3055 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3056 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3058 /* Otherwise return implementation defined alignment. */
3059 unsigned int al
= 1;
3060 enum machine_mode mode
, vmode
;
3061 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3063 vs
= 1 << floor_log2 (vs
);
3064 static enum mode_class classes
[]
3065 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3066 for (int i
= 0; i
< 4; i
+= 2)
3067 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3069 mode
= GET_MODE_WIDER_MODE (mode
))
3071 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3072 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3075 && GET_MODE_SIZE (vmode
) < vs
3076 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3077 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3079 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3080 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3082 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3083 / GET_MODE_SIZE (mode
));
3084 if (TYPE_MODE (type
) != vmode
)
3086 if (TYPE_ALIGN_UNIT (type
) > al
)
3087 al
= TYPE_ALIGN_UNIT (type
);
3089 return build_int_cst (integer_type_node
, al
);
3092 /* Return maximum possible vectorization factor for the target. */
3099 || !flag_tree_loop_optimize
3100 || (!flag_tree_loop_vectorize
3101 && (global_options_set
.x_flag_tree_loop_vectorize
3102 || global_options_set
.x_flag_tree_vectorize
)))
3105 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3108 vs
= 1 << floor_log2 (vs
);
3111 enum machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
3112 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
3113 return GET_MODE_NUNITS (vqimode
);
3117 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3121 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
3122 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
3126 max_vf
= omp_max_vf ();
3129 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3130 OMP_CLAUSE_SAFELEN
);
3131 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3133 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3135 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3139 idx
= create_tmp_var (unsigned_type_node
, NULL
);
3140 lane
= create_tmp_var (unsigned_type_node
, NULL
);
3146 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3147 tree avar
= create_tmp_var_raw (atype
, NULL
);
3148 if (TREE_ADDRESSABLE (new_var
))
3149 TREE_ADDRESSABLE (avar
) = 1;
3150 DECL_ATTRIBUTES (avar
)
3151 = tree_cons (get_identifier ("omp simd array"), NULL
,
3152 DECL_ATTRIBUTES (avar
));
3153 gimple_add_tmp_var (avar
);
3154 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3155 NULL_TREE
, NULL_TREE
);
3156 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3157 NULL_TREE
, NULL_TREE
);
3158 if (DECL_P (new_var
))
3160 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3161 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3166 /* Helper function of lower_rec_input_clauses. For a reference
3167 in simd reduction, add an underlying variable it will reference. */
3170 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3172 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3173 if (TREE_CONSTANT (z
))
3175 const char *name
= NULL
;
3176 if (DECL_NAME (new_vard
))
3177 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3179 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3180 gimple_add_tmp_var (z
);
3181 TREE_ADDRESSABLE (z
) = 1;
3182 z
= build_fold_addr_expr_loc (loc
, z
);
3183 gimplify_assign (new_vard
, z
, ilist
);
3187 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3188 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3189 private variables. Initialization statements go in ILIST, while calls
3190 to destructors go in DLIST. */
3193 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3194 omp_context
*ctx
, struct omp_for_data
*fd
)
3196 tree c
, dtor
, copyin_seq
, x
, ptr
;
3197 bool copyin_by_ref
= false;
3198 bool lastprivate_firstprivate
= false;
3199 bool reduction_omp_orig_ref
= false;
3201 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3202 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3204 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3205 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3206 gimple_seq llist
[2] = { NULL
, NULL
};
3210 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3211 with data sharing clauses referencing variable sized vars. That
3212 is unnecessarily hard to support and very unlikely to result in
3213 vectorized code anyway. */
3215 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3216 switch (OMP_CLAUSE_CODE (c
))
3218 case OMP_CLAUSE_LINEAR
:
3219 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3222 case OMP_CLAUSE_REDUCTION
:
3223 case OMP_CLAUSE_PRIVATE
:
3224 case OMP_CLAUSE_FIRSTPRIVATE
:
3225 case OMP_CLAUSE_LASTPRIVATE
:
3226 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3233 /* Do all the fixed sized types in the first pass, and the variable sized
3234 types in the second pass. This makes sure that the scalar arguments to
3235 the variable sized types are processed before we use them in the
3236 variable sized operations. */
3237 for (pass
= 0; pass
< 2; ++pass
)
3239 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3241 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3244 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3248 case OMP_CLAUSE_PRIVATE
:
3249 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3252 case OMP_CLAUSE_SHARED
:
3253 /* Ignore shared directives in teams construct. */
3254 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3256 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3258 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3261 case OMP_CLAUSE_FIRSTPRIVATE
:
3262 case OMP_CLAUSE_COPYIN
:
3263 case OMP_CLAUSE_LINEAR
:
3265 case OMP_CLAUSE_REDUCTION
:
3266 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3267 reduction_omp_orig_ref
= true;
3269 case OMP_CLAUSE__LOOPTEMP_
:
3270 /* Handle _looptemp_ clauses only on parallel. */
3274 case OMP_CLAUSE_LASTPRIVATE
:
3275 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3277 lastprivate_firstprivate
= true;
3281 /* Even without corresponding firstprivate, if
3282 decl is Fortran allocatable, it needs outer var
3285 && lang_hooks
.decls
.omp_private_outer_ref
3286 (OMP_CLAUSE_DECL (c
)))
3287 lastprivate_firstprivate
= true;
3289 case OMP_CLAUSE_ALIGNED
:
3292 var
= OMP_CLAUSE_DECL (c
);
3293 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3294 && !is_global_var (var
))
3296 new_var
= maybe_lookup_decl (var
, ctx
);
3297 if (new_var
== NULL_TREE
)
3298 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3299 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3300 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3301 omp_clause_aligned_alignment (c
));
3302 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3303 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3304 gimplify_and_add (x
, ilist
);
3306 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3307 && is_global_var (var
))
3309 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3310 new_var
= lookup_decl (var
, ctx
);
3311 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3312 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3313 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3314 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3315 omp_clause_aligned_alignment (c
));
3316 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3317 x
= create_tmp_var (ptype
, NULL
);
3318 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3319 gimplify_and_add (t
, ilist
);
3320 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3321 SET_DECL_VALUE_EXPR (new_var
, t
);
3322 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3329 new_var
= var
= OMP_CLAUSE_DECL (c
);
3330 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3331 new_var
= lookup_decl (var
, ctx
);
3333 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3338 else if (is_variable_sized (var
))
3340 /* For variable sized types, we need to allocate the
3341 actual storage here. Call alloca and store the
3342 result in the pointer decl that we created elsewhere. */
3346 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3351 ptr
= DECL_VALUE_EXPR (new_var
);
3352 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3353 ptr
= TREE_OPERAND (ptr
, 0);
3354 gcc_assert (DECL_P (ptr
));
3355 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3357 /* void *tmp = __builtin_alloca */
3358 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3359 stmt
= gimple_build_call (atmp
, 1, x
);
3360 tmp
= create_tmp_var_raw (ptr_type_node
, NULL
);
3361 gimple_add_tmp_var (tmp
);
3362 gimple_call_set_lhs (stmt
, tmp
);
3364 gimple_seq_add_stmt (ilist
, stmt
);
3366 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3367 gimplify_assign (ptr
, x
, ilist
);
3370 else if (is_reference (var
))
3372 /* For references that are being privatized for Fortran,
3373 allocate new backing storage for the new pointer
3374 variable. This allows us to avoid changing all the
3375 code that expects a pointer to something that expects
3376 a direct variable. */
3380 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3381 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3383 x
= build_receiver_ref (var
, false, ctx
);
3384 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3386 else if (TREE_CONSTANT (x
))
3388 /* For reduction in SIMD loop, defer adding the
3389 initialization of the reference, because if we decide
3390 to use SIMD array for it, the initilization could cause
3392 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3396 const char *name
= NULL
;
3397 if (DECL_NAME (var
))
3398 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3400 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3402 gimple_add_tmp_var (x
);
3403 TREE_ADDRESSABLE (x
) = 1;
3404 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3409 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3410 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3415 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3416 gimplify_assign (new_var
, x
, ilist
);
3419 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3421 else if (c_kind
== OMP_CLAUSE_REDUCTION
3422 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3430 switch (OMP_CLAUSE_CODE (c
))
3432 case OMP_CLAUSE_SHARED
:
3433 /* Ignore shared directives in teams construct. */
3434 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3436 /* Shared global vars are just accessed directly. */
3437 if (is_global_var (new_var
))
3439 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3440 needs to be delayed until after fixup_child_record_type so
3441 that we get the correct type during the dereference. */
3442 by_ref
= use_pointer_for_field (var
, ctx
);
3443 x
= build_receiver_ref (var
, by_ref
, ctx
);
3444 SET_DECL_VALUE_EXPR (new_var
, x
);
3445 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3447 /* ??? If VAR is not passed by reference, and the variable
3448 hasn't been initialized yet, then we'll get a warning for
3449 the store into the omp_data_s structure. Ideally, we'd be
3450 able to notice this and not store anything at all, but
3451 we're generating code too early. Suppress the warning. */
3453 TREE_NO_WARNING (var
) = 1;
3456 case OMP_CLAUSE_LASTPRIVATE
:
3457 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3461 case OMP_CLAUSE_PRIVATE
:
3462 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3463 x
= build_outer_var_ref (var
, ctx
);
3464 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3466 if (is_task_ctx (ctx
))
3467 x
= build_receiver_ref (var
, false, ctx
);
3469 x
= build_outer_var_ref (var
, ctx
);
3475 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3478 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3479 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3480 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3481 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3482 idx
, lane
, ivar
, lvar
))
3485 x
= lang_hooks
.decls
.omp_clause_default_ctor
3486 (c
, unshare_expr (ivar
), x
);
3488 gimplify_and_add (x
, &llist
[0]);
3491 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3494 gimple_seq tseq
= NULL
;
3497 gimplify_stmt (&dtor
, &tseq
);
3498 gimple_seq_add_seq (&llist
[1], tseq
);
3505 gimplify_and_add (nx
, ilist
);
3509 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3512 gimple_seq tseq
= NULL
;
3515 gimplify_stmt (&dtor
, &tseq
);
3516 gimple_seq_add_seq (dlist
, tseq
);
3520 case OMP_CLAUSE_LINEAR
:
3521 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3522 goto do_firstprivate
;
3523 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3526 x
= build_outer_var_ref (var
, ctx
);
3529 case OMP_CLAUSE_FIRSTPRIVATE
:
3530 if (is_task_ctx (ctx
))
3532 if (is_reference (var
) || is_variable_sized (var
))
3534 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3536 || use_pointer_for_field (var
, NULL
))
3538 x
= build_receiver_ref (var
, false, ctx
);
3539 SET_DECL_VALUE_EXPR (new_var
, x
);
3540 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3545 x
= build_outer_var_ref (var
, ctx
);
3548 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3549 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3551 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3552 tree stept
= TREE_TYPE (t
);
3553 tree ct
= find_omp_clause (clauses
,
3554 OMP_CLAUSE__LOOPTEMP_
);
3556 tree l
= OMP_CLAUSE_DECL (ct
);
3557 tree n1
= fd
->loop
.n1
;
3558 tree step
= fd
->loop
.step
;
3559 tree itype
= TREE_TYPE (l
);
3560 if (POINTER_TYPE_P (itype
))
3561 itype
= signed_type_for (itype
);
3562 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3563 if (TYPE_UNSIGNED (itype
)
3564 && fd
->loop
.cond_code
== GT_EXPR
)
3565 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3566 fold_build1 (NEGATE_EXPR
, itype
, l
),
3567 fold_build1 (NEGATE_EXPR
,
3570 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3571 t
= fold_build2 (MULT_EXPR
, stept
,
3572 fold_convert (stept
, l
), t
);
3574 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3576 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3578 gimplify_and_add (x
, ilist
);
3582 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3583 x
= fold_build2 (POINTER_PLUS_EXPR
,
3584 TREE_TYPE (x
), x
, t
);
3586 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3589 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3590 || TREE_ADDRESSABLE (new_var
))
3591 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3592 idx
, lane
, ivar
, lvar
))
3594 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
3596 tree iv
= create_tmp_var (TREE_TYPE (new_var
), NULL
);
3597 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
3598 gimplify_and_add (x
, ilist
);
3599 gimple_stmt_iterator gsi
3600 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3602 = gimple_build_assign (unshare_expr (lvar
), iv
);
3603 gsi_insert_before_without_update (&gsi
, g
,
3605 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3606 enum tree_code code
= PLUS_EXPR
;
3607 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
3608 code
= POINTER_PLUS_EXPR
;
3609 g
= gimple_build_assign_with_ops (code
, iv
, iv
, t
);
3610 gsi_insert_before_without_update (&gsi
, g
,
3614 x
= lang_hooks
.decls
.omp_clause_copy_ctor
3615 (c
, unshare_expr (ivar
), x
);
3616 gimplify_and_add (x
, &llist
[0]);
3617 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3620 gimple_seq tseq
= NULL
;
3623 gimplify_stmt (&dtor
, &tseq
);
3624 gimple_seq_add_seq (&llist
[1], tseq
);
3629 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
3630 gimplify_and_add (x
, ilist
);
3633 case OMP_CLAUSE__LOOPTEMP_
:
3634 gcc_assert (is_parallel_ctx (ctx
));
3635 x
= build_outer_var_ref (var
, ctx
);
3636 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3637 gimplify_and_add (x
, ilist
);
3640 case OMP_CLAUSE_COPYIN
:
3641 by_ref
= use_pointer_for_field (var
, NULL
);
3642 x
= build_receiver_ref (var
, by_ref
, ctx
);
3643 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
3644 append_to_statement_list (x
, ©in_seq
);
3645 copyin_by_ref
|= by_ref
;
3648 case OMP_CLAUSE_REDUCTION
:
3649 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3651 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3653 x
= build_outer_var_ref (var
, ctx
);
3655 if (is_reference (var
)
3656 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
3658 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3659 SET_DECL_VALUE_EXPR (placeholder
, x
);
3660 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3661 tree new_vard
= new_var
;
3662 if (is_reference (var
))
3664 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3665 new_vard
= TREE_OPERAND (new_var
, 0);
3666 gcc_assert (DECL_P (new_vard
));
3669 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3670 idx
, lane
, ivar
, lvar
))
3672 if (new_vard
== new_var
)
3674 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
3675 SET_DECL_VALUE_EXPR (new_var
, ivar
);
3679 SET_DECL_VALUE_EXPR (new_vard
,
3680 build_fold_addr_expr (ivar
));
3681 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3683 x
= lang_hooks
.decls
.omp_clause_default_ctor
3684 (c
, unshare_expr (ivar
),
3685 build_outer_var_ref (var
, ctx
));
3687 gimplify_and_add (x
, &llist
[0]);
3688 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3690 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3691 lower_omp (&tseq
, ctx
);
3692 gimple_seq_add_seq (&llist
[0], tseq
);
3694 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3695 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3696 lower_omp (&tseq
, ctx
);
3697 gimple_seq_add_seq (&llist
[1], tseq
);
3698 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3699 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3700 if (new_vard
== new_var
)
3701 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3703 SET_DECL_VALUE_EXPR (new_vard
,
3704 build_fold_addr_expr (lvar
));
3705 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3710 gimplify_stmt (&dtor
, &tseq
);
3711 gimple_seq_add_seq (&llist
[1], tseq
);
3715 /* If this is a reference to constant size reduction var
3716 with placeholder, we haven't emitted the initializer
3717 for it because it is undesirable if SIMD arrays are used.
3718 But if they aren't used, we need to emit the deferred
3719 initialization now. */
3720 else if (is_reference (var
) && is_simd
)
3721 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3722 x
= lang_hooks
.decls
.omp_clause_default_ctor
3723 (c
, unshare_expr (new_var
),
3724 build_outer_var_ref (var
, ctx
));
3726 gimplify_and_add (x
, ilist
);
3727 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3729 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3730 lower_omp (&tseq
, ctx
);
3731 gimple_seq_add_seq (ilist
, tseq
);
3733 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3736 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3737 lower_omp (&tseq
, ctx
);
3738 gimple_seq_add_seq (dlist
, tseq
);
3739 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3741 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3746 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
3747 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
3748 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3750 /* reduction(-:var) sums up the partial results, so it
3751 acts identically to reduction(+:var). */
3752 if (code
== MINUS_EXPR
)
3755 tree new_vard
= new_var
;
3756 if (is_simd
&& is_reference (var
))
3758 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3759 new_vard
= TREE_OPERAND (new_var
, 0);
3760 gcc_assert (DECL_P (new_vard
));
3763 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3764 idx
, lane
, ivar
, lvar
))
3766 tree ref
= build_outer_var_ref (var
, ctx
);
3768 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
3770 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
3771 ref
= build_outer_var_ref (var
, ctx
);
3772 gimplify_assign (ref
, x
, &llist
[1]);
3774 if (new_vard
!= new_var
)
3776 SET_DECL_VALUE_EXPR (new_vard
,
3777 build_fold_addr_expr (lvar
));
3778 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3783 if (is_reference (var
) && is_simd
)
3784 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3785 gimplify_assign (new_var
, x
, ilist
);
3788 tree ref
= build_outer_var_ref (var
, ctx
);
3790 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3791 ref
= build_outer_var_ref (var
, ctx
);
3792 gimplify_assign (ref
, x
, dlist
);
3806 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
3807 /* Don't want uninit warnings on simduid, it is always uninitialized,
3808 but we use it not for the value, but for the DECL_UID only. */
3809 TREE_NO_WARNING (uid
) = 1;
3811 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
3812 gimple_call_set_lhs (g
, lane
);
3813 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3814 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
3815 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
3816 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
3817 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3818 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3819 g
= gimple_build_assign_with_ops (INTEGER_CST
, lane
,
3820 build_int_cst (unsigned_type_node
, 0),
3822 gimple_seq_add_stmt (ilist
, g
);
3823 for (int i
= 0; i
< 2; i
++)
3826 tree vf
= create_tmp_var (unsigned_type_node
, NULL
);
3827 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
3828 gimple_call_set_lhs (g
, vf
);
3829 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
3830 gimple_seq_add_stmt (seq
, g
);
3831 tree t
= build_int_cst (unsigned_type_node
, 0);
3832 g
= gimple_build_assign_with_ops (INTEGER_CST
, idx
, t
, NULL_TREE
);
3833 gimple_seq_add_stmt (seq
, g
);
3834 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
3835 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
3836 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
3837 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
3838 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
3839 gimple_seq_add_seq (seq
, llist
[i
]);
3840 t
= build_int_cst (unsigned_type_node
, 1);
3841 g
= gimple_build_assign_with_ops (PLUS_EXPR
, idx
, idx
, t
);
3842 gimple_seq_add_stmt (seq
, g
);
3843 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
3844 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
3845 gimple_seq_add_stmt (seq
, g
);
3846 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
3850 /* The copyin sequence is not to be executed by the main thread, since
3851 that would result in self-copies. Perhaps not visible to scalars,
3852 but it certainly is to C++ operator=. */
3855 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
3857 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
3858 build_int_cst (TREE_TYPE (x
), 0));
3859 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
3860 gimplify_and_add (x
, ilist
);
3863 /* If any copyin variable is passed by reference, we must ensure the
3864 master thread doesn't modify it before it is copied over in all
3865 threads. Similarly for variables in both firstprivate and
3866 lastprivate clauses we need to ensure the lastprivate copying
3867 happens after firstprivate copying in all threads. And similarly
3868 for UDRs if initializer expression refers to omp_orig. */
3869 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
3871 /* Don't add any barrier for #pragma omp simd or
3872 #pragma omp distribute. */
3873 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3874 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
3875 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
3878 /* If max_vf is non-zero, then we can use only a vectorization factor
3879 up to the max_vf we chose. So stick it into the safelen clause. */
3882 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3883 OMP_CLAUSE_SAFELEN
);
3885 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
3886 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3889 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
3890 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
3892 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3893 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3899 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3900 both parallel and workshare constructs. PREDICATE may be NULL if it's
3904 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
3907 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
3908 bool par_clauses
= false;
3909 tree simduid
= NULL
, lastlane
= NULL
;
3911 /* Early exit if there are no lastprivate or linear clauses. */
3912 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
3913 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
3914 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
3915 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
3917 if (clauses
== NULL
)
3919 /* If this was a workshare clause, see if it had been combined
3920 with its parallel. In that case, look for the clauses on the
3921 parallel statement itself. */
3922 if (is_parallel_ctx (ctx
))
3926 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
3929 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
3930 OMP_CLAUSE_LASTPRIVATE
);
3931 if (clauses
== NULL
)
3939 tree label_true
, arm1
, arm2
;
3941 label
= create_artificial_label (UNKNOWN_LOCATION
);
3942 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
3943 arm1
= TREE_OPERAND (predicate
, 0);
3944 arm2
= TREE_OPERAND (predicate
, 1);
3945 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3946 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3947 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
3949 gimple_seq_add_stmt (stmt_list
, stmt
);
3950 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
3953 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3954 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3956 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
3958 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
3961 for (c
= clauses
; c
;)
3964 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3966 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
3967 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3968 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
3970 var
= OMP_CLAUSE_DECL (c
);
3971 new_var
= lookup_decl (var
, ctx
);
3973 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
3975 tree val
= DECL_VALUE_EXPR (new_var
);
3976 if (TREE_CODE (val
) == ARRAY_REF
3977 && VAR_P (TREE_OPERAND (val
, 0))
3978 && lookup_attribute ("omp simd array",
3979 DECL_ATTRIBUTES (TREE_OPERAND (val
,
3982 if (lastlane
== NULL
)
3984 lastlane
= create_tmp_var (unsigned_type_node
, NULL
);
3986 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
3988 TREE_OPERAND (val
, 1));
3989 gimple_call_set_lhs (g
, lastlane
);
3990 gimple_seq_add_stmt (stmt_list
, g
);
3992 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
3993 TREE_OPERAND (val
, 0), lastlane
,
3994 NULL_TREE
, NULL_TREE
);
3998 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
3999 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
4001 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
4002 gimple_seq_add_seq (stmt_list
,
4003 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
4004 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
4006 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4007 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
4009 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
4010 gimple_seq_add_seq (stmt_list
,
4011 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
4012 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
4015 x
= build_outer_var_ref (var
, ctx
);
4016 if (is_reference (var
))
4017 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4018 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
4019 gimplify_and_add (x
, stmt_list
);
4021 c
= OMP_CLAUSE_CHAIN (c
);
4022 if (c
== NULL
&& !par_clauses
)
4024 /* If this was a workshare clause, see if it had been combined
4025 with its parallel. In that case, continue looking for the
4026 clauses also on the parallel statement itself. */
4027 if (is_parallel_ctx (ctx
))
4031 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4034 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4035 OMP_CLAUSE_LASTPRIVATE
);
4041 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
4045 /* Generate code to implement the REDUCTION clauses. */
4048 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
4050 gimple_seq sub_seq
= NULL
;
4055 /* SIMD reductions are handled in lower_rec_input_clauses. */
4056 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4057 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4060 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4061 update in that case, otherwise use a lock. */
4062 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
4063 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
4065 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4067 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4077 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4079 tree var
, ref
, new_var
;
4080 enum tree_code code
;
4081 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4083 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
4086 var
= OMP_CLAUSE_DECL (c
);
4087 new_var
= lookup_decl (var
, ctx
);
4088 if (is_reference (var
))
4089 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4090 ref
= build_outer_var_ref (var
, ctx
);
4091 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4093 /* reduction(-:var) sums up the partial results, so it acts
4094 identically to reduction(+:var). */
4095 if (code
== MINUS_EXPR
)
4100 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
4102 addr
= save_expr (addr
);
4103 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
4104 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
4105 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
4106 gimplify_and_add (x
, stmt_seqp
);
4110 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4112 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4114 if (is_reference (var
)
4115 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4117 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
4118 SET_DECL_VALUE_EXPR (placeholder
, ref
);
4119 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4120 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
4121 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
4122 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4123 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
4127 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4128 ref
= build_outer_var_ref (var
, ctx
);
4129 gimplify_assign (ref
, x
, &sub_seq
);
4133 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4135 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4137 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4139 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4141 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4145 /* Generate code to implement the COPYPRIVATE clauses. */
4148 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4153 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4155 tree var
, new_var
, ref
, x
;
4157 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4159 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4162 var
= OMP_CLAUSE_DECL (c
);
4163 by_ref
= use_pointer_for_field (var
, NULL
);
4165 ref
= build_sender_ref (var
, ctx
);
4166 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4169 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4170 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4172 gimplify_assign (ref
, x
, slist
);
4174 ref
= build_receiver_ref (var
, false, ctx
);
4177 ref
= fold_convert_loc (clause_loc
,
4178 build_pointer_type (TREE_TYPE (new_var
)),
4180 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4182 if (is_reference (var
))
4184 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4185 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4186 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4188 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4189 gimplify_and_add (x
, rlist
);
4194 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4195 and REDUCTION from the sender (aka parent) side. */
4198 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4203 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4205 tree val
, ref
, x
, var
;
4206 bool by_ref
, do_in
= false, do_out
= false;
4207 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4209 switch (OMP_CLAUSE_CODE (c
))
4211 case OMP_CLAUSE_PRIVATE
:
4212 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4215 case OMP_CLAUSE_FIRSTPRIVATE
:
4216 case OMP_CLAUSE_COPYIN
:
4217 case OMP_CLAUSE_LASTPRIVATE
:
4218 case OMP_CLAUSE_REDUCTION
:
4219 case OMP_CLAUSE__LOOPTEMP_
:
4225 val
= OMP_CLAUSE_DECL (c
);
4226 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4228 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4229 && is_global_var (var
))
4231 if (is_variable_sized (val
))
4233 by_ref
= use_pointer_for_field (val
, NULL
);
4235 switch (OMP_CLAUSE_CODE (c
))
4237 case OMP_CLAUSE_PRIVATE
:
4238 case OMP_CLAUSE_FIRSTPRIVATE
:
4239 case OMP_CLAUSE_COPYIN
:
4240 case OMP_CLAUSE__LOOPTEMP_
:
4244 case OMP_CLAUSE_LASTPRIVATE
:
4245 if (by_ref
|| is_reference (val
))
4247 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4254 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4259 case OMP_CLAUSE_REDUCTION
:
4261 do_out
= !(by_ref
|| is_reference (val
));
4270 ref
= build_sender_ref (val
, ctx
);
4271 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4272 gimplify_assign (ref
, x
, ilist
);
4273 if (is_task_ctx (ctx
))
4274 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4279 ref
= build_sender_ref (val
, ctx
);
4280 gimplify_assign (var
, ref
, olist
);
4285 /* Generate code to implement SHARED from the sender (aka parent)
4286 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4287 list things that got automatically shared. */
4290 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4292 tree var
, ovar
, nvar
, f
, x
, record_type
;
4294 if (ctx
->record_type
== NULL
)
4297 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4298 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4300 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4301 nvar
= maybe_lookup_decl (ovar
, ctx
);
4302 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4305 /* If CTX is a nested parallel directive. Find the immediately
4306 enclosing parallel or workshare construct that contains a
4307 mapping for OVAR. */
4308 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4310 if (use_pointer_for_field (ovar
, ctx
))
4312 x
= build_sender_ref (ovar
, ctx
);
4313 var
= build_fold_addr_expr (var
);
4314 gimplify_assign (x
, var
, ilist
);
4318 x
= build_sender_ref (ovar
, ctx
);
4319 gimplify_assign (x
, var
, ilist
);
4321 if (!TREE_READONLY (var
)
4322 /* We don't need to receive a new reference to a result
4323 or parm decl. In fact we may not store to it as we will
4324 invalidate any pending RSO and generate wrong gimple
4326 && !((TREE_CODE (var
) == RESULT_DECL
4327 || TREE_CODE (var
) == PARM_DECL
)
4328 && DECL_BY_REFERENCE (var
)))
4330 x
= build_sender_ref (ovar
, ctx
);
4331 gimplify_assign (var
, x
, olist
);
4338 /* A convenience function to build an empty GIMPLE_COND with just the
4342 gimple_build_cond_empty (tree cond
)
4344 enum tree_code pred_code
;
4347 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4348 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4352 /* Build the function calls to GOMP_parallel_start etc to actually
4353 generate the parallel operation. REGION is the parallel region
4354 being expanded. BB is the block where to insert the code. WS_ARGS
4355 will be set if this is a call to a combined parallel+workshare
4356 construct, it contains the list of additional arguments needed by
4357 the workshare construct. */
4360 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4361 gimple entry_stmt
, vec
<tree
, va_gc
> *ws_args
)
4363 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4364 gimple_stmt_iterator gsi
;
4366 enum built_in_function start_ix
;
4368 location_t clause_loc
;
4369 vec
<tree
, va_gc
> *args
;
4371 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4373 /* Determine what flavor of GOMP_parallel we will be
4375 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4376 if (is_combined_parallel (region
))
4378 switch (region
->inner
->type
)
4380 case GIMPLE_OMP_FOR
:
4381 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4382 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4383 + (region
->inner
->sched_kind
4384 == OMP_CLAUSE_SCHEDULE_RUNTIME
4385 ? 3 : region
->inner
->sched_kind
));
4386 start_ix
= (enum built_in_function
)start_ix2
;
4388 case GIMPLE_OMP_SECTIONS
:
4389 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4396 /* By default, the value of NUM_THREADS is zero (selected at run time)
4397 and there is no conditional. */
4399 val
= build_int_cst (unsigned_type_node
, 0);
4400 flags
= build_int_cst (unsigned_type_node
, 0);
4402 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4404 cond
= OMP_CLAUSE_IF_EXPR (c
);
4406 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4409 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4410 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4413 clause_loc
= gimple_location (entry_stmt
);
4415 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4417 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4419 /* Ensure 'val' is of the correct type. */
4420 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4422 /* If we found the clause 'if (cond)', build either
4423 (cond != 0) or (cond ? val : 1u). */
4426 cond
= gimple_boolify (cond
);
4428 if (integer_zerop (val
))
4429 val
= fold_build2_loc (clause_loc
,
4430 EQ_EXPR
, unsigned_type_node
, cond
,
4431 build_int_cst (TREE_TYPE (cond
), 0));
4434 basic_block cond_bb
, then_bb
, else_bb
;
4435 edge e
, e_then
, e_else
;
4436 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4438 tmp_var
= create_tmp_var (TREE_TYPE (val
), NULL
);
4439 if (gimple_in_ssa_p (cfun
))
4441 tmp_then
= make_ssa_name (tmp_var
, NULL
);
4442 tmp_else
= make_ssa_name (tmp_var
, NULL
);
4443 tmp_join
= make_ssa_name (tmp_var
, NULL
);
4452 e
= split_block (bb
, NULL
);
4457 then_bb
= create_empty_bb (cond_bb
);
4458 else_bb
= create_empty_bb (then_bb
);
4459 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4460 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4462 stmt
= gimple_build_cond_empty (cond
);
4463 gsi
= gsi_start_bb (cond_bb
);
4464 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4466 gsi
= gsi_start_bb (then_bb
);
4467 stmt
= gimple_build_assign (tmp_then
, val
);
4468 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4470 gsi
= gsi_start_bb (else_bb
);
4471 stmt
= gimple_build_assign
4472 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4473 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4475 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4476 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4477 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4478 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4479 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4480 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4482 if (gimple_in_ssa_p (cfun
))
4484 gimple phi
= create_phi_node (tmp_join
, bb
);
4485 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4486 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4492 gsi
= gsi_start_bb (bb
);
4493 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4494 false, GSI_CONTINUE_LINKING
);
4497 gsi
= gsi_last_bb (bb
);
4498 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4500 t1
= null_pointer_node
;
4502 t1
= build_fold_addr_expr (t
);
4503 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4505 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4506 args
->quick_push (t2
);
4507 args
->quick_push (t1
);
4508 args
->quick_push (val
);
4510 args
->splice (*ws_args
);
4511 args
->quick_push (flags
);
4513 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4514 builtin_decl_explicit (start_ix
), args
);
4516 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4517 false, GSI_CONTINUE_LINKING
);
4520 /* Insert a function call whose name is FUNC_NAME with the information from
4521 ENTRY_STMT into the basic_block BB. */
4524 expand_cilk_for_call (basic_block bb
, gimple entry_stmt
,
4525 vec
<tree
, va_gc
> *ws_args
)
4528 gimple_stmt_iterator gsi
;
4529 vec
<tree
, va_gc
> *args
;
4531 gcc_assert (vec_safe_length (ws_args
) == 2);
4532 tree func_name
= (*ws_args
)[0];
4533 tree grain
= (*ws_args
)[1];
4535 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4536 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
4537 gcc_assert (count
!= NULL_TREE
);
4538 count
= OMP_CLAUSE_OPERAND (count
, 0);
4540 gsi
= gsi_last_bb (bb
);
4541 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4543 t1
= null_pointer_node
;
4545 t1
= build_fold_addr_expr (t
);
4546 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4548 vec_alloc (args
, 4);
4549 args
->quick_push (t2
);
4550 args
->quick_push (t1
);
4551 args
->quick_push (count
);
4552 args
->quick_push (grain
);
4553 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
4555 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
4556 GSI_CONTINUE_LINKING
);
4559 /* Build the function call to GOMP_task to actually
4560 generate the task operation. BB is the block where to insert the code. */
4563 expand_task_call (basic_block bb
, gimple entry_stmt
)
4565 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
4566 gimple_stmt_iterator gsi
;
4567 location_t loc
= gimple_location (entry_stmt
);
4569 clauses
= gimple_omp_task_clauses (entry_stmt
);
4571 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4573 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
4575 cond
= boolean_true_node
;
4577 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
4578 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
4579 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
4580 flags
= build_int_cst (unsigned_type_node
,
4581 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
4583 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
4586 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
4587 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
4588 build_int_cst (unsigned_type_node
, 2),
4589 build_int_cst (unsigned_type_node
, 0));
4590 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
4593 depend
= OMP_CLAUSE_DECL (depend
);
4595 depend
= build_int_cst (ptr_type_node
, 0);
4597 gsi
= gsi_last_bb (bb
);
4598 t
= gimple_omp_task_data_arg (entry_stmt
);
4600 t2
= null_pointer_node
;
4602 t2
= build_fold_addr_expr_loc (loc
, t
);
4603 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
4604 t
= gimple_omp_task_copy_fn (entry_stmt
);
4606 t3
= null_pointer_node
;
4608 t3
= build_fold_addr_expr_loc (loc
, t
);
4610 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
4612 gimple_omp_task_arg_size (entry_stmt
),
4613 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
4616 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4617 false, GSI_CONTINUE_LINKING
);
4621 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4622 catch handler and return it. This prevents programs from violating the
4623 structured block semantics with throws. */
4626 maybe_catch_exception (gimple_seq body
)
4631 if (!flag_exceptions
)
4634 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
4635 decl
= lang_hooks
.eh_protect_cleanup_actions ();
4637 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
4639 g
= gimple_build_eh_must_not_throw (decl
);
4640 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
4643 return gimple_seq_alloc_with_stmt (g
);
4646 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4649 vec2chain (vec
<tree
, va_gc
> *v
)
4651 tree chain
= NULL_TREE
, t
;
4654 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
4656 DECL_CHAIN (t
) = chain
;
4664 /* Remove barriers in REGION->EXIT's block. Note that this is only
4665 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4666 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4667 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4671 remove_exit_barrier (struct omp_region
*region
)
4673 gimple_stmt_iterator gsi
;
4674 basic_block exit_bb
;
4678 int any_addressable_vars
= -1;
4680 exit_bb
= region
->exit
;
4682 /* If the parallel region doesn't return, we don't have REGION->EXIT
4687 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4688 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4689 statements that can appear in between are extremely limited -- no
4690 memory operations at all. Here, we allow nothing at all, so the
4691 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4692 gsi
= gsi_last_bb (exit_bb
);
4693 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
4695 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
4698 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
4700 gsi
= gsi_last_bb (e
->src
);
4701 if (gsi_end_p (gsi
))
4703 stmt
= gsi_stmt (gsi
);
4704 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
4705 && !gimple_omp_return_nowait_p (stmt
))
4707 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4708 in many cases. If there could be tasks queued, the barrier
4709 might be needed to let the tasks run before some local
4710 variable of the parallel that the task uses as shared
4711 runs out of scope. The task can be spawned either
4712 from within current function (this would be easy to check)
4713 or from some function it calls and gets passed an address
4714 of such a variable. */
4715 if (any_addressable_vars
< 0)
4717 gimple parallel_stmt
= last_stmt (region
->entry
);
4718 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
4719 tree local_decls
, block
, decl
;
4722 any_addressable_vars
= 0;
4723 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
4724 if (TREE_ADDRESSABLE (decl
))
4726 any_addressable_vars
= 1;
4729 for (block
= gimple_block (stmt
);
4730 !any_addressable_vars
4732 && TREE_CODE (block
) == BLOCK
;
4733 block
= BLOCK_SUPERCONTEXT (block
))
4735 for (local_decls
= BLOCK_VARS (block
);
4737 local_decls
= DECL_CHAIN (local_decls
))
4738 if (TREE_ADDRESSABLE (local_decls
))
4740 any_addressable_vars
= 1;
4743 if (block
== gimple_block (parallel_stmt
))
4747 if (!any_addressable_vars
)
4748 gimple_omp_return_set_nowait (stmt
);
4754 remove_exit_barriers (struct omp_region
*region
)
4756 if (region
->type
== GIMPLE_OMP_PARALLEL
)
4757 remove_exit_barrier (region
);
4761 region
= region
->inner
;
4762 remove_exit_barriers (region
);
4763 while (region
->next
)
4765 region
= region
->next
;
4766 remove_exit_barriers (region
);
4771 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4772 calls. These can't be declared as const functions, but
4773 within one parallel body they are constant, so they can be
4774 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4775 which are declared const. Similarly for task body, except
4776 that in untied task omp_get_thread_num () can change at any task
4777 scheduling point. */
4780 optimize_omp_library_calls (gimple entry_stmt
)
4783 gimple_stmt_iterator gsi
;
4784 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4785 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
4786 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4787 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
4788 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
4789 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
4790 OMP_CLAUSE_UNTIED
) != NULL
);
4792 FOR_EACH_BB_FN (bb
, cfun
)
4793 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4795 gimple call
= gsi_stmt (gsi
);
4798 if (is_gimple_call (call
)
4799 && (decl
= gimple_call_fndecl (call
))
4800 && DECL_EXTERNAL (decl
)
4801 && TREE_PUBLIC (decl
)
4802 && DECL_INITIAL (decl
) == NULL
)
4806 if (DECL_NAME (decl
) == thr_num_id
)
4808 /* In #pragma omp task untied omp_get_thread_num () can change
4809 during the execution of the task region. */
4812 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4814 else if (DECL_NAME (decl
) == num_thr_id
)
4815 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4819 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
4820 || gimple_call_num_args (call
) != 0)
4823 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
4826 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
4827 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
4828 TREE_TYPE (TREE_TYPE (built_in
))))
4831 gimple_call_set_fndecl (call
, built_in
);
4836 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4840 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
4844 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4845 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
4848 if (TREE_CODE (t
) == ADDR_EXPR
)
4849 recompute_tree_invariant_for_addr_expr (t
);
4851 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
4855 /* Prepend TO = FROM assignment before *GSI_P. */
4858 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
4860 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
4861 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
4862 true, GSI_SAME_STMT
);
4863 gimple stmt
= gimple_build_assign (to
, from
);
4864 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
4865 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
4866 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
4868 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
4869 gimple_regimplify_operands (stmt
, &gsi
);
4873 /* Expand the OpenMP parallel or task directive starting at REGION. */
4876 expand_omp_taskreg (struct omp_region
*region
)
4878 basic_block entry_bb
, exit_bb
, new_bb
;
4879 struct function
*child_cfun
;
4880 tree child_fn
, block
, t
;
4881 gimple_stmt_iterator gsi
;
4882 gimple entry_stmt
, stmt
;
4884 vec
<tree
, va_gc
> *ws_args
;
4886 entry_stmt
= last_stmt (region
->entry
);
4887 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
4888 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
4890 entry_bb
= region
->entry
;
4891 exit_bb
= region
->exit
;
4895 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
4896 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
4897 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
4900 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4901 and the inner statement contains the name of the built-in function
4903 ws_args
= region
->inner
->ws_args
;
4904 else if (is_combined_parallel (region
))
4905 ws_args
= region
->ws_args
;
4909 if (child_cfun
->cfg
)
4911 /* Due to inlining, it may happen that we have already outlined
4912 the region, in which case all we need to do is make the
4913 sub-graph unreachable and emit the parallel call. */
4914 edge entry_succ_e
, exit_succ_e
;
4916 entry_succ_e
= single_succ_edge (entry_bb
);
4918 gsi
= gsi_last_bb (entry_bb
);
4919 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
4920 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
4921 gsi_remove (&gsi
, true);
4926 exit_succ_e
= single_succ_edge (exit_bb
);
4927 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
4929 remove_edge_and_dominated_blocks (entry_succ_e
);
4933 unsigned srcidx
, dstidx
, num
;
4935 /* If the parallel region needs data sent from the parent
4936 function, then the very first statement (except possible
4937 tree profile counter updates) of the parallel body
4938 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4939 &.OMP_DATA_O is passed as an argument to the child function,
4940 we need to replace it with the argument as seen by the child
4943 In most cases, this will end up being the identity assignment
4944 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4945 a function call that has been inlined, the original PARM_DECL
4946 .OMP_DATA_I may have been converted into a different local
4947 variable. In which case, we need to keep the assignment. */
4948 if (gimple_omp_taskreg_data_arg (entry_stmt
))
4950 basic_block entry_succ_bb
= single_succ (entry_bb
);
4952 gimple parcopy_stmt
= NULL
;
4954 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
4958 gcc_assert (!gsi_end_p (gsi
));
4959 stmt
= gsi_stmt (gsi
);
4960 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
4963 if (gimple_num_ops (stmt
) == 2)
4965 tree arg
= gimple_assign_rhs1 (stmt
);
4967 /* We're ignore the subcode because we're
4968 effectively doing a STRIP_NOPS. */
4970 if (TREE_CODE (arg
) == ADDR_EXPR
4971 && TREE_OPERAND (arg
, 0)
4972 == gimple_omp_taskreg_data_arg (entry_stmt
))
4974 parcopy_stmt
= stmt
;
4980 gcc_assert (parcopy_stmt
!= NULL
);
4981 arg
= DECL_ARGUMENTS (child_fn
);
4983 if (!gimple_in_ssa_p (cfun
))
4985 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
4986 gsi_remove (&gsi
, true);
4989 /* ?? Is setting the subcode really necessary ?? */
4990 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
4991 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
4996 /* If we are in ssa form, we must load the value from the default
4997 definition of the argument. That should not be defined now,
4998 since the argument is not used uninitialized. */
4999 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
5000 narg
= make_ssa_name (arg
, gimple_build_nop ());
5001 set_ssa_default_def (cfun
, arg
, narg
);
5002 /* ?? Is setting the subcode really necessary ?? */
5003 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
5004 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
5005 update_stmt (parcopy_stmt
);
5009 /* Declare local variables needed in CHILD_CFUN. */
5010 block
= DECL_INITIAL (child_fn
);
5011 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
5012 /* The gimplifier could record temporaries in parallel/task block
5013 rather than in containing function's local_decls chain,
5014 which would mean cgraph missed finalizing them. Do it now. */
5015 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
5016 if (TREE_CODE (t
) == VAR_DECL
5018 && !DECL_EXTERNAL (t
))
5019 varpool_node::finalize_decl (t
);
5020 DECL_SAVED_TREE (child_fn
) = NULL
;
5021 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5022 gimple_set_body (child_fn
, NULL
);
5023 TREE_USED (block
) = 1;
5025 /* Reset DECL_CONTEXT on function arguments. */
5026 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
5027 DECL_CONTEXT (t
) = child_fn
;
5029 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5030 so that it can be moved to the child function. */
5031 gsi
= gsi_last_bb (entry_bb
);
5032 stmt
= gsi_stmt (gsi
);
5033 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
5034 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
5035 gsi_remove (&gsi
, true);
5036 e
= split_block (entry_bb
, stmt
);
5038 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5040 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5043 gsi
= gsi_last_bb (exit_bb
);
5044 gcc_assert (!gsi_end_p (gsi
)
5045 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5046 stmt
= gimple_build_return (NULL
);
5047 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5048 gsi_remove (&gsi
, true);
5051 /* Move the parallel region into CHILD_CFUN. */
5053 if (gimple_in_ssa_p (cfun
))
5055 init_tree_ssa (child_cfun
);
5056 init_ssa_operands (child_cfun
);
5057 child_cfun
->gimple_df
->in_ssa_p
= true;
5061 block
= gimple_block (entry_stmt
);
5063 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
5065 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
5066 /* When the OMP expansion process cannot guarantee an up-to-date
5067 loop tree arrange for the child function to fixup loops. */
5068 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5069 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
5071 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5072 num
= vec_safe_length (child_cfun
->local_decls
);
5073 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
5075 t
= (*child_cfun
->local_decls
)[srcidx
];
5076 if (DECL_CONTEXT (t
) == cfun
->decl
)
5078 if (srcidx
!= dstidx
)
5079 (*child_cfun
->local_decls
)[dstidx
] = t
;
5083 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
5085 /* Inform the callgraph about the new function. */
5086 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
5087 cgraph_node::add_new_function (child_fn
, true);
5089 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5090 fixed in a following pass. */
5091 push_cfun (child_cfun
);
5093 optimize_omp_library_calls (entry_stmt
);
5094 cgraph_edge::rebuild_edges ();
5096 /* Some EH regions might become dead, see PR34608. If
5097 pass_cleanup_cfg isn't the first pass to happen with the
5098 new child, these dead EH edges might cause problems.
5099 Clean them up now. */
5100 if (flag_exceptions
)
5103 bool changed
= false;
5105 FOR_EACH_BB_FN (bb
, cfun
)
5106 changed
|= gimple_purge_dead_eh_edges (bb
);
5108 cleanup_tree_cfg ();
5110 if (gimple_in_ssa_p (cfun
))
5111 update_ssa (TODO_update_ssa
);
5115 /* Emit a library call to launch the children threads. */
5117 expand_cilk_for_call (new_bb
, entry_stmt
, ws_args
);
5118 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5119 expand_parallel_call (region
, new_bb
, entry_stmt
, ws_args
);
5121 expand_task_call (new_bb
, entry_stmt
);
5122 if (gimple_in_ssa_p (cfun
))
5123 update_ssa (TODO_update_ssa_only_virtuals
);
5127 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5128 of the combined collapse > 1 loop constructs, generate code like:
5129 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5134 count3 = (adj + N32 - N31) / STEP3;
5135 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5140 count2 = (adj + N22 - N21) / STEP2;
5141 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5146 count1 = (adj + N12 - N11) / STEP1;
5147 count = count1 * count2 * count3;
5148 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5150 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5151 of the combined loop constructs, just initialize COUNTS array
5152 from the _looptemp_ clauses. */
5154 /* NOTE: It *could* be better to moosh all of the BBs together,
5155 creating one larger BB with all the computation and the unexpected
5156 jump at the end. I.e.
5158 bool zero3, zero2, zero1, zero;
5161 count3 = (N32 - N31) /[cl] STEP3;
5163 count2 = (N22 - N21) /[cl] STEP2;
5165 count1 = (N12 - N11) /[cl] STEP1;
5166 zero = zero3 || zero2 || zero1;
5167 count = count1 * count2 * count3;
5168 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5170 After all, we expect the zero=false, and thus we expect to have to
5171 evaluate all of the comparison expressions, so short-circuiting
5172 oughtn't be a win. Since the condition isn't protecting a
5173 denominator, we're not concerned about divide-by-zero, so we can
5174 fully evaluate count even if a numerator turned out to be wrong.
5176 It seems like putting this all together would create much better
5177 scheduling opportunities, and less pressure on the chip's branch
5181 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5182 basic_block
&entry_bb
, tree
*counts
,
5183 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5184 basic_block
&l2_dom_bb
)
5186 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5191 /* Collapsed loops need work for expansion into SSA form. */
5192 gcc_assert (!gimple_in_ssa_p (cfun
));
5194 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5195 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5197 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5198 isn't supposed to be handled, as the inner loop doesn't
5200 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5201 OMP_CLAUSE__LOOPTEMP_
);
5202 gcc_assert (innerc
);
5203 for (i
= 0; i
< fd
->collapse
; i
++)
5205 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5206 OMP_CLAUSE__LOOPTEMP_
);
5207 gcc_assert (innerc
);
5209 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5211 counts
[0] = NULL_TREE
;
5216 for (i
= 0; i
< fd
->collapse
; i
++)
5218 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5220 if (SSA_VAR_P (fd
->loop
.n2
)
5221 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5222 fold_convert (itype
, fd
->loops
[i
].n1
),
5223 fold_convert (itype
, fd
->loops
[i
].n2
)))
5224 == NULL_TREE
|| !integer_onep (t
)))
5227 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5228 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5229 true, GSI_SAME_STMT
);
5230 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5231 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5232 true, GSI_SAME_STMT
);
5233 stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5234 NULL_TREE
, NULL_TREE
);
5235 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5236 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
5237 expand_omp_regimplify_p
, NULL
, NULL
)
5238 || walk_tree (gimple_cond_rhs_ptr (stmt
),
5239 expand_omp_regimplify_p
, NULL
, NULL
))
5241 *gsi
= gsi_for_stmt (stmt
);
5242 gimple_regimplify_operands (stmt
, gsi
);
5244 e
= split_block (entry_bb
, stmt
);
5245 if (zero_iter_bb
== NULL
)
5247 first_zero_iter
= i
;
5248 zero_iter_bb
= create_empty_bb (entry_bb
);
5249 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5250 *gsi
= gsi_after_labels (zero_iter_bb
);
5251 stmt
= gimple_build_assign (fd
->loop
.n2
,
5252 build_zero_cst (type
));
5253 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
5254 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5257 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5258 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5259 e
->flags
= EDGE_TRUE_VALUE
;
5260 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5261 if (l2_dom_bb
== NULL
)
5262 l2_dom_bb
= entry_bb
;
5264 *gsi
= gsi_last_bb (entry_bb
);
5267 if (POINTER_TYPE_P (itype
))
5268 itype
= signed_type_for (itype
);
5269 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5271 t
= fold_build2 (PLUS_EXPR
, itype
,
5272 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5273 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5274 fold_convert (itype
, fd
->loops
[i
].n2
));
5275 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5276 fold_convert (itype
, fd
->loops
[i
].n1
));
5277 /* ?? We could probably use CEIL_DIV_EXPR instead of
5278 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5279 generate the same code in the end because generically we
5280 don't know that the values involved must be negative for
5282 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5283 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5284 fold_build1 (NEGATE_EXPR
, itype
, t
),
5285 fold_build1 (NEGATE_EXPR
, itype
,
5286 fold_convert (itype
,
5287 fd
->loops
[i
].step
)));
5289 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5290 fold_convert (itype
, fd
->loops
[i
].step
));
5291 t
= fold_convert (type
, t
);
5292 if (TREE_CODE (t
) == INTEGER_CST
)
5296 counts
[i
] = create_tmp_reg (type
, ".count");
5297 expand_omp_build_assign (gsi
, counts
[i
], t
);
5299 if (SSA_VAR_P (fd
->loop
.n2
))
5304 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5305 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5311 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5313 V3 = N31 + (T % count3) * STEP3;
5315 V2 = N21 + (T % count2) * STEP2;
5317 V1 = N11 + T * STEP1;
5318 if this loop doesn't have an inner loop construct combined with it.
5319 If it does have an inner loop construct combined with it and the
5320 iteration count isn't known constant, store values from counts array
5321 into its _looptemp_ temporaries instead. */
5324 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5325 tree
*counts
, gimple inner_stmt
, tree startvar
)
5328 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5330 /* If fd->loop.n2 is constant, then no propagation of the counts
5331 is needed, they are constant. */
5332 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5335 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5336 ? gimple_omp_parallel_clauses (inner_stmt
)
5337 : gimple_omp_for_clauses (inner_stmt
);
5338 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5339 isn't supposed to be handled, as the inner loop doesn't
5341 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5342 gcc_assert (innerc
);
5343 for (i
= 0; i
< fd
->collapse
; i
++)
5345 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5346 OMP_CLAUSE__LOOPTEMP_
);
5347 gcc_assert (innerc
);
5350 tree tem
= OMP_CLAUSE_DECL (innerc
);
5351 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5352 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5353 false, GSI_CONTINUE_LINKING
);
5354 gimple stmt
= gimple_build_assign (tem
, t
);
5355 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5361 tree type
= TREE_TYPE (fd
->loop
.v
);
5362 tree tem
= create_tmp_reg (type
, ".tem");
5363 gimple stmt
= gimple_build_assign (tem
, startvar
);
5364 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5366 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5368 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5370 if (POINTER_TYPE_P (vtype
))
5371 itype
= signed_type_for (vtype
);
5373 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5376 t
= fold_convert (itype
, t
);
5377 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5378 fold_convert (itype
, fd
->loops
[i
].step
));
5379 if (POINTER_TYPE_P (vtype
))
5380 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5382 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5383 t
= force_gimple_operand_gsi (gsi
, t
,
5384 DECL_P (fd
->loops
[i
].v
)
5385 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5387 GSI_CONTINUE_LINKING
);
5388 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5389 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5392 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5393 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5394 false, GSI_CONTINUE_LINKING
);
5395 stmt
= gimple_build_assign (tem
, t
);
5396 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5402 /* Helper function for expand_omp_for_*. Generate code like:
5405 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5409 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5416 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5417 basic_block body_bb
)
5419 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5421 gimple_stmt_iterator gsi
;
5427 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5429 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5431 bb
= create_empty_bb (last_bb
);
5432 add_bb_to_loop (bb
, last_bb
->loop_father
);
5433 gsi
= gsi_start_bb (bb
);
5435 if (i
< fd
->collapse
- 1)
5437 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5438 e
->probability
= REG_BR_PROB_BASE
/ 8;
5440 t
= fd
->loops
[i
+ 1].n1
;
5441 t
= force_gimple_operand_gsi (&gsi
, t
,
5442 DECL_P (fd
->loops
[i
+ 1].v
)
5443 && TREE_ADDRESSABLE (fd
->loops
[i
5446 GSI_CONTINUE_LINKING
);
5447 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5448 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5453 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5455 if (POINTER_TYPE_P (vtype
))
5456 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5458 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5459 t
= force_gimple_operand_gsi (&gsi
, t
,
5460 DECL_P (fd
->loops
[i
].v
)
5461 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5462 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5463 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5464 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5468 t
= fd
->loops
[i
].n2
;
5469 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5470 false, GSI_CONTINUE_LINKING
);
5471 tree v
= fd
->loops
[i
].v
;
5472 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5473 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5474 false, GSI_CONTINUE_LINKING
);
5475 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5476 stmt
= gimple_build_cond_empty (t
);
5477 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5478 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5479 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5482 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5490 /* A subroutine of expand_omp_for. Generate code for a parallel
5491 loop with any schedule. Given parameters:
5493 for (V = N1; V cond N2; V += STEP) BODY;
5495 where COND is "<" or ">", we generate pseudocode
5497 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5498 if (more) goto L0; else goto L3;
5505 if (V cond iend) goto L1; else goto L2;
5507 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5510 If this is a combined omp parallel loop, instead of the call to
5511 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5512 If this is gimple_omp_for_combined_p loop, then instead of assigning
5513 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5514 inner GIMPLE_OMP_FOR and V += STEP; and
5515 if (V cond iend) goto L1; else goto L2; are removed.
5517 For collapsed loops, given parameters:
5519 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5520 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5521 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5524 we generate pseudocode
5526 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5531 count3 = (adj + N32 - N31) / STEP3;
5532 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5537 count2 = (adj + N22 - N21) / STEP2;
5538 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5543 count1 = (adj + N12 - N11) / STEP1;
5544 count = count1 * count2 * count3;
5549 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5550 if (more) goto L0; else goto L3;
5554 V3 = N31 + (T % count3) * STEP3;
5556 V2 = N21 + (T % count2) * STEP2;
5558 V1 = N11 + T * STEP1;
5563 if (V < iend) goto L10; else goto L2;
5566 if (V3 cond3 N32) goto L1; else goto L11;
5570 if (V2 cond2 N22) goto L1; else goto L12;
5576 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5582 expand_omp_for_generic (struct omp_region
*region
,
5583 struct omp_for_data
*fd
,
5584 enum built_in_function start_fn
,
5585 enum built_in_function next_fn
,
5588 tree type
, istart0
, iend0
, iend
;
5589 tree t
, vmain
, vback
, bias
= NULL_TREE
;
5590 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
5591 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
5592 gimple_stmt_iterator gsi
;
5594 bool in_combined_parallel
= is_combined_parallel (region
);
5595 bool broken_loop
= region
->cont
== NULL
;
5597 tree
*counts
= NULL
;
5600 gcc_assert (!broken_loop
|| !in_combined_parallel
);
5601 gcc_assert (fd
->iter_type
== long_integer_type_node
5602 || !in_combined_parallel
);
5604 type
= TREE_TYPE (fd
->loop
.v
);
5605 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
5606 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
5607 TREE_ADDRESSABLE (istart0
) = 1;
5608 TREE_ADDRESSABLE (iend0
) = 1;
5610 /* See if we need to bias by LLONG_MIN. */
5611 if (fd
->iter_type
== long_long_unsigned_type_node
5612 && TREE_CODE (type
) == INTEGER_TYPE
5613 && !TYPE_UNSIGNED (type
))
5617 if (fd
->loop
.cond_code
== LT_EXPR
)
5620 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5624 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5627 if (TREE_CODE (n1
) != INTEGER_CST
5628 || TREE_CODE (n2
) != INTEGER_CST
5629 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
5630 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
5633 entry_bb
= region
->entry
;
5634 cont_bb
= region
->cont
;
5636 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5637 gcc_assert (broken_loop
5638 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
5639 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
5640 l1_bb
= single_succ (l0_bb
);
5643 l2_bb
= create_empty_bb (cont_bb
);
5644 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
5645 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5649 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5650 exit_bb
= region
->exit
;
5652 gsi
= gsi_last_bb (entry_bb
);
5654 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5655 if (fd
->collapse
> 1)
5657 int first_zero_iter
= -1;
5658 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
5660 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5661 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5662 zero_iter_bb
, first_zero_iter
,
5667 /* Some counts[i] vars might be uninitialized if
5668 some loop has zero iterations. But the body shouldn't
5669 be executed in that case, so just avoid uninit warnings. */
5670 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
5671 if (SSA_VAR_P (counts
[i
]))
5672 TREE_NO_WARNING (counts
[i
]) = 1;
5674 e
= split_block (entry_bb
, gsi_stmt (gsi
));
5676 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
5677 gsi
= gsi_last_bb (entry_bb
);
5678 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
5679 get_immediate_dominator (CDI_DOMINATORS
,
5683 if (in_combined_parallel
)
5685 /* In a combined parallel loop, emit a call to
5686 GOMP_loop_foo_next. */
5687 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5688 build_fold_addr_expr (istart0
),
5689 build_fold_addr_expr (iend0
));
5693 tree t0
, t1
, t2
, t3
, t4
;
5694 /* If this is not a combined parallel loop, emit a call to
5695 GOMP_loop_foo_start in ENTRY_BB. */
5696 t4
= build_fold_addr_expr (iend0
);
5697 t3
= build_fold_addr_expr (istart0
);
5698 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
5701 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5703 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5704 OMP_CLAUSE__LOOPTEMP_
);
5705 gcc_assert (innerc
);
5706 t0
= OMP_CLAUSE_DECL (innerc
);
5707 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5708 OMP_CLAUSE__LOOPTEMP_
);
5709 gcc_assert (innerc
);
5710 t1
= OMP_CLAUSE_DECL (innerc
);
5712 if (POINTER_TYPE_P (TREE_TYPE (t0
))
5713 && TYPE_PRECISION (TREE_TYPE (t0
))
5714 != TYPE_PRECISION (fd
->iter_type
))
5716 /* Avoid casting pointers to integer of a different size. */
5717 tree itype
= signed_type_for (type
);
5718 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
5719 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
5723 t1
= fold_convert (fd
->iter_type
, t1
);
5724 t0
= fold_convert (fd
->iter_type
, t0
);
5728 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
5729 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
5731 if (fd
->iter_type
== long_integer_type_node
)
5735 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5736 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5737 6, t0
, t1
, t2
, t
, t3
, t4
);
5740 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5741 5, t0
, t1
, t2
, t3
, t4
);
5749 /* The GOMP_loop_ull_*start functions have additional boolean
5750 argument, true for < loops and false for > loops.
5751 In Fortran, the C bool type can be different from
5752 boolean_type_node. */
5753 bfn_decl
= builtin_decl_explicit (start_fn
);
5754 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
5755 t5
= build_int_cst (c_bool_type
,
5756 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
5759 tree bfn_decl
= builtin_decl_explicit (start_fn
);
5760 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5761 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
5764 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5765 6, t5
, t0
, t1
, t2
, t3
, t4
);
5768 if (TREE_TYPE (t
) != boolean_type_node
)
5769 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5770 t
, build_int_cst (TREE_TYPE (t
), 0));
5771 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5772 true, GSI_SAME_STMT
);
5773 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5775 /* Remove the GIMPLE_OMP_FOR statement. */
5776 gsi_remove (&gsi
, true);
5778 /* Iteration setup for sequential loop goes in L0_BB. */
5779 tree startvar
= fd
->loop
.v
;
5780 tree endvar
= NULL_TREE
;
5782 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5784 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
5785 && gimple_omp_for_kind (inner_stmt
)
5786 == GF_OMP_FOR_KIND_SIMD
);
5787 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
5788 OMP_CLAUSE__LOOPTEMP_
);
5789 gcc_assert (innerc
);
5790 startvar
= OMP_CLAUSE_DECL (innerc
);
5791 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5792 OMP_CLAUSE__LOOPTEMP_
);
5793 gcc_assert (innerc
);
5794 endvar
= OMP_CLAUSE_DECL (innerc
);
5797 gsi
= gsi_start_bb (l0_bb
);
5800 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5801 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5802 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5803 t
= fold_convert (TREE_TYPE (startvar
), t
);
5804 t
= force_gimple_operand_gsi (&gsi
, t
,
5806 && TREE_ADDRESSABLE (startvar
),
5807 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5808 stmt
= gimple_build_assign (startvar
, t
);
5809 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5813 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5814 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5815 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5816 t
= fold_convert (TREE_TYPE (startvar
), t
);
5817 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5818 false, GSI_CONTINUE_LINKING
);
5821 stmt
= gimple_build_assign (endvar
, iend
);
5822 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5823 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
5824 stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
5826 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, iend
,
5828 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5830 if (fd
->collapse
> 1)
5831 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
5835 /* Code to control the increment and predicate for the sequential
5836 loop goes in the CONT_BB. */
5837 gsi
= gsi_last_bb (cont_bb
);
5838 stmt
= gsi_stmt (gsi
);
5839 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
5840 vmain
= gimple_omp_continue_control_use (stmt
);
5841 vback
= gimple_omp_continue_control_def (stmt
);
5843 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5845 if (POINTER_TYPE_P (type
))
5846 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
5848 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
5849 t
= force_gimple_operand_gsi (&gsi
, t
,
5851 && TREE_ADDRESSABLE (vback
),
5852 NULL_TREE
, true, GSI_SAME_STMT
);
5853 stmt
= gimple_build_assign (vback
, t
);
5854 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5856 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
5857 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
5859 stmt
= gimple_build_cond_empty (t
);
5860 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5863 /* Remove GIMPLE_OMP_CONTINUE. */
5864 gsi_remove (&gsi
, true);
5866 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
5867 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
5869 /* Emit code to get the next parallel iteration in L2_BB. */
5870 gsi
= gsi_start_bb (l2_bb
);
5872 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5873 build_fold_addr_expr (istart0
),
5874 build_fold_addr_expr (iend0
));
5875 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5876 false, GSI_CONTINUE_LINKING
);
5877 if (TREE_TYPE (t
) != boolean_type_node
)
5878 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5879 t
, build_int_cst (TREE_TYPE (t
), 0));
5880 stmt
= gimple_build_cond_empty (t
);
5881 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5884 /* Add the loop cleanup function. */
5885 gsi
= gsi_last_bb (exit_bb
);
5886 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
5887 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
5888 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5889 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
5891 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
5892 stmt
= gimple_build_call (t
, 0);
5893 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5894 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
5895 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5896 gsi_remove (&gsi
, true);
5898 /* Connect the new blocks. */
5899 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
5900 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
5906 e
= find_edge (cont_bb
, l3_bb
);
5907 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
5909 phis
= phi_nodes (l3_bb
);
5910 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5912 gimple phi
= gsi_stmt (gsi
);
5913 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
5914 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
5918 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
5919 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
5920 e
= find_edge (cont_bb
, l1_bb
);
5921 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5926 else if (fd
->collapse
> 1)
5929 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
5932 e
->flags
= EDGE_TRUE_VALUE
;
5935 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5936 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
5940 e
= find_edge (cont_bb
, l2_bb
);
5941 e
->flags
= EDGE_FALLTHRU
;
5943 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
5945 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
5946 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
5947 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
5948 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
5949 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
5950 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
5951 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
5952 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
5954 struct loop
*outer_loop
= alloc_loop ();
5955 outer_loop
->header
= l0_bb
;
5956 outer_loop
->latch
= l2_bb
;
5957 add_loop (outer_loop
, l0_bb
->loop_father
);
5959 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5961 struct loop
*loop
= alloc_loop ();
5962 loop
->header
= l1_bb
;
5963 /* The loop may have multiple latches. */
5964 add_loop (loop
, outer_loop
);
5970 /* A subroutine of expand_omp_for. Generate code for a parallel
5971 loop with static schedule and no specified chunk size. Given
5974 for (V = N1; V cond N2; V += STEP) BODY;
5976 where COND is "<" or ">", we generate pseudocode
5978 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5983 if ((__typeof (V)) -1 > 0 && cond is >)
5984 n = -(adj + N2 - N1) / -STEP;
5986 n = (adj + N2 - N1) / STEP;
5989 if (threadid < tt) goto L3; else goto L4;
5994 s0 = q * threadid + tt;
5997 if (s0 >= e0) goto L2; else goto L0;
6003 if (V cond e) goto L1;
6008 expand_omp_for_static_nochunk (struct omp_region
*region
,
6009 struct omp_for_data
*fd
,
6012 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
6013 tree type
, itype
, vmain
, vback
;
6014 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
6015 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
6017 gimple_stmt_iterator gsi
;
6020 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6021 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6022 bool broken_loop
= region
->cont
== NULL
;
6023 tree
*counts
= NULL
;
6026 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6027 if (POINTER_TYPE_P (type
))
6028 itype
= signed_type_for (type
);
6030 entry_bb
= region
->entry
;
6031 cont_bb
= region
->cont
;
6032 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6033 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6034 gcc_assert (broken_loop
6035 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
6036 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6037 body_bb
= single_succ (seq_start_bb
);
6040 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6041 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6043 exit_bb
= region
->exit
;
6045 /* Iteration space partitioning goes in ENTRY_BB. */
6046 gsi
= gsi_last_bb (entry_bb
);
6047 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6049 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6051 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6052 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6055 if (fd
->collapse
> 1)
6057 int first_zero_iter
= -1;
6058 basic_block l2_dom_bb
= NULL
;
6060 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6061 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6062 fin_bb
, first_zero_iter
,
6066 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6067 t
= integer_one_node
;
6069 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6070 fold_convert (type
, fd
->loop
.n1
),
6071 fold_convert (type
, fd
->loop
.n2
));
6072 if (fd
->collapse
== 1
6073 && TYPE_UNSIGNED (type
)
6074 && (t
== NULL_TREE
|| !integer_onep (t
)))
6076 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6077 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6078 true, GSI_SAME_STMT
);
6079 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6080 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6081 true, GSI_SAME_STMT
);
6082 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6083 NULL_TREE
, NULL_TREE
);
6084 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6085 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
6086 expand_omp_regimplify_p
, NULL
, NULL
)
6087 || walk_tree (gimple_cond_rhs_ptr (stmt
),
6088 expand_omp_regimplify_p
, NULL
, NULL
))
6090 gsi
= gsi_for_stmt (stmt
);
6091 gimple_regimplify_operands (stmt
, &gsi
);
6093 ep
= split_block (entry_bb
, stmt
);
6094 ep
->flags
= EDGE_TRUE_VALUE
;
6095 entry_bb
= ep
->dest
;
6096 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6097 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6098 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6099 if (gimple_in_ssa_p (cfun
))
6101 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6102 for (gsi
= gsi_start_phis (fin_bb
);
6103 !gsi_end_p (gsi
); gsi_next (&gsi
))
6105 gimple phi
= gsi_stmt (gsi
);
6106 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6107 ep
, UNKNOWN_LOCATION
);
6110 gsi
= gsi_last_bb (entry_bb
);
6113 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6114 t
= fold_convert (itype
, t
);
6115 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6116 true, GSI_SAME_STMT
);
6118 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6119 t
= fold_convert (itype
, t
);
6120 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6121 true, GSI_SAME_STMT
);
6125 step
= fd
->loop
.step
;
6126 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6128 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6129 OMP_CLAUSE__LOOPTEMP_
);
6130 gcc_assert (innerc
);
6131 n1
= OMP_CLAUSE_DECL (innerc
);
6132 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6133 OMP_CLAUSE__LOOPTEMP_
);
6134 gcc_assert (innerc
);
6135 n2
= OMP_CLAUSE_DECL (innerc
);
6137 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6138 true, NULL_TREE
, true, GSI_SAME_STMT
);
6139 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6140 true, NULL_TREE
, true, GSI_SAME_STMT
);
6141 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6142 true, NULL_TREE
, true, GSI_SAME_STMT
);
6144 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6145 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6146 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6147 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6148 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6149 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6150 fold_build1 (NEGATE_EXPR
, itype
, t
),
6151 fold_build1 (NEGATE_EXPR
, itype
, step
));
6153 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6154 t
= fold_convert (itype
, t
);
6155 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6157 q
= create_tmp_reg (itype
, "q");
6158 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
6159 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6160 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
6162 tt
= create_tmp_reg (itype
, "tt");
6163 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
6164 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6165 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
6167 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
6168 stmt
= gimple_build_cond_empty (t
);
6169 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6171 second_bb
= split_block (entry_bb
, stmt
)->dest
;
6172 gsi
= gsi_last_bb (second_bb
);
6173 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6175 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
6177 stmt
= gimple_build_assign_with_ops (PLUS_EXPR
, q
, q
,
6178 build_int_cst (itype
, 1));
6179 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6181 third_bb
= split_block (second_bb
, stmt
)->dest
;
6182 gsi
= gsi_last_bb (third_bb
);
6183 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6185 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6186 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6187 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6189 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6190 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6192 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6193 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6195 /* Remove the GIMPLE_OMP_FOR statement. */
6196 gsi_remove (&gsi
, true);
6198 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6199 gsi
= gsi_start_bb (seq_start_bb
);
6201 tree startvar
= fd
->loop
.v
;
6202 tree endvar
= NULL_TREE
;
6204 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6206 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6207 ? gimple_omp_parallel_clauses (inner_stmt
)
6208 : gimple_omp_for_clauses (inner_stmt
);
6209 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6210 gcc_assert (innerc
);
6211 startvar
= OMP_CLAUSE_DECL (innerc
);
6212 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6213 OMP_CLAUSE__LOOPTEMP_
);
6214 gcc_assert (innerc
);
6215 endvar
= OMP_CLAUSE_DECL (innerc
);
6217 t
= fold_convert (itype
, s0
);
6218 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6219 if (POINTER_TYPE_P (type
))
6220 t
= fold_build_pointer_plus (n1
, t
);
6222 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6223 t
= fold_convert (TREE_TYPE (startvar
), t
);
6224 t
= force_gimple_operand_gsi (&gsi
, t
,
6226 && TREE_ADDRESSABLE (startvar
),
6227 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6228 stmt
= gimple_build_assign (startvar
, t
);
6229 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6231 t
= fold_convert (itype
, e0
);
6232 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6233 if (POINTER_TYPE_P (type
))
6234 t
= fold_build_pointer_plus (n1
, t
);
6236 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6237 t
= fold_convert (TREE_TYPE (startvar
), t
);
6238 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6239 false, GSI_CONTINUE_LINKING
);
6242 stmt
= gimple_build_assign (endvar
, e
);
6243 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6244 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6245 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6247 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6249 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6251 if (fd
->collapse
> 1)
6252 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6256 /* The code controlling the sequential loop replaces the
6257 GIMPLE_OMP_CONTINUE. */
6258 gsi
= gsi_last_bb (cont_bb
);
6259 stmt
= gsi_stmt (gsi
);
6260 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6261 vmain
= gimple_omp_continue_control_use (stmt
);
6262 vback
= gimple_omp_continue_control_def (stmt
);
6264 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6266 if (POINTER_TYPE_P (type
))
6267 t
= fold_build_pointer_plus (vmain
, step
);
6269 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6270 t
= force_gimple_operand_gsi (&gsi
, t
,
6272 && TREE_ADDRESSABLE (vback
),
6273 NULL_TREE
, true, GSI_SAME_STMT
);
6274 stmt
= gimple_build_assign (vback
, t
);
6275 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6277 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6278 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6280 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6283 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6284 gsi_remove (&gsi
, true);
6286 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6287 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6290 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6291 gsi
= gsi_last_bb (exit_bb
);
6292 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6294 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6295 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6297 gsi_remove (&gsi
, true);
6299 /* Connect all the blocks. */
6300 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6301 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6302 ep
= find_edge (entry_bb
, second_bb
);
6303 ep
->flags
= EDGE_TRUE_VALUE
;
6304 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6305 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6306 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6310 ep
= find_edge (cont_bb
, body_bb
);
6311 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6316 else if (fd
->collapse
> 1)
6319 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6322 ep
->flags
= EDGE_TRUE_VALUE
;
6323 find_edge (cont_bb
, fin_bb
)->flags
6324 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6327 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6328 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6329 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6331 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6332 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6333 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6334 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6336 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6338 struct loop
*loop
= alloc_loop ();
6339 loop
->header
= body_bb
;
6340 if (collapse_bb
== NULL
)
6341 loop
->latch
= cont_bb
;
6342 add_loop (loop
, body_bb
->loop_father
);
6347 /* A subroutine of expand_omp_for. Generate code for a parallel
6348 loop with static schedule and a specified chunk size. Given
6351 for (V = N1; V cond N2; V += STEP) BODY;
6353 where COND is "<" or ">", we generate pseudocode
6355 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6360 if ((__typeof (V)) -1 > 0 && cond is >)
6361 n = -(adj + N2 - N1) / -STEP;
6363 n = (adj + N2 - N1) / STEP;
6365 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6366 here so that V is defined
6367 if the loop is not entered
6369 s0 = (trip * nthreads + threadid) * CHUNK;
6370 e0 = min(s0 + CHUNK, n);
6371 if (s0 < n) goto L1; else goto L4;
6378 if (V cond e) goto L2; else goto L3;
6386 expand_omp_for_static_chunk (struct omp_region
*region
,
6387 struct omp_for_data
*fd
, gimple inner_stmt
)
6389 tree n
, s0
, e0
, e
, t
;
6390 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6391 tree type
, itype
, vmain
, vback
, vextra
;
6392 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6393 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6394 gimple_stmt_iterator gsi
;
6397 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6398 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6399 bool broken_loop
= region
->cont
== NULL
;
6400 tree
*counts
= NULL
;
6403 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6404 if (POINTER_TYPE_P (type
))
6405 itype
= signed_type_for (type
);
6407 entry_bb
= region
->entry
;
6408 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6410 iter_part_bb
= se
->dest
;
6411 cont_bb
= region
->cont
;
6412 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6413 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6414 gcc_assert (broken_loop
6415 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6416 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6417 body_bb
= single_succ (seq_start_bb
);
6420 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6421 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6422 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6424 exit_bb
= region
->exit
;
6426 /* Trip and adjustment setup goes in ENTRY_BB. */
6427 gsi
= gsi_last_bb (entry_bb
);
6428 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6430 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6432 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6433 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6436 if (fd
->collapse
> 1)
6438 int first_zero_iter
= -1;
6439 basic_block l2_dom_bb
= NULL
;
6441 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6442 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6443 fin_bb
, first_zero_iter
,
6447 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6448 t
= integer_one_node
;
6450 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6451 fold_convert (type
, fd
->loop
.n1
),
6452 fold_convert (type
, fd
->loop
.n2
));
6453 if (fd
->collapse
== 1
6454 && TYPE_UNSIGNED (type
)
6455 && (t
== NULL_TREE
|| !integer_onep (t
)))
6457 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6458 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6459 true, GSI_SAME_STMT
);
6460 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6461 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6462 true, GSI_SAME_STMT
);
6463 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6464 NULL_TREE
, NULL_TREE
);
6465 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6466 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
6467 expand_omp_regimplify_p
, NULL
, NULL
)
6468 || walk_tree (gimple_cond_rhs_ptr (stmt
),
6469 expand_omp_regimplify_p
, NULL
, NULL
))
6471 gsi
= gsi_for_stmt (stmt
);
6472 gimple_regimplify_operands (stmt
, &gsi
);
6474 se
= split_block (entry_bb
, stmt
);
6475 se
->flags
= EDGE_TRUE_VALUE
;
6476 entry_bb
= se
->dest
;
6477 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6478 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6479 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6480 if (gimple_in_ssa_p (cfun
))
6482 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6483 for (gsi
= gsi_start_phis (fin_bb
);
6484 !gsi_end_p (gsi
); gsi_next (&gsi
))
6486 gimple phi
= gsi_stmt (gsi
);
6487 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6488 se
, UNKNOWN_LOCATION
);
6491 gsi
= gsi_last_bb (entry_bb
);
6494 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6495 t
= fold_convert (itype
, t
);
6496 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6497 true, GSI_SAME_STMT
);
6499 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6500 t
= fold_convert (itype
, t
);
6501 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6502 true, GSI_SAME_STMT
);
6506 step
= fd
->loop
.step
;
6507 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6509 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6510 OMP_CLAUSE__LOOPTEMP_
);
6511 gcc_assert (innerc
);
6512 n1
= OMP_CLAUSE_DECL (innerc
);
6513 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6514 OMP_CLAUSE__LOOPTEMP_
);
6515 gcc_assert (innerc
);
6516 n2
= OMP_CLAUSE_DECL (innerc
);
6518 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6519 true, NULL_TREE
, true, GSI_SAME_STMT
);
6520 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6521 true, NULL_TREE
, true, GSI_SAME_STMT
);
6522 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6523 true, NULL_TREE
, true, GSI_SAME_STMT
);
6525 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
6526 true, NULL_TREE
, true, GSI_SAME_STMT
);
6528 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6529 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6530 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6531 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6532 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6533 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6534 fold_build1 (NEGATE_EXPR
, itype
, t
),
6535 fold_build1 (NEGATE_EXPR
, itype
, step
));
6537 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6538 t
= fold_convert (itype
, t
);
6539 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6540 true, GSI_SAME_STMT
);
6542 trip_var
= create_tmp_reg (itype
, ".trip");
6543 if (gimple_in_ssa_p (cfun
))
6545 trip_init
= make_ssa_name (trip_var
, NULL
);
6546 trip_main
= make_ssa_name (trip_var
, NULL
);
6547 trip_back
= make_ssa_name (trip_var
, NULL
);
6551 trip_init
= trip_var
;
6552 trip_main
= trip_var
;
6553 trip_back
= trip_var
;
6556 stmt
= gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
6557 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6559 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
6560 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6561 if (POINTER_TYPE_P (type
))
6562 t
= fold_build_pointer_plus (n1
, t
);
6564 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6565 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6566 true, GSI_SAME_STMT
);
6568 /* Remove the GIMPLE_OMP_FOR. */
6569 gsi_remove (&gsi
, true);
6571 /* Iteration space partitioning goes in ITER_PART_BB. */
6572 gsi
= gsi_last_bb (iter_part_bb
);
6574 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
6575 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
6576 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
6577 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6578 false, GSI_CONTINUE_LINKING
);
6580 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
6581 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
6582 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6583 false, GSI_CONTINUE_LINKING
);
6585 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
6586 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
6588 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6589 gsi
= gsi_start_bb (seq_start_bb
);
6591 tree startvar
= fd
->loop
.v
;
6592 tree endvar
= NULL_TREE
;
6594 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6596 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6597 ? gimple_omp_parallel_clauses (inner_stmt
)
6598 : gimple_omp_for_clauses (inner_stmt
);
6599 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6600 gcc_assert (innerc
);
6601 startvar
= OMP_CLAUSE_DECL (innerc
);
6602 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6603 OMP_CLAUSE__LOOPTEMP_
);
6604 gcc_assert (innerc
);
6605 endvar
= OMP_CLAUSE_DECL (innerc
);
6608 t
= fold_convert (itype
, s0
);
6609 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6610 if (POINTER_TYPE_P (type
))
6611 t
= fold_build_pointer_plus (n1
, t
);
6613 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6614 t
= fold_convert (TREE_TYPE (startvar
), t
);
6615 t
= force_gimple_operand_gsi (&gsi
, t
,
6617 && TREE_ADDRESSABLE (startvar
),
6618 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6619 stmt
= gimple_build_assign (startvar
, t
);
6620 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6622 t
= fold_convert (itype
, e0
);
6623 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6624 if (POINTER_TYPE_P (type
))
6625 t
= fold_build_pointer_plus (n1
, t
);
6627 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6628 t
= fold_convert (TREE_TYPE (startvar
), t
);
6629 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6630 false, GSI_CONTINUE_LINKING
);
6633 stmt
= gimple_build_assign (endvar
, e
);
6634 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6635 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6636 stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6638 stmt
= gimple_build_assign_with_ops (NOP_EXPR
, fd
->loop
.v
, e
,
6640 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6642 if (fd
->collapse
> 1)
6643 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6647 /* The code controlling the sequential loop goes in CONT_BB,
6648 replacing the GIMPLE_OMP_CONTINUE. */
6649 gsi
= gsi_last_bb (cont_bb
);
6650 stmt
= gsi_stmt (gsi
);
6651 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6652 vmain
= gimple_omp_continue_control_use (stmt
);
6653 vback
= gimple_omp_continue_control_def (stmt
);
6655 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6657 if (POINTER_TYPE_P (type
))
6658 t
= fold_build_pointer_plus (vmain
, step
);
6660 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6661 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
6662 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6663 true, GSI_SAME_STMT
);
6664 stmt
= gimple_build_assign (vback
, t
);
6665 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6667 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6668 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6670 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6673 /* Remove GIMPLE_OMP_CONTINUE. */
6674 gsi_remove (&gsi
, true);
6676 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6677 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6679 /* Trip update code goes into TRIP_UPDATE_BB. */
6680 gsi
= gsi_start_bb (trip_update_bb
);
6682 t
= build_int_cst (itype
, 1);
6683 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
6684 stmt
= gimple_build_assign (trip_back
, t
);
6685 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6688 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6689 gsi
= gsi_last_bb (exit_bb
);
6690 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6692 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6693 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6695 gsi_remove (&gsi
, true);
6697 /* Connect the new blocks. */
6698 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
6699 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
6703 se
= find_edge (cont_bb
, body_bb
);
6704 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6709 else if (fd
->collapse
> 1)
6712 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6715 se
->flags
= EDGE_TRUE_VALUE
;
6716 find_edge (cont_bb
, trip_update_bb
)->flags
6717 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6719 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
6722 if (gimple_in_ssa_p (cfun
))
6724 gimple_stmt_iterator psi
;
6730 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
6732 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6733 remove arguments of the phi nodes in fin_bb. We need to create
6734 appropriate phi nodes in iter_part_bb instead. */
6735 se
= single_pred_edge (fin_bb
);
6736 re
= single_succ_edge (trip_update_bb
);
6737 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
6738 ene
= single_succ_edge (entry_bb
);
6740 psi
= gsi_start_phis (fin_bb
);
6741 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
6742 gsi_next (&psi
), ++i
)
6745 source_location locus
;
6747 phi
= gsi_stmt (psi
);
6748 t
= gimple_phi_result (phi
);
6749 gcc_assert (t
== redirect_edge_var_map_result (vm
));
6750 nphi
= create_phi_node (t
, iter_part_bb
);
6752 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
6753 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
6755 /* A special case -- fd->loop.v is not yet computed in
6756 iter_part_bb, we need to use vextra instead. */
6757 if (t
== fd
->loop
.v
)
6759 add_phi_arg (nphi
, t
, ene
, locus
);
6760 locus
= redirect_edge_var_map_location (vm
);
6761 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
6763 gcc_assert (!gsi_end_p (psi
) && i
== head
->length ());
6764 redirect_edge_var_map_clear (re
);
6767 psi
= gsi_start_phis (fin_bb
);
6768 if (gsi_end_p (psi
))
6770 remove_phi_node (&psi
, false);
6773 /* Make phi node for trip. */
6774 phi
= create_phi_node (trip_main
, iter_part_bb
);
6775 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
6777 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
6782 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
6783 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
6784 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
6785 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6786 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6787 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
6788 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
6789 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6790 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6794 struct loop
*trip_loop
= alloc_loop ();
6795 trip_loop
->header
= iter_part_bb
;
6796 trip_loop
->latch
= trip_update_bb
;
6797 add_loop (trip_loop
, iter_part_bb
->loop_father
);
6799 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6801 struct loop
*loop
= alloc_loop ();
6802 loop
->header
= body_bb
;
6803 if (collapse_bb
== NULL
)
6804 loop
->latch
= cont_bb
;
6805 add_loop (loop
, trip_loop
);
6810 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6812 for (V = N1; V cond N2; V += STEP) BODY;
6814 where COND is "<" or ">" or "!=", we generate pseudocode
6816 for (ind_var = low; ind_var < high; ind_var++)
6818 V = n1 + (ind_var * STEP)
6823 In the above pseudocode, low and high are function parameters of the
6824 child function. In the function below, we are inserting a temp.
6825 variable that will be making a call to two OMP functions that will not be
6826 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6827 with _Cilk_for). These functions are replaced with low and high
6828 by the function that handles taskreg. */
6832 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
6834 bool broken_loop
= region
->cont
== NULL
;
6835 basic_block entry_bb
= region
->entry
;
6836 basic_block cont_bb
= region
->cont
;
6838 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6839 gcc_assert (broken_loop
6840 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6841 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
6842 basic_block l1_bb
, l2_bb
;
6846 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
6847 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6848 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
6849 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6853 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
6854 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
6855 l2_bb
= single_succ (l1_bb
);
6857 basic_block exit_bb
= region
->exit
;
6858 basic_block l2_dom_bb
= NULL
;
6860 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
6862 /* Below statements until the "tree high_val = ..." are pseudo statements
6863 used to pass information to be used by expand_omp_taskreg.
6864 low_val and high_val will be replaced by the __low and __high
6865 parameter from the child function.
6867 The call_exprs part is a place-holder, it is mainly used
6868 to distinctly identify to the top-level part that this is
6869 where we should put low and high (reasoning given in header
6873 = gimple_omp_parallel_child_fn (last_stmt (region
->outer
->entry
));
6874 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
6875 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
6877 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
6879 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
6882 gcc_assert (low_val
&& high_val
);
6884 tree type
= TREE_TYPE (low_val
);
6885 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
6886 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6888 /* Not needed in SSA form right now. */
6889 gcc_assert (!gimple_in_ssa_p (cfun
));
6890 if (l2_dom_bb
== NULL
)
6896 gimple stmt
= gimple_build_assign (ind_var
, n1
);
6898 /* Replace the GIMPLE_OMP_FOR statement. */
6899 gsi_replace (&gsi
, stmt
, true);
6903 /* Code to control the increment goes in the CONT_BB. */
6904 gsi
= gsi_last_bb (cont_bb
);
6905 stmt
= gsi_stmt (gsi
);
6906 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6907 stmt
= gimple_build_assign_with_ops (PLUS_EXPR
, ind_var
, ind_var
,
6908 build_one_cst (type
));
6910 /* Replace GIMPLE_OMP_CONTINUE. */
6911 gsi_replace (&gsi
, stmt
, true);
6914 /* Emit the condition in L1_BB. */
6915 gsi
= gsi_after_labels (l1_bb
);
6916 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
6917 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
6919 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
6920 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
6921 fd
->loop
.n1
, fold_convert (sizetype
, t
));
6923 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
6924 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
6925 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
6926 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
6928 /* The condition is always '<' since the runtime will fill in the low
6930 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
6931 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6933 /* Remove GIMPLE_OMP_RETURN. */
6934 gsi
= gsi_last_bb (exit_bb
);
6935 gsi_remove (&gsi
, true);
6937 /* Connect the new blocks. */
6938 remove_edge (FALLTHRU_EDGE (entry_bb
));
6943 remove_edge (BRANCH_EDGE (entry_bb
));
6944 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
6946 e
= BRANCH_EDGE (l1_bb
);
6947 ne
= FALLTHRU_EDGE (l1_bb
);
6948 e
->flags
= EDGE_TRUE_VALUE
;
6952 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6954 ne
= single_succ_edge (l1_bb
);
6955 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6958 ne
->flags
= EDGE_FALSE_VALUE
;
6959 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6960 ne
->probability
= REG_BR_PROB_BASE
/ 8;
6962 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
6963 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
6964 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
6968 struct loop
*loop
= alloc_loop ();
6969 loop
->header
= l1_bb
;
6970 loop
->latch
= cont_bb
;
6971 add_loop (loop
, l1_bb
->loop_father
);
6972 loop
->safelen
= INT_MAX
;
6975 /* Pick the correct library function based on the precision of the
6976 induction variable type. */
6977 tree lib_fun
= NULL_TREE
;
6978 if (TYPE_PRECISION (type
) == 32)
6979 lib_fun
= cilk_for_32_fndecl
;
6980 else if (TYPE_PRECISION (type
) == 64)
6981 lib_fun
= cilk_for_64_fndecl
;
6985 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
6987 /* WS_ARGS contains the library function flavor to call:
6988 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
6989 user-defined grain value. If the user does not define one, then zero
6990 is passed in by the parser. */
6991 vec_alloc (region
->ws_args
, 2);
6992 region
->ws_args
->quick_push (lib_fun
);
6993 region
->ws_args
->quick_push (fd
->chunk_size
);
6996 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6997 loop. Given parameters:
6999 for (V = N1; V cond N2; V += STEP) BODY;
7001 where COND is "<" or ">", we generate pseudocode
7009 if (V cond N2) goto L0; else goto L2;
7012 For collapsed loops, given parameters:
7014 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7015 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7016 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7019 we generate pseudocode
7025 count3 = (adj + N32 - N31) / STEP3;
7030 count2 = (adj + N22 - N21) / STEP2;
7035 count1 = (adj + N12 - N11) / STEP1;
7036 count = count1 * count2 * count3;
7046 V2 += (V3 cond3 N32) ? 0 : STEP2;
7047 V3 = (V3 cond3 N32) ? V3 : N31;
7048 V1 += (V2 cond2 N22) ? 0 : STEP1;
7049 V2 = (V2 cond2 N22) ? V2 : N21;
7051 if (V < count) goto L0; else goto L2;
7057 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
7060 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
7061 gimple_stmt_iterator gsi
;
7063 bool broken_loop
= region
->cont
== NULL
;
7065 tree
*counts
= NULL
;
7067 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7068 OMP_CLAUSE_SAFELEN
);
7069 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7070 OMP_CLAUSE__SIMDUID_
);
7073 type
= TREE_TYPE (fd
->loop
.v
);
7074 entry_bb
= region
->entry
;
7075 cont_bb
= region
->cont
;
7076 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7077 gcc_assert (broken_loop
7078 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7079 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7082 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7083 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7084 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7085 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7089 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7090 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7091 l2_bb
= single_succ (l1_bb
);
7093 exit_bb
= region
->exit
;
7096 gsi
= gsi_last_bb (entry_bb
);
7098 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7099 /* Not needed in SSA form right now. */
7100 gcc_assert (!gimple_in_ssa_p (cfun
));
7101 if (fd
->collapse
> 1)
7103 int first_zero_iter
= -1;
7104 basic_block zero_iter_bb
= l2_bb
;
7106 counts
= XALLOCAVEC (tree
, fd
->collapse
);
7107 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7108 zero_iter_bb
, first_zero_iter
,
7111 if (l2_dom_bb
== NULL
)
7116 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7118 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7119 OMP_CLAUSE__LOOPTEMP_
);
7120 gcc_assert (innerc
);
7121 n1
= OMP_CLAUSE_DECL (innerc
);
7122 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7123 OMP_CLAUSE__LOOPTEMP_
);
7124 gcc_assert (innerc
);
7125 n2
= OMP_CLAUSE_DECL (innerc
);
7126 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7127 fold_convert (type
, n1
));
7128 if (fd
->collapse
> 1)
7131 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
7137 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7138 fold_convert (type
, fd
->loop
.n1
));
7139 if (fd
->collapse
> 1)
7140 for (i
= 0; i
< fd
->collapse
; i
++)
7142 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7143 if (POINTER_TYPE_P (itype
))
7144 itype
= signed_type_for (itype
);
7145 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
7146 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7150 /* Remove the GIMPLE_OMP_FOR statement. */
7151 gsi_remove (&gsi
, true);
7155 /* Code to control the increment goes in the CONT_BB. */
7156 gsi
= gsi_last_bb (cont_bb
);
7157 stmt
= gsi_stmt (gsi
);
7158 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7160 if (POINTER_TYPE_P (type
))
7161 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
7163 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
7164 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7166 if (fd
->collapse
> 1)
7168 i
= fd
->collapse
- 1;
7169 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7171 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
7172 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
7176 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
7178 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7181 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7183 for (i
= fd
->collapse
- 1; i
> 0; i
--)
7185 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7186 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
7187 if (POINTER_TYPE_P (itype2
))
7188 itype2
= signed_type_for (itype2
);
7189 t
= build3 (COND_EXPR
, itype2
,
7190 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7192 fold_convert (itype
, fd
->loops
[i
].n2
)),
7193 build_int_cst (itype2
, 0),
7194 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
7195 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
7196 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
7198 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
7199 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
7201 t
= build3 (COND_EXPR
, itype
,
7202 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7204 fold_convert (itype
, fd
->loops
[i
].n2
)),
7206 fold_convert (itype
, fd
->loops
[i
].n1
));
7207 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7211 /* Remove GIMPLE_OMP_CONTINUE. */
7212 gsi_remove (&gsi
, true);
7215 /* Emit the condition in L1_BB. */
7216 gsi
= gsi_start_bb (l1_bb
);
7218 t
= fold_convert (type
, n2
);
7219 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7220 false, GSI_CONTINUE_LINKING
);
7221 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
7222 stmt
= gimple_build_cond_empty (t
);
7223 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7224 if (walk_tree (gimple_cond_lhs_ptr (stmt
), expand_omp_regimplify_p
,
7226 || walk_tree (gimple_cond_rhs_ptr (stmt
), expand_omp_regimplify_p
,
7229 gsi
= gsi_for_stmt (stmt
);
7230 gimple_regimplify_operands (stmt
, &gsi
);
7233 /* Remove GIMPLE_OMP_RETURN. */
7234 gsi
= gsi_last_bb (exit_bb
);
7235 gsi_remove (&gsi
, true);
7237 /* Connect the new blocks. */
7238 remove_edge (FALLTHRU_EDGE (entry_bb
));
7242 remove_edge (BRANCH_EDGE (entry_bb
));
7243 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7245 e
= BRANCH_EDGE (l1_bb
);
7246 ne
= FALLTHRU_EDGE (l1_bb
);
7247 e
->flags
= EDGE_TRUE_VALUE
;
7251 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7253 ne
= single_succ_edge (l1_bb
);
7254 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7257 ne
->flags
= EDGE_FALSE_VALUE
;
7258 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7259 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7261 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7262 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7263 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7267 struct loop
*loop
= alloc_loop ();
7268 loop
->header
= l1_bb
;
7269 loop
->latch
= cont_bb
;
7270 add_loop (loop
, l1_bb
->loop_father
);
7271 if (safelen
== NULL_TREE
)
7272 loop
->safelen
= INT_MAX
;
7275 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
7276 if (TREE_CODE (safelen
) != INTEGER_CST
)
7278 else if (!tree_fits_uhwi_p (safelen
)
7279 || tree_to_uhwi (safelen
) > INT_MAX
)
7280 loop
->safelen
= INT_MAX
;
7282 loop
->safelen
= tree_to_uhwi (safelen
);
7283 if (loop
->safelen
== 1)
7288 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
7289 cfun
->has_simduid_loops
= true;
7291 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7293 if ((flag_tree_loop_vectorize
7294 || (!global_options_set
.x_flag_tree_loop_vectorize
7295 && !global_options_set
.x_flag_tree_vectorize
))
7296 && flag_tree_loop_optimize
7297 && loop
->safelen
> 1)
7299 loop
->force_vectorize
= true;
7300 cfun
->has_force_vectorize_loops
= true;
7306 /* Expand the OpenMP loop defined by REGION. */
7309 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
7311 struct omp_for_data fd
;
7312 struct omp_for_data_loop
*loops
;
7315 = (struct omp_for_data_loop
*)
7316 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
7317 * sizeof (struct omp_for_data_loop
));
7318 extract_omp_for_data (last_stmt (region
->entry
), &fd
, loops
);
7319 region
->sched_kind
= fd
.sched_kind
;
7321 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
7322 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7323 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7326 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
7327 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7328 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7331 /* If there isn't a continue then this is a degerate case where
7332 the introduction of abnormal edges during lowering will prevent
7333 original loops from being detected. Fix that up. */
7334 loops_state_set (LOOPS_NEED_FIXUP
);
7336 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
7337 expand_omp_simd (region
, &fd
);
7338 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
7339 expand_cilk_for (region
, &fd
);
7340 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
7341 && !fd
.have_ordered
)
7343 if (fd
.chunk_size
== NULL
)
7344 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
7346 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
7350 int fn_index
, start_ix
, next_ix
;
7352 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
7353 == GF_OMP_FOR_KIND_FOR
);
7354 if (fd
.chunk_size
== NULL
7355 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
7356 fd
.chunk_size
= integer_zero_node
;
7357 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
7358 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
7359 ? 3 : fd
.sched_kind
;
7360 fn_index
+= fd
.have_ordered
* 4;
7361 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
7362 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
7363 if (fd
.iter_type
== long_long_unsigned_type_node
)
7365 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7366 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
7367 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7368 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7370 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7371 (enum built_in_function
) next_ix
, inner_stmt
);
7374 if (gimple_in_ssa_p (cfun
))
7375 update_ssa (TODO_update_ssa_only_virtuals
);
7379 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7381 v = GOMP_sections_start (n);
7398 v = GOMP_sections_next ();
7403 If this is a combined parallel sections, replace the call to
7404 GOMP_sections_start with call to GOMP_sections_next. */
7407 expand_omp_sections (struct omp_region
*region
)
7409 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7411 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7412 gimple_stmt_iterator si
, switch_si
;
7413 gimple sections_stmt
, stmt
, cont
;
7416 struct omp_region
*inner
;
7418 bool exit_reachable
= region
->cont
!= NULL
;
7420 gcc_assert (region
->exit
!= NULL
);
7421 entry_bb
= region
->entry
;
7422 l0_bb
= single_succ (entry_bb
);
7423 l1_bb
= region
->cont
;
7424 l2_bb
= region
->exit
;
7425 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7426 l2
= gimple_block_label (l2_bb
);
7429 /* This can happen if there are reductions. */
7430 len
= EDGE_COUNT (l0_bb
->succs
);
7431 gcc_assert (len
> 0);
7432 e
= EDGE_SUCC (l0_bb
, len
- 1);
7433 si
= gsi_last_bb (e
->dest
);
7436 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7437 l2
= gimple_block_label (e
->dest
);
7439 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7441 si
= gsi_last_bb (e
->dest
);
7443 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7445 l2
= gimple_block_label (e
->dest
);
7451 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7453 default_bb
= create_empty_bb (l0_bb
);
7455 /* We will build a switch() with enough cases for all the
7456 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7457 and a default case to abort if something goes wrong. */
7458 len
= EDGE_COUNT (l0_bb
->succs
);
7460 /* Use vec::quick_push on label_vec throughout, since we know the size
7462 auto_vec
<tree
> label_vec (len
);
7464 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7465 GIMPLE_OMP_SECTIONS statement. */
7466 si
= gsi_last_bb (entry_bb
);
7467 sections_stmt
= gsi_stmt (si
);
7468 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
7469 vin
= gimple_omp_sections_control (sections_stmt
);
7470 if (!is_combined_parallel (region
))
7472 /* If we are not inside a combined parallel+sections region,
7473 call GOMP_sections_start. */
7474 t
= build_int_cst (unsigned_type_node
, len
- 1);
7475 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
7476 stmt
= gimple_build_call (u
, 1, t
);
7480 /* Otherwise, call GOMP_sections_next. */
7481 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7482 stmt
= gimple_build_call (u
, 0);
7484 gimple_call_set_lhs (stmt
, vin
);
7485 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7486 gsi_remove (&si
, true);
7488 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7490 switch_si
= gsi_last_bb (l0_bb
);
7491 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
7494 cont
= last_stmt (l1_bb
);
7495 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
7496 vmain
= gimple_omp_continue_control_use (cont
);
7497 vnext
= gimple_omp_continue_control_def (cont
);
7505 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
7506 label_vec
.quick_push (t
);
7509 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7510 for (inner
= region
->inner
, casei
= 1;
7512 inner
= inner
->next
, i
++, casei
++)
7514 basic_block s_entry_bb
, s_exit_bb
;
7516 /* Skip optional reduction region. */
7517 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
7524 s_entry_bb
= inner
->entry
;
7525 s_exit_bb
= inner
->exit
;
7527 t
= gimple_block_label (s_entry_bb
);
7528 u
= build_int_cst (unsigned_type_node
, casei
);
7529 u
= build_case_label (u
, NULL
, t
);
7530 label_vec
.quick_push (u
);
7532 si
= gsi_last_bb (s_entry_bb
);
7533 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
7534 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
7535 gsi_remove (&si
, true);
7536 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
7538 if (s_exit_bb
== NULL
)
7541 si
= gsi_last_bb (s_exit_bb
);
7542 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7543 gsi_remove (&si
, true);
7545 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
7548 /* Error handling code goes in DEFAULT_BB. */
7549 t
= gimple_block_label (default_bb
);
7550 u
= build_case_label (NULL
, NULL
, t
);
7551 make_edge (l0_bb
, default_bb
, 0);
7552 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
7554 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
7555 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
7556 gsi_remove (&switch_si
, true);
7558 si
= gsi_start_bb (default_bb
);
7559 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
7560 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
7566 /* Code to get the next section goes in L1_BB. */
7567 si
= gsi_last_bb (l1_bb
);
7568 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
7570 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7571 stmt
= gimple_build_call (bfn_decl
, 0);
7572 gimple_call_set_lhs (stmt
, vnext
);
7573 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7574 gsi_remove (&si
, true);
7576 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
7579 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7580 si
= gsi_last_bb (l2_bb
);
7581 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
7582 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
7583 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
7584 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
7586 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
7587 stmt
= gimple_build_call (t
, 0);
7588 if (gimple_omp_return_lhs (gsi_stmt (si
)))
7589 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
7590 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7591 gsi_remove (&si
, true);
7593 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
7597 /* Expand code for an OpenMP single directive. We've already expanded
7598 much of the code, here we simply place the GOMP_barrier call. */
7601 expand_omp_single (struct omp_region
*region
)
7603 basic_block entry_bb
, exit_bb
;
7604 gimple_stmt_iterator si
;
7606 entry_bb
= region
->entry
;
7607 exit_bb
= region
->exit
;
7609 si
= gsi_last_bb (entry_bb
);
7610 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
7611 gsi_remove (&si
, true);
7612 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7614 si
= gsi_last_bb (exit_bb
);
7615 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
7617 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
7618 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
7620 gsi_remove (&si
, true);
7621 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7625 /* Generic expansion for OpenMP synchronization directives: master,
7626 ordered and critical. All we need to do here is remove the entry
7627 and exit markers for REGION. */
7630 expand_omp_synch (struct omp_region
*region
)
7632 basic_block entry_bb
, exit_bb
;
7633 gimple_stmt_iterator si
;
7635 entry_bb
= region
->entry
;
7636 exit_bb
= region
->exit
;
7638 si
= gsi_last_bb (entry_bb
);
7639 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
7640 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
7641 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
7642 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
7643 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
7644 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
7645 gsi_remove (&si
, true);
7646 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7650 si
= gsi_last_bb (exit_bb
);
7651 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7652 gsi_remove (&si
, true);
7653 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7657 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7658 operation as a normal volatile load. */
7661 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
7662 tree loaded_val
, int index
)
7664 enum built_in_function tmpbase
;
7665 gimple_stmt_iterator gsi
;
7666 basic_block store_bb
;
7669 tree decl
, call
, type
, itype
;
7671 gsi
= gsi_last_bb (load_bb
);
7672 stmt
= gsi_stmt (gsi
);
7673 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7674 loc
= gimple_location (stmt
);
7676 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7677 is smaller than word size, then expand_atomic_load assumes that the load
7678 is atomic. We could avoid the builtin entirely in this case. */
7680 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7681 decl
= builtin_decl_explicit (tmpbase
);
7682 if (decl
== NULL_TREE
)
7685 type
= TREE_TYPE (loaded_val
);
7686 itype
= TREE_TYPE (TREE_TYPE (decl
));
7688 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
7689 build_int_cst (NULL
,
7690 gimple_omp_atomic_seq_cst_p (stmt
)
7692 : MEMMODEL_RELAXED
));
7693 if (!useless_type_conversion_p (type
, itype
))
7694 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7695 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7697 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7698 gsi_remove (&gsi
, true);
7700 store_bb
= single_succ (load_bb
);
7701 gsi
= gsi_last_bb (store_bb
);
7702 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7703 gsi_remove (&gsi
, true);
7705 if (gimple_in_ssa_p (cfun
))
7706 update_ssa (TODO_update_ssa_no_phi
);
7711 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7712 operation as a normal volatile store. */
7715 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
7716 tree loaded_val
, tree stored_val
, int index
)
7718 enum built_in_function tmpbase
;
7719 gimple_stmt_iterator gsi
;
7720 basic_block store_bb
= single_succ (load_bb
);
7723 tree decl
, call
, type
, itype
;
7724 enum machine_mode imode
;
7727 gsi
= gsi_last_bb (load_bb
);
7728 stmt
= gsi_stmt (gsi
);
7729 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7731 /* If the load value is needed, then this isn't a store but an exchange. */
7732 exchange
= gimple_omp_atomic_need_value_p (stmt
);
7734 gsi
= gsi_last_bb (store_bb
);
7735 stmt
= gsi_stmt (gsi
);
7736 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
7737 loc
= gimple_location (stmt
);
7739 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7740 is smaller than word size, then expand_atomic_store assumes that the store
7741 is atomic. We could avoid the builtin entirely in this case. */
7743 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
7744 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
7745 decl
= builtin_decl_explicit (tmpbase
);
7746 if (decl
== NULL_TREE
)
7749 type
= TREE_TYPE (stored_val
);
7751 /* Dig out the type of the function's second argument. */
7752 itype
= TREE_TYPE (decl
);
7753 itype
= TYPE_ARG_TYPES (itype
);
7754 itype
= TREE_CHAIN (itype
);
7755 itype
= TREE_VALUE (itype
);
7756 imode
= TYPE_MODE (itype
);
7758 if (exchange
&& !can_atomic_exchange_p (imode
, true))
7761 if (!useless_type_conversion_p (itype
, type
))
7762 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
7763 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
7764 build_int_cst (NULL
,
7765 gimple_omp_atomic_seq_cst_p (stmt
)
7767 : MEMMODEL_RELAXED
));
7770 if (!useless_type_conversion_p (type
, itype
))
7771 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7772 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7775 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7776 gsi_remove (&gsi
, true);
7778 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7779 gsi
= gsi_last_bb (load_bb
);
7780 gsi_remove (&gsi
, true);
7782 if (gimple_in_ssa_p (cfun
))
7783 update_ssa (TODO_update_ssa_no_phi
);
7788 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7789 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7790 size of the data type, and thus usable to find the index of the builtin
7791 decl. Returns false if the expression is not of the proper form. */
7794 expand_omp_atomic_fetch_op (basic_block load_bb
,
7795 tree addr
, tree loaded_val
,
7796 tree stored_val
, int index
)
7798 enum built_in_function oldbase
, newbase
, tmpbase
;
7799 tree decl
, itype
, call
;
7801 basic_block store_bb
= single_succ (load_bb
);
7802 gimple_stmt_iterator gsi
;
7805 enum tree_code code
;
7806 bool need_old
, need_new
;
7807 enum machine_mode imode
;
7810 /* We expect to find the following sequences:
7813 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7816 val = tmp OP something; (or: something OP tmp)
7817 GIMPLE_OMP_STORE (val)
7819 ???FIXME: Allow a more flexible sequence.
7820 Perhaps use data flow to pick the statements.
7824 gsi
= gsi_after_labels (store_bb
);
7825 stmt
= gsi_stmt (gsi
);
7826 loc
= gimple_location (stmt
);
7827 if (!is_gimple_assign (stmt
))
7830 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
7832 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
7833 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
7834 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
7835 gcc_checking_assert (!need_old
|| !need_new
);
7837 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
7840 /* Check for one of the supported fetch-op operations. */
7841 code
= gimple_assign_rhs_code (stmt
);
7845 case POINTER_PLUS_EXPR
:
7846 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
7847 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
7850 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
7851 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
7854 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
7855 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
7858 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
7859 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
7862 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
7863 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
7869 /* Make sure the expression is of the proper form. */
7870 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
7871 rhs
= gimple_assign_rhs2 (stmt
);
7872 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
7873 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
7874 rhs
= gimple_assign_rhs1 (stmt
);
7878 tmpbase
= ((enum built_in_function
)
7879 ((need_new
? newbase
: oldbase
) + index
+ 1));
7880 decl
= builtin_decl_explicit (tmpbase
);
7881 if (decl
== NULL_TREE
)
7883 itype
= TREE_TYPE (TREE_TYPE (decl
));
7884 imode
= TYPE_MODE (itype
);
7886 /* We could test all of the various optabs involved, but the fact of the
7887 matter is that (with the exception of i486 vs i586 and xadd) all targets
7888 that support any atomic operaton optab also implements compare-and-swap.
7889 Let optabs.c take care of expanding any compare-and-swap loop. */
7890 if (!can_compare_and_swap_p (imode
, true))
7893 gsi
= gsi_last_bb (load_bb
);
7894 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7896 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7897 It only requires that the operation happen atomically. Thus we can
7898 use the RELAXED memory model. */
7899 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
7900 fold_convert_loc (loc
, itype
, rhs
),
7901 build_int_cst (NULL
,
7902 seq_cst
? MEMMODEL_SEQ_CST
7903 : MEMMODEL_RELAXED
));
7905 if (need_old
|| need_new
)
7907 lhs
= need_old
? loaded_val
: stored_val
;
7908 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
7909 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
7912 call
= fold_convert_loc (loc
, void_type_node
, call
);
7913 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7914 gsi_remove (&gsi
, true);
7916 gsi
= gsi_last_bb (store_bb
);
7917 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7918 gsi_remove (&gsi
, true);
7919 gsi
= gsi_last_bb (store_bb
);
7920 gsi_remove (&gsi
, true);
7922 if (gimple_in_ssa_p (cfun
))
7923 update_ssa (TODO_update_ssa_no_phi
);
7928 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7932 newval = rhs; // with oldval replacing *addr in rhs
7933 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7934 if (oldval != newval)
7937 INDEX is log2 of the size of the data type, and thus usable to find the
7938 index of the builtin decl. */
7941 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
7942 tree addr
, tree loaded_val
, tree stored_val
,
7945 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
7946 tree type
, itype
, cmpxchg
, iaddr
;
7947 gimple_stmt_iterator si
;
7948 basic_block loop_header
= single_succ (load_bb
);
7951 enum built_in_function fncode
;
7953 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7954 order to use the RELAXED memory model effectively. */
7955 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7957 cmpxchg
= builtin_decl_explicit (fncode
);
7958 if (cmpxchg
== NULL_TREE
)
7960 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
7961 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
7963 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
7966 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7967 si
= gsi_last_bb (load_bb
);
7968 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7970 /* For floating-point values, we'll need to view-convert them to integers
7971 so that we can perform the atomic compare and swap. Simplify the
7972 following code by always setting up the "i"ntegral variables. */
7973 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
7977 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
7980 = force_gimple_operand_gsi (&si
,
7981 fold_convert (TREE_TYPE (iaddr
), addr
),
7982 false, NULL_TREE
, true, GSI_SAME_STMT
);
7983 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
7984 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
7985 loadedi
= create_tmp_var (itype
, NULL
);
7986 if (gimple_in_ssa_p (cfun
))
7987 loadedi
= make_ssa_name (loadedi
, NULL
);
7992 loadedi
= loaded_val
;
7995 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7996 tree loaddecl
= builtin_decl_explicit (fncode
);
7999 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
8000 build_call_expr (loaddecl
, 2, iaddr
,
8001 build_int_cst (NULL_TREE
,
8002 MEMMODEL_RELAXED
)));
8004 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
8005 build_int_cst (TREE_TYPE (iaddr
), 0));
8008 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
8011 /* Move the value to the LOADEDI temporary. */
8012 if (gimple_in_ssa_p (cfun
))
8014 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
8015 phi
= create_phi_node (loadedi
, loop_header
);
8016 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
8020 gsi_insert_before (&si
,
8021 gimple_build_assign (loadedi
, initial
),
8023 if (loadedi
!= loaded_val
)
8025 gimple_stmt_iterator gsi2
;
8028 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
8029 gsi2
= gsi_start_bb (loop_header
);
8030 if (gimple_in_ssa_p (cfun
))
8033 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8034 true, GSI_SAME_STMT
);
8035 stmt
= gimple_build_assign (loaded_val
, x
);
8036 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
8040 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
8041 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8042 true, GSI_SAME_STMT
);
8045 gsi_remove (&si
, true);
8047 si
= gsi_last_bb (store_bb
);
8048 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8051 storedi
= stored_val
;
8054 force_gimple_operand_gsi (&si
,
8055 build1 (VIEW_CONVERT_EXPR
, itype
,
8056 stored_val
), true, NULL_TREE
, true,
8059 /* Build the compare&swap statement. */
8060 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
8061 new_storedi
= force_gimple_operand_gsi (&si
,
8062 fold_convert (TREE_TYPE (loadedi
),
8065 true, GSI_SAME_STMT
);
8067 if (gimple_in_ssa_p (cfun
))
8071 old_vali
= create_tmp_var (TREE_TYPE (loadedi
), NULL
);
8072 stmt
= gimple_build_assign (old_vali
, loadedi
);
8073 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8075 stmt
= gimple_build_assign (loadedi
, new_storedi
);
8076 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8079 /* Note that we always perform the comparison as an integer, even for
8080 floating point. This allows the atomic operation to properly
8081 succeed even with NaNs and -0.0. */
8082 stmt
= gimple_build_cond_empty
8083 (build2 (NE_EXPR
, boolean_type_node
,
8084 new_storedi
, old_vali
));
8085 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8088 e
= single_succ_edge (store_bb
);
8089 e
->flags
&= ~EDGE_FALLTHRU
;
8090 e
->flags
|= EDGE_FALSE_VALUE
;
8092 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
8094 /* Copy the new value to loadedi (we already did that before the condition
8095 if we are not in SSA). */
8096 if (gimple_in_ssa_p (cfun
))
8098 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
8099 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
8102 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8103 gsi_remove (&si
, true);
8105 struct loop
*loop
= alloc_loop ();
8106 loop
->header
= loop_header
;
8107 loop
->latch
= store_bb
;
8108 add_loop (loop
, loop_header
->loop_father
);
8110 if (gimple_in_ssa_p (cfun
))
8111 update_ssa (TODO_update_ssa_no_phi
);
8116 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8118 GOMP_atomic_start ();
8122 The result is not globally atomic, but works so long as all parallel
8123 references are within #pragma omp atomic directives. According to
8124 responses received from omp@openmp.org, appears to be within spec.
8125 Which makes sense, since that's how several other compilers handle
8126 this situation as well.
8127 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8128 expanding. STORED_VAL is the operand of the matching
8129 GIMPLE_OMP_ATOMIC_STORE.
8132 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8136 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8141 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
8142 tree addr
, tree loaded_val
, tree stored_val
)
8144 gimple_stmt_iterator si
;
8148 si
= gsi_last_bb (load_bb
);
8149 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8151 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
8152 t
= build_call_expr (t
, 0);
8153 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8155 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
8156 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8157 gsi_remove (&si
, true);
8159 si
= gsi_last_bb (store_bb
);
8160 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8162 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
8164 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8166 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
8167 t
= build_call_expr (t
, 0);
8168 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8169 gsi_remove (&si
, true);
8171 if (gimple_in_ssa_p (cfun
))
8172 update_ssa (TODO_update_ssa_no_phi
);
8176 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8177 using expand_omp_atomic_fetch_op. If it failed, we try to
8178 call expand_omp_atomic_pipeline, and if it fails too, the
8179 ultimate fallback is wrapping the operation in a mutex
8180 (expand_omp_atomic_mutex). REGION is the atomic region built
8181 by build_omp_regions_1(). */
8184 expand_omp_atomic (struct omp_region
*region
)
8186 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
8187 gimple load
= last_stmt (load_bb
), store
= last_stmt (store_bb
);
8188 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
8189 tree addr
= gimple_omp_atomic_load_rhs (load
);
8190 tree stored_val
= gimple_omp_atomic_store_val (store
);
8191 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8192 HOST_WIDE_INT index
;
8194 /* Make sure the type is one of the supported sizes. */
8195 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
8196 index
= exact_log2 (index
);
8197 if (index
>= 0 && index
<= 4)
8199 unsigned int align
= TYPE_ALIGN_UNIT (type
);
8201 /* __sync builtins require strict data alignment. */
8202 if (exact_log2 (align
) >= index
)
8205 if (loaded_val
== stored_val
8206 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8207 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8208 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8209 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
8213 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8214 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8215 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8216 && store_bb
== single_succ (load_bb
)
8217 && first_stmt (store_bb
) == store
8218 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
8222 /* When possible, use specialized atomic update functions. */
8223 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
8224 && store_bb
== single_succ (load_bb
)
8225 && expand_omp_atomic_fetch_op (load_bb
, addr
,
8226 loaded_val
, stored_val
, index
))
8229 /* If we don't have specialized __sync builtins, try and implement
8230 as a compare and swap loop. */
8231 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
8232 loaded_val
, stored_val
, index
))
8237 /* The ultimate fallback is wrapping the operation in a mutex. */
8238 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
8242 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8245 expand_omp_target (struct omp_region
*region
)
8247 basic_block entry_bb
, exit_bb
, new_bb
;
8248 struct function
*child_cfun
= NULL
;
8249 tree child_fn
= NULL_TREE
, block
, t
;
8250 gimple_stmt_iterator gsi
;
8251 gimple entry_stmt
, stmt
;
8254 entry_stmt
= last_stmt (region
->entry
);
8255 new_bb
= region
->entry
;
8256 int kind
= gimple_omp_target_kind (entry_stmt
);
8257 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8259 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
8260 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
8263 entry_bb
= region
->entry
;
8264 exit_bb
= region
->exit
;
8266 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8268 unsigned srcidx
, dstidx
, num
;
8270 /* If the target region needs data sent from the parent
8271 function, then the very first statement (except possible
8272 tree profile counter updates) of the parallel body
8273 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8274 &.OMP_DATA_O is passed as an argument to the child function,
8275 we need to replace it with the argument as seen by the child
8278 In most cases, this will end up being the identity assignment
8279 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8280 a function call that has been inlined, the original PARM_DECL
8281 .OMP_DATA_I may have been converted into a different local
8282 variable. In which case, we need to keep the assignment. */
8283 if (gimple_omp_target_data_arg (entry_stmt
))
8285 basic_block entry_succ_bb
= single_succ (entry_bb
);
8286 gimple_stmt_iterator gsi
;
8288 gimple tgtcopy_stmt
= NULL
;
8290 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt
), 0);
8292 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
8294 gcc_assert (!gsi_end_p (gsi
));
8295 stmt
= gsi_stmt (gsi
);
8296 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
8299 if (gimple_num_ops (stmt
) == 2)
8301 tree arg
= gimple_assign_rhs1 (stmt
);
8303 /* We're ignoring the subcode because we're
8304 effectively doing a STRIP_NOPS. */
8306 if (TREE_CODE (arg
) == ADDR_EXPR
8307 && TREE_OPERAND (arg
, 0) == sender
)
8309 tgtcopy_stmt
= stmt
;
8315 gcc_assert (tgtcopy_stmt
!= NULL
);
8316 arg
= DECL_ARGUMENTS (child_fn
);
8318 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
8319 gsi_remove (&gsi
, true);
8322 /* Declare local variables needed in CHILD_CFUN. */
8323 block
= DECL_INITIAL (child_fn
);
8324 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
8325 /* The gimplifier could record temporaries in target block
8326 rather than in containing function's local_decls chain,
8327 which would mean cgraph missed finalizing them. Do it now. */
8328 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
8329 if (TREE_CODE (t
) == VAR_DECL
8331 && !DECL_EXTERNAL (t
))
8332 varpool_node::finalize_decl (t
);
8333 DECL_SAVED_TREE (child_fn
) = NULL
;
8334 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8335 gimple_set_body (child_fn
, NULL
);
8336 TREE_USED (block
) = 1;
8338 /* Reset DECL_CONTEXT on function arguments. */
8339 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
8340 DECL_CONTEXT (t
) = child_fn
;
8342 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8343 so that it can be moved to the child function. */
8344 gsi
= gsi_last_bb (entry_bb
);
8345 stmt
= gsi_stmt (gsi
);
8346 gcc_assert (stmt
&& gimple_code (stmt
) == GIMPLE_OMP_TARGET
8347 && gimple_omp_target_kind (stmt
)
8348 == GF_OMP_TARGET_KIND_REGION
);
8349 gsi_remove (&gsi
, true);
8350 e
= split_block (entry_bb
, stmt
);
8352 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8354 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8357 gsi
= gsi_last_bb (exit_bb
);
8358 gcc_assert (!gsi_end_p (gsi
)
8359 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
8360 stmt
= gimple_build_return (NULL
);
8361 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
8362 gsi_remove (&gsi
, true);
8365 /* Move the target region into CHILD_CFUN. */
8367 block
= gimple_block (entry_stmt
);
8369 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
8371 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
8372 /* When the OMP expansion process cannot guarantee an up-to-date
8373 loop tree arrange for the child function to fixup loops. */
8374 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
8375 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
8377 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8378 num
= vec_safe_length (child_cfun
->local_decls
);
8379 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
8381 t
= (*child_cfun
->local_decls
)[srcidx
];
8382 if (DECL_CONTEXT (t
) == cfun
->decl
)
8384 if (srcidx
!= dstidx
)
8385 (*child_cfun
->local_decls
)[dstidx
] = t
;
8389 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
8391 /* Inform the callgraph about the new function. */
8392 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
8393 cgraph_node::add_new_function (child_fn
, true);
8395 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8396 fixed in a following pass. */
8397 push_cfun (child_cfun
);
8398 cgraph_edge::rebuild_edges ();
8400 /* Some EH regions might become dead, see PR34608. If
8401 pass_cleanup_cfg isn't the first pass to happen with the
8402 new child, these dead EH edges might cause problems.
8403 Clean them up now. */
8404 if (flag_exceptions
)
8407 bool changed
= false;
8409 FOR_EACH_BB_FN (bb
, cfun
)
8410 changed
|= gimple_purge_dead_eh_edges (bb
);
8412 cleanup_tree_cfg ();
8417 /* Emit a library call to launch the target region, or do data
8419 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
8420 enum built_in_function start_ix
;
8421 location_t clause_loc
;
8423 clauses
= gimple_omp_target_clauses (entry_stmt
);
8425 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8426 start_ix
= BUILT_IN_GOMP_TARGET
;
8427 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
8428 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
8430 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
8432 /* By default, the value of DEVICE is -1 (let runtime library choose)
8433 and there is no conditional. */
8435 device
= build_int_cst (integer_type_node
, -1);
8437 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
8439 cond
= OMP_CLAUSE_IF_EXPR (c
);
8441 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
8444 device
= OMP_CLAUSE_DEVICE_ID (c
);
8445 clause_loc
= OMP_CLAUSE_LOCATION (c
);
8448 clause_loc
= gimple_location (entry_stmt
);
8450 /* Ensure 'device' is of the correct type. */
8451 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
8453 /* If we found the clause 'if (cond)', build
8454 (cond ? device : -2). */
8457 cond
= gimple_boolify (cond
);
8459 basic_block cond_bb
, then_bb
, else_bb
;
8463 tmp_var
= create_tmp_var (TREE_TYPE (device
), NULL
);
8464 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8466 gsi
= gsi_last_bb (new_bb
);
8468 e
= split_block (new_bb
, gsi_stmt (gsi
));
8471 e
= split_block (new_bb
, NULL
);
8476 then_bb
= create_empty_bb (cond_bb
);
8477 else_bb
= create_empty_bb (then_bb
);
8478 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
8479 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
8481 stmt
= gimple_build_cond_empty (cond
);
8482 gsi
= gsi_last_bb (cond_bb
);
8483 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8485 gsi
= gsi_start_bb (then_bb
);
8486 stmt
= gimple_build_assign (tmp_var
, device
);
8487 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8489 gsi
= gsi_start_bb (else_bb
);
8490 stmt
= gimple_build_assign (tmp_var
,
8491 build_int_cst (integer_type_node
, -2));
8492 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8494 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
8495 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
8496 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
8497 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
8498 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
8499 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
8504 gsi
= gsi_last_bb (new_bb
);
8505 t
= gimple_omp_target_data_arg (entry_stmt
);
8508 t1
= size_zero_node
;
8509 t2
= build_zero_cst (ptr_type_node
);
8515 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
8516 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
8517 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
8518 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
8519 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
8523 /* FIXME: This will be address of
8524 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8525 symbol, as soon as the linker plugin is able to create it for us. */
8526 tree openmp_target
= build_zero_cst (ptr_type_node
);
8527 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8529 tree fnaddr
= build_fold_addr_expr (child_fn
);
8530 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 7,
8531 device
, fnaddr
, openmp_target
, t1
, t2
, t3
, t4
);
8534 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 6,
8535 device
, openmp_target
, t1
, t2
, t3
, t4
);
8536 gimple_set_location (g
, gimple_location (entry_stmt
));
8537 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
8538 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8541 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
8542 gsi_remove (&gsi
, true);
8544 if (kind
== GF_OMP_TARGET_KIND_DATA
&& region
->exit
)
8546 gsi
= gsi_last_bb (region
->exit
);
8548 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
8549 gsi_remove (&gsi
, true);
8554 /* Expand the parallel region tree rooted at REGION. Expansion
8555 proceeds in depth-first order. Innermost regions are expanded
8556 first. This way, parallel regions that require a new function to
8557 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8558 internal dependencies in their body. */
8561 expand_omp (struct omp_region
*region
)
8565 location_t saved_location
;
8566 gimple inner_stmt
= NULL
;
8568 /* First, determine whether this is a combined parallel+workshare
8570 if (region
->type
== GIMPLE_OMP_PARALLEL
)
8571 determine_parallel_type (region
);
8573 if (region
->type
== GIMPLE_OMP_FOR
8574 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
8575 inner_stmt
= last_stmt (region
->inner
->entry
);
8578 expand_omp (region
->inner
);
8580 saved_location
= input_location
;
8581 if (gimple_has_location (last_stmt (region
->entry
)))
8582 input_location
= gimple_location (last_stmt (region
->entry
));
8584 switch (region
->type
)
8586 case GIMPLE_OMP_PARALLEL
:
8587 case GIMPLE_OMP_TASK
:
8588 expand_omp_taskreg (region
);
8591 case GIMPLE_OMP_FOR
:
8592 expand_omp_for (region
, inner_stmt
);
8595 case GIMPLE_OMP_SECTIONS
:
8596 expand_omp_sections (region
);
8599 case GIMPLE_OMP_SECTION
:
8600 /* Individual omp sections are handled together with their
8601 parent GIMPLE_OMP_SECTIONS region. */
8604 case GIMPLE_OMP_SINGLE
:
8605 expand_omp_single (region
);
8608 case GIMPLE_OMP_MASTER
:
8609 case GIMPLE_OMP_TASKGROUP
:
8610 case GIMPLE_OMP_ORDERED
:
8611 case GIMPLE_OMP_CRITICAL
:
8612 case GIMPLE_OMP_TEAMS
:
8613 expand_omp_synch (region
);
8616 case GIMPLE_OMP_ATOMIC_LOAD
:
8617 expand_omp_atomic (region
);
8620 case GIMPLE_OMP_TARGET
:
8621 expand_omp_target (region
);
8628 input_location
= saved_location
;
8629 region
= region
->next
;
8634 /* Helper for build_omp_regions. Scan the dominator tree starting at
8635 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8636 true, the function ends once a single tree is built (otherwise, whole
8637 forest of OMP constructs may be built). */
8640 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
8643 gimple_stmt_iterator gsi
;
8647 gsi
= gsi_last_bb (bb
);
8648 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
8650 struct omp_region
*region
;
8651 enum gimple_code code
;
8653 stmt
= gsi_stmt (gsi
);
8654 code
= gimple_code (stmt
);
8655 if (code
== GIMPLE_OMP_RETURN
)
8657 /* STMT is the return point out of region PARENT. Mark it
8658 as the exit point and make PARENT the immediately
8659 enclosing region. */
8660 gcc_assert (parent
);
8663 parent
= parent
->outer
;
8665 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
8667 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8668 GIMPLE_OMP_RETURN, but matches with
8669 GIMPLE_OMP_ATOMIC_LOAD. */
8670 gcc_assert (parent
);
8671 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
8674 parent
= parent
->outer
;
8677 else if (code
== GIMPLE_OMP_CONTINUE
)
8679 gcc_assert (parent
);
8682 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
8684 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8685 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8688 else if (code
== GIMPLE_OMP_TARGET
8689 && gimple_omp_target_kind (stmt
) == GF_OMP_TARGET_KIND_UPDATE
)
8690 new_omp_region (bb
, code
, parent
);
8693 /* Otherwise, this directive becomes the parent for a new
8695 region
= new_omp_region (bb
, code
, parent
);
8700 if (single_tree
&& !parent
)
8703 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
8705 son
= next_dom_son (CDI_DOMINATORS
, son
))
8706 build_omp_regions_1 (son
, parent
, single_tree
);
8709 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8713 build_omp_regions_root (basic_block root
)
8715 gcc_assert (root_omp_region
== NULL
);
8716 build_omp_regions_1 (root
, NULL
, true);
8717 gcc_assert (root_omp_region
!= NULL
);
8720 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8723 omp_expand_local (basic_block head
)
8725 build_omp_regions_root (head
);
8726 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
8728 fprintf (dump_file
, "\nOMP region tree\n\n");
8729 dump_omp_region (dump_file
, root_omp_region
, 0);
8730 fprintf (dump_file
, "\n");
8733 remove_exit_barriers (root_omp_region
);
8734 expand_omp (root_omp_region
);
8736 free_omp_regions ();
8739 /* Scan the CFG and build a tree of OMP regions. Return the root of
8740 the OMP region tree. */
8743 build_omp_regions (void)
8745 gcc_assert (root_omp_region
== NULL
);
8746 calculate_dominance_info (CDI_DOMINATORS
);
8747 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
8750 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8753 execute_expand_omp (void)
8755 build_omp_regions ();
8757 if (!root_omp_region
)
8762 fprintf (dump_file
, "\nOMP region tree\n\n");
8763 dump_omp_region (dump_file
, root_omp_region
, 0);
8764 fprintf (dump_file
, "\n");
8767 remove_exit_barriers (root_omp_region
);
8769 expand_omp (root_omp_region
);
8771 cleanup_tree_cfg ();
8773 free_omp_regions ();
8778 /* OMP expansion -- the default pass, run before creation of SSA form. */
8782 const pass_data pass_data_expand_omp
=
8784 GIMPLE_PASS
, /* type */
8785 "ompexp", /* name */
8786 OPTGROUP_NONE
, /* optinfo_flags */
8787 TV_NONE
, /* tv_id */
8788 PROP_gimple_any
, /* properties_required */
8789 0, /* properties_provided */
8790 0, /* properties_destroyed */
8791 0, /* todo_flags_start */
8792 0, /* todo_flags_finish */
8795 class pass_expand_omp
: public gimple_opt_pass
8798 pass_expand_omp (gcc::context
*ctxt
)
8799 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
8802 /* opt_pass methods: */
8803 virtual bool gate (function
*)
8805 return ((flag_openmp
!= 0 || flag_openmp_simd
!= 0
8806 || flag_cilkplus
!= 0) && !seen_error ());
8809 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
8811 }; // class pass_expand_omp
8816 make_pass_expand_omp (gcc::context
*ctxt
)
8818 return new pass_expand_omp (ctxt
);
8821 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8823 /* If ctx is a worksharing context inside of a cancellable parallel
8824 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8825 and conditional branch to parallel's cancel_label to handle
8826 cancellation in the implicit barrier. */
8829 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
8831 gimple omp_return
= gimple_seq_last_stmt (*body
);
8832 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
8833 if (gimple_omp_return_nowait_p (omp_return
))
8836 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
8837 && ctx
->outer
->cancellable
)
8839 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
8840 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
8841 tree lhs
= create_tmp_var (c_bool_type
, NULL
);
8842 gimple_omp_return_set_lhs (omp_return
, lhs
);
8843 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
8844 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
8845 fold_convert (c_bool_type
,
8846 boolean_false_node
),
8847 ctx
->outer
->cancel_label
, fallthru_label
);
8848 gimple_seq_add_stmt (body
, g
);
8849 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
8853 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8854 CTX is the enclosing OMP context for the current statement. */
8857 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8859 tree block
, control
;
8860 gimple_stmt_iterator tgsi
;
8861 gimple stmt
, new_stmt
, bind
, t
;
8862 gimple_seq ilist
, dlist
, olist
, new_body
;
8864 stmt
= gsi_stmt (*gsi_p
);
8866 push_gimplify_context ();
8870 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
8871 &ilist
, &dlist
, ctx
, NULL
);
8873 new_body
= gimple_omp_body (stmt
);
8874 gimple_omp_set_body (stmt
, NULL
);
8875 tgsi
= gsi_start (new_body
);
8876 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
8881 sec_start
= gsi_stmt (tgsi
);
8882 sctx
= maybe_lookup_ctx (sec_start
);
8885 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
8886 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
8887 GSI_CONTINUE_LINKING
);
8888 gimple_omp_set_body (sec_start
, NULL
);
8890 if (gsi_one_before_end_p (tgsi
))
8892 gimple_seq l
= NULL
;
8893 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
8895 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
8896 gimple_omp_section_set_last (sec_start
);
8899 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
8900 GSI_CONTINUE_LINKING
);
8903 block
= make_node (BLOCK
);
8904 bind
= gimple_build_bind (NULL
, new_body
, block
);
8907 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
8909 block
= make_node (BLOCK
);
8910 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
8911 gsi_replace (gsi_p
, new_stmt
, true);
8913 pop_gimplify_context (new_stmt
);
8914 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
8915 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
8916 if (BLOCK_VARS (block
))
8917 TREE_USED (block
) = 1;
8920 gimple_seq_add_seq (&new_body
, ilist
);
8921 gimple_seq_add_stmt (&new_body
, stmt
);
8922 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
8923 gimple_seq_add_stmt (&new_body
, bind
);
8925 control
= create_tmp_var (unsigned_type_node
, ".section");
8926 t
= gimple_build_omp_continue (control
, control
);
8927 gimple_omp_sections_set_control (stmt
, control
);
8928 gimple_seq_add_stmt (&new_body
, t
);
8930 gimple_seq_add_seq (&new_body
, olist
);
8931 if (ctx
->cancellable
)
8932 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
8933 gimple_seq_add_seq (&new_body
, dlist
);
8935 new_body
= maybe_catch_exception (new_body
);
8937 t
= gimple_build_omp_return
8938 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
8939 OMP_CLAUSE_NOWAIT
));
8940 gimple_seq_add_stmt (&new_body
, t
);
8941 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
8943 gimple_bind_set_body (new_stmt
, new_body
);
8947 /* A subroutine of lower_omp_single. Expand the simple form of
8948 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8950 if (GOMP_single_start ())
8952 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8954 FIXME. It may be better to delay expanding the logic of this until
8955 pass_expand_omp. The expanded logic may make the job more difficult
8956 to a synchronization analysis pass. */
8959 lower_omp_single_simple (gimple single_stmt
, gimple_seq
*pre_p
)
8961 location_t loc
= gimple_location (single_stmt
);
8962 tree tlabel
= create_artificial_label (loc
);
8963 tree flabel
= create_artificial_label (loc
);
8967 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
8968 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)), NULL
);
8969 call
= gimple_build_call (decl
, 0);
8970 gimple_call_set_lhs (call
, lhs
);
8971 gimple_seq_add_stmt (pre_p
, call
);
8973 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
8974 fold_convert_loc (loc
, TREE_TYPE (lhs
),
8977 gimple_seq_add_stmt (pre_p
, cond
);
8978 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
8979 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
8980 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
8984 /* A subroutine of lower_omp_single. Expand the simple form of
8985 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8987 #pragma omp single copyprivate (a, b, c)
8989 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8992 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8998 GOMP_single_copy_end (©out);
9009 FIXME. It may be better to delay expanding the logic of this until
9010 pass_expand_omp. The expanded logic may make the job more difficult
9011 to a synchronization analysis pass. */
9014 lower_omp_single_copy (gimple single_stmt
, gimple_seq
*pre_p
, omp_context
*ctx
)
9016 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
9017 gimple_seq copyin_seq
;
9018 location_t loc
= gimple_location (single_stmt
);
9020 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
9022 ptr_type
= build_pointer_type (ctx
->record_type
);
9023 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
9025 l0
= create_artificial_label (loc
);
9026 l1
= create_artificial_label (loc
);
9027 l2
= create_artificial_label (loc
);
9029 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
9030 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
9031 t
= fold_convert_loc (loc
, ptr_type
, t
);
9032 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
9034 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
9035 build_int_cst (ptr_type
, 0));
9036 t
= build3 (COND_EXPR
, void_type_node
, t
,
9037 build_and_jump (&l0
), build_and_jump (&l1
));
9038 gimplify_and_add (t
, pre_p
);
9040 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
9042 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
9045 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
9048 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9049 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
9050 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
9051 gimplify_and_add (t
, pre_p
);
9053 t
= build_and_jump (&l2
);
9054 gimplify_and_add (t
, pre_p
);
9056 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
9058 gimple_seq_add_seq (pre_p
, copyin_seq
);
9060 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
9064 /* Expand code for an OpenMP single directive. */
9067 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9070 gimple t
, bind
, single_stmt
= gsi_stmt (*gsi_p
);
9071 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
9073 push_gimplify_context ();
9075 block
= make_node (BLOCK
);
9076 bind
= gimple_build_bind (NULL
, NULL
, block
);
9077 gsi_replace (gsi_p
, bind
, true);
9080 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
9081 &bind_body
, &dlist
, ctx
, NULL
);
9082 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
9084 gimple_seq_add_stmt (&bind_body
, single_stmt
);
9086 if (ctx
->record_type
)
9087 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
9089 lower_omp_single_simple (single_stmt
, &bind_body
);
9091 gimple_omp_set_body (single_stmt
, NULL
);
9093 gimple_seq_add_seq (&bind_body
, dlist
);
9095 bind_body
= maybe_catch_exception (bind_body
);
9097 t
= gimple_build_omp_return
9098 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
9099 OMP_CLAUSE_NOWAIT
));
9100 gimple_seq_add_stmt (&bind_body_tail
, t
);
9101 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
9102 if (ctx
->record_type
)
9104 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
9105 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
9106 TREE_THIS_VOLATILE (clobber
) = 1;
9107 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
9108 clobber
), GSI_SAME_STMT
);
9110 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
9111 gimple_bind_set_body (bind
, bind_body
);
9113 pop_gimplify_context (bind
);
9115 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9116 BLOCK_VARS (block
) = ctx
->block_vars
;
9117 if (BLOCK_VARS (block
))
9118 TREE_USED (block
) = 1;
9122 /* Expand code for an OpenMP master directive. */
9125 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9127 tree block
, lab
= NULL
, x
, bfn_decl
;
9128 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
9129 location_t loc
= gimple_location (stmt
);
9132 push_gimplify_context ();
9134 block
= make_node (BLOCK
);
9135 bind
= gimple_build_bind (NULL
, NULL
, block
);
9136 gsi_replace (gsi_p
, bind
, true);
9137 gimple_bind_add_stmt (bind
, stmt
);
9139 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
9140 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
9141 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
9142 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
9144 gimplify_and_add (x
, &tseq
);
9145 gimple_bind_add_seq (bind
, tseq
);
9147 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9148 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9149 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9150 gimple_omp_set_body (stmt
, NULL
);
9152 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
9154 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9156 pop_gimplify_context (bind
);
9158 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9159 BLOCK_VARS (block
) = ctx
->block_vars
;
9163 /* Expand code for an OpenMP taskgroup directive. */
9166 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9168 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
9169 tree block
= make_node (BLOCK
);
9171 bind
= gimple_build_bind (NULL
, NULL
, block
);
9172 gsi_replace (gsi_p
, bind
, true);
9173 gimple_bind_add_stmt (bind
, stmt
);
9175 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
9177 gimple_bind_add_stmt (bind
, x
);
9179 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9180 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9181 gimple_omp_set_body (stmt
, NULL
);
9183 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9185 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9186 BLOCK_VARS (block
) = ctx
->block_vars
;
9190 /* Expand code for an OpenMP ordered directive. */
9193 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9196 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
9198 push_gimplify_context ();
9200 block
= make_node (BLOCK
);
9201 bind
= gimple_build_bind (NULL
, NULL
, block
);
9202 gsi_replace (gsi_p
, bind
, true);
9203 gimple_bind_add_stmt (bind
, stmt
);
9205 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
9207 gimple_bind_add_stmt (bind
, x
);
9209 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9210 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9211 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9212 gimple_omp_set_body (stmt
, NULL
);
9214 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
9215 gimple_bind_add_stmt (bind
, x
);
9217 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9219 pop_gimplify_context (bind
);
9221 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9222 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
9226 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9227 substitution of a couple of function calls. But in the NAMED case,
9228 requires that languages coordinate a symbol name. It is therefore
9229 best put here in common code. */
9231 static GTY((param1_is (tree
), param2_is (tree
)))
9232 splay_tree critical_name_mutexes
;
9235 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9238 tree name
, lock
, unlock
;
9239 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
9240 location_t loc
= gimple_location (stmt
);
9243 name
= gimple_omp_critical_name (stmt
);
9249 if (!critical_name_mutexes
)
9250 critical_name_mutexes
9251 = splay_tree_new_ggc (splay_tree_compare_pointers
,
9252 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s
,
9253 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s
);
9255 n
= splay_tree_lookup (critical_name_mutexes
, (splay_tree_key
) name
);
9260 decl
= create_tmp_var_raw (ptr_type_node
, NULL
);
9262 new_str
= ACONCAT ((".gomp_critical_user_",
9263 IDENTIFIER_POINTER (name
), NULL
));
9264 DECL_NAME (decl
) = get_identifier (new_str
);
9265 TREE_PUBLIC (decl
) = 1;
9266 TREE_STATIC (decl
) = 1;
9267 DECL_COMMON (decl
) = 1;
9268 DECL_ARTIFICIAL (decl
) = 1;
9269 DECL_IGNORED_P (decl
) = 1;
9270 varpool_node::finalize_decl (decl
);
9272 splay_tree_insert (critical_name_mutexes
, (splay_tree_key
) name
,
9273 (splay_tree_value
) decl
);
9276 decl
= (tree
) n
->value
;
9278 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
9279 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
9281 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
9282 unlock
= build_call_expr_loc (loc
, unlock
, 1,
9283 build_fold_addr_expr_loc (loc
, decl
));
9287 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
9288 lock
= build_call_expr_loc (loc
, lock
, 0);
9290 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
9291 unlock
= build_call_expr_loc (loc
, unlock
, 0);
9294 push_gimplify_context ();
9296 block
= make_node (BLOCK
);
9297 bind
= gimple_build_bind (NULL
, NULL
, block
);
9298 gsi_replace (gsi_p
, bind
, true);
9299 gimple_bind_add_stmt (bind
, stmt
);
9301 tbody
= gimple_bind_body (bind
);
9302 gimplify_and_add (lock
, &tbody
);
9303 gimple_bind_set_body (bind
, tbody
);
9305 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9306 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9307 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9308 gimple_omp_set_body (stmt
, NULL
);
9310 tbody
= gimple_bind_body (bind
);
9311 gimplify_and_add (unlock
, &tbody
);
9312 gimple_bind_set_body (bind
, tbody
);
9314 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9316 pop_gimplify_context (bind
);
9317 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9318 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
9322 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9323 for a lastprivate clause. Given a loop control predicate of (V
9324 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9325 is appended to *DLIST, iterator initialization is appended to
9329 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
9330 gimple_seq
*dlist
, struct omp_context
*ctx
)
9332 tree clauses
, cond
, vinit
;
9333 enum tree_code cond_code
;
9336 cond_code
= fd
->loop
.cond_code
;
9337 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
9339 /* When possible, use a strict equality expression. This can let VRP
9340 type optimizations deduce the value and remove a copy. */
9341 if (tree_fits_shwi_p (fd
->loop
.step
))
9343 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
9344 if (step
== 1 || step
== -1)
9345 cond_code
= EQ_EXPR
;
9348 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, fd
->loop
.n2
);
9350 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
9352 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
9353 if (!gimple_seq_empty_p (stmts
))
9355 gimple_seq_add_seq (&stmts
, *dlist
);
9358 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9359 vinit
= fd
->loop
.n1
;
9360 if (cond_code
== EQ_EXPR
9361 && tree_fits_shwi_p (fd
->loop
.n2
)
9362 && ! integer_zerop (fd
->loop
.n2
))
9363 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
9365 vinit
= unshare_expr (vinit
);
9367 /* Initialize the iterator variable, so that threads that don't execute
9368 any iterations don't execute the lastprivate clauses by accident. */
9369 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
9374 /* Lower code for an OpenMP loop directive. */
9377 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9380 struct omp_for_data fd
, *fdp
= NULL
;
9381 gimple stmt
= gsi_stmt (*gsi_p
), new_stmt
;
9382 gimple_seq omp_for_body
, body
, dlist
;
9385 push_gimplify_context ();
9387 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
9389 block
= make_node (BLOCK
);
9390 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
9391 /* Replace at gsi right away, so that 'stmt' is no member
9392 of a sequence anymore as we're going to add to to a different
9394 gsi_replace (gsi_p
, new_stmt
, true);
9396 /* Move declaration of temporaries in the loop body before we make
9398 omp_for_body
= gimple_omp_body (stmt
);
9399 if (!gimple_seq_empty_p (omp_for_body
)
9400 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
9402 gimple inner_bind
= gimple_seq_first_stmt (omp_for_body
);
9403 tree vars
= gimple_bind_vars (inner_bind
);
9404 gimple_bind_append_vars (new_stmt
, vars
);
9405 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9406 keep them on the inner_bind and it's block. */
9407 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
9408 if (gimple_bind_block (inner_bind
))
9409 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
9412 if (gimple_omp_for_combined_into_p (stmt
))
9414 extract_omp_for_data (stmt
, &fd
, NULL
);
9417 /* We need two temporaries with fd.loop.v type (istart/iend)
9418 and then (fd.collapse - 1) temporaries with the same
9419 type for count2 ... countN-1 vars if not constant. */
9421 tree type
= fd
.iter_type
;
9423 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
9424 count
+= fd
.collapse
- 1;
9425 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
9426 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
9430 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
9431 OMP_CLAUSE__LOOPTEMP_
);
9432 for (i
= 0; i
< count
; i
++)
9437 gcc_assert (outerc
);
9438 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
9439 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
9440 OMP_CLAUSE__LOOPTEMP_
);
9444 temp
= create_tmp_var (type
, NULL
);
9445 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
9447 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
9448 OMP_CLAUSE_DECL (*pc
) = temp
;
9449 pc
= &OMP_CLAUSE_CHAIN (*pc
);
9454 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9457 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
9459 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
9461 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9463 /* Lower the header expressions. At this point, we can assume that
9464 the header is of the form:
9466 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9468 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9469 using the .omp_data_s mapping, if needed. */
9470 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
9472 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
9473 if (!is_gimple_min_invariant (*rhs_p
))
9474 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9476 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
9477 if (!is_gimple_min_invariant (*rhs_p
))
9478 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9480 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
9481 if (!is_gimple_min_invariant (*rhs_p
))
9482 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9485 /* Once lowered, extract the bounds and clauses. */
9486 extract_omp_for_data (stmt
, &fd
, NULL
);
9488 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
9490 gimple_seq_add_stmt (&body
, stmt
);
9491 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
9493 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
9496 /* After the loop, add exit clauses. */
9497 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
9499 if (ctx
->cancellable
)
9500 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
9502 gimple_seq_add_seq (&body
, dlist
);
9504 body
= maybe_catch_exception (body
);
9506 /* Region exit marker goes at the end of the loop body. */
9507 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
9508 maybe_add_implicit_barrier_cancel (ctx
, &body
);
9509 pop_gimplify_context (new_stmt
);
9511 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
9512 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
9513 if (BLOCK_VARS (block
))
9514 TREE_USED (block
) = 1;
9516 gimple_bind_set_body (new_stmt
, body
);
9517 gimple_omp_set_body (stmt
, NULL
);
9518 gimple_omp_for_set_pre_body (stmt
, NULL
);
9521 /* Callback for walk_stmts. Check if the current statement only contains
9522 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9525 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
9526 bool *handled_ops_p
,
9527 struct walk_stmt_info
*wi
)
9529 int *info
= (int *) wi
->info
;
9530 gimple stmt
= gsi_stmt (*gsi_p
);
9532 *handled_ops_p
= true;
9533 switch (gimple_code (stmt
))
9537 case GIMPLE_OMP_FOR
:
9538 case GIMPLE_OMP_SECTIONS
:
9539 *info
= *info
== 0 ? 1 : -1;
9548 struct omp_taskcopy_context
9550 /* This field must be at the beginning, as we do "inheritance": Some
9551 callback functions for tree-inline.c (e.g., omp_copy_decl)
9552 receive a copy_body_data pointer that is up-casted to an
9553 omp_context pointer. */
9559 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
9561 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
9563 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
9564 return create_tmp_var (TREE_TYPE (var
), NULL
);
9570 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
9572 tree name
, new_fields
= NULL
, type
, f
;
9574 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
9575 name
= DECL_NAME (TYPE_NAME (orig_type
));
9576 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
9577 TYPE_DECL
, name
, type
);
9578 TYPE_NAME (type
) = name
;
9580 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
9582 tree new_f
= copy_node (f
);
9583 DECL_CONTEXT (new_f
) = type
;
9584 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
9585 TREE_CHAIN (new_f
) = new_fields
;
9586 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9587 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9588 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
9591 tcctx
->cb
.decl_map
->put (f
, new_f
);
9593 TYPE_FIELDS (type
) = nreverse (new_fields
);
9598 /* Create task copyfn. */
9601 create_task_copyfn (gimple task_stmt
, omp_context
*ctx
)
9603 struct function
*child_cfun
;
9604 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
9605 tree record_type
, srecord_type
, bind
, list
;
9606 bool record_needs_remap
= false, srecord_needs_remap
= false;
9608 struct omp_taskcopy_context tcctx
;
9609 location_t loc
= gimple_location (task_stmt
);
9611 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
9612 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
9613 gcc_assert (child_cfun
->cfg
== NULL
);
9614 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
9616 /* Reset DECL_CONTEXT on function arguments. */
9617 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
9618 DECL_CONTEXT (t
) = child_fn
;
9620 /* Populate the function. */
9621 push_gimplify_context ();
9622 push_cfun (child_cfun
);
9624 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
9625 TREE_SIDE_EFFECTS (bind
) = 1;
9627 DECL_SAVED_TREE (child_fn
) = bind
;
9628 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
9630 /* Remap src and dst argument types if needed. */
9631 record_type
= ctx
->record_type
;
9632 srecord_type
= ctx
->srecord_type
;
9633 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
9634 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9636 record_needs_remap
= true;
9639 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
9640 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9642 srecord_needs_remap
= true;
9646 if (record_needs_remap
|| srecord_needs_remap
)
9648 memset (&tcctx
, '\0', sizeof (tcctx
));
9649 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
9650 tcctx
.cb
.dst_fn
= child_fn
;
9651 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
9652 gcc_checking_assert (tcctx
.cb
.src_node
);
9653 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
9654 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
9655 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
9656 tcctx
.cb
.eh_lp_nr
= 0;
9657 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
9658 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
9661 if (record_needs_remap
)
9662 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
9663 if (srecord_needs_remap
)
9664 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
9667 tcctx
.cb
.decl_map
= NULL
;
9669 arg
= DECL_ARGUMENTS (child_fn
);
9670 TREE_TYPE (arg
) = build_pointer_type (record_type
);
9671 sarg
= DECL_CHAIN (arg
);
9672 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
9674 /* First pass: initialize temporaries used in record_type and srecord_type
9675 sizes and field offsets. */
9676 if (tcctx
.cb
.decl_map
)
9677 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9678 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9682 decl
= OMP_CLAUSE_DECL (c
);
9683 p
= tcctx
.cb
.decl_map
->get (decl
);
9686 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9687 sf
= (tree
) n
->value
;
9688 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9689 src
= build_simple_mem_ref_loc (loc
, sarg
);
9690 src
= omp_build_component_ref (src
, sf
);
9691 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
9692 append_to_statement_list (t
, &list
);
9695 /* Second pass: copy shared var pointers and copy construct non-VLA
9696 firstprivate vars. */
9697 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9698 switch (OMP_CLAUSE_CODE (c
))
9700 case OMP_CLAUSE_SHARED
:
9701 decl
= OMP_CLAUSE_DECL (c
);
9702 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9705 f
= (tree
) n
->value
;
9706 if (tcctx
.cb
.decl_map
)
9707 f
= *tcctx
.cb
.decl_map
->get (f
);
9708 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9709 sf
= (tree
) n
->value
;
9710 if (tcctx
.cb
.decl_map
)
9711 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9712 src
= build_simple_mem_ref_loc (loc
, sarg
);
9713 src
= omp_build_component_ref (src
, sf
);
9714 dst
= build_simple_mem_ref_loc (loc
, arg
);
9715 dst
= omp_build_component_ref (dst
, f
);
9716 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9717 append_to_statement_list (t
, &list
);
9719 case OMP_CLAUSE_FIRSTPRIVATE
:
9720 decl
= OMP_CLAUSE_DECL (c
);
9721 if (is_variable_sized (decl
))
9723 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9726 f
= (tree
) n
->value
;
9727 if (tcctx
.cb
.decl_map
)
9728 f
= *tcctx
.cb
.decl_map
->get (f
);
9729 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9732 sf
= (tree
) n
->value
;
9733 if (tcctx
.cb
.decl_map
)
9734 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9735 src
= build_simple_mem_ref_loc (loc
, sarg
);
9736 src
= omp_build_component_ref (src
, sf
);
9737 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
9738 src
= build_simple_mem_ref_loc (loc
, src
);
9742 dst
= build_simple_mem_ref_loc (loc
, arg
);
9743 dst
= omp_build_component_ref (dst
, f
);
9744 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9745 append_to_statement_list (t
, &list
);
9747 case OMP_CLAUSE_PRIVATE
:
9748 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
9750 decl
= OMP_CLAUSE_DECL (c
);
9751 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9752 f
= (tree
) n
->value
;
9753 if (tcctx
.cb
.decl_map
)
9754 f
= *tcctx
.cb
.decl_map
->get (f
);
9755 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9758 sf
= (tree
) n
->value
;
9759 if (tcctx
.cb
.decl_map
)
9760 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9761 src
= build_simple_mem_ref_loc (loc
, sarg
);
9762 src
= omp_build_component_ref (src
, sf
);
9763 if (use_pointer_for_field (decl
, NULL
))
9764 src
= build_simple_mem_ref_loc (loc
, src
);
9768 dst
= build_simple_mem_ref_loc (loc
, arg
);
9769 dst
= omp_build_component_ref (dst
, f
);
9770 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9771 append_to_statement_list (t
, &list
);
9777 /* Last pass: handle VLA firstprivates. */
9778 if (tcctx
.cb
.decl_map
)
9779 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9780 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9784 decl
= OMP_CLAUSE_DECL (c
);
9785 if (!is_variable_sized (decl
))
9787 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9790 f
= (tree
) n
->value
;
9791 f
= *tcctx
.cb
.decl_map
->get (f
);
9792 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
9793 ind
= DECL_VALUE_EXPR (decl
);
9794 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
9795 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
9796 n
= splay_tree_lookup (ctx
->sfield_map
,
9797 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9798 sf
= (tree
) n
->value
;
9799 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9800 src
= build_simple_mem_ref_loc (loc
, sarg
);
9801 src
= omp_build_component_ref (src
, sf
);
9802 src
= build_simple_mem_ref_loc (loc
, src
);
9803 dst
= build_simple_mem_ref_loc (loc
, arg
);
9804 dst
= omp_build_component_ref (dst
, f
);
9805 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9806 append_to_statement_list (t
, &list
);
9807 n
= splay_tree_lookup (ctx
->field_map
,
9808 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9809 df
= (tree
) n
->value
;
9810 df
= *tcctx
.cb
.decl_map
->get (df
);
9811 ptr
= build_simple_mem_ref_loc (loc
, arg
);
9812 ptr
= omp_build_component_ref (ptr
, df
);
9813 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
9814 build_fold_addr_expr_loc (loc
, dst
));
9815 append_to_statement_list (t
, &list
);
9818 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
9819 append_to_statement_list (t
, &list
);
9821 if (tcctx
.cb
.decl_map
)
9822 delete tcctx
.cb
.decl_map
;
9823 pop_gimplify_context (NULL
);
9824 BIND_EXPR_BODY (bind
) = list
;
9829 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
9833 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
9835 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
9837 gcc_assert (clauses
);
9838 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9839 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
9840 switch (OMP_CLAUSE_DEPEND_KIND (c
))
9842 case OMP_CLAUSE_DEPEND_IN
:
9845 case OMP_CLAUSE_DEPEND_OUT
:
9846 case OMP_CLAUSE_DEPEND_INOUT
:
9852 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
9853 tree array
= create_tmp_var (type
, NULL
);
9854 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
9856 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
9857 gimple_seq_add_stmt (iseq
, g
);
9858 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
9860 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
9861 gimple_seq_add_stmt (iseq
, g
);
9862 for (i
= 0; i
< 2; i
++)
9864 if ((i
? n_in
: n_out
) == 0)
9866 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9867 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
9868 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
9870 tree t
= OMP_CLAUSE_DECL (c
);
9871 t
= fold_convert (ptr_type_node
, t
);
9872 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
9873 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
9874 NULL_TREE
, NULL_TREE
);
9875 g
= gimple_build_assign (r
, t
);
9876 gimple_seq_add_stmt (iseq
, g
);
9879 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
9880 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
9881 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
9882 OMP_CLAUSE_CHAIN (c
) = *p
;
9884 tree clobber
= build_constructor (type
, NULL
);
9885 TREE_THIS_VOLATILE (clobber
) = 1;
9886 g
= gimple_build_assign (array
, clobber
);
9887 gimple_seq_add_stmt (oseq
, g
);
9890 /* Lower the OpenMP parallel or task directive in the current statement
9891 in GSI_P. CTX holds context information for the directive. */
9894 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9898 gimple stmt
= gsi_stmt (*gsi_p
);
9899 gimple par_bind
, bind
, dep_bind
= NULL
;
9900 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
9901 location_t loc
= gimple_location (stmt
);
9903 clauses
= gimple_omp_taskreg_clauses (stmt
);
9904 par_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
9905 par_body
= gimple_bind_body (par_bind
);
9906 child_fn
= ctx
->cb
.dst_fn
;
9907 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
9908 && !gimple_omp_parallel_combined_p (stmt
))
9910 struct walk_stmt_info wi
;
9913 memset (&wi
, 0, sizeof (wi
));
9916 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
9918 gimple_omp_parallel_set_combined_p (stmt
, true);
9920 gimple_seq dep_ilist
= NULL
;
9921 gimple_seq dep_olist
= NULL
;
9922 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
9923 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
9925 push_gimplify_context ();
9926 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
9927 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
9930 if (ctx
->srecord_type
)
9931 create_task_copyfn (stmt
, ctx
);
9933 push_gimplify_context ();
9938 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
9939 lower_omp (&par_body
, ctx
);
9940 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
9941 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
9943 /* Declare all the variables created by mapping and the variables
9944 declared in the scope of the parallel body. */
9945 record_vars_into (ctx
->block_vars
, child_fn
);
9946 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
9948 if (ctx
->record_type
)
9951 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
9952 : ctx
->record_type
, ".omp_data_o");
9953 DECL_NAMELESS (ctx
->sender_decl
) = 1;
9954 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
9955 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
9960 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
9961 lower_send_shared_vars (&ilist
, &olist
, ctx
);
9963 if (ctx
->record_type
)
9965 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
9966 TREE_THIS_VOLATILE (clobber
) = 1;
9967 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
9971 /* Once all the expansions are done, sequence all the different
9972 fragments inside gimple_omp_body. */
9976 if (ctx
->record_type
)
9978 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9979 /* fixup_child_record_type might have changed receiver_decl's type. */
9980 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
9981 gimple_seq_add_stmt (&new_body
,
9982 gimple_build_assign (ctx
->receiver_decl
, t
));
9985 gimple_seq_add_seq (&new_body
, par_ilist
);
9986 gimple_seq_add_seq (&new_body
, par_body
);
9987 gimple_seq_add_seq (&new_body
, par_rlist
);
9988 if (ctx
->cancellable
)
9989 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
9990 gimple_seq_add_seq (&new_body
, par_olist
);
9991 new_body
= maybe_catch_exception (new_body
);
9992 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
9993 gimple_omp_set_body (stmt
, new_body
);
9995 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
9996 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
9997 gimple_bind_add_seq (bind
, ilist
);
9998 gimple_bind_add_stmt (bind
, stmt
);
9999 gimple_bind_add_seq (bind
, olist
);
10001 pop_gimplify_context (NULL
);
10005 gimple_bind_add_seq (dep_bind
, dep_ilist
);
10006 gimple_bind_add_stmt (dep_bind
, bind
);
10007 gimple_bind_add_seq (dep_bind
, dep_olist
);
10008 pop_gimplify_context (dep_bind
);
10012 /* Lower the OpenMP target directive in the current statement
10013 in GSI_P. CTX holds context information for the directive. */
10016 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10019 tree child_fn
, t
, c
;
10020 gimple stmt
= gsi_stmt (*gsi_p
);
10021 gimple tgt_bind
= NULL
, bind
;
10022 gimple_seq tgt_body
= NULL
, olist
, ilist
, new_body
;
10023 location_t loc
= gimple_location (stmt
);
10024 int kind
= gimple_omp_target_kind (stmt
);
10025 unsigned int map_cnt
= 0;
10027 clauses
= gimple_omp_target_clauses (stmt
);
10028 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10030 tgt_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
10031 tgt_body
= gimple_bind_body (tgt_bind
);
10033 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10034 tgt_body
= gimple_omp_body (stmt
);
10035 child_fn
= ctx
->cb
.dst_fn
;
10037 push_gimplify_context ();
10039 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
10040 switch (OMP_CLAUSE_CODE (c
))
10046 case OMP_CLAUSE_MAP
:
10047 case OMP_CLAUSE_TO
:
10048 case OMP_CLAUSE_FROM
:
10049 var
= OMP_CLAUSE_DECL (c
);
10052 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
10053 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
10058 if (DECL_SIZE (var
)
10059 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
10061 tree var2
= DECL_VALUE_EXPR (var
);
10062 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
10063 var2
= TREE_OPERAND (var2
, 0);
10064 gcc_assert (DECL_P (var2
));
10068 if (!maybe_lookup_field (var
, ctx
))
10071 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10073 x
= build_receiver_ref (var
, true, ctx
);
10074 tree new_var
= lookup_decl (var
, ctx
);
10075 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10076 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
10077 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
10078 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
10079 x
= build_simple_mem_ref (x
);
10080 SET_DECL_VALUE_EXPR (new_var
, x
);
10081 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
10086 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10088 target_nesting_level
++;
10089 lower_omp (&tgt_body
, ctx
);
10090 target_nesting_level
--;
10092 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10093 lower_omp (&tgt_body
, ctx
);
10095 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10097 /* Declare all the variables created by mapping and the variables
10098 declared in the scope of the target body. */
10099 record_vars_into (ctx
->block_vars
, child_fn
);
10100 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
10105 if (ctx
->record_type
)
10108 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
10109 DECL_NAMELESS (ctx
->sender_decl
) = 1;
10110 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
10111 t
= make_tree_vec (3);
10112 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
10113 TREE_VEC_ELT (t
, 1)
10114 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
10115 ".omp_data_sizes");
10116 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
10117 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
10118 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
10119 TREE_VEC_ELT (t
, 2)
10120 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node
,
10122 ".omp_data_kinds");
10123 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
10124 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
10125 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
10126 gimple_omp_target_set_data_arg (stmt
, t
);
10128 vec
<constructor_elt
, va_gc
> *vsize
;
10129 vec
<constructor_elt
, va_gc
> *vkind
;
10130 vec_alloc (vsize
, map_cnt
);
10131 vec_alloc (vkind
, map_cnt
);
10132 unsigned int map_idx
= 0;
10134 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
10135 switch (OMP_CLAUSE_CODE (c
))
10141 case OMP_CLAUSE_MAP
:
10142 case OMP_CLAUSE_TO
:
10143 case OMP_CLAUSE_FROM
:
10145 ovar
= OMP_CLAUSE_DECL (c
);
10146 if (!DECL_P (ovar
))
10148 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10149 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
10151 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
10152 == get_base_address (ovar
));
10153 nc
= OMP_CLAUSE_CHAIN (c
);
10154 ovar
= OMP_CLAUSE_DECL (nc
);
10158 tree x
= build_sender_ref (ovar
, ctx
);
10160 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
10161 gimplify_assign (x
, v
, &ilist
);
10167 if (DECL_SIZE (ovar
)
10168 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
10170 tree ovar2
= DECL_VALUE_EXPR (ovar
);
10171 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
10172 ovar2
= TREE_OPERAND (ovar2
, 0);
10173 gcc_assert (DECL_P (ovar2
));
10176 if (!maybe_lookup_field (ovar
, ctx
))
10180 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
10181 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
10182 talign
= DECL_ALIGN_UNIT (ovar
);
10185 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
10186 tree x
= build_sender_ref (ovar
, ctx
);
10187 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10188 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
10189 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
10190 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
10192 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
10194 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)), NULL
);
10195 mark_addressable (avar
);
10196 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
10197 talign
= DECL_ALIGN_UNIT (avar
);
10198 avar
= build_fold_addr_expr (avar
);
10199 gimplify_assign (x
, avar
, &ilist
);
10201 else if (is_gimple_reg (var
))
10203 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
10204 tree avar
= create_tmp_var (TREE_TYPE (var
), NULL
);
10205 mark_addressable (avar
);
10206 if (OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_ALLOC
10207 && OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_FROM
)
10208 gimplify_assign (avar
, var
, &ilist
);
10209 avar
= build_fold_addr_expr (avar
);
10210 gimplify_assign (x
, avar
, &ilist
);
10211 if ((OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_FROM
10212 || OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_TOFROM
)
10213 && !TYPE_READONLY (TREE_TYPE (var
)))
10215 x
= build_sender_ref (ovar
, ctx
);
10216 x
= build_simple_mem_ref (x
);
10217 gimplify_assign (var
, x
, &olist
);
10222 var
= build_fold_addr_expr (var
);
10223 gimplify_assign (x
, var
, &ilist
);
10226 tree s
= OMP_CLAUSE_SIZE (c
);
10227 if (s
== NULL_TREE
)
10228 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
10229 s
= fold_convert (size_type_node
, s
);
10230 tree purpose
= size_int (map_idx
++);
10231 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
10232 if (TREE_CODE (s
) != INTEGER_CST
)
10233 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
10235 unsigned char tkind
= 0;
10236 switch (OMP_CLAUSE_CODE (c
))
10238 case OMP_CLAUSE_MAP
:
10239 tkind
= OMP_CLAUSE_MAP_KIND (c
);
10241 case OMP_CLAUSE_TO
:
10242 tkind
= OMP_CLAUSE_MAP_TO
;
10244 case OMP_CLAUSE_FROM
:
10245 tkind
= OMP_CLAUSE_MAP_FROM
;
10248 gcc_unreachable ();
10250 talign
= ceil_log2 (talign
);
10251 tkind
|= talign
<< 3;
10252 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
10253 build_int_cst (unsigned_char_type_node
,
10259 gcc_assert (map_idx
== map_cnt
);
10261 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
10262 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
10263 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
10264 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
10265 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
10267 gimple_seq initlist
= NULL
;
10268 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
10269 TREE_VEC_ELT (t
, 1)),
10270 &initlist
, true, NULL_TREE
);
10271 gimple_seq_add_seq (&ilist
, initlist
);
10273 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
10275 TREE_THIS_VOLATILE (clobber
) = 1;
10276 gimple_seq_add_stmt (&olist
,
10277 gimple_build_assign (TREE_VEC_ELT (t
, 1),
10281 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
10282 TREE_THIS_VOLATILE (clobber
) = 1;
10283 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
10287 /* Once all the expansions are done, sequence all the different
10288 fragments inside gimple_omp_body. */
10292 if (ctx
->record_type
&& kind
== GF_OMP_TARGET_KIND_REGION
)
10294 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10295 /* fixup_child_record_type might have changed receiver_decl's type. */
10296 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
10297 gimple_seq_add_stmt (&new_body
,
10298 gimple_build_assign (ctx
->receiver_decl
, t
));
10301 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10303 gimple_seq_add_seq (&new_body
, tgt_body
);
10304 new_body
= maybe_catch_exception (new_body
);
10306 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10307 new_body
= tgt_body
;
10308 if (kind
!= GF_OMP_TARGET_KIND_UPDATE
)
10310 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
10311 gimple_omp_set_body (stmt
, new_body
);
10314 bind
= gimple_build_bind (NULL
, NULL
,
10315 tgt_bind
? gimple_bind_block (tgt_bind
)
10317 gsi_replace (gsi_p
, bind
, true);
10318 gimple_bind_add_seq (bind
, ilist
);
10319 gimple_bind_add_stmt (bind
, stmt
);
10320 gimple_bind_add_seq (bind
, olist
);
10322 pop_gimplify_context (NULL
);
10325 /* Expand code for an OpenMP teams directive. */
10328 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10330 gimple teams_stmt
= gsi_stmt (*gsi_p
);
10331 push_gimplify_context ();
10333 tree block
= make_node (BLOCK
);
10334 gimple bind
= gimple_build_bind (NULL
, NULL
, block
);
10335 gsi_replace (gsi_p
, bind
, true);
10336 gimple_seq bind_body
= NULL
;
10337 gimple_seq dlist
= NULL
;
10338 gimple_seq olist
= NULL
;
10340 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
10341 OMP_CLAUSE_NUM_TEAMS
);
10342 if (num_teams
== NULL_TREE
)
10343 num_teams
= build_int_cst (unsigned_type_node
, 0);
10346 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
10347 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
10348 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
10350 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
10351 OMP_CLAUSE_THREAD_LIMIT
);
10352 if (thread_limit
== NULL_TREE
)
10353 thread_limit
= build_int_cst (unsigned_type_node
, 0);
10356 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
10357 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
10358 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
10362 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
10363 &bind_body
, &dlist
, ctx
, NULL
);
10364 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
10365 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
10366 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
10368 location_t loc
= gimple_location (teams_stmt
);
10369 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
10370 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
10371 gimple_set_location (call
, loc
);
10372 gimple_seq_add_stmt (&bind_body
, call
);
10374 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
10375 gimple_omp_set_body (teams_stmt
, NULL
);
10376 gimple_seq_add_seq (&bind_body
, olist
);
10377 gimple_seq_add_seq (&bind_body
, dlist
);
10378 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
10379 gimple_bind_set_body (bind
, bind_body
);
10381 pop_gimplify_context (bind
);
10383 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10384 BLOCK_VARS (block
) = ctx
->block_vars
;
10385 if (BLOCK_VARS (block
))
10386 TREE_USED (block
) = 1;
10390 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10391 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10392 of OpenMP context, but with task_shared_vars set. */
10395 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
10400 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10401 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
10404 if (task_shared_vars
10406 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
10409 /* If a global variable has been privatized, TREE_CONSTANT on
10410 ADDR_EXPR might be wrong. */
10411 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
10412 recompute_tree_invariant_for_addr_expr (t
);
10414 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
10419 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10421 gimple stmt
= gsi_stmt (*gsi_p
);
10422 struct walk_stmt_info wi
;
10424 if (gimple_has_location (stmt
))
10425 input_location
= gimple_location (stmt
);
10427 if (task_shared_vars
)
10428 memset (&wi
, '\0', sizeof (wi
));
10430 /* If we have issued syntax errors, avoid doing any heavy lifting.
10431 Just replace the OpenMP directives with a NOP to avoid
10432 confusing RTL expansion. */
10433 if (seen_error () && is_gimple_omp (stmt
))
10435 gsi_replace (gsi_p
, gimple_build_nop (), true);
10439 switch (gimple_code (stmt
))
10442 if ((ctx
|| task_shared_vars
)
10443 && (walk_tree (gimple_cond_lhs_ptr (stmt
), lower_omp_regimplify_p
,
10444 ctx
? NULL
: &wi
, NULL
)
10445 || walk_tree (gimple_cond_rhs_ptr (stmt
), lower_omp_regimplify_p
,
10446 ctx
? NULL
: &wi
, NULL
)))
10447 gimple_regimplify_operands (stmt
, gsi_p
);
10450 lower_omp (gimple_catch_handler_ptr (stmt
), ctx
);
10452 case GIMPLE_EH_FILTER
:
10453 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
10456 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
10457 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
10459 case GIMPLE_TRANSACTION
:
10460 lower_omp (gimple_transaction_body_ptr (stmt
), ctx
);
10463 lower_omp (gimple_bind_body_ptr (stmt
), ctx
);
10465 case GIMPLE_OMP_PARALLEL
:
10466 case GIMPLE_OMP_TASK
:
10467 ctx
= maybe_lookup_ctx (stmt
);
10469 if (ctx
->cancellable
)
10470 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10471 lower_omp_taskreg (gsi_p
, ctx
);
10473 case GIMPLE_OMP_FOR
:
10474 ctx
= maybe_lookup_ctx (stmt
);
10476 if (ctx
->cancellable
)
10477 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10478 lower_omp_for (gsi_p
, ctx
);
10480 case GIMPLE_OMP_SECTIONS
:
10481 ctx
= maybe_lookup_ctx (stmt
);
10483 if (ctx
->cancellable
)
10484 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10485 lower_omp_sections (gsi_p
, ctx
);
10487 case GIMPLE_OMP_SINGLE
:
10488 ctx
= maybe_lookup_ctx (stmt
);
10490 lower_omp_single (gsi_p
, ctx
);
10492 case GIMPLE_OMP_MASTER
:
10493 ctx
= maybe_lookup_ctx (stmt
);
10495 lower_omp_master (gsi_p
, ctx
);
10497 case GIMPLE_OMP_TASKGROUP
:
10498 ctx
= maybe_lookup_ctx (stmt
);
10500 lower_omp_taskgroup (gsi_p
, ctx
);
10502 case GIMPLE_OMP_ORDERED
:
10503 ctx
= maybe_lookup_ctx (stmt
);
10505 lower_omp_ordered (gsi_p
, ctx
);
10507 case GIMPLE_OMP_CRITICAL
:
10508 ctx
= maybe_lookup_ctx (stmt
);
10510 lower_omp_critical (gsi_p
, ctx
);
10512 case GIMPLE_OMP_ATOMIC_LOAD
:
10513 if ((ctx
|| task_shared_vars
)
10514 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt
),
10515 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
10516 gimple_regimplify_operands (stmt
, gsi_p
);
10518 case GIMPLE_OMP_TARGET
:
10519 ctx
= maybe_lookup_ctx (stmt
);
10521 lower_omp_target (gsi_p
, ctx
);
10523 case GIMPLE_OMP_TEAMS
:
10524 ctx
= maybe_lookup_ctx (stmt
);
10526 lower_omp_teams (gsi_p
, ctx
);
10530 fndecl
= gimple_call_fndecl (stmt
);
10532 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
10533 switch (DECL_FUNCTION_CODE (fndecl
))
10535 case BUILT_IN_GOMP_BARRIER
:
10539 case BUILT_IN_GOMP_CANCEL
:
10540 case BUILT_IN_GOMP_CANCELLATION_POINT
:
10543 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
10544 cctx
= cctx
->outer
;
10545 gcc_assert (gimple_call_lhs (stmt
) == NULL_TREE
);
10546 if (!cctx
->cancellable
)
10548 if (DECL_FUNCTION_CODE (fndecl
)
10549 == BUILT_IN_GOMP_CANCELLATION_POINT
)
10551 stmt
= gimple_build_nop ();
10552 gsi_replace (gsi_p
, stmt
, false);
10556 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
10558 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
10559 gimple_call_set_fndecl (stmt
, fndecl
);
10560 gimple_call_set_fntype (stmt
, TREE_TYPE (fndecl
));
10563 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)), NULL
);
10564 gimple_call_set_lhs (stmt
, lhs
);
10565 tree fallthru_label
;
10566 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
10568 g
= gimple_build_label (fallthru_label
);
10569 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10570 g
= gimple_build_cond (NE_EXPR
, lhs
,
10571 fold_convert (TREE_TYPE (lhs
),
10572 boolean_false_node
),
10573 cctx
->cancel_label
, fallthru_label
);
10574 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10581 if ((ctx
|| task_shared_vars
)
10582 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
10585 /* Just remove clobbers, this should happen only if we have
10586 "privatized" local addressable variables in SIMD regions,
10587 the clobber isn't needed in that case and gimplifying address
10588 of the ARRAY_REF into a pointer and creating MEM_REF based
10589 clobber would create worse code than we get with the clobber
10591 if (gimple_clobber_p (stmt
))
10593 gsi_replace (gsi_p
, gimple_build_nop (), true);
10596 gimple_regimplify_operands (stmt
, gsi_p
);
10603 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
10605 location_t saved_location
= input_location
;
10606 gimple_stmt_iterator gsi
;
10607 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10608 lower_omp_1 (&gsi
, ctx
);
10609 /* During gimplification, we have not always invoked fold_stmt
10610 (gimplify.c:maybe_fold_stmt); call it now. */
10611 if (target_nesting_level
)
10612 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10614 input_location
= saved_location
;
10617 /* Main entry point. */
10619 static unsigned int
10620 execute_lower_omp (void)
10626 /* This pass always runs, to provide PROP_gimple_lomp.
10627 But there is nothing to do unless -fopenmp is given. */
10628 if (flag_openmp
== 0 && flag_openmp_simd
== 0 && flag_cilkplus
== 0)
10631 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
10632 delete_omp_context
);
10634 body
= gimple_body (current_function_decl
);
10635 scan_omp (&body
, NULL
);
10636 gcc_assert (taskreg_nesting_level
== 0);
10637 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
10638 finish_taskreg_scan (ctx
);
10639 taskreg_contexts
.release ();
10641 if (all_contexts
->root
)
10643 if (task_shared_vars
)
10644 push_gimplify_context ();
10645 lower_omp (&body
, NULL
);
10646 if (task_shared_vars
)
10647 pop_gimplify_context (NULL
);
10652 splay_tree_delete (all_contexts
);
10653 all_contexts
= NULL
;
10655 BITMAP_FREE (task_shared_vars
);
10661 const pass_data pass_data_lower_omp
=
10663 GIMPLE_PASS
, /* type */
10664 "omplower", /* name */
10665 OPTGROUP_NONE
, /* optinfo_flags */
10666 TV_NONE
, /* tv_id */
10667 PROP_gimple_any
, /* properties_required */
10668 PROP_gimple_lomp
, /* properties_provided */
10669 0, /* properties_destroyed */
10670 0, /* todo_flags_start */
10671 0, /* todo_flags_finish */
10674 class pass_lower_omp
: public gimple_opt_pass
10677 pass_lower_omp (gcc::context
*ctxt
)
10678 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
10681 /* opt_pass methods: */
10682 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
10684 }; // class pass_lower_omp
10686 } // anon namespace
10689 make_pass_lower_omp (gcc::context
*ctxt
)
10691 return new pass_lower_omp (ctxt
);
10694 /* The following is a utility to diagnose OpenMP structured block violations.
10695 It is not part of the "omplower" pass, as that's invoked too late. It
10696 should be invoked by the respective front ends after gimplification. */
10698 static splay_tree all_labels
;
10700 /* Check for mismatched contexts and generate an error if needed. Return
10701 true if an error is detected. */
10704 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
10705 gimple branch_ctx
, gimple label_ctx
)
10707 if (label_ctx
== branch_ctx
)
10712 Previously we kept track of the label's entire context in diagnose_sb_[12]
10713 so we could traverse it and issue a correct "exit" or "enter" error
10714 message upon a structured block violation.
10716 We built the context by building a list with tree_cons'ing, but there is
10717 no easy counterpart in gimple tuples. It seems like far too much work
10718 for issuing exit/enter error messages. If someone really misses the
10719 distinct error message... patches welcome.
10723 /* Try to avoid confusing the user by producing and error message
10724 with correct "exit" or "enter" verbiage. We prefer "exit"
10725 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10726 if (branch_ctx
== NULL
)
10732 if (TREE_VALUE (label_ctx
) == branch_ctx
)
10737 label_ctx
= TREE_CHAIN (label_ctx
);
10742 error ("invalid exit from OpenMP structured block");
10744 error ("invalid entry to OpenMP structured block");
10747 bool cilkplus_block
= false;
10751 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
10752 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
10754 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
10755 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
10756 cilkplus_block
= true;
10759 /* If it's obvious we have an invalid entry, be specific about the error. */
10760 if (branch_ctx
== NULL
)
10762 if (cilkplus_block
)
10763 error ("invalid entry to Cilk Plus structured block");
10765 error ("invalid entry to OpenMP structured block");
10769 /* Otherwise, be vague and lazy, but efficient. */
10770 if (cilkplus_block
)
10771 error ("invalid branch to/from a Cilk Plus structured block");
10773 error ("invalid branch to/from an OpenMP structured block");
10776 gsi_replace (gsi_p
, gimple_build_nop (), false);
10780 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10781 where each label is found. */
10784 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10785 struct walk_stmt_info
*wi
)
10787 gimple context
= (gimple
) wi
->info
;
10788 gimple inner_context
;
10789 gimple stmt
= gsi_stmt (*gsi_p
);
10791 *handled_ops_p
= true;
10793 switch (gimple_code (stmt
))
10797 case GIMPLE_OMP_PARALLEL
:
10798 case GIMPLE_OMP_TASK
:
10799 case GIMPLE_OMP_SECTIONS
:
10800 case GIMPLE_OMP_SINGLE
:
10801 case GIMPLE_OMP_SECTION
:
10802 case GIMPLE_OMP_MASTER
:
10803 case GIMPLE_OMP_ORDERED
:
10804 case GIMPLE_OMP_CRITICAL
:
10805 case GIMPLE_OMP_TARGET
:
10806 case GIMPLE_OMP_TEAMS
:
10807 case GIMPLE_OMP_TASKGROUP
:
10808 /* The minimal context here is just the current OMP construct. */
10809 inner_context
= stmt
;
10810 wi
->info
= inner_context
;
10811 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10812 wi
->info
= context
;
10815 case GIMPLE_OMP_FOR
:
10816 inner_context
= stmt
;
10817 wi
->info
= inner_context
;
10818 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10820 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
10821 diagnose_sb_1
, NULL
, wi
);
10822 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10823 wi
->info
= context
;
10827 splay_tree_insert (all_labels
, (splay_tree_key
) gimple_label_label (stmt
),
10828 (splay_tree_value
) context
);
10838 /* Pass 2: Check each branch and see if its context differs from that of
10839 the destination label's context. */
10842 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10843 struct walk_stmt_info
*wi
)
10845 gimple context
= (gimple
) wi
->info
;
10847 gimple stmt
= gsi_stmt (*gsi_p
);
10849 *handled_ops_p
= true;
10851 switch (gimple_code (stmt
))
10855 case GIMPLE_OMP_PARALLEL
:
10856 case GIMPLE_OMP_TASK
:
10857 case GIMPLE_OMP_SECTIONS
:
10858 case GIMPLE_OMP_SINGLE
:
10859 case GIMPLE_OMP_SECTION
:
10860 case GIMPLE_OMP_MASTER
:
10861 case GIMPLE_OMP_ORDERED
:
10862 case GIMPLE_OMP_CRITICAL
:
10863 case GIMPLE_OMP_TARGET
:
10864 case GIMPLE_OMP_TEAMS
:
10865 case GIMPLE_OMP_TASKGROUP
:
10867 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10868 wi
->info
= context
;
10871 case GIMPLE_OMP_FOR
:
10873 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10875 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
10876 diagnose_sb_2
, NULL
, wi
);
10877 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
10878 wi
->info
= context
;
10883 tree lab
= gimple_cond_true_label (stmt
);
10886 n
= splay_tree_lookup (all_labels
,
10887 (splay_tree_key
) lab
);
10888 diagnose_sb_0 (gsi_p
, context
,
10889 n
? (gimple
) n
->value
: NULL
);
10891 lab
= gimple_cond_false_label (stmt
);
10894 n
= splay_tree_lookup (all_labels
,
10895 (splay_tree_key
) lab
);
10896 diagnose_sb_0 (gsi_p
, context
,
10897 n
? (gimple
) n
->value
: NULL
);
10904 tree lab
= gimple_goto_dest (stmt
);
10905 if (TREE_CODE (lab
) != LABEL_DECL
)
10908 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10909 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
10913 case GIMPLE_SWITCH
:
10916 for (i
= 0; i
< gimple_switch_num_labels (stmt
); ++i
)
10918 tree lab
= CASE_LABEL (gimple_switch_label (stmt
, i
));
10919 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
10920 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
10926 case GIMPLE_RETURN
:
10927 diagnose_sb_0 (gsi_p
, context
, NULL
);
10937 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10940 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
10943 gimple last
= last_stmt (bb
);
10944 enum gimple_code code
= gimple_code (last
);
10945 struct omp_region
*cur_region
= *region
;
10946 bool fallthru
= false;
10950 case GIMPLE_OMP_PARALLEL
:
10951 case GIMPLE_OMP_TASK
:
10952 case GIMPLE_OMP_FOR
:
10953 case GIMPLE_OMP_SINGLE
:
10954 case GIMPLE_OMP_TEAMS
:
10955 case GIMPLE_OMP_MASTER
:
10956 case GIMPLE_OMP_TASKGROUP
:
10957 case GIMPLE_OMP_ORDERED
:
10958 case GIMPLE_OMP_CRITICAL
:
10959 case GIMPLE_OMP_SECTION
:
10960 cur_region
= new_omp_region (bb
, code
, cur_region
);
10964 case GIMPLE_OMP_TARGET
:
10965 cur_region
= new_omp_region (bb
, code
, cur_region
);
10967 if (gimple_omp_target_kind (last
) == GF_OMP_TARGET_KIND_UPDATE
)
10968 cur_region
= cur_region
->outer
;
10971 case GIMPLE_OMP_SECTIONS
:
10972 cur_region
= new_omp_region (bb
, code
, cur_region
);
10976 case GIMPLE_OMP_SECTIONS_SWITCH
:
10980 case GIMPLE_OMP_ATOMIC_LOAD
:
10981 case GIMPLE_OMP_ATOMIC_STORE
:
10985 case GIMPLE_OMP_RETURN
:
10986 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10987 somewhere other than the next block. This will be
10989 cur_region
->exit
= bb
;
10990 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
10991 cur_region
= cur_region
->outer
;
10994 case GIMPLE_OMP_CONTINUE
:
10995 cur_region
->cont
= bb
;
10996 switch (cur_region
->type
)
10998 case GIMPLE_OMP_FOR
:
10999 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11000 succs edges as abnormal to prevent splitting
11002 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
11003 /* Make the loopback edge. */
11004 make_edge (bb
, single_succ (cur_region
->entry
),
11007 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11008 corresponds to the case that the body of the loop
11009 is not executed at all. */
11010 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
11011 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
11015 case GIMPLE_OMP_SECTIONS
:
11016 /* Wire up the edges into and out of the nested sections. */
11018 basic_block switch_bb
= single_succ (cur_region
->entry
);
11020 struct omp_region
*i
;
11021 for (i
= cur_region
->inner
; i
; i
= i
->next
)
11023 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
11024 make_edge (switch_bb
, i
->entry
, 0);
11025 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
11028 /* Make the loopback edge to the block with
11029 GIMPLE_OMP_SECTIONS_SWITCH. */
11030 make_edge (bb
, switch_bb
, 0);
11032 /* Make the edge from the switch to exit. */
11033 make_edge (switch_bb
, bb
->next_bb
, 0);
11039 gcc_unreachable ();
11044 gcc_unreachable ();
11047 if (*region
!= cur_region
)
11049 *region
= cur_region
;
11051 *region_idx
= cur_region
->entry
->index
;
11059 static unsigned int
11060 diagnose_omp_structured_block_errors (void)
11062 struct walk_stmt_info wi
;
11063 gimple_seq body
= gimple_body (current_function_decl
);
11065 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
11067 memset (&wi
, 0, sizeof (wi
));
11068 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
11070 memset (&wi
, 0, sizeof (wi
));
11071 wi
.want_locations
= true;
11072 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
11074 gimple_set_body (current_function_decl
, body
);
11076 splay_tree_delete (all_labels
);
11084 const pass_data pass_data_diagnose_omp_blocks
=
11086 GIMPLE_PASS
, /* type */
11087 "*diagnose_omp_blocks", /* name */
11088 OPTGROUP_NONE
, /* optinfo_flags */
11089 TV_NONE
, /* tv_id */
11090 PROP_gimple_any
, /* properties_required */
11091 0, /* properties_provided */
11092 0, /* properties_destroyed */
11093 0, /* todo_flags_start */
11094 0, /* todo_flags_finish */
11097 class pass_diagnose_omp_blocks
: public gimple_opt_pass
11100 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
11101 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
11104 /* opt_pass methods: */
11105 virtual bool gate (function
*) { return flag_openmp
|| flag_cilkplus
; }
11106 virtual unsigned int execute (function
*)
11108 return diagnose_omp_structured_block_errors ();
11111 }; // class pass_diagnose_omp_blocks
11113 } // anon namespace
11116 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
11118 return new pass_diagnose_omp_blocks (ctxt
);
11121 /* SIMD clone supporting code. */
11123 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11124 of arguments to reserve space for. */
11126 static struct cgraph_simd_clone
*
11127 simd_clone_struct_alloc (int nargs
)
11129 struct cgraph_simd_clone
*clone_info
;
11130 size_t len
= (sizeof (struct cgraph_simd_clone
)
11131 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
11132 clone_info
= (struct cgraph_simd_clone
*)
11133 ggc_internal_cleared_alloc (len
);
11137 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11140 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
11141 struct cgraph_simd_clone
*from
)
11143 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
11144 + ((from
->nargs
- from
->inbranch
)
11145 * sizeof (struct cgraph_simd_clone_arg
))));
11148 /* Return vector of parameter types of function FNDECL. This uses
11149 TYPE_ARG_TYPES if available, otherwise falls back to types of
11150 DECL_ARGUMENTS types. */
11153 simd_clone_vector_of_formal_parm_types (tree fndecl
)
11155 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
11156 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
11157 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
11160 FOR_EACH_VEC_ELT (args
, i
, arg
)
11161 args
[i
] = TREE_TYPE (args
[i
]);
11165 /* Given a simd function in NODE, extract the simd specific
11166 information from the OMP clauses passed in CLAUSES, and return
11167 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11168 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11169 otherwise set to FALSE. */
11171 static struct cgraph_simd_clone
*
11172 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
11173 bool *inbranch_specified
)
11175 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11178 *inbranch_specified
= false;
11180 n
= args
.length ();
11181 if (n
> 0 && args
.last () == void_type_node
)
11184 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11185 be cloned have a distinctive artificial label in addition to "omp
11189 && lookup_attribute ("cilk simd function",
11190 DECL_ATTRIBUTES (node
->decl
)));
11192 /* Allocate one more than needed just in case this is an in-branch
11193 clone which will require a mask argument. */
11194 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
11195 clone_info
->nargs
= n
;
11196 clone_info
->cilk_elemental
= cilk_clone
;
11203 clauses
= TREE_VALUE (clauses
);
11204 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
11207 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
11209 switch (OMP_CLAUSE_CODE (t
))
11211 case OMP_CLAUSE_INBRANCH
:
11212 clone_info
->inbranch
= 1;
11213 *inbranch_specified
= true;
11215 case OMP_CLAUSE_NOTINBRANCH
:
11216 clone_info
->inbranch
= 0;
11217 *inbranch_specified
= true;
11219 case OMP_CLAUSE_SIMDLEN
:
11220 clone_info
->simdlen
11221 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
11223 case OMP_CLAUSE_LINEAR
:
11225 tree decl
= OMP_CLAUSE_DECL (t
);
11226 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
11227 int argno
= TREE_INT_CST_LOW (decl
);
11228 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
11230 clone_info
->args
[argno
].arg_type
11231 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
11232 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
11233 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
11234 && clone_info
->args
[argno
].linear_step
< n
);
11238 if (POINTER_TYPE_P (args
[argno
]))
11239 step
= fold_convert (ssizetype
, step
);
11240 if (!tree_fits_shwi_p (step
))
11242 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
11243 "ignoring large linear step");
11247 else if (integer_zerop (step
))
11249 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
11250 "ignoring zero linear step");
11256 clone_info
->args
[argno
].arg_type
11257 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
11258 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
11263 case OMP_CLAUSE_UNIFORM
:
11265 tree decl
= OMP_CLAUSE_DECL (t
);
11266 int argno
= tree_to_uhwi (decl
);
11267 clone_info
->args
[argno
].arg_type
11268 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
11271 case OMP_CLAUSE_ALIGNED
:
11273 tree decl
= OMP_CLAUSE_DECL (t
);
11274 int argno
= tree_to_uhwi (decl
);
11275 clone_info
->args
[argno
].alignment
11276 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
11287 /* Given a SIMD clone in NODE, calculate the characteristic data
11288 type and return the coresponding type. The characteristic data
11289 type is computed as described in the Intel Vector ABI. */
11292 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
11293 struct cgraph_simd_clone
*clone_info
)
11295 tree type
= integer_type_node
;
11296 tree fndecl
= node
->decl
;
11298 /* a) For non-void function, the characteristic data type is the
11300 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
11301 type
= TREE_TYPE (TREE_TYPE (fndecl
));
11303 /* b) If the function has any non-uniform, non-linear parameters,
11304 then the characteristic data type is the type of the first
11308 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
11309 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
11310 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
11318 /* c) If the characteristic data type determined by a) or b) above
11319 is struct, union, or class type which is pass-by-value (except
11320 for the type that maps to the built-in complex data type), the
11321 characteristic data type is int. */
11322 if (RECORD_OR_UNION_TYPE_P (type
)
11323 && !aggregate_value_p (type
, NULL
)
11324 && TREE_CODE (type
) != COMPLEX_TYPE
)
11325 return integer_type_node
;
11327 /* d) If none of the above three classes is applicable, the
11328 characteristic data type is int. */
11332 /* e) For Intel Xeon Phi native and offload compilation, if the
11333 resulting characteristic data type is 8-bit or 16-bit integer
11334 data type, the characteristic data type is int. */
11335 /* Well, we don't handle Xeon Phi yet. */
11339 simd_clone_mangle (struct cgraph_node
*node
,
11340 struct cgraph_simd_clone
*clone_info
)
11342 char vecsize_mangle
= clone_info
->vecsize_mangle
;
11343 char mask
= clone_info
->inbranch
? 'M' : 'N';
11344 unsigned int simdlen
= clone_info
->simdlen
;
11348 gcc_assert (vecsize_mangle
&& simdlen
);
11350 pp_string (&pp
, "_ZGV");
11351 pp_character (&pp
, vecsize_mangle
);
11352 pp_character (&pp
, mask
);
11353 pp_decimal_int (&pp
, simdlen
);
11355 for (n
= 0; n
< clone_info
->nargs
; ++n
)
11357 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
11359 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
11360 pp_character (&pp
, 'u');
11361 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
11363 gcc_assert (arg
.linear_step
!= 0);
11364 pp_character (&pp
, 'l');
11365 if (arg
.linear_step
> 1)
11366 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
11367 else if (arg
.linear_step
< 0)
11369 pp_character (&pp
, 'n');
11370 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
11374 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
11376 pp_character (&pp
, 's');
11377 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
11380 pp_character (&pp
, 'v');
11383 pp_character (&pp
, 'a');
11384 pp_decimal_int (&pp
, arg
.alignment
);
11388 pp_underscore (&pp
);
11390 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
)));
11391 const char *str
= pp_formatted_text (&pp
);
11393 /* If there already is a SIMD clone with the same mangled name, don't
11394 add another one. This can happen e.g. for
11395 #pragma omp declare simd
11396 #pragma omp declare simd simdlen(8)
11397 int foo (int, int);
11398 if the simdlen is assumed to be 8 for the first one, etc. */
11399 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
11400 clone
= clone
->simdclone
->next_clone
)
11401 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
11405 return get_identifier (str
);
11408 /* Create a simd clone of OLD_NODE and return it. */
11410 static struct cgraph_node
*
11411 simd_clone_create (struct cgraph_node
*old_node
)
11413 struct cgraph_node
*new_node
;
11414 if (old_node
->definition
)
11416 if (!old_node
->has_gimple_body_p ())
11418 old_node
->get_body ();
11419 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
11425 tree old_decl
= old_node
->decl
;
11426 tree new_decl
= copy_node (old_node
->decl
);
11427 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
11428 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
11429 SET_DECL_RTL (new_decl
, NULL
);
11430 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
11431 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
11432 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
11433 symtab
->call_cgraph_insertion_hooks (new_node
);
11435 if (new_node
== NULL
)
11438 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
11440 /* The function cgraph_function_versioning () will force the new
11441 symbol local. Undo this, and inherit external visability from
11443 new_node
->local
.local
= old_node
->local
.local
;
11444 new_node
->externally_visible
= old_node
->externally_visible
;
11449 /* Adjust the return type of the given function to its appropriate
11450 vector counterpart. Returns a simd array to be used throughout the
11451 function as a return value. */
11454 simd_clone_adjust_return_type (struct cgraph_node
*node
)
11456 tree fndecl
= node
->decl
;
11457 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
11458 unsigned int veclen
;
11461 /* Adjust the function return type. */
11462 if (orig_rettype
== void_type_node
)
11464 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
11465 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
)))
11466 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
))))
11467 veclen
= node
->simdclone
->vecsize_int
;
11469 veclen
= node
->simdclone
->vecsize_float
;
11470 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl
))));
11471 if (veclen
> node
->simdclone
->simdlen
)
11472 veclen
= node
->simdclone
->simdlen
;
11473 if (veclen
== node
->simdclone
->simdlen
)
11474 TREE_TYPE (TREE_TYPE (fndecl
))
11475 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)),
11476 node
->simdclone
->simdlen
);
11479 t
= build_vector_type (TREE_TYPE (TREE_TYPE (fndecl
)), veclen
);
11480 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
11481 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
11483 if (!node
->definition
)
11486 t
= DECL_RESULT (fndecl
);
11487 /* Adjust the DECL_RESULT. */
11488 gcc_assert (TREE_TYPE (t
) != void_type_node
);
11489 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
11492 tree atype
= build_array_type_nelts (orig_rettype
,
11493 node
->simdclone
->simdlen
);
11494 if (veclen
!= node
->simdclone
->simdlen
)
11495 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
11497 /* Set up a SIMD array to use as the return value. */
11498 tree retval
= create_tmp_var_raw (atype
, "retval");
11499 gimple_add_tmp_var (retval
);
11503 /* Each vector argument has a corresponding array to be used locally
11504 as part of the eventual loop. Create such temporary array and
11507 PREFIX is the prefix to be used for the temporary.
11509 TYPE is the inner element type.
11511 SIMDLEN is the number of elements. */
11514 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
11516 tree atype
= build_array_type_nelts (type
, simdlen
);
11517 tree avar
= create_tmp_var_raw (atype
, prefix
);
11518 gimple_add_tmp_var (avar
);
11522 /* Modify the function argument types to their corresponding vector
11523 counterparts if appropriate. Also, create one array for each simd
11524 argument to be used locally when using the function arguments as
11527 NODE is the function whose arguments are to be adjusted.
11529 Returns an adjustment vector that will be filled describing how the
11530 argument types will be adjusted. */
11532 static ipa_parm_adjustment_vec
11533 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
11536 ipa_parm_adjustment_vec adjustments
;
11538 if (node
->definition
)
11539 args
= ipa_get_vector_of_formal_parms (node
->decl
);
11541 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11542 adjustments
.create (args
.length ());
11543 unsigned i
, j
, veclen
;
11544 struct ipa_parm_adjustment adj
;
11545 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
11547 memset (&adj
, 0, sizeof (adj
));
11548 tree parm
= args
[i
];
11549 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
11550 adj
.base_index
= i
;
11553 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
11554 node
->simdclone
->args
[i
].orig_type
= parm_type
;
11556 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
11558 /* No adjustment necessary for scalar arguments. */
11559 adj
.op
= IPA_PARM_OP_COPY
;
11563 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
11564 veclen
= node
->simdclone
->vecsize_int
;
11566 veclen
= node
->simdclone
->vecsize_float
;
11567 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
11568 if (veclen
> node
->simdclone
->simdlen
)
11569 veclen
= node
->simdclone
->simdlen
;
11570 adj
.arg_prefix
= "simd";
11571 adj
.type
= build_vector_type (parm_type
, veclen
);
11572 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
11573 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11575 adjustments
.safe_push (adj
);
11578 memset (&adj
, 0, sizeof (adj
));
11579 adj
.op
= IPA_PARM_OP_NEW
;
11580 adj
.arg_prefix
= "simd";
11581 adj
.base_index
= i
;
11582 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
11586 if (node
->definition
)
11587 node
->simdclone
->args
[i
].simd_array
11588 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
11589 parm_type
, node
->simdclone
->simdlen
);
11591 adjustments
.safe_push (adj
);
11594 if (node
->simdclone
->inbranch
)
11597 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
11600 memset (&adj
, 0, sizeof (adj
));
11601 adj
.op
= IPA_PARM_OP_NEW
;
11602 adj
.arg_prefix
= "mask";
11604 adj
.base_index
= i
;
11605 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
11606 veclen
= node
->simdclone
->vecsize_int
;
11608 veclen
= node
->simdclone
->vecsize_float
;
11609 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
11610 if (veclen
> node
->simdclone
->simdlen
)
11611 veclen
= node
->simdclone
->simdlen
;
11612 adj
.type
= build_vector_type (base_type
, veclen
);
11613 adjustments
.safe_push (adj
);
11615 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11616 adjustments
.safe_push (adj
);
11618 /* We have previously allocated one extra entry for the mask. Use
11620 struct cgraph_simd_clone
*sc
= node
->simdclone
;
11622 if (node
->definition
)
11624 sc
->args
[i
].orig_arg
11625 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
11626 sc
->args
[i
].simd_array
11627 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
11629 sc
->args
[i
].orig_type
= base_type
;
11630 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
11633 if (node
->definition
)
11634 ipa_modify_formal_parameters (node
->decl
, adjustments
);
11637 tree new_arg_types
= NULL_TREE
, new_reversed
;
11638 bool last_parm_void
= false;
11639 if (args
.length () > 0 && args
.last () == void_type_node
)
11640 last_parm_void
= true;
11642 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
11643 j
= adjustments
.length ();
11644 for (i
= 0; i
< j
; i
++)
11646 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
11648 if (adj
->op
== IPA_PARM_OP_COPY
)
11649 ptype
= args
[adj
->base_index
];
11652 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
11654 new_reversed
= nreverse (new_arg_types
);
11655 if (last_parm_void
)
11658 TREE_CHAIN (new_arg_types
) = void_list_node
;
11660 new_reversed
= void_list_node
;
11663 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
11664 TYPE_ARG_TYPES (new_type
) = new_reversed
;
11665 TREE_TYPE (node
->decl
) = new_type
;
11667 adjustments
.release ();
11670 return adjustments
;
11673 /* Initialize and copy the function arguments in NODE to their
11674 corresponding local simd arrays. Returns a fresh gimple_seq with
11675 the instruction sequence generated. */
11678 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
11679 ipa_parm_adjustment_vec adjustments
)
11681 gimple_seq seq
= NULL
;
11682 unsigned i
= 0, j
= 0, k
;
11684 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
11686 arg
= DECL_CHAIN (arg
), i
++, j
++)
11688 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
11691 node
->simdclone
->args
[i
].vector_arg
= arg
;
11693 tree array
= node
->simdclone
->args
[i
].simd_array
;
11694 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
11696 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11697 tree ptr
= build_fold_addr_expr (array
);
11698 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11699 build_int_cst (ptype
, 0));
11700 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11701 gimplify_and_add (t
, &seq
);
11705 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
11706 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11707 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
11709 tree ptr
= build_fold_addr_expr (array
);
11713 arg
= DECL_CHAIN (arg
);
11717 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
11718 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11719 build_int_cst (ptype
, k
* elemsize
));
11720 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11721 gimplify_and_add (t
, &seq
);
11728 /* Callback info for ipa_simd_modify_stmt_ops below. */
11730 struct modify_stmt_info
{
11731 ipa_parm_adjustment_vec adjustments
;
11733 /* True if the parent statement was modified by
11734 ipa_simd_modify_stmt_ops. */
11738 /* Callback for walk_gimple_op.
11740 Adjust operands from a given statement as specified in the
11741 adjustments vector in the callback data. */
11744 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
11746 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
11747 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
11748 tree
*orig_tp
= tp
;
11749 if (TREE_CODE (*tp
) == ADDR_EXPR
)
11750 tp
= &TREE_OPERAND (*tp
, 0);
11751 struct ipa_parm_adjustment
*cand
= NULL
;
11752 if (TREE_CODE (*tp
) == PARM_DECL
)
11753 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
11757 *walk_subtrees
= 0;
11760 tree repl
= NULL_TREE
;
11762 repl
= unshare_expr (cand
->new_decl
);
11767 *walk_subtrees
= 0;
11768 bool modified
= info
->modified
;
11769 info
->modified
= false;
11770 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
11771 if (!info
->modified
)
11773 info
->modified
= modified
;
11776 info
->modified
= modified
;
11785 repl
= build_fold_addr_expr (repl
);
11787 if (is_gimple_debug (info
->stmt
))
11789 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
11790 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
11791 DECL_ARTIFICIAL (vexpr
) = 1;
11792 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
11793 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
11798 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
),
11800 repl
= gimple_assign_lhs (stmt
);
11802 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
11803 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11806 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
11808 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
11814 info
->modified
= true;
11818 /* Traverse the function body and perform all modifications as
11819 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11820 modified such that the replacement/reduction value will now be an
11821 offset into the corresponding simd_array.
11823 This function will replace all function argument uses with their
11824 corresponding simd array elements, and ajust the return values
11828 ipa_simd_modify_function_body (struct cgraph_node
*node
,
11829 ipa_parm_adjustment_vec adjustments
,
11830 tree retval_array
, tree iter
)
11833 unsigned int i
, j
, l
;
11835 /* Re-use the adjustments array, but this time use it to replace
11836 every function argument use to an offset into the corresponding
11838 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
11840 if (!node
->simdclone
->args
[i
].vector_arg
)
11843 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
11844 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
11845 adjustments
[j
].new_decl
11846 = build4 (ARRAY_REF
,
11848 node
->simdclone
->args
[i
].simd_array
,
11850 NULL_TREE
, NULL_TREE
);
11851 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
11852 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
11853 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
11856 l
= adjustments
.length ();
11857 for (i
= 1; i
< num_ssa_names
; i
++)
11859 tree name
= ssa_name (i
);
11861 && SSA_NAME_VAR (name
)
11862 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
11864 for (j
= 0; j
< l
; j
++)
11865 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
11866 && adjustments
[j
].new_decl
)
11869 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
11872 = copy_var_decl (adjustments
[j
].base
,
11873 DECL_NAME (adjustments
[j
].base
),
11874 TREE_TYPE (adjustments
[j
].base
));
11875 adjustments
[j
].new_ssa_base
= base_var
;
11878 base_var
= adjustments
[j
].new_ssa_base
;
11879 if (SSA_NAME_IS_DEFAULT_DEF (name
))
11881 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11882 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
11883 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
11884 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
11885 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11886 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
11887 gimple stmt
= gimple_build_assign (name
, new_decl
);
11888 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11891 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
11896 struct modify_stmt_info info
;
11897 info
.adjustments
= adjustments
;
11899 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
11901 gimple_stmt_iterator gsi
;
11903 gsi
= gsi_start_bb (bb
);
11904 while (!gsi_end_p (gsi
))
11906 gimple stmt
= gsi_stmt (gsi
);
11908 struct walk_stmt_info wi
;
11910 memset (&wi
, 0, sizeof (wi
));
11911 info
.modified
= false;
11913 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
11915 if (gimple_code (stmt
) == GIMPLE_RETURN
)
11917 tree retval
= gimple_return_retval (stmt
);
11920 gsi_remove (&gsi
, true);
11924 /* Replace `return foo' with `retval_array[iter] = foo'. */
11925 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
11926 retval_array
, iter
, NULL
, NULL
);
11927 stmt
= gimple_build_assign (ref
, retval
);
11928 gsi_replace (&gsi
, stmt
, true);
11929 info
.modified
= true;
11934 update_stmt (stmt
);
11935 if (maybe_clean_eh_stmt (stmt
))
11936 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
11943 /* Adjust the argument types in NODE to their appropriate vector
11947 simd_clone_adjust (struct cgraph_node
*node
)
11949 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
11951 targetm
.simd_clone
.adjust (node
);
11953 tree retval
= simd_clone_adjust_return_type (node
);
11954 ipa_parm_adjustment_vec adjustments
11955 = simd_clone_adjust_argument_types (node
);
11957 push_gimplify_context ();
11959 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
11961 /* Adjust all uses of vector arguments accordingly. Adjust all
11962 return values accordingly. */
11963 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
11964 tree iter1
= make_ssa_name (iter
, NULL
);
11965 tree iter2
= make_ssa_name (iter
, NULL
);
11966 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
11968 /* Initialize the iteration variable. */
11969 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
11970 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
11971 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
11972 /* Insert the SIMD array and iv initialization at function
11974 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
11976 pop_gimplify_context (NULL
);
11978 /* Create a new BB right before the original exit BB, to hold the
11979 iteration increment and the condition/branch. */
11980 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
11981 basic_block incr_bb
= create_empty_bb (orig_exit
);
11982 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
11983 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11984 flag. Set it now to be a FALLTHRU_EDGE. */
11985 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
11986 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
11987 for (unsigned i
= 0;
11988 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
11990 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
11991 redirect_edge_succ (e
, incr_bb
);
11993 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
11994 e
->probability
= REG_BR_PROB_BASE
;
11995 gsi
= gsi_last_bb (incr_bb
);
11996 gimple g
= gimple_build_assign_with_ops (PLUS_EXPR
, iter2
, iter1
,
11997 build_int_cst (unsigned_type_node
,
11999 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12001 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12002 struct loop
*loop
= alloc_loop ();
12003 cfun
->has_force_vectorize_loops
= true;
12004 loop
->safelen
= node
->simdclone
->simdlen
;
12005 loop
->force_vectorize
= true;
12006 loop
->header
= body_bb
;
12008 /* Branch around the body if the mask applies. */
12009 if (node
->simdclone
->inbranch
)
12011 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
12013 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
12014 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)), NULL
);
12015 tree aref
= build4 (ARRAY_REF
,
12016 TREE_TYPE (TREE_TYPE (mask_array
)),
12019 g
= gimple_build_assign (mask
, aref
);
12020 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12021 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
12022 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
12024 aref
= build1 (VIEW_CONVERT_EXPR
,
12025 build_nonstandard_integer_type (bitsize
, 0), mask
);
12026 mask
= make_ssa_name (TREE_TYPE (aref
), NULL
);
12027 g
= gimple_build_assign (mask
, aref
);
12028 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12031 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
12033 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12034 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
12035 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
12038 /* Generate the condition. */
12039 g
= gimple_build_cond (LT_EXPR
,
12041 build_int_cst (unsigned_type_node
,
12042 node
->simdclone
->simdlen
),
12044 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12045 e
= split_block (incr_bb
, gsi_stmt (gsi
));
12046 basic_block latch_bb
= e
->dest
;
12047 basic_block new_exit_bb
;
12048 new_exit_bb
= split_block (latch_bb
, NULL
)->dest
;
12049 loop
->latch
= latch_bb
;
12051 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
12053 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
12054 /* The successor of incr_bb is already pointing to latch_bb; just
12056 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12057 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
12059 gimple phi
= create_phi_node (iter1
, body_bb
);
12060 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
12061 edge latch_edge
= single_succ_edge (latch_bb
);
12062 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
12064 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
12066 /* Generate the new return. */
12067 gsi
= gsi_last_bb (new_exit_bb
);
12069 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
12070 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
12071 retval
= TREE_OPERAND (retval
, 0);
12074 retval
= build1 (VIEW_CONVERT_EXPR
,
12075 TREE_TYPE (TREE_TYPE (node
->decl
)),
12077 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
12078 false, GSI_CONTINUE_LINKING
);
12080 g
= gimple_build_return (retval
);
12081 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12083 /* Handle aligned clauses by replacing default defs of the aligned
12084 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12085 lhs. Handle linear by adding PHIs. */
12086 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
12087 if (node
->simdclone
->args
[i
].alignment
12088 && node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
12089 && (node
->simdclone
->args
[i
].alignment
12090 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
12091 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
12094 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
12095 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
12096 tree def
= ssa_default_def (cfun
, orig_arg
);
12097 if (def
&& !has_zero_uses (def
))
12099 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
12100 gimple_seq seq
= NULL
;
12101 bool need_cvt
= false;
12103 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
12105 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
12108 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
, NULL
);
12109 gimple_call_set_lhs (g
, t
);
12110 gimple_seq_add_stmt_without_update (&seq
, g
);
12113 t
= make_ssa_name (orig_arg
, NULL
);
12114 g
= gimple_build_assign_with_ops (NOP_EXPR
, t
,
12115 gimple_call_lhs (g
),
12117 gimple_seq_add_stmt_without_update (&seq
, g
);
12119 gsi_insert_seq_on_edge_immediate
12120 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
12122 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
12123 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
12125 node
->create_edge (cgraph_node::get_create (fn
),
12126 call
, entry_bb
->count
, freq
);
12128 imm_use_iterator iter
;
12129 use_operand_p use_p
;
12131 tree repl
= gimple_get_lhs (g
);
12132 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
12133 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
12136 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
12137 SET_USE (use_p
, repl
);
12140 else if (node
->simdclone
->args
[i
].arg_type
12141 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
12143 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
12144 tree def
= ssa_default_def (cfun
, orig_arg
);
12145 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12146 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
12147 if (def
&& !has_zero_uses (def
))
12149 iter1
= make_ssa_name (orig_arg
, NULL
);
12150 iter2
= make_ssa_name (orig_arg
, NULL
);
12151 phi
= create_phi_node (iter1
, body_bb
);
12152 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
12153 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
12154 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12155 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
12156 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12157 ? TREE_TYPE (orig_arg
) : sizetype
;
12159 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
12160 g
= gimple_build_assign_with_ops (code
, iter2
, iter1
, addcst
);
12161 gsi
= gsi_last_bb (incr_bb
);
12162 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
12164 imm_use_iterator iter
;
12165 use_operand_p use_p
;
12167 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
12168 if (use_stmt
== phi
)
12171 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
12172 SET_USE (use_p
, iter1
);
12176 calculate_dominance_info (CDI_DOMINATORS
);
12177 add_loop (loop
, loop
->header
->loop_father
);
12178 update_ssa (TODO_update_ssa
);
12183 /* If the function in NODE is tagged as an elemental SIMD function,
12184 create the appropriate SIMD clones. */
12187 expand_simd_clones (struct cgraph_node
*node
)
12189 tree attr
= lookup_attribute ("omp declare simd",
12190 DECL_ATTRIBUTES (node
->decl
));
12191 if (attr
== NULL_TREE
12192 || node
->global
.inlined_to
12193 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
12197 #pragma omp declare simd
12199 in C, there we don't know the argument types at all. */
12200 if (!node
->definition
12201 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
12206 /* Start with parsing the "omp declare simd" attribute(s). */
12207 bool inbranch_clause_specified
;
12208 struct cgraph_simd_clone
*clone_info
12209 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
12210 &inbranch_clause_specified
);
12211 if (clone_info
== NULL
)
12214 int orig_simdlen
= clone_info
->simdlen
;
12215 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
12216 /* The target can return 0 (no simd clones should be created),
12217 1 (just one ISA of simd clones should be created) or higher
12218 count of ISA variants. In that case, clone_info is initialized
12219 for the first ISA variant. */
12221 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
12226 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12227 also create one inbranch and one !inbranch clone of it. */
12228 for (int i
= 0; i
< count
* 2; i
++)
12230 struct cgraph_simd_clone
*clone
= clone_info
;
12231 if (inbranch_clause_specified
&& (i
& 1) != 0)
12236 clone
= simd_clone_struct_alloc (clone_info
->nargs
12238 simd_clone_struct_copy (clone
, clone_info
);
12239 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12240 and simd_clone_adjust_argument_types did to the first
12242 clone
->nargs
-= clone_info
->inbranch
;
12243 clone
->simdlen
= orig_simdlen
;
12244 /* And call the target hook again to get the right ISA. */
12245 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
12249 clone
->inbranch
= 1;
12252 /* simd_clone_mangle might fail if such a clone has been created
12254 tree id
= simd_clone_mangle (node
, clone
);
12255 if (id
== NULL_TREE
)
12258 /* Only when we are sure we want to create the clone actually
12259 clone the function (or definitions) or create another
12260 extern FUNCTION_DECL (for prototypes without definitions). */
12261 struct cgraph_node
*n
= simd_clone_create (node
);
12265 n
->simdclone
= clone
;
12266 clone
->origin
= node
;
12267 clone
->next_clone
= NULL
;
12268 if (node
->simd_clones
== NULL
)
12270 clone
->prev_clone
= n
;
12271 node
->simd_clones
= n
;
12275 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
12276 clone
->prev_clone
->simdclone
->next_clone
= n
;
12277 node
->simd_clones
->simdclone
->prev_clone
= n
;
12279 symtab
->change_decl_assembler_name (n
->decl
, id
);
12280 /* And finally adjust the return type, parameters and for
12281 definitions also function body. */
12282 if (node
->definition
)
12283 simd_clone_adjust (n
);
12286 simd_clone_adjust_return_type (n
);
12287 simd_clone_adjust_argument_types (n
);
12291 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
12294 /* Entry point for IPA simd clone creation pass. */
12296 static unsigned int
12297 ipa_omp_simd_clone (void)
12299 struct cgraph_node
*node
;
12300 FOR_EACH_FUNCTION (node
)
12301 expand_simd_clones (node
);
12307 const pass_data pass_data_omp_simd_clone
=
12309 SIMPLE_IPA_PASS
, /* type */
12310 "simdclone", /* name */
12311 OPTGROUP_NONE
, /* optinfo_flags */
12312 TV_NONE
, /* tv_id */
12313 ( PROP_ssa
| PROP_cfg
), /* properties_required */
12314 0, /* properties_provided */
12315 0, /* properties_destroyed */
12316 0, /* todo_flags_start */
12317 0, /* todo_flags_finish */
12320 class pass_omp_simd_clone
: public simple_ipa_opt_pass
12323 pass_omp_simd_clone(gcc::context
*ctxt
)
12324 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
12327 /* opt_pass methods: */
12328 virtual bool gate (function
*);
12329 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
12333 pass_omp_simd_clone::gate (function
*)
12335 return ((flag_openmp
|| flag_openmp_simd
12337 || (in_lto_p
&& !flag_wpa
))
12338 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
12341 } // anon namespace
12343 simple_ipa_opt_pass
*
12344 make_pass_omp_simd_clone (gcc::context
*ctxt
)
12346 return new pass_omp_simd_clone (ctxt
);
12349 #include "gt-omp-low.h"