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-2015 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
26 #include "coretypes.h"
31 #include "double-int.h"
38 #include "fold-const.h"
39 #include "stringpool.h"
40 #include "stor-layout.h"
43 #include "hard-reg-set.h"
46 #include "dominance.h"
49 #include "basic-block.h"
50 #include "tree-ssa-alias.h"
51 #include "internal-fn.h"
52 #include "gimple-fold.h"
53 #include "gimple-expr.h"
57 #include "gimple-iterator.h"
58 #include "gimplify-me.h"
59 #include "gimple-walk.h"
60 #include "tree-iterator.h"
61 #include "tree-inline.h"
62 #include "langhooks.h"
63 #include "diagnostic-core.h"
64 #include "gimple-ssa.h"
66 #include "plugin-api.h"
70 #include "tree-phinodes.h"
71 #include "ssa-iterators.h"
72 #include "tree-ssanames.h"
73 #include "tree-into-ssa.h"
79 #include "tree-pass.h"
81 #include "splay-tree.h"
82 #include "insn-codes.h"
86 #include "common/common-target.h"
88 #include "gimple-low.h"
89 #include "tree-cfgcleanup.h"
90 #include "pretty-print.h"
91 #include "alloc-pool.h"
92 #include "symbol-summary.h"
94 #include "tree-nested.h"
98 #include "lto-section-names.h"
101 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
102 phases. The first phase scans the function looking for OMP statements
103 and then for variables that must be replaced to satisfy data sharing
104 clauses. The second phase expands code for the constructs, as well as
105 re-gimplifying things when variables have been replaced with complex
108 Final code generation is done by pass_expand_omp. The flowgraph is
109 scanned for parallel regions which are then moved to a new
110 function, to be invoked by the thread library. */
112 /* Parallel region information. Every parallel and workshare
113 directive is enclosed between two markers, the OMP_* directive
114 and a corresponding OMP_RETURN statement. */
118 /* The enclosing region. */
119 struct omp_region
*outer
;
121 /* First child region. */
122 struct omp_region
*inner
;
124 /* Next peer region. */
125 struct omp_region
*next
;
127 /* Block containing the omp directive as its last stmt. */
130 /* Block containing the OMP_RETURN as its last stmt. */
133 /* Block containing the OMP_CONTINUE as its last stmt. */
136 /* If this is a combined parallel+workshare region, this is a list
137 of additional arguments needed by the combined parallel+workshare
139 vec
<tree
, va_gc
> *ws_args
;
141 /* The code for the omp directive of this region. */
142 enum gimple_code type
;
144 /* Schedule kind, only used for OMP_FOR type regions. */
145 enum omp_clause_schedule_kind sched_kind
;
147 /* True if this is a combined parallel+workshare region. */
148 bool is_combined_parallel
;
151 /* Context structure. Used to store information about each parallel
152 directive in the code. */
154 typedef struct omp_context
156 /* This field must be at the beginning, as we do "inheritance": Some
157 callback functions for tree-inline.c (e.g., omp_copy_decl)
158 receive a copy_body_data pointer that is up-casted to an
159 omp_context pointer. */
162 /* The tree of contexts corresponding to the encountered constructs. */
163 struct omp_context
*outer
;
166 /* Map variables to fields in a structure that allows communication
167 between sending and receiving threads. */
168 splay_tree field_map
;
173 /* These are used just by task contexts, if task firstprivate fn is
174 needed. srecord_type is used to communicate from the thread
175 that encountered the task construct to task firstprivate fn,
176 record_type is allocated by GOMP_task, initialized by task firstprivate
177 fn and passed to the task body fn. */
178 splay_tree sfield_map
;
181 /* A chain of variables to add to the top-level block surrounding the
182 construct. In the case of a parallel, this is in the child function. */
185 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
186 barriers should jump to during omplower pass. */
189 /* What to do with variables with implicitly determined sharing
191 enum omp_clause_default_kind default_kind
;
193 /* Nesting depth of this context. Used to beautify error messages re
194 invalid gotos. The outermost ctx is depth 1, with depth 0 being
195 reserved for the main body of the function. */
198 /* True if this parallel directive is nested within another. */
201 /* True if this construct can be cancelled. */
206 struct omp_for_data_loop
208 tree v
, n1
, n2
, step
;
209 enum tree_code cond_code
;
212 /* A structure describing the main elements of a parallel loop. */
216 struct omp_for_data_loop loop
;
221 bool have_nowait
, have_ordered
;
222 enum omp_clause_schedule_kind sched_kind
;
223 struct omp_for_data_loop
*loops
;
227 static splay_tree all_contexts
;
228 static int taskreg_nesting_level
;
229 static int target_nesting_level
;
230 static struct omp_region
*root_omp_region
;
231 static bitmap task_shared_vars
;
232 static vec
<omp_context
*> taskreg_contexts
;
234 static void scan_omp (gimple_seq
*, omp_context
*);
235 static tree
scan_omp_1_op (tree
*, int *, void *);
237 #define WALK_SUBSTMTS \
241 case GIMPLE_EH_FILTER: \
242 case GIMPLE_TRANSACTION: \
243 /* The sub-statements for these should be walked. */ \
244 *handled_ops_p = false; \
247 /* Holds offload tables with decls. */
248 vec
<tree
, va_gc
> *offload_funcs
, *offload_vars
;
250 /* Convenience function for calling scan_omp_1_op on tree operands. */
253 scan_omp_op (tree
*tp
, omp_context
*ctx
)
255 struct walk_stmt_info wi
;
257 memset (&wi
, 0, sizeof (wi
));
259 wi
.want_locations
= true;
261 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
264 static void lower_omp (gimple_seq
*, omp_context
*);
265 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
266 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
268 /* Find an OpenMP clause of type KIND within CLAUSES. */
271 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
273 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
274 if (OMP_CLAUSE_CODE (clauses
) == kind
)
280 /* Return true if CTX is for an omp parallel. */
283 is_parallel_ctx (omp_context
*ctx
)
285 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
289 /* Return true if CTX is for an omp target region. */
292 is_targetreg_ctx (omp_context
*ctx
)
294 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
295 && gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_REGION
;
299 /* Return true if CTX is for an omp task. */
302 is_task_ctx (omp_context
*ctx
)
304 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
308 /* Return true if CTX is for an omp parallel or omp task. */
311 is_taskreg_ctx (omp_context
*ctx
)
313 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
314 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
318 /* Return true if REGION is a combined parallel+workshare region. */
321 is_combined_parallel (struct omp_region
*region
)
323 return region
->is_combined_parallel
;
327 /* Extract the header elements of parallel loop FOR_STMT and store
331 extract_omp_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
332 struct omp_for_data_loop
*loops
)
334 tree t
, var
, *collapse_iter
, *collapse_count
;
335 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
336 struct omp_for_data_loop
*loop
;
338 struct omp_for_data_loop dummy_loop
;
339 location_t loc
= gimple_location (for_stmt
);
340 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
341 bool distribute
= gimple_omp_for_kind (for_stmt
)
342 == GF_OMP_FOR_KIND_DISTRIBUTE
;
344 fd
->for_stmt
= for_stmt
;
346 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
347 if (fd
->collapse
> 1)
350 fd
->loops
= &fd
->loop
;
352 fd
->have_nowait
= distribute
|| simd
;
353 fd
->have_ordered
= false;
354 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
355 fd
->chunk_size
= NULL_TREE
;
356 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
357 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
358 collapse_iter
= NULL
;
359 collapse_count
= NULL
;
361 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
362 switch (OMP_CLAUSE_CODE (t
))
364 case OMP_CLAUSE_NOWAIT
:
365 fd
->have_nowait
= true;
367 case OMP_CLAUSE_ORDERED
:
368 fd
->have_ordered
= true;
370 case OMP_CLAUSE_SCHEDULE
:
371 gcc_assert (!distribute
);
372 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
373 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
375 case OMP_CLAUSE_DIST_SCHEDULE
:
376 gcc_assert (distribute
);
377 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
379 case OMP_CLAUSE_COLLAPSE
:
380 if (fd
->collapse
> 1)
382 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
383 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
390 /* FIXME: for now map schedule(auto) to schedule(static).
391 There should be analysis to determine whether all iterations
392 are approximately the same amount of work (then schedule(static)
393 is best) or if it varies (then schedule(dynamic,N) is better). */
394 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
396 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
397 gcc_assert (fd
->chunk_size
== NULL
);
399 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
400 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
401 gcc_assert (fd
->chunk_size
== NULL
);
402 else if (fd
->chunk_size
== NULL
)
404 /* We only need to compute a default chunk size for ordered
405 static loops and dynamic loops. */
406 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
408 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
409 ? integer_zero_node
: integer_one_node
;
412 for (i
= 0; i
< fd
->collapse
; i
++)
414 if (fd
->collapse
== 1)
416 else if (loops
!= NULL
)
421 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
422 gcc_assert (SSA_VAR_P (loop
->v
));
423 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
424 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
425 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
426 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
428 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
429 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
430 switch (loop
->cond_code
)
436 gcc_assert (gimple_omp_for_kind (for_stmt
)
437 == GF_OMP_FOR_KIND_CILKSIMD
438 || (gimple_omp_for_kind (for_stmt
)
439 == GF_OMP_FOR_KIND_CILKFOR
));
442 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
443 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
445 loop
->n2
= fold_build2_loc (loc
,
446 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
447 build_int_cst (TREE_TYPE (loop
->n2
), 1));
448 loop
->cond_code
= LT_EXPR
;
451 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
452 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
454 loop
->n2
= fold_build2_loc (loc
,
455 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
456 build_int_cst (TREE_TYPE (loop
->n2
), 1));
457 loop
->cond_code
= GT_EXPR
;
463 t
= gimple_omp_for_incr (for_stmt
, i
);
464 gcc_assert (TREE_OPERAND (t
, 0) == var
);
465 switch (TREE_CODE (t
))
468 loop
->step
= TREE_OPERAND (t
, 1);
470 case POINTER_PLUS_EXPR
:
471 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
474 loop
->step
= TREE_OPERAND (t
, 1);
475 loop
->step
= fold_build1_loc (loc
,
476 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
484 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
485 && !fd
->have_ordered
))
487 if (fd
->collapse
== 1)
488 iter_type
= TREE_TYPE (loop
->v
);
490 || TYPE_PRECISION (iter_type
)
491 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
493 = build_nonstandard_integer_type
494 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
496 else if (iter_type
!= long_long_unsigned_type_node
)
498 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
499 iter_type
= long_long_unsigned_type_node
;
500 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
501 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
502 >= TYPE_PRECISION (iter_type
))
506 if (loop
->cond_code
== LT_EXPR
)
507 n
= fold_build2_loc (loc
,
508 PLUS_EXPR
, TREE_TYPE (loop
->v
),
509 loop
->n2
, loop
->step
);
512 if (TREE_CODE (n
) != INTEGER_CST
513 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
514 iter_type
= long_long_unsigned_type_node
;
516 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
517 > TYPE_PRECISION (iter_type
))
521 if (loop
->cond_code
== LT_EXPR
)
524 n2
= fold_build2_loc (loc
,
525 PLUS_EXPR
, TREE_TYPE (loop
->v
),
526 loop
->n2
, loop
->step
);
530 n1
= fold_build2_loc (loc
,
531 MINUS_EXPR
, TREE_TYPE (loop
->v
),
532 loop
->n2
, loop
->step
);
535 if (TREE_CODE (n1
) != INTEGER_CST
536 || TREE_CODE (n2
) != INTEGER_CST
537 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
538 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
539 iter_type
= long_long_unsigned_type_node
;
543 if (collapse_count
&& *collapse_count
== NULL
)
545 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
546 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
547 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
548 if (t
&& integer_zerop (t
))
549 count
= build_zero_cst (long_long_unsigned_type_node
);
550 else if ((i
== 0 || count
!= NULL_TREE
)
551 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
552 && TREE_CONSTANT (loop
->n1
)
553 && TREE_CONSTANT (loop
->n2
)
554 && TREE_CODE (loop
->step
) == INTEGER_CST
)
556 tree itype
= TREE_TYPE (loop
->v
);
558 if (POINTER_TYPE_P (itype
))
559 itype
= signed_type_for (itype
);
560 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
561 t
= fold_build2_loc (loc
,
563 fold_convert_loc (loc
, itype
, loop
->step
), t
);
564 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
565 fold_convert_loc (loc
, itype
, loop
->n2
));
566 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
567 fold_convert_loc (loc
, itype
, loop
->n1
));
568 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
569 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
570 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
571 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
572 fold_convert_loc (loc
, itype
,
575 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
576 fold_convert_loc (loc
, itype
, loop
->step
));
577 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
578 if (count
!= NULL_TREE
)
579 count
= fold_build2_loc (loc
,
580 MULT_EXPR
, long_long_unsigned_type_node
,
584 if (TREE_CODE (count
) != INTEGER_CST
)
587 else if (count
&& !integer_zerop (count
))
594 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
595 || fd
->have_ordered
))
597 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
598 iter_type
= long_long_unsigned_type_node
;
600 iter_type
= long_integer_type_node
;
602 else if (collapse_iter
&& *collapse_iter
!= NULL
)
603 iter_type
= TREE_TYPE (*collapse_iter
);
604 fd
->iter_type
= iter_type
;
605 if (collapse_iter
&& *collapse_iter
== NULL
)
606 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
607 if (collapse_count
&& *collapse_count
== NULL
)
610 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
612 *collapse_count
= create_tmp_var (iter_type
, ".count");
615 if (fd
->collapse
> 1)
617 fd
->loop
.v
= *collapse_iter
;
618 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
619 fd
->loop
.n2
= *collapse_count
;
620 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
621 fd
->loop
.cond_code
= LT_EXPR
;
626 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
627 is the immediate dominator of PAR_ENTRY_BB, return true if there
628 are no data dependencies that would prevent expanding the parallel
629 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
631 When expanding a combined parallel+workshare region, the call to
632 the child function may need additional arguments in the case of
633 GIMPLE_OMP_FOR regions. In some cases, these arguments are
634 computed out of variables passed in from the parent to the child
635 via 'struct .omp_data_s'. For instance:
637 #pragma omp parallel for schedule (guided, i * 4)
642 # BLOCK 2 (PAR_ENTRY_BB)
644 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
646 # BLOCK 3 (WS_ENTRY_BB)
647 .omp_data_i = &.omp_data_o;
648 D.1667 = .omp_data_i->i;
650 #pragma omp for schedule (guided, D.1598)
652 When we outline the parallel region, the call to the child function
653 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
654 that value is computed *after* the call site. So, in principle we
655 cannot do the transformation.
657 To see whether the code in WS_ENTRY_BB blocks the combined
658 parallel+workshare call, we collect all the variables used in the
659 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
660 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
663 FIXME. If we had the SSA form built at this point, we could merely
664 hoist the code in block 3 into block 2 and be done with it. But at
665 this point we don't have dataflow information and though we could
666 hack something up here, it is really not worth the aggravation. */
669 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
671 struct omp_for_data fd
;
672 gimple ws_stmt
= last_stmt (ws_entry_bb
);
674 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
677 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
679 extract_omp_for_data (as_a
<gomp_for
*> (ws_stmt
), &fd
, NULL
);
681 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
683 if (fd
.iter_type
!= long_integer_type_node
)
686 /* FIXME. We give up too easily here. If any of these arguments
687 are not constants, they will likely involve variables that have
688 been mapped into fields of .omp_data_s for sharing with the child
689 function. With appropriate data flow, it would be possible to
691 if (!is_gimple_min_invariant (fd
.loop
.n1
)
692 || !is_gimple_min_invariant (fd
.loop
.n2
)
693 || !is_gimple_min_invariant (fd
.loop
.step
)
694 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
701 /* Collect additional arguments needed to emit a combined
702 parallel+workshare call. WS_STMT is the workshare directive being
705 static vec
<tree
, va_gc
> *
706 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
709 location_t loc
= gimple_location (ws_stmt
);
710 vec
<tree
, va_gc
> *ws_args
;
712 if (gomp_for
*for_stmt
= dyn_cast
<gomp_for
*> (ws_stmt
))
714 struct omp_for_data fd
;
717 extract_omp_for_data (for_stmt
, &fd
, NULL
);
721 if (gimple_omp_for_combined_into_p (for_stmt
))
724 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
725 OMP_CLAUSE__LOOPTEMP_
);
727 n1
= OMP_CLAUSE_DECL (innerc
);
728 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
729 OMP_CLAUSE__LOOPTEMP_
);
731 n2
= OMP_CLAUSE_DECL (innerc
);
734 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
736 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
737 ws_args
->quick_push (t
);
739 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
740 ws_args
->quick_push (t
);
742 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
743 ws_args
->quick_push (t
);
747 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
748 ws_args
->quick_push (t
);
753 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
755 /* Number of sections is equal to the number of edges from the
756 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
757 the exit of the sections region. */
758 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
759 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
760 vec_alloc (ws_args
, 1);
761 ws_args
->quick_push (t
);
769 /* Discover whether REGION is a combined parallel+workshare region. */
772 determine_parallel_type (struct omp_region
*region
)
774 basic_block par_entry_bb
, par_exit_bb
;
775 basic_block ws_entry_bb
, ws_exit_bb
;
777 if (region
== NULL
|| region
->inner
== NULL
778 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
779 || region
->inner
->cont
== NULL
)
782 /* We only support parallel+for and parallel+sections. */
783 if (region
->type
!= GIMPLE_OMP_PARALLEL
784 || (region
->inner
->type
!= GIMPLE_OMP_FOR
785 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
788 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
789 WS_EXIT_BB -> PAR_EXIT_BB. */
790 par_entry_bb
= region
->entry
;
791 par_exit_bb
= region
->exit
;
792 ws_entry_bb
= region
->inner
->entry
;
793 ws_exit_bb
= region
->inner
->exit
;
795 if (single_succ (par_entry_bb
) == ws_entry_bb
796 && single_succ (ws_exit_bb
) == par_exit_bb
797 && workshare_safe_to_combine_p (ws_entry_bb
)
798 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
799 || (last_and_only_stmt (ws_entry_bb
)
800 && last_and_only_stmt (par_exit_bb
))))
802 gimple par_stmt
= last_stmt (par_entry_bb
);
803 gimple ws_stmt
= last_stmt (ws_entry_bb
);
805 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
807 /* If this is a combined parallel loop, we need to determine
808 whether or not to use the combined library calls. There
809 are two cases where we do not apply the transformation:
810 static loops and any kind of ordered loop. In the first
811 case, we already open code the loop so there is no need
812 to do anything else. In the latter case, the combined
813 parallel loop call would still need extra synchronization
814 to implement ordered semantics, so there would not be any
815 gain in using the combined call. */
816 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
817 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
819 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
820 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
822 region
->is_combined_parallel
= false;
823 region
->inner
->is_combined_parallel
= false;
828 region
->is_combined_parallel
= true;
829 region
->inner
->is_combined_parallel
= true;
830 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
835 /* Return true if EXPR is variable sized. */
838 is_variable_sized (const_tree expr
)
840 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
843 /* Return true if DECL is a reference type. */
846 is_reference (tree decl
)
848 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
851 /* Lookup variables in the decl or field splay trees. The "maybe" form
852 allows for the variable form to not have been entered, otherwise we
853 assert that the variable must have been entered. */
856 lookup_decl (tree var
, omp_context
*ctx
)
858 tree
*n
= ctx
->cb
.decl_map
->get (var
);
863 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
865 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
866 return n
? *n
: NULL_TREE
;
870 lookup_field (tree var
, omp_context
*ctx
)
873 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
874 return (tree
) n
->value
;
878 lookup_sfield (tree var
, omp_context
*ctx
)
881 n
= splay_tree_lookup (ctx
->sfield_map
882 ? ctx
->sfield_map
: ctx
->field_map
,
883 (splay_tree_key
) var
);
884 return (tree
) n
->value
;
888 maybe_lookup_field (tree var
, omp_context
*ctx
)
891 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
892 return n
? (tree
) n
->value
: NULL_TREE
;
895 /* Return true if DECL should be copied by pointer. SHARED_CTX is
896 the parallel context if DECL is to be shared. */
899 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
901 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
904 /* We can only use copy-in/copy-out semantics for shared variables
905 when we know the value is not accessible from an outer scope. */
908 /* ??? Trivially accessible from anywhere. But why would we even
909 be passing an address in this case? Should we simply assert
910 this to be false, or should we have a cleanup pass that removes
911 these from the list of mappings? */
912 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
915 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
916 without analyzing the expression whether or not its location
917 is accessible to anyone else. In the case of nested parallel
918 regions it certainly may be. */
919 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
922 /* Do not use copy-in/copy-out for variables that have their
924 if (TREE_ADDRESSABLE (decl
))
927 /* lower_send_shared_vars only uses copy-in, but not copy-out
929 if (TREE_READONLY (decl
)
930 || ((TREE_CODE (decl
) == RESULT_DECL
931 || TREE_CODE (decl
) == PARM_DECL
)
932 && DECL_BY_REFERENCE (decl
)))
935 /* Disallow copy-in/out in nested parallel if
936 decl is shared in outer parallel, otherwise
937 each thread could store the shared variable
938 in its own copy-in location, making the
939 variable no longer really shared. */
940 if (shared_ctx
->is_nested
)
944 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
945 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
952 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
953 c
; c
= OMP_CLAUSE_CHAIN (c
))
954 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
955 && OMP_CLAUSE_DECL (c
) == decl
)
959 goto maybe_mark_addressable_and_ret
;
963 /* For tasks avoid using copy-in/out. As tasks can be
964 deferred or executed in different thread, when GOMP_task
965 returns, the task hasn't necessarily terminated. */
966 if (is_task_ctx (shared_ctx
))
969 maybe_mark_addressable_and_ret
:
970 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
971 if (is_gimple_reg (outer
))
973 /* Taking address of OUTER in lower_send_shared_vars
974 might need regimplification of everything that uses the
976 if (!task_shared_vars
)
977 task_shared_vars
= BITMAP_ALLOC (NULL
);
978 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
979 TREE_ADDRESSABLE (outer
) = 1;
988 /* Construct a new automatic decl similar to VAR. */
991 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
993 tree copy
= copy_var_decl (var
, name
, type
);
995 DECL_CONTEXT (copy
) = current_function_decl
;
996 DECL_CHAIN (copy
) = ctx
->block_vars
;
997 ctx
->block_vars
= copy
;
1003 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
1005 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
1008 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1011 omp_build_component_ref (tree obj
, tree field
)
1013 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
1014 if (TREE_THIS_VOLATILE (field
))
1015 TREE_THIS_VOLATILE (ret
) |= 1;
1016 if (TREE_READONLY (field
))
1017 TREE_READONLY (ret
) |= 1;
1021 /* Build tree nodes to access the field for VAR on the receiver side. */
1024 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1026 tree x
, field
= lookup_field (var
, ctx
);
1028 /* If the receiver record type was remapped in the child function,
1029 remap the field into the new record type. */
1030 x
= maybe_lookup_field (field
, ctx
);
1034 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1035 x
= omp_build_component_ref (x
, field
);
1037 x
= build_simple_mem_ref (x
);
1042 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1043 of a parallel, this is a component reference; for workshare constructs
1044 this is some variable. */
1047 build_outer_var_ref (tree var
, omp_context
*ctx
)
1051 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1053 else if (is_variable_sized (var
))
1055 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1056 x
= build_outer_var_ref (x
, ctx
);
1057 x
= build_simple_mem_ref (x
);
1059 else if (is_taskreg_ctx (ctx
))
1061 bool by_ref
= use_pointer_for_field (var
, NULL
);
1062 x
= build_receiver_ref (var
, by_ref
, ctx
);
1064 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1065 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1067 /* #pragma omp simd isn't a worksharing construct, and can reference even
1068 private vars in its linear etc. clauses. */
1070 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1071 x
= lookup_decl (var
, ctx
->outer
);
1072 else if (ctx
->outer
)
1073 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1077 else if (ctx
->outer
)
1078 x
= lookup_decl (var
, ctx
->outer
);
1079 else if (is_reference (var
))
1080 /* This can happen with orphaned constructs. If var is reference, it is
1081 possible it is shared and as such valid. */
1086 if (is_reference (var
))
1087 x
= build_simple_mem_ref (x
);
1092 /* Build tree nodes to access the field for VAR on the sender side. */
1095 build_sender_ref (tree var
, omp_context
*ctx
)
1097 tree field
= lookup_sfield (var
, ctx
);
1098 return omp_build_component_ref (ctx
->sender_decl
, field
);
1101 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1104 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1106 tree field
, type
, sfield
= NULL_TREE
;
1108 gcc_assert ((mask
& 1) == 0
1109 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1110 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1111 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1113 type
= TREE_TYPE (var
);
1116 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1117 type
= build_pointer_type (build_pointer_type (type
));
1120 type
= build_pointer_type (type
);
1121 else if ((mask
& 3) == 1 && is_reference (var
))
1122 type
= TREE_TYPE (type
);
1124 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1125 FIELD_DECL
, DECL_NAME (var
), type
);
1127 /* Remember what variable this field was created for. This does have a
1128 side effect of making dwarf2out ignore this member, so for helpful
1129 debugging we clear it later in delete_omp_context. */
1130 DECL_ABSTRACT_ORIGIN (field
) = var
;
1131 if (type
== TREE_TYPE (var
))
1133 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1134 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1135 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1138 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1140 if ((mask
& 3) == 3)
1142 insert_field_into_struct (ctx
->record_type
, field
);
1143 if (ctx
->srecord_type
)
1145 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1146 FIELD_DECL
, DECL_NAME (var
), type
);
1147 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1148 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1149 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1150 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1151 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1156 if (ctx
->srecord_type
== NULL_TREE
)
1160 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1161 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1162 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1164 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1165 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1166 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1167 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1168 splay_tree_insert (ctx
->sfield_map
,
1169 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1170 (splay_tree_value
) sfield
);
1174 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1175 : ctx
->srecord_type
, field
);
1179 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1180 (splay_tree_value
) field
);
1181 if ((mask
& 2) && ctx
->sfield_map
)
1182 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1183 (splay_tree_value
) sfield
);
1187 install_var_local (tree var
, omp_context
*ctx
)
1189 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1190 insert_decl_map (&ctx
->cb
, var
, new_var
);
1194 /* Adjust the replacement for DECL in CTX for the new context. This means
1195 copying the DECL_VALUE_EXPR, and fixing up the type. */
1198 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1200 tree new_decl
, size
;
1202 new_decl
= lookup_decl (decl
, ctx
);
1204 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1206 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1207 && DECL_HAS_VALUE_EXPR_P (decl
))
1209 tree ve
= DECL_VALUE_EXPR (decl
);
1210 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1211 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1212 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1215 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1217 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1218 if (size
== error_mark_node
)
1219 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1220 DECL_SIZE (new_decl
) = size
;
1222 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1223 if (size
== error_mark_node
)
1224 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1225 DECL_SIZE_UNIT (new_decl
) = size
;
1229 /* The callback for remap_decl. Search all containing contexts for a
1230 mapping of the variable; this avoids having to duplicate the splay
1231 tree ahead of time. We know a mapping doesn't already exist in the
1232 given context. Create new mappings to implement default semantics. */
1235 omp_copy_decl (tree var
, copy_body_data
*cb
)
1237 omp_context
*ctx
= (omp_context
*) cb
;
1240 if (TREE_CODE (var
) == LABEL_DECL
)
1242 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1243 DECL_CONTEXT (new_var
) = current_function_decl
;
1244 insert_decl_map (&ctx
->cb
, var
, new_var
);
1248 while (!is_taskreg_ctx (ctx
))
1253 new_var
= maybe_lookup_decl (var
, ctx
);
1258 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1261 return error_mark_node
;
1265 /* Debugging dumps for parallel regions. */
1266 void dump_omp_region (FILE *, struct omp_region
*, int);
1267 void debug_omp_region (struct omp_region
*);
1268 void debug_all_omp_regions (void);
1270 /* Dump the parallel region tree rooted at REGION. */
1273 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1275 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1276 gimple_code_name
[region
->type
]);
1279 dump_omp_region (file
, region
->inner
, indent
+ 4);
1283 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1284 region
->cont
->index
);
1288 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1289 region
->exit
->index
);
1291 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1294 dump_omp_region (file
, region
->next
, indent
);
1298 debug_omp_region (struct omp_region
*region
)
1300 dump_omp_region (stderr
, region
, 0);
1304 debug_all_omp_regions (void)
1306 dump_omp_region (stderr
, root_omp_region
, 0);
1310 /* Create a new parallel region starting at STMT inside region PARENT. */
1312 static struct omp_region
*
1313 new_omp_region (basic_block bb
, enum gimple_code type
,
1314 struct omp_region
*parent
)
1316 struct omp_region
*region
= XCNEW (struct omp_region
);
1318 region
->outer
= parent
;
1320 region
->type
= type
;
1324 /* This is a nested region. Add it to the list of inner
1325 regions in PARENT. */
1326 region
->next
= parent
->inner
;
1327 parent
->inner
= region
;
1331 /* This is a toplevel region. Add it to the list of toplevel
1332 regions in ROOT_OMP_REGION. */
1333 region
->next
= root_omp_region
;
1334 root_omp_region
= region
;
1340 /* Release the memory associated with the region tree rooted at REGION. */
1343 free_omp_region_1 (struct omp_region
*region
)
1345 struct omp_region
*i
, *n
;
1347 for (i
= region
->inner
; i
; i
= n
)
1350 free_omp_region_1 (i
);
1356 /* Release the memory for the entire omp region tree. */
1359 free_omp_regions (void)
1361 struct omp_region
*r
, *n
;
1362 for (r
= root_omp_region
; r
; r
= n
)
1365 free_omp_region_1 (r
);
1367 root_omp_region
= NULL
;
1371 /* Create a new context, with OUTER_CTX being the surrounding context. */
1373 static omp_context
*
1374 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1376 omp_context
*ctx
= XCNEW (omp_context
);
1378 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1379 (splay_tree_value
) ctx
);
1384 ctx
->outer
= outer_ctx
;
1385 ctx
->cb
= outer_ctx
->cb
;
1386 ctx
->cb
.block
= NULL
;
1387 ctx
->depth
= outer_ctx
->depth
+ 1;
1391 ctx
->cb
.src_fn
= current_function_decl
;
1392 ctx
->cb
.dst_fn
= current_function_decl
;
1393 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1394 gcc_checking_assert (ctx
->cb
.src_node
);
1395 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1396 ctx
->cb
.src_cfun
= cfun
;
1397 ctx
->cb
.copy_decl
= omp_copy_decl
;
1398 ctx
->cb
.eh_lp_nr
= 0;
1399 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1403 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1408 static gimple_seq
maybe_catch_exception (gimple_seq
);
1410 /* Finalize task copyfn. */
1413 finalize_task_copyfn (gomp_task
*task_stmt
)
1415 struct function
*child_cfun
;
1417 gimple_seq seq
= NULL
, new_seq
;
1420 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1421 if (child_fn
== NULL_TREE
)
1424 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1425 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1427 push_cfun (child_cfun
);
1428 bind
= gimplify_body (child_fn
, false);
1429 gimple_seq_add_stmt (&seq
, bind
);
1430 new_seq
= maybe_catch_exception (seq
);
1433 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1435 gimple_seq_add_stmt (&seq
, bind
);
1437 gimple_set_body (child_fn
, seq
);
1440 /* Inform the callgraph about the new function. */
1441 cgraph_node::add_new_function (child_fn
, false);
1444 /* Destroy a omp_context data structures. Called through the splay tree
1445 value delete callback. */
1448 delete_omp_context (splay_tree_value value
)
1450 omp_context
*ctx
= (omp_context
*) value
;
1452 delete ctx
->cb
.decl_map
;
1455 splay_tree_delete (ctx
->field_map
);
1456 if (ctx
->sfield_map
)
1457 splay_tree_delete (ctx
->sfield_map
);
1459 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1460 it produces corrupt debug information. */
1461 if (ctx
->record_type
)
1464 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1465 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1467 if (ctx
->srecord_type
)
1470 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1471 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1474 if (is_task_ctx (ctx
))
1475 finalize_task_copyfn (as_a
<gomp_task
*> (ctx
->stmt
));
1480 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1484 fixup_child_record_type (omp_context
*ctx
)
1486 tree f
, type
= ctx
->record_type
;
1488 /* ??? It isn't sufficient to just call remap_type here, because
1489 variably_modified_type_p doesn't work the way we expect for
1490 record types. Testing each field for whether it needs remapping
1491 and creating a new record by hand works, however. */
1492 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1493 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1497 tree name
, new_fields
= NULL
;
1499 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1500 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1501 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1502 TYPE_DECL
, name
, type
);
1503 TYPE_NAME (type
) = name
;
1505 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1507 tree new_f
= copy_node (f
);
1508 DECL_CONTEXT (new_f
) = type
;
1509 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1510 DECL_CHAIN (new_f
) = new_fields
;
1511 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1512 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1514 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1518 /* Arrange to be able to look up the receiver field
1519 given the sender field. */
1520 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1521 (splay_tree_value
) new_f
);
1523 TYPE_FIELDS (type
) = nreverse (new_fields
);
1527 TREE_TYPE (ctx
->receiver_decl
)
1528 = build_qualified_type (build_reference_type (type
), TYPE_QUAL_RESTRICT
);
1531 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1532 specified by CLAUSES. */
1535 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1538 bool scan_array_reductions
= false;
1540 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1544 switch (OMP_CLAUSE_CODE (c
))
1546 case OMP_CLAUSE_PRIVATE
:
1547 decl
= OMP_CLAUSE_DECL (c
);
1548 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1550 else if (!is_variable_sized (decl
))
1551 install_var_local (decl
, ctx
);
1554 case OMP_CLAUSE_SHARED
:
1555 decl
= OMP_CLAUSE_DECL (c
);
1556 /* Ignore shared directives in teams construct. */
1557 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1559 /* Global variables don't need to be copied,
1560 the receiver side will use them directly. */
1561 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1562 if (is_global_var (odecl
))
1564 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1567 gcc_assert (is_taskreg_ctx (ctx
));
1568 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1569 || !is_variable_sized (decl
));
1570 /* Global variables don't need to be copied,
1571 the receiver side will use them directly. */
1572 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1574 by_ref
= use_pointer_for_field (decl
, ctx
);
1575 if (! TREE_READONLY (decl
)
1576 || TREE_ADDRESSABLE (decl
)
1578 || is_reference (decl
))
1580 install_var_field (decl
, by_ref
, 3, ctx
);
1581 install_var_local (decl
, ctx
);
1584 /* We don't need to copy const scalar vars back. */
1585 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1588 case OMP_CLAUSE_LASTPRIVATE
:
1589 /* Let the corresponding firstprivate clause create
1591 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1595 case OMP_CLAUSE_FIRSTPRIVATE
:
1596 case OMP_CLAUSE_REDUCTION
:
1597 case OMP_CLAUSE_LINEAR
:
1598 decl
= OMP_CLAUSE_DECL (c
);
1600 if (is_variable_sized (decl
))
1602 if (is_task_ctx (ctx
))
1603 install_var_field (decl
, false, 1, ctx
);
1606 else if (is_taskreg_ctx (ctx
))
1609 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1610 by_ref
= use_pointer_for_field (decl
, NULL
);
1612 if (is_task_ctx (ctx
)
1613 && (global
|| by_ref
|| is_reference (decl
)))
1615 install_var_field (decl
, false, 1, ctx
);
1617 install_var_field (decl
, by_ref
, 2, ctx
);
1620 install_var_field (decl
, by_ref
, 3, ctx
);
1622 install_var_local (decl
, ctx
);
1625 case OMP_CLAUSE__LOOPTEMP_
:
1626 gcc_assert (is_parallel_ctx (ctx
));
1627 decl
= OMP_CLAUSE_DECL (c
);
1628 install_var_field (decl
, false, 3, ctx
);
1629 install_var_local (decl
, ctx
);
1632 case OMP_CLAUSE_COPYPRIVATE
:
1633 case OMP_CLAUSE_COPYIN
:
1634 decl
= OMP_CLAUSE_DECL (c
);
1635 by_ref
= use_pointer_for_field (decl
, NULL
);
1636 install_var_field (decl
, by_ref
, 3, ctx
);
1639 case OMP_CLAUSE_DEFAULT
:
1640 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1643 case OMP_CLAUSE_FINAL
:
1645 case OMP_CLAUSE_NUM_THREADS
:
1646 case OMP_CLAUSE_NUM_TEAMS
:
1647 case OMP_CLAUSE_THREAD_LIMIT
:
1648 case OMP_CLAUSE_DEVICE
:
1649 case OMP_CLAUSE_SCHEDULE
:
1650 case OMP_CLAUSE_DIST_SCHEDULE
:
1651 case OMP_CLAUSE_DEPEND
:
1652 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1654 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1658 case OMP_CLAUSE_FROM
:
1659 case OMP_CLAUSE_MAP
:
1661 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1662 decl
= OMP_CLAUSE_DECL (c
);
1663 /* Global variables with "omp declare target" attribute
1664 don't need to be copied, the receiver side will use them
1666 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1668 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1669 && varpool_node::get_create (decl
)->offloadable
)
1671 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1672 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
)
1674 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1675 #pragma omp target data, there is nothing to map for
1677 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
1678 && !POINTER_TYPE_P (TREE_TYPE (decl
)))
1683 if (DECL_SIZE (decl
)
1684 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1686 tree decl2
= DECL_VALUE_EXPR (decl
);
1687 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1688 decl2
= TREE_OPERAND (decl2
, 0);
1689 gcc_assert (DECL_P (decl2
));
1690 install_var_field (decl2
, true, 3, ctx
);
1691 install_var_local (decl2
, ctx
);
1692 install_var_local (decl
, ctx
);
1696 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1697 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1698 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1699 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1700 install_var_field (decl
, true, 7, ctx
);
1702 install_var_field (decl
, true, 3, ctx
);
1703 if (gimple_omp_target_kind (ctx
->stmt
)
1704 == GF_OMP_TARGET_KIND_REGION
)
1705 install_var_local (decl
, ctx
);
1710 tree base
= get_base_address (decl
);
1711 tree nc
= OMP_CLAUSE_CHAIN (c
);
1714 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1715 && OMP_CLAUSE_DECL (nc
) == base
1716 && OMP_CLAUSE_MAP_KIND (nc
) == OMP_CLAUSE_MAP_POINTER
1717 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1719 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1720 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1726 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1727 decl
= OMP_CLAUSE_DECL (c
);
1729 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1730 (splay_tree_key
) decl
));
1732 = build_decl (OMP_CLAUSE_LOCATION (c
),
1733 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1734 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1735 insert_field_into_struct (ctx
->record_type
, field
);
1736 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1737 (splay_tree_value
) field
);
1742 case OMP_CLAUSE_NOWAIT
:
1743 case OMP_CLAUSE_ORDERED
:
1744 case OMP_CLAUSE_COLLAPSE
:
1745 case OMP_CLAUSE_UNTIED
:
1746 case OMP_CLAUSE_MERGEABLE
:
1747 case OMP_CLAUSE_PROC_BIND
:
1748 case OMP_CLAUSE_SAFELEN
:
1751 case OMP_CLAUSE_ALIGNED
:
1752 decl
= OMP_CLAUSE_DECL (c
);
1753 if (is_global_var (decl
)
1754 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1755 install_var_local (decl
, ctx
);
1763 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1765 switch (OMP_CLAUSE_CODE (c
))
1767 case OMP_CLAUSE_LASTPRIVATE
:
1768 /* Let the corresponding firstprivate clause create
1770 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1771 scan_array_reductions
= true;
1772 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1776 case OMP_CLAUSE_PRIVATE
:
1777 case OMP_CLAUSE_FIRSTPRIVATE
:
1778 case OMP_CLAUSE_REDUCTION
:
1779 case OMP_CLAUSE_LINEAR
:
1780 decl
= OMP_CLAUSE_DECL (c
);
1781 if (is_variable_sized (decl
))
1782 install_var_local (decl
, ctx
);
1783 fixup_remapped_decl (decl
, ctx
,
1784 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1785 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1786 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1787 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1788 scan_array_reductions
= true;
1789 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1790 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1791 scan_array_reductions
= true;
1794 case OMP_CLAUSE_SHARED
:
1795 /* Ignore shared directives in teams construct. */
1796 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1798 decl
= OMP_CLAUSE_DECL (c
);
1799 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1800 fixup_remapped_decl (decl
, ctx
, false);
1803 case OMP_CLAUSE_MAP
:
1804 if (gimple_omp_target_kind (ctx
->stmt
) == GF_OMP_TARGET_KIND_DATA
)
1806 decl
= OMP_CLAUSE_DECL (c
);
1808 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1809 && varpool_node::get_create (decl
)->offloadable
)
1813 if (OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
1814 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1815 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1817 tree new_decl
= lookup_decl (decl
, ctx
);
1818 TREE_TYPE (new_decl
)
1819 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1821 else if (DECL_SIZE (decl
)
1822 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1824 tree decl2
= DECL_VALUE_EXPR (decl
);
1825 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1826 decl2
= TREE_OPERAND (decl2
, 0);
1827 gcc_assert (DECL_P (decl2
));
1828 fixup_remapped_decl (decl2
, ctx
, false);
1829 fixup_remapped_decl (decl
, ctx
, true);
1832 fixup_remapped_decl (decl
, ctx
, false);
1836 case OMP_CLAUSE_COPYPRIVATE
:
1837 case OMP_CLAUSE_COPYIN
:
1838 case OMP_CLAUSE_DEFAULT
:
1840 case OMP_CLAUSE_NUM_THREADS
:
1841 case OMP_CLAUSE_NUM_TEAMS
:
1842 case OMP_CLAUSE_THREAD_LIMIT
:
1843 case OMP_CLAUSE_DEVICE
:
1844 case OMP_CLAUSE_SCHEDULE
:
1845 case OMP_CLAUSE_DIST_SCHEDULE
:
1846 case OMP_CLAUSE_NOWAIT
:
1847 case OMP_CLAUSE_ORDERED
:
1848 case OMP_CLAUSE_COLLAPSE
:
1849 case OMP_CLAUSE_UNTIED
:
1850 case OMP_CLAUSE_FINAL
:
1851 case OMP_CLAUSE_MERGEABLE
:
1852 case OMP_CLAUSE_PROC_BIND
:
1853 case OMP_CLAUSE_SAFELEN
:
1854 case OMP_CLAUSE_ALIGNED
:
1855 case OMP_CLAUSE_DEPEND
:
1856 case OMP_CLAUSE__LOOPTEMP_
:
1858 case OMP_CLAUSE_FROM
:
1859 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1867 if (scan_array_reductions
)
1868 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1869 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1870 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1872 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
1873 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
1875 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
1876 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1877 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
1878 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1879 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1880 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
1883 /* Create a new name for omp child function. Returns an identifier. If
1884 IS_CILK_FOR is true then the suffix for the child function is
1888 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
1891 return clone_function_name (current_function_decl
, "_cilk_for_fn");
1892 return clone_function_name (current_function_decl
,
1893 task_copy
? "_omp_cpyfn" : "_omp_fn");
1896 /* Returns the type of the induction variable for the child function for
1897 _Cilk_for and the types for _high and _low variables based on TYPE. */
1900 cilk_for_check_loop_diff_type (tree type
)
1902 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
1904 if (TYPE_UNSIGNED (type
))
1905 return uint32_type_node
;
1907 return integer_type_node
;
1911 if (TYPE_UNSIGNED (type
))
1912 return uint64_type_node
;
1914 return long_long_integer_type_node
;
1918 /* Build a decl for the omp child function. It'll not contain a body
1919 yet, just the bare decl. */
1922 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
1924 tree decl
, type
, name
, t
;
1927 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
1928 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
1929 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
1930 tree cilk_var_type
= NULL_TREE
;
1932 name
= create_omp_child_function_name (task_copy
,
1933 cilk_for_count
!= NULL_TREE
);
1935 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1936 ptr_type_node
, NULL_TREE
);
1937 else if (cilk_for_count
)
1939 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
1940 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
1941 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1942 cilk_var_type
, cilk_var_type
, NULL_TREE
);
1945 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
1947 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
1950 ctx
->cb
.dst_fn
= decl
;
1952 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
1954 TREE_STATIC (decl
) = 1;
1955 TREE_USED (decl
) = 1;
1956 DECL_ARTIFICIAL (decl
) = 1;
1957 DECL_IGNORED_P (decl
) = 0;
1958 TREE_PUBLIC (decl
) = 0;
1959 DECL_UNINLINABLE (decl
) = 1;
1960 DECL_EXTERNAL (decl
) = 0;
1961 DECL_CONTEXT (decl
) = NULL_TREE
;
1962 DECL_INITIAL (decl
) = make_node (BLOCK
);
1963 if (cgraph_node::get (current_function_decl
)->offloadable
)
1964 cgraph_node::get_create (decl
)->offloadable
= 1;
1968 for (octx
= ctx
; octx
; octx
= octx
->outer
)
1969 if (is_targetreg_ctx (octx
))
1971 cgraph_node::get_create (decl
)->offloadable
= 1;
1972 #ifdef ENABLE_OFFLOADING
1973 g
->have_offload
= true;
1979 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1980 RESULT_DECL
, NULL_TREE
, void_type_node
);
1981 DECL_ARTIFICIAL (t
) = 1;
1982 DECL_IGNORED_P (t
) = 1;
1983 DECL_CONTEXT (t
) = decl
;
1984 DECL_RESULT (decl
) = t
;
1986 /* _Cilk_for's child function requires two extra parameters called
1987 __low and __high that are set the by Cilk runtime when it calls this
1991 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1992 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
1993 DECL_ARTIFICIAL (t
) = 1;
1994 DECL_NAMELESS (t
) = 1;
1995 DECL_ARG_TYPE (t
) = ptr_type_node
;
1996 DECL_CONTEXT (t
) = current_function_decl
;
1998 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1999 DECL_ARGUMENTS (decl
) = t
;
2001 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2002 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
2003 DECL_ARTIFICIAL (t
) = 1;
2004 DECL_NAMELESS (t
) = 1;
2005 DECL_ARG_TYPE (t
) = ptr_type_node
;
2006 DECL_CONTEXT (t
) = current_function_decl
;
2008 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2009 DECL_ARGUMENTS (decl
) = t
;
2012 tree data_name
= get_identifier (".omp_data_i");
2013 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
2015 DECL_ARTIFICIAL (t
) = 1;
2016 DECL_NAMELESS (t
) = 1;
2017 DECL_ARG_TYPE (t
) = ptr_type_node
;
2018 DECL_CONTEXT (t
) = current_function_decl
;
2021 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2022 DECL_ARGUMENTS (decl
) = t
;
2024 ctx
->receiver_decl
= t
;
2027 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2028 PARM_DECL
, get_identifier (".omp_data_o"),
2030 DECL_ARTIFICIAL (t
) = 1;
2031 DECL_NAMELESS (t
) = 1;
2032 DECL_ARG_TYPE (t
) = ptr_type_node
;
2033 DECL_CONTEXT (t
) = current_function_decl
;
2035 TREE_ADDRESSABLE (t
) = 1;
2036 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2037 DECL_ARGUMENTS (decl
) = t
;
2040 /* Allocate memory for the function structure. The call to
2041 allocate_struct_function clobbers CFUN, so we need to restore
2043 push_struct_function (decl
);
2044 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2048 /* Callback for walk_gimple_seq. Check if combined parallel
2049 contains gimple_omp_for_combined_into_p OMP_FOR. */
2052 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2053 bool *handled_ops_p
,
2054 struct walk_stmt_info
*wi
)
2056 gimple stmt
= gsi_stmt (*gsi_p
);
2058 *handled_ops_p
= true;
2059 switch (gimple_code (stmt
))
2063 case GIMPLE_OMP_FOR
:
2064 if (gimple_omp_for_combined_into_p (stmt
)
2065 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
2068 return integer_zero_node
;
2077 /* Scan an OpenMP parallel directive. */
2080 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2084 gomp_parallel
*stmt
= as_a
<gomp_parallel
*> (gsi_stmt (*gsi
));
2086 /* Ignore parallel directives with empty bodies, unless there
2087 are copyin clauses. */
2089 && empty_body_p (gimple_omp_body (stmt
))
2090 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2091 OMP_CLAUSE_COPYIN
) == NULL
)
2093 gsi_replace (gsi
, gimple_build_nop (), false);
2097 if (gimple_omp_parallel_combined_p (stmt
))
2099 struct walk_stmt_info wi
;
2101 memset (&wi
, 0, sizeof (wi
));
2103 walk_gimple_seq (gimple_omp_body (stmt
),
2104 find_combined_for
, NULL
, &wi
);
2107 gomp_for
*for_stmt
= as_a
<gomp_for
*> ((gimple
) wi
.info
);
2108 struct omp_for_data fd
;
2109 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2110 /* We need two temporaries with fd.loop.v type (istart/iend)
2111 and then (fd.collapse - 1) temporaries with the same
2112 type for count2 ... countN-1 vars if not constant. */
2113 size_t count
= 2, i
;
2114 tree type
= fd
.iter_type
;
2116 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2117 count
+= fd
.collapse
- 1;
2118 for (i
= 0; i
< count
; i
++)
2120 tree temp
= create_tmp_var (type
);
2121 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2122 OMP_CLAUSE__LOOPTEMP_
);
2123 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2124 OMP_CLAUSE_DECL (c
) = temp
;
2125 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2126 gimple_omp_parallel_set_clauses (stmt
, c
);
2131 ctx
= new_omp_context (stmt
, outer_ctx
);
2132 taskreg_contexts
.safe_push (ctx
);
2133 if (taskreg_nesting_level
> 1)
2134 ctx
->is_nested
= true;
2135 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2136 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2137 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2138 name
= create_tmp_var_name (".omp_data_s");
2139 name
= build_decl (gimple_location (stmt
),
2140 TYPE_DECL
, name
, ctx
->record_type
);
2141 DECL_ARTIFICIAL (name
) = 1;
2142 DECL_NAMELESS (name
) = 1;
2143 TYPE_NAME (ctx
->record_type
) = name
;
2144 create_omp_child_function (ctx
, false);
2145 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2147 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2148 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2150 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2151 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2154 /* Scan an OpenMP task directive. */
2157 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2161 gomp_task
*stmt
= as_a
<gomp_task
*> (gsi_stmt (*gsi
));
2163 /* Ignore task directives with empty bodies. */
2165 && empty_body_p (gimple_omp_body (stmt
)))
2167 gsi_replace (gsi
, gimple_build_nop (), false);
2171 ctx
= new_omp_context (stmt
, outer_ctx
);
2172 taskreg_contexts
.safe_push (ctx
);
2173 if (taskreg_nesting_level
> 1)
2174 ctx
->is_nested
= true;
2175 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2176 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2177 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2178 name
= create_tmp_var_name (".omp_data_s");
2179 name
= build_decl (gimple_location (stmt
),
2180 TYPE_DECL
, name
, ctx
->record_type
);
2181 DECL_ARTIFICIAL (name
) = 1;
2182 DECL_NAMELESS (name
) = 1;
2183 TYPE_NAME (ctx
->record_type
) = name
;
2184 create_omp_child_function (ctx
, false);
2185 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2187 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2189 if (ctx
->srecord_type
)
2191 name
= create_tmp_var_name (".omp_data_a");
2192 name
= build_decl (gimple_location (stmt
),
2193 TYPE_DECL
, name
, ctx
->srecord_type
);
2194 DECL_ARTIFICIAL (name
) = 1;
2195 DECL_NAMELESS (name
) = 1;
2196 TYPE_NAME (ctx
->srecord_type
) = name
;
2197 create_omp_child_function (ctx
, true);
2200 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2202 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2204 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2205 t
= build_int_cst (long_integer_type_node
, 0);
2206 gimple_omp_task_set_arg_size (stmt
, t
);
2207 t
= build_int_cst (long_integer_type_node
, 1);
2208 gimple_omp_task_set_arg_align (stmt
, t
);
2213 /* If any decls have been made addressable during scan_omp,
2214 adjust their fields if needed, and layout record types
2215 of parallel/task constructs. */
2218 finish_taskreg_scan (omp_context
*ctx
)
2220 if (ctx
->record_type
== NULL_TREE
)
2223 /* If any task_shared_vars were needed, verify all
2224 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2225 statements if use_pointer_for_field hasn't changed
2226 because of that. If it did, update field types now. */
2227 if (task_shared_vars
)
2231 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2232 c
; c
= OMP_CLAUSE_CHAIN (c
))
2233 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
2235 tree decl
= OMP_CLAUSE_DECL (c
);
2237 /* Global variables don't need to be copied,
2238 the receiver side will use them directly. */
2239 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2241 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2242 || !use_pointer_for_field (decl
, ctx
))
2244 tree field
= lookup_field (decl
, ctx
);
2245 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2246 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2248 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2249 TREE_THIS_VOLATILE (field
) = 0;
2250 DECL_USER_ALIGN (field
) = 0;
2251 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2252 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2253 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2254 if (ctx
->srecord_type
)
2256 tree sfield
= lookup_sfield (decl
, ctx
);
2257 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2258 TREE_THIS_VOLATILE (sfield
) = 0;
2259 DECL_USER_ALIGN (sfield
) = 0;
2260 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2261 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2262 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2267 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2269 layout_type (ctx
->record_type
);
2270 fixup_child_record_type (ctx
);
2274 location_t loc
= gimple_location (ctx
->stmt
);
2275 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2276 /* Move VLA fields to the end. */
2277 p
= &TYPE_FIELDS (ctx
->record_type
);
2279 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2280 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2283 *p
= TREE_CHAIN (*p
);
2284 TREE_CHAIN (*q
) = NULL_TREE
;
2285 q
= &TREE_CHAIN (*q
);
2288 p
= &DECL_CHAIN (*p
);
2290 layout_type (ctx
->record_type
);
2291 fixup_child_record_type (ctx
);
2292 if (ctx
->srecord_type
)
2293 layout_type (ctx
->srecord_type
);
2294 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2295 TYPE_SIZE_UNIT (ctx
->record_type
));
2296 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2297 t
= build_int_cst (long_integer_type_node
,
2298 TYPE_ALIGN_UNIT (ctx
->record_type
));
2299 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2304 /* Scan an OpenMP loop directive. */
2307 scan_omp_for (gomp_for
*stmt
, omp_context
*outer_ctx
)
2312 ctx
= new_omp_context (stmt
, outer_ctx
);
2314 scan_sharing_clauses (gimple_omp_for_clauses (stmt
), ctx
);
2316 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2317 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2319 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2320 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2321 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2322 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2324 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2327 /* Scan an OpenMP sections directive. */
2330 scan_omp_sections (gomp_sections
*stmt
, omp_context
*outer_ctx
)
2334 ctx
= new_omp_context (stmt
, outer_ctx
);
2335 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2336 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2339 /* Scan an OpenMP single directive. */
2342 scan_omp_single (gomp_single
*stmt
, omp_context
*outer_ctx
)
2347 ctx
= new_omp_context (stmt
, outer_ctx
);
2348 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2349 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2350 name
= create_tmp_var_name (".omp_copy_s");
2351 name
= build_decl (gimple_location (stmt
),
2352 TYPE_DECL
, name
, ctx
->record_type
);
2353 TYPE_NAME (ctx
->record_type
) = name
;
2355 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2356 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2358 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2359 ctx
->record_type
= NULL
;
2361 layout_type (ctx
->record_type
);
2364 /* Scan an OpenMP target{, data, update} directive. */
2367 scan_omp_target (gomp_target
*stmt
, omp_context
*outer_ctx
)
2371 int kind
= gimple_omp_target_kind (stmt
);
2373 ctx
= new_omp_context (stmt
, outer_ctx
);
2374 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2375 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2376 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2377 name
= create_tmp_var_name (".omp_data_t");
2378 name
= build_decl (gimple_location (stmt
),
2379 TYPE_DECL
, name
, ctx
->record_type
);
2380 DECL_ARTIFICIAL (name
) = 1;
2381 DECL_NAMELESS (name
) = 1;
2382 TYPE_NAME (ctx
->record_type
) = name
;
2383 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2385 create_omp_child_function (ctx
, false);
2386 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2389 scan_sharing_clauses (gimple_omp_target_clauses (stmt
), ctx
);
2390 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2392 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2393 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2396 TYPE_FIELDS (ctx
->record_type
)
2397 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2398 #ifdef ENABLE_CHECKING
2400 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2401 for (field
= TYPE_FIELDS (ctx
->record_type
);
2403 field
= DECL_CHAIN (field
))
2404 gcc_assert (DECL_ALIGN (field
) == align
);
2406 layout_type (ctx
->record_type
);
2407 if (kind
== GF_OMP_TARGET_KIND_REGION
)
2408 fixup_child_record_type (ctx
);
2412 /* Scan an OpenMP teams directive. */
2415 scan_omp_teams (gomp_teams
*stmt
, omp_context
*outer_ctx
)
2417 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2418 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2419 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2422 /* Check OpenMP nesting restrictions. */
2424 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2428 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2429 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2431 error_at (gimple_location (stmt
),
2432 "OpenMP constructs may not be nested inside simd region");
2435 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2437 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2438 || (gimple_omp_for_kind (stmt
)
2439 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2440 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2442 error_at (gimple_location (stmt
),
2443 "only distribute or parallel constructs are allowed to "
2444 "be closely nested inside teams construct");
2449 switch (gimple_code (stmt
))
2451 case GIMPLE_OMP_FOR
:
2452 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2454 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2456 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2458 error_at (gimple_location (stmt
),
2459 "distribute construct must be closely nested inside "
2467 if (is_gimple_call (stmt
)
2468 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2469 == BUILT_IN_GOMP_CANCEL
2470 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2471 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2473 const char *bad
= NULL
;
2474 const char *kind
= NULL
;
2477 error_at (gimple_location (stmt
), "orphaned %qs construct",
2478 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2479 == BUILT_IN_GOMP_CANCEL
2480 ? "#pragma omp cancel"
2481 : "#pragma omp cancellation point");
2484 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2485 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2489 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2490 bad
= "#pragma omp parallel";
2491 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2492 == BUILT_IN_GOMP_CANCEL
2493 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2494 ctx
->cancellable
= true;
2498 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2499 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2500 bad
= "#pragma omp for";
2501 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2502 == BUILT_IN_GOMP_CANCEL
2503 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2505 ctx
->cancellable
= true;
2506 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2508 warning_at (gimple_location (stmt
), 0,
2509 "%<#pragma omp cancel for%> inside "
2510 "%<nowait%> for construct");
2511 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2512 OMP_CLAUSE_ORDERED
))
2513 warning_at (gimple_location (stmt
), 0,
2514 "%<#pragma omp cancel for%> inside "
2515 "%<ordered%> for construct");
2520 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2521 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2522 bad
= "#pragma omp sections";
2523 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2524 == BUILT_IN_GOMP_CANCEL
2525 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2527 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2529 ctx
->cancellable
= true;
2530 if (find_omp_clause (gimple_omp_sections_clauses
2533 warning_at (gimple_location (stmt
), 0,
2534 "%<#pragma omp cancel sections%> inside "
2535 "%<nowait%> sections construct");
2539 gcc_assert (ctx
->outer
2540 && gimple_code (ctx
->outer
->stmt
)
2541 == GIMPLE_OMP_SECTIONS
);
2542 ctx
->outer
->cancellable
= true;
2543 if (find_omp_clause (gimple_omp_sections_clauses
2546 warning_at (gimple_location (stmt
), 0,
2547 "%<#pragma omp cancel sections%> inside "
2548 "%<nowait%> sections construct");
2554 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2555 bad
= "#pragma omp task";
2557 ctx
->cancellable
= true;
2561 error_at (gimple_location (stmt
), "invalid arguments");
2566 error_at (gimple_location (stmt
),
2567 "%<%s %s%> construct not closely nested inside of %qs",
2568 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2569 == BUILT_IN_GOMP_CANCEL
2570 ? "#pragma omp cancel"
2571 : "#pragma omp cancellation point", kind
, bad
);
2576 case GIMPLE_OMP_SECTIONS
:
2577 case GIMPLE_OMP_SINGLE
:
2578 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2579 switch (gimple_code (ctx
->stmt
))
2581 case GIMPLE_OMP_FOR
:
2582 case GIMPLE_OMP_SECTIONS
:
2583 case GIMPLE_OMP_SINGLE
:
2584 case GIMPLE_OMP_ORDERED
:
2585 case GIMPLE_OMP_MASTER
:
2586 case GIMPLE_OMP_TASK
:
2587 case GIMPLE_OMP_CRITICAL
:
2588 if (is_gimple_call (stmt
))
2590 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2591 != BUILT_IN_GOMP_BARRIER
)
2593 error_at (gimple_location (stmt
),
2594 "barrier region may not be closely nested inside "
2595 "of work-sharing, critical, ordered, master or "
2596 "explicit task region");
2599 error_at (gimple_location (stmt
),
2600 "work-sharing region may not be closely nested inside "
2601 "of work-sharing, critical, ordered, master or explicit "
2604 case GIMPLE_OMP_PARALLEL
:
2610 case GIMPLE_OMP_MASTER
:
2611 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2612 switch (gimple_code (ctx
->stmt
))
2614 case GIMPLE_OMP_FOR
:
2615 case GIMPLE_OMP_SECTIONS
:
2616 case GIMPLE_OMP_SINGLE
:
2617 case GIMPLE_OMP_TASK
:
2618 error_at (gimple_location (stmt
),
2619 "master region may not be closely nested inside "
2620 "of work-sharing or explicit task region");
2622 case GIMPLE_OMP_PARALLEL
:
2628 case GIMPLE_OMP_ORDERED
:
2629 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2630 switch (gimple_code (ctx
->stmt
))
2632 case GIMPLE_OMP_CRITICAL
:
2633 case GIMPLE_OMP_TASK
:
2634 error_at (gimple_location (stmt
),
2635 "ordered region may not be closely nested inside "
2636 "of critical or explicit task region");
2638 case GIMPLE_OMP_FOR
:
2639 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2640 OMP_CLAUSE_ORDERED
) == NULL
)
2642 error_at (gimple_location (stmt
),
2643 "ordered region must be closely nested inside "
2644 "a loop region with an ordered clause");
2648 case GIMPLE_OMP_PARALLEL
:
2649 error_at (gimple_location (stmt
),
2650 "ordered region must be closely nested inside "
2651 "a loop region with an ordered clause");
2657 case GIMPLE_OMP_CRITICAL
:
2660 = gimple_omp_critical_name (as_a
<gomp_critical
*> (stmt
));
2661 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2662 if (gomp_critical
*other_crit
2663 = dyn_cast
<gomp_critical
*> (ctx
->stmt
))
2664 if (this_stmt_name
== gimple_omp_critical_name (other_crit
))
2666 error_at (gimple_location (stmt
),
2667 "critical region may not be nested inside a critical "
2668 "region with the same name");
2673 case GIMPLE_OMP_TEAMS
:
2675 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2676 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2678 error_at (gimple_location (stmt
),
2679 "teams construct not closely nested inside of target "
2684 case GIMPLE_OMP_TARGET
:
2685 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2686 if (is_targetreg_ctx (ctx
))
2689 switch (gimple_omp_target_kind (stmt
))
2691 case GF_OMP_TARGET_KIND_REGION
: name
= "target"; break;
2692 case GF_OMP_TARGET_KIND_DATA
: name
= "target data"; break;
2693 case GF_OMP_TARGET_KIND_UPDATE
: name
= "target update"; break;
2694 default: gcc_unreachable ();
2696 warning_at (gimple_location (stmt
), 0,
2697 "%s construct inside of target region", name
);
2707 /* Helper function scan_omp.
2709 Callback for walk_tree or operators in walk_gimple_stmt used to
2710 scan for OpenMP directives in TP. */
2713 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
2715 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
2716 omp_context
*ctx
= (omp_context
*) wi
->info
;
2719 switch (TREE_CODE (t
))
2726 *tp
= remap_decl (t
, &ctx
->cb
);
2730 if (ctx
&& TYPE_P (t
))
2731 *tp
= remap_type (t
, &ctx
->cb
);
2732 else if (!DECL_P (t
))
2737 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
2738 if (tem
!= TREE_TYPE (t
))
2740 if (TREE_CODE (t
) == INTEGER_CST
)
2741 *tp
= wide_int_to_tree (tem
, t
);
2743 TREE_TYPE (t
) = tem
;
2753 /* Return true if FNDECL is a setjmp or a longjmp. */
2756 setjmp_or_longjmp_p (const_tree fndecl
)
2758 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
2759 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
2760 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
2763 tree declname
= DECL_NAME (fndecl
);
2766 const char *name
= IDENTIFIER_POINTER (declname
);
2767 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
2771 /* Helper function for scan_omp.
2773 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2774 the current statement in GSI. */
2777 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
2778 struct walk_stmt_info
*wi
)
2780 gimple stmt
= gsi_stmt (*gsi
);
2781 omp_context
*ctx
= (omp_context
*) wi
->info
;
2783 if (gimple_has_location (stmt
))
2784 input_location
= gimple_location (stmt
);
2786 /* Check the OpenMP nesting restrictions. */
2787 bool remove
= false;
2788 if (is_gimple_omp (stmt
))
2789 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2790 else if (is_gimple_call (stmt
))
2792 tree fndecl
= gimple_call_fndecl (stmt
);
2795 if (setjmp_or_longjmp_p (fndecl
)
2797 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2798 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2801 error_at (gimple_location (stmt
),
2802 "setjmp/longjmp inside simd construct");
2804 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
2805 switch (DECL_FUNCTION_CODE (fndecl
))
2807 case BUILT_IN_GOMP_BARRIER
:
2808 case BUILT_IN_GOMP_CANCEL
:
2809 case BUILT_IN_GOMP_CANCELLATION_POINT
:
2810 case BUILT_IN_GOMP_TASKYIELD
:
2811 case BUILT_IN_GOMP_TASKWAIT
:
2812 case BUILT_IN_GOMP_TASKGROUP_START
:
2813 case BUILT_IN_GOMP_TASKGROUP_END
:
2814 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2823 stmt
= gimple_build_nop ();
2824 gsi_replace (gsi
, stmt
, false);
2827 *handled_ops_p
= true;
2829 switch (gimple_code (stmt
))
2831 case GIMPLE_OMP_PARALLEL
:
2832 taskreg_nesting_level
++;
2833 scan_omp_parallel (gsi
, ctx
);
2834 taskreg_nesting_level
--;
2837 case GIMPLE_OMP_TASK
:
2838 taskreg_nesting_level
++;
2839 scan_omp_task (gsi
, ctx
);
2840 taskreg_nesting_level
--;
2843 case GIMPLE_OMP_FOR
:
2844 scan_omp_for (as_a
<gomp_for
*> (stmt
), ctx
);
2847 case GIMPLE_OMP_SECTIONS
:
2848 scan_omp_sections (as_a
<gomp_sections
*> (stmt
), ctx
);
2851 case GIMPLE_OMP_SINGLE
:
2852 scan_omp_single (as_a
<gomp_single
*> (stmt
), ctx
);
2855 case GIMPLE_OMP_SECTION
:
2856 case GIMPLE_OMP_MASTER
:
2857 case GIMPLE_OMP_TASKGROUP
:
2858 case GIMPLE_OMP_ORDERED
:
2859 case GIMPLE_OMP_CRITICAL
:
2860 ctx
= new_omp_context (stmt
, ctx
);
2861 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2864 case GIMPLE_OMP_TARGET
:
2865 scan_omp_target (as_a
<gomp_target
*> (stmt
), ctx
);
2868 case GIMPLE_OMP_TEAMS
:
2869 scan_omp_teams (as_a
<gomp_teams
*> (stmt
), ctx
);
2876 *handled_ops_p
= false;
2878 for (var
= gimple_bind_vars (as_a
<gbind
*> (stmt
));
2880 var
= DECL_CHAIN (var
))
2881 insert_decl_map (&ctx
->cb
, var
, var
);
2885 *handled_ops_p
= false;
2893 /* Scan all the statements starting at the current statement. CTX
2894 contains context information about the OpenMP directives and
2895 clauses found during the scan. */
2898 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
2900 location_t saved_location
;
2901 struct walk_stmt_info wi
;
2903 memset (&wi
, 0, sizeof (wi
));
2905 wi
.want_locations
= true;
2907 saved_location
= input_location
;
2908 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
2909 input_location
= saved_location
;
2912 /* Re-gimplification and code generation routines. */
2914 /* Build a call to GOMP_barrier. */
2917 build_omp_barrier (tree lhs
)
2919 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
2920 : BUILT_IN_GOMP_BARRIER
);
2921 gcall
*g
= gimple_build_call (fndecl
, 0);
2923 gimple_call_set_lhs (g
, lhs
);
2927 /* If a context was created for STMT when it was scanned, return it. */
2929 static omp_context
*
2930 maybe_lookup_ctx (gimple stmt
)
2933 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
2934 return n
? (omp_context
*) n
->value
: NULL
;
2938 /* Find the mapping for DECL in CTX or the immediately enclosing
2939 context that has a mapping for DECL.
2941 If CTX is a nested parallel directive, we may have to use the decl
2942 mappings created in CTX's parent context. Suppose that we have the
2943 following parallel nesting (variable UIDs showed for clarity):
2946 #omp parallel shared(iD.1562) -> outer parallel
2947 iD.1562 = iD.1562 + 1;
2949 #omp parallel shared (iD.1562) -> inner parallel
2950 iD.1562 = iD.1562 - 1;
2952 Each parallel structure will create a distinct .omp_data_s structure
2953 for copying iD.1562 in/out of the directive:
2955 outer parallel .omp_data_s.1.i -> iD.1562
2956 inner parallel .omp_data_s.2.i -> iD.1562
2958 A shared variable mapping will produce a copy-out operation before
2959 the parallel directive and a copy-in operation after it. So, in
2960 this case we would have:
2963 .omp_data_o.1.i = iD.1562;
2964 #omp parallel shared(iD.1562) -> outer parallel
2965 .omp_data_i.1 = &.omp_data_o.1
2966 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2968 .omp_data_o.2.i = iD.1562; -> **
2969 #omp parallel shared(iD.1562) -> inner parallel
2970 .omp_data_i.2 = &.omp_data_o.2
2971 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2974 ** This is a problem. The symbol iD.1562 cannot be referenced
2975 inside the body of the outer parallel region. But since we are
2976 emitting this copy operation while expanding the inner parallel
2977 directive, we need to access the CTX structure of the outer
2978 parallel directive to get the correct mapping:
2980 .omp_data_o.2.i = .omp_data_i.1->i
2982 Since there may be other workshare or parallel directives enclosing
2983 the parallel directive, it may be necessary to walk up the context
2984 parent chain. This is not a problem in general because nested
2985 parallelism happens only rarely. */
2988 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2993 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2994 t
= maybe_lookup_decl (decl
, up
);
2996 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
2998 return t
? t
: decl
;
3002 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3003 in outer contexts. */
3006 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3011 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3012 t
= maybe_lookup_decl (decl
, up
);
3014 return t
? t
: decl
;
3018 /* Construct the initialization value for reduction CLAUSE. */
3021 omp_reduction_init (tree clause
, tree type
)
3023 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
3024 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
3031 case TRUTH_ORIF_EXPR
:
3032 case TRUTH_XOR_EXPR
:
3034 return build_zero_cst (type
);
3037 case TRUTH_AND_EXPR
:
3038 case TRUTH_ANDIF_EXPR
:
3040 return fold_convert_loc (loc
, type
, integer_one_node
);
3043 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3046 if (SCALAR_FLOAT_TYPE_P (type
))
3048 REAL_VALUE_TYPE max
, min
;
3049 if (HONOR_INFINITIES (type
))
3052 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3055 real_maxval (&min
, 1, TYPE_MODE (type
));
3056 return build_real (type
, min
);
3060 gcc_assert (INTEGRAL_TYPE_P (type
));
3061 return TYPE_MIN_VALUE (type
);
3065 if (SCALAR_FLOAT_TYPE_P (type
))
3067 REAL_VALUE_TYPE max
;
3068 if (HONOR_INFINITIES (type
))
3071 real_maxval (&max
, 0, TYPE_MODE (type
));
3072 return build_real (type
, max
);
3076 gcc_assert (INTEGRAL_TYPE_P (type
));
3077 return TYPE_MAX_VALUE (type
);
3085 /* Return alignment to be assumed for var in CLAUSE, which should be
3086 OMP_CLAUSE_ALIGNED. */
3089 omp_clause_aligned_alignment (tree clause
)
3091 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3092 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3094 /* Otherwise return implementation defined alignment. */
3095 unsigned int al
= 1;
3096 machine_mode mode
, vmode
;
3097 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3099 vs
= 1 << floor_log2 (vs
);
3100 static enum mode_class classes
[]
3101 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3102 for (int i
= 0; i
< 4; i
+= 2)
3103 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3105 mode
= GET_MODE_WIDER_MODE (mode
))
3107 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3108 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3111 && GET_MODE_SIZE (vmode
) < vs
3112 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3113 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3115 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3116 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3118 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3119 / GET_MODE_SIZE (mode
));
3120 if (TYPE_MODE (type
) != vmode
)
3122 if (TYPE_ALIGN_UNIT (type
) > al
)
3123 al
= TYPE_ALIGN_UNIT (type
);
3125 return build_int_cst (integer_type_node
, al
);
3128 /* Return maximum possible vectorization factor for the target. */
3135 || !flag_tree_loop_optimize
3136 || (!flag_tree_loop_vectorize
3137 && (global_options_set
.x_flag_tree_loop_vectorize
3138 || global_options_set
.x_flag_tree_vectorize
)))
3141 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3144 vs
= 1 << floor_log2 (vs
);
3147 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
3148 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
3149 return GET_MODE_NUNITS (vqimode
);
3153 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3157 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
3158 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
3162 max_vf
= omp_max_vf ();
3165 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3166 OMP_CLAUSE_SAFELEN
);
3167 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3169 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3171 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3175 idx
= create_tmp_var (unsigned_type_node
);
3176 lane
= create_tmp_var (unsigned_type_node
);
3182 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3183 tree avar
= create_tmp_var_raw (atype
);
3184 if (TREE_ADDRESSABLE (new_var
))
3185 TREE_ADDRESSABLE (avar
) = 1;
3186 DECL_ATTRIBUTES (avar
)
3187 = tree_cons (get_identifier ("omp simd array"), NULL
,
3188 DECL_ATTRIBUTES (avar
));
3189 gimple_add_tmp_var (avar
);
3190 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3191 NULL_TREE
, NULL_TREE
);
3192 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3193 NULL_TREE
, NULL_TREE
);
3194 if (DECL_P (new_var
))
3196 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3197 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3202 /* Helper function of lower_rec_input_clauses. For a reference
3203 in simd reduction, add an underlying variable it will reference. */
3206 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3208 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3209 if (TREE_CONSTANT (z
))
3211 const char *name
= NULL
;
3212 if (DECL_NAME (new_vard
))
3213 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3215 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3216 gimple_add_tmp_var (z
);
3217 TREE_ADDRESSABLE (z
) = 1;
3218 z
= build_fold_addr_expr_loc (loc
, z
);
3219 gimplify_assign (new_vard
, z
, ilist
);
3223 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3224 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3225 private variables. Initialization statements go in ILIST, while calls
3226 to destructors go in DLIST. */
3229 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3230 omp_context
*ctx
, struct omp_for_data
*fd
)
3232 tree c
, dtor
, copyin_seq
, x
, ptr
;
3233 bool copyin_by_ref
= false;
3234 bool lastprivate_firstprivate
= false;
3235 bool reduction_omp_orig_ref
= false;
3237 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3238 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3240 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3241 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3242 gimple_seq llist
[2] = { NULL
, NULL
};
3246 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3247 with data sharing clauses referencing variable sized vars. That
3248 is unnecessarily hard to support and very unlikely to result in
3249 vectorized code anyway. */
3251 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3252 switch (OMP_CLAUSE_CODE (c
))
3254 case OMP_CLAUSE_LINEAR
:
3255 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3258 case OMP_CLAUSE_REDUCTION
:
3259 case OMP_CLAUSE_PRIVATE
:
3260 case OMP_CLAUSE_FIRSTPRIVATE
:
3261 case OMP_CLAUSE_LASTPRIVATE
:
3262 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3269 /* Do all the fixed sized types in the first pass, and the variable sized
3270 types in the second pass. This makes sure that the scalar arguments to
3271 the variable sized types are processed before we use them in the
3272 variable sized operations. */
3273 for (pass
= 0; pass
< 2; ++pass
)
3275 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3277 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3280 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3284 case OMP_CLAUSE_PRIVATE
:
3285 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3288 case OMP_CLAUSE_SHARED
:
3289 /* Ignore shared directives in teams construct. */
3290 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3292 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3294 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3297 case OMP_CLAUSE_FIRSTPRIVATE
:
3298 case OMP_CLAUSE_COPYIN
:
3299 case OMP_CLAUSE_LINEAR
:
3301 case OMP_CLAUSE_REDUCTION
:
3302 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3303 reduction_omp_orig_ref
= true;
3305 case OMP_CLAUSE__LOOPTEMP_
:
3306 /* Handle _looptemp_ clauses only on parallel. */
3310 case OMP_CLAUSE_LASTPRIVATE
:
3311 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3313 lastprivate_firstprivate
= true;
3317 /* Even without corresponding firstprivate, if
3318 decl is Fortran allocatable, it needs outer var
3321 && lang_hooks
.decls
.omp_private_outer_ref
3322 (OMP_CLAUSE_DECL (c
)))
3323 lastprivate_firstprivate
= true;
3325 case OMP_CLAUSE_ALIGNED
:
3328 var
= OMP_CLAUSE_DECL (c
);
3329 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3330 && !is_global_var (var
))
3332 new_var
= maybe_lookup_decl (var
, ctx
);
3333 if (new_var
== NULL_TREE
)
3334 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3335 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3336 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3337 omp_clause_aligned_alignment (c
));
3338 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3339 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3340 gimplify_and_add (x
, ilist
);
3342 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3343 && is_global_var (var
))
3345 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3346 new_var
= lookup_decl (var
, ctx
);
3347 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3348 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3349 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3350 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3351 omp_clause_aligned_alignment (c
));
3352 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3353 x
= create_tmp_var (ptype
);
3354 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3355 gimplify_and_add (t
, ilist
);
3356 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3357 SET_DECL_VALUE_EXPR (new_var
, t
);
3358 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3365 new_var
= var
= OMP_CLAUSE_DECL (c
);
3366 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3367 new_var
= lookup_decl (var
, ctx
);
3369 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3374 else if (is_variable_sized (var
))
3376 /* For variable sized types, we need to allocate the
3377 actual storage here. Call alloca and store the
3378 result in the pointer decl that we created elsewhere. */
3382 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3387 ptr
= DECL_VALUE_EXPR (new_var
);
3388 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3389 ptr
= TREE_OPERAND (ptr
, 0);
3390 gcc_assert (DECL_P (ptr
));
3391 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3393 /* void *tmp = __builtin_alloca */
3394 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3395 stmt
= gimple_build_call (atmp
, 1, x
);
3396 tmp
= create_tmp_var_raw (ptr_type_node
);
3397 gimple_add_tmp_var (tmp
);
3398 gimple_call_set_lhs (stmt
, tmp
);
3400 gimple_seq_add_stmt (ilist
, stmt
);
3402 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3403 gimplify_assign (ptr
, x
, ilist
);
3406 else if (is_reference (var
))
3408 /* For references that are being privatized for Fortran,
3409 allocate new backing storage for the new pointer
3410 variable. This allows us to avoid changing all the
3411 code that expects a pointer to something that expects
3412 a direct variable. */
3416 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3417 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3419 x
= build_receiver_ref (var
, false, ctx
);
3420 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3422 else if (TREE_CONSTANT (x
))
3424 /* For reduction in SIMD loop, defer adding the
3425 initialization of the reference, because if we decide
3426 to use SIMD array for it, the initilization could cause
3428 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3432 const char *name
= NULL
;
3433 if (DECL_NAME (var
))
3434 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3436 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3438 gimple_add_tmp_var (x
);
3439 TREE_ADDRESSABLE (x
) = 1;
3440 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3445 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3446 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3451 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3452 gimplify_assign (new_var
, x
, ilist
);
3455 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3457 else if (c_kind
== OMP_CLAUSE_REDUCTION
3458 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3466 switch (OMP_CLAUSE_CODE (c
))
3468 case OMP_CLAUSE_SHARED
:
3469 /* Ignore shared directives in teams construct. */
3470 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3472 /* Shared global vars are just accessed directly. */
3473 if (is_global_var (new_var
))
3475 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3476 needs to be delayed until after fixup_child_record_type so
3477 that we get the correct type during the dereference. */
3478 by_ref
= use_pointer_for_field (var
, ctx
);
3479 x
= build_receiver_ref (var
, by_ref
, ctx
);
3480 SET_DECL_VALUE_EXPR (new_var
, x
);
3481 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3483 /* ??? If VAR is not passed by reference, and the variable
3484 hasn't been initialized yet, then we'll get a warning for
3485 the store into the omp_data_s structure. Ideally, we'd be
3486 able to notice this and not store anything at all, but
3487 we're generating code too early. Suppress the warning. */
3489 TREE_NO_WARNING (var
) = 1;
3492 case OMP_CLAUSE_LASTPRIVATE
:
3493 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3497 case OMP_CLAUSE_PRIVATE
:
3498 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3499 x
= build_outer_var_ref (var
, ctx
);
3500 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3502 if (is_task_ctx (ctx
))
3503 x
= build_receiver_ref (var
, false, ctx
);
3505 x
= build_outer_var_ref (var
, ctx
);
3511 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3514 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3515 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3516 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3517 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3518 idx
, lane
, ivar
, lvar
))
3521 x
= lang_hooks
.decls
.omp_clause_default_ctor
3522 (c
, unshare_expr (ivar
), x
);
3524 gimplify_and_add (x
, &llist
[0]);
3527 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3530 gimple_seq tseq
= NULL
;
3533 gimplify_stmt (&dtor
, &tseq
);
3534 gimple_seq_add_seq (&llist
[1], tseq
);
3541 gimplify_and_add (nx
, ilist
);
3545 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3548 gimple_seq tseq
= NULL
;
3551 gimplify_stmt (&dtor
, &tseq
);
3552 gimple_seq_add_seq (dlist
, tseq
);
3556 case OMP_CLAUSE_LINEAR
:
3557 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3558 goto do_firstprivate
;
3559 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3562 x
= build_outer_var_ref (var
, ctx
);
3565 case OMP_CLAUSE_FIRSTPRIVATE
:
3566 if (is_task_ctx (ctx
))
3568 if (is_reference (var
) || is_variable_sized (var
))
3570 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3572 || use_pointer_for_field (var
, NULL
))
3574 x
= build_receiver_ref (var
, false, ctx
);
3575 SET_DECL_VALUE_EXPR (new_var
, x
);
3576 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3581 x
= build_outer_var_ref (var
, ctx
);
3584 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3585 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3587 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3588 tree stept
= TREE_TYPE (t
);
3589 tree ct
= find_omp_clause (clauses
,
3590 OMP_CLAUSE__LOOPTEMP_
);
3592 tree l
= OMP_CLAUSE_DECL (ct
);
3593 tree n1
= fd
->loop
.n1
;
3594 tree step
= fd
->loop
.step
;
3595 tree itype
= TREE_TYPE (l
);
3596 if (POINTER_TYPE_P (itype
))
3597 itype
= signed_type_for (itype
);
3598 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3599 if (TYPE_UNSIGNED (itype
)
3600 && fd
->loop
.cond_code
== GT_EXPR
)
3601 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3602 fold_build1 (NEGATE_EXPR
, itype
, l
),
3603 fold_build1 (NEGATE_EXPR
,
3606 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3607 t
= fold_build2 (MULT_EXPR
, stept
,
3608 fold_convert (stept
, l
), t
);
3610 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3612 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3614 gimplify_and_add (x
, ilist
);
3618 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3619 x
= fold_build2 (POINTER_PLUS_EXPR
,
3620 TREE_TYPE (x
), x
, t
);
3622 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3625 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3626 || TREE_ADDRESSABLE (new_var
))
3627 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3628 idx
, lane
, ivar
, lvar
))
3630 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
3632 tree iv
= create_tmp_var (TREE_TYPE (new_var
));
3633 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
3634 gimplify_and_add (x
, ilist
);
3635 gimple_stmt_iterator gsi
3636 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3638 = gimple_build_assign (unshare_expr (lvar
), iv
);
3639 gsi_insert_before_without_update (&gsi
, g
,
3641 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3642 enum tree_code code
= PLUS_EXPR
;
3643 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
3644 code
= POINTER_PLUS_EXPR
;
3645 g
= gimple_build_assign (iv
, code
, iv
, t
);
3646 gsi_insert_before_without_update (&gsi
, g
,
3650 x
= lang_hooks
.decls
.omp_clause_copy_ctor
3651 (c
, unshare_expr (ivar
), x
);
3652 gimplify_and_add (x
, &llist
[0]);
3653 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3656 gimple_seq tseq
= NULL
;
3659 gimplify_stmt (&dtor
, &tseq
);
3660 gimple_seq_add_seq (&llist
[1], tseq
);
3665 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
3666 gimplify_and_add (x
, ilist
);
3669 case OMP_CLAUSE__LOOPTEMP_
:
3670 gcc_assert (is_parallel_ctx (ctx
));
3671 x
= build_outer_var_ref (var
, ctx
);
3672 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3673 gimplify_and_add (x
, ilist
);
3676 case OMP_CLAUSE_COPYIN
:
3677 by_ref
= use_pointer_for_field (var
, NULL
);
3678 x
= build_receiver_ref (var
, by_ref
, ctx
);
3679 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
3680 append_to_statement_list (x
, ©in_seq
);
3681 copyin_by_ref
|= by_ref
;
3684 case OMP_CLAUSE_REDUCTION
:
3685 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3687 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3689 x
= build_outer_var_ref (var
, ctx
);
3691 if (is_reference (var
)
3692 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
3694 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3695 SET_DECL_VALUE_EXPR (placeholder
, x
);
3696 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3697 tree new_vard
= new_var
;
3698 if (is_reference (var
))
3700 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3701 new_vard
= TREE_OPERAND (new_var
, 0);
3702 gcc_assert (DECL_P (new_vard
));
3705 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3706 idx
, lane
, ivar
, lvar
))
3708 if (new_vard
== new_var
)
3710 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
3711 SET_DECL_VALUE_EXPR (new_var
, ivar
);
3715 SET_DECL_VALUE_EXPR (new_vard
,
3716 build_fold_addr_expr (ivar
));
3717 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3719 x
= lang_hooks
.decls
.omp_clause_default_ctor
3720 (c
, unshare_expr (ivar
),
3721 build_outer_var_ref (var
, ctx
));
3723 gimplify_and_add (x
, &llist
[0]);
3724 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3726 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3727 lower_omp (&tseq
, ctx
);
3728 gimple_seq_add_seq (&llist
[0], tseq
);
3730 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3731 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3732 lower_omp (&tseq
, ctx
);
3733 gimple_seq_add_seq (&llist
[1], tseq
);
3734 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3735 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3736 if (new_vard
== new_var
)
3737 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3739 SET_DECL_VALUE_EXPR (new_vard
,
3740 build_fold_addr_expr (lvar
));
3741 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3746 gimplify_stmt (&dtor
, &tseq
);
3747 gimple_seq_add_seq (&llist
[1], tseq
);
3751 /* If this is a reference to constant size reduction var
3752 with placeholder, we haven't emitted the initializer
3753 for it because it is undesirable if SIMD arrays are used.
3754 But if they aren't used, we need to emit the deferred
3755 initialization now. */
3756 else if (is_reference (var
) && is_simd
)
3757 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3758 x
= lang_hooks
.decls
.omp_clause_default_ctor
3759 (c
, unshare_expr (new_var
),
3760 build_outer_var_ref (var
, ctx
));
3762 gimplify_and_add (x
, ilist
);
3763 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
3765 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
3766 lower_omp (&tseq
, ctx
);
3767 gimple_seq_add_seq (ilist
, tseq
);
3769 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
3772 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
3773 lower_omp (&tseq
, ctx
);
3774 gimple_seq_add_seq (dlist
, tseq
);
3775 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3777 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
3782 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
3783 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
3784 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3786 /* reduction(-:var) sums up the partial results, so it
3787 acts identically to reduction(+:var). */
3788 if (code
== MINUS_EXPR
)
3791 tree new_vard
= new_var
;
3792 if (is_simd
&& is_reference (var
))
3794 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
3795 new_vard
= TREE_OPERAND (new_var
, 0);
3796 gcc_assert (DECL_P (new_vard
));
3799 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3800 idx
, lane
, ivar
, lvar
))
3802 tree ref
= build_outer_var_ref (var
, ctx
);
3804 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
3806 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
3807 ref
= build_outer_var_ref (var
, ctx
);
3808 gimplify_assign (ref
, x
, &llist
[1]);
3810 if (new_vard
!= new_var
)
3812 SET_DECL_VALUE_EXPR (new_vard
,
3813 build_fold_addr_expr (lvar
));
3814 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
3819 if (is_reference (var
) && is_simd
)
3820 handle_simd_reference (clause_loc
, new_vard
, ilist
);
3821 gimplify_assign (new_var
, x
, ilist
);
3824 tree ref
= build_outer_var_ref (var
, ctx
);
3826 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3827 ref
= build_outer_var_ref (var
, ctx
);
3828 gimplify_assign (ref
, x
, dlist
);
3842 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
3843 /* Don't want uninit warnings on simduid, it is always uninitialized,
3844 but we use it not for the value, but for the DECL_UID only. */
3845 TREE_NO_WARNING (uid
) = 1;
3847 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
3848 gimple_call_set_lhs (g
, lane
);
3849 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3850 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
3851 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
3852 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
3853 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3854 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3855 g
= gimple_build_assign (lane
, INTEGER_CST
,
3856 build_int_cst (unsigned_type_node
, 0));
3857 gimple_seq_add_stmt (ilist
, g
);
3858 for (int i
= 0; i
< 2; i
++)
3861 tree vf
= create_tmp_var (unsigned_type_node
);
3862 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
3863 gimple_call_set_lhs (g
, vf
);
3864 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
3865 gimple_seq_add_stmt (seq
, g
);
3866 tree t
= build_int_cst (unsigned_type_node
, 0);
3867 g
= gimple_build_assign (idx
, INTEGER_CST
, t
);
3868 gimple_seq_add_stmt (seq
, g
);
3869 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
3870 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
3871 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
3872 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
3873 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
3874 gimple_seq_add_seq (seq
, llist
[i
]);
3875 t
= build_int_cst (unsigned_type_node
, 1);
3876 g
= gimple_build_assign (idx
, PLUS_EXPR
, idx
, t
);
3877 gimple_seq_add_stmt (seq
, g
);
3878 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
3879 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
3880 gimple_seq_add_stmt (seq
, g
);
3881 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
3885 /* The copyin sequence is not to be executed by the main thread, since
3886 that would result in self-copies. Perhaps not visible to scalars,
3887 but it certainly is to C++ operator=. */
3890 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
3892 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
3893 build_int_cst (TREE_TYPE (x
), 0));
3894 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
3895 gimplify_and_add (x
, ilist
);
3898 /* If any copyin variable is passed by reference, we must ensure the
3899 master thread doesn't modify it before it is copied over in all
3900 threads. Similarly for variables in both firstprivate and
3901 lastprivate clauses we need to ensure the lastprivate copying
3902 happens after firstprivate copying in all threads. And similarly
3903 for UDRs if initializer expression refers to omp_orig. */
3904 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
3906 /* Don't add any barrier for #pragma omp simd or
3907 #pragma omp distribute. */
3908 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3909 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
3910 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
3913 /* If max_vf is non-zero, then we can use only a vectorization factor
3914 up to the max_vf we chose. So stick it into the safelen clause. */
3917 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3918 OMP_CLAUSE_SAFELEN
);
3920 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
3921 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3924 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
3925 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
3927 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
3928 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
3934 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3935 both parallel and workshare constructs. PREDICATE may be NULL if it's
3939 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
3942 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
3943 bool par_clauses
= false;
3944 tree simduid
= NULL
, lastlane
= NULL
;
3946 /* Early exit if there are no lastprivate or linear clauses. */
3947 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
3948 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
3949 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
3950 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
3952 if (clauses
== NULL
)
3954 /* If this was a workshare clause, see if it had been combined
3955 with its parallel. In that case, look for the clauses on the
3956 parallel statement itself. */
3957 if (is_parallel_ctx (ctx
))
3961 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
3964 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
3965 OMP_CLAUSE_LASTPRIVATE
);
3966 if (clauses
== NULL
)
3974 tree label_true
, arm1
, arm2
;
3976 label
= create_artificial_label (UNKNOWN_LOCATION
);
3977 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
3978 arm1
= TREE_OPERAND (predicate
, 0);
3979 arm2
= TREE_OPERAND (predicate
, 1);
3980 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3981 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
3982 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
3984 gimple_seq_add_stmt (stmt_list
, stmt
);
3985 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
3988 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3989 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3991 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
3993 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
3996 for (c
= clauses
; c
;)
3999 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4001 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4002 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4003 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
4005 var
= OMP_CLAUSE_DECL (c
);
4006 new_var
= lookup_decl (var
, ctx
);
4008 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
4010 tree val
= DECL_VALUE_EXPR (new_var
);
4011 if (TREE_CODE (val
) == ARRAY_REF
4012 && VAR_P (TREE_OPERAND (val
, 0))
4013 && lookup_attribute ("omp simd array",
4014 DECL_ATTRIBUTES (TREE_OPERAND (val
,
4017 if (lastlane
== NULL
)
4019 lastlane
= create_tmp_var (unsigned_type_node
);
4021 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
4023 TREE_OPERAND (val
, 1));
4024 gimple_call_set_lhs (g
, lastlane
);
4025 gimple_seq_add_stmt (stmt_list
, g
);
4027 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
4028 TREE_OPERAND (val
, 0), lastlane
,
4029 NULL_TREE
, NULL_TREE
);
4033 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4034 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
4036 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
4037 gimple_seq_add_seq (stmt_list
,
4038 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
4039 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
4041 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4042 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
4044 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
4045 gimple_seq_add_seq (stmt_list
,
4046 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
4047 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
4050 x
= build_outer_var_ref (var
, ctx
);
4051 if (is_reference (var
))
4052 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4053 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
4054 gimplify_and_add (x
, stmt_list
);
4056 c
= OMP_CLAUSE_CHAIN (c
);
4057 if (c
== NULL
&& !par_clauses
)
4059 /* If this was a workshare clause, see if it had been combined
4060 with its parallel. In that case, continue looking for the
4061 clauses also on the parallel statement itself. */
4062 if (is_parallel_ctx (ctx
))
4066 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4069 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4070 OMP_CLAUSE_LASTPRIVATE
);
4076 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
4080 /* Generate code to implement the REDUCTION clauses. */
4083 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
4085 gimple_seq sub_seq
= NULL
;
4090 /* SIMD reductions are handled in lower_rec_input_clauses. */
4091 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4092 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4095 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4096 update in that case, otherwise use a lock. */
4097 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
4098 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
4100 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4102 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4112 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4114 tree var
, ref
, new_var
;
4115 enum tree_code code
;
4116 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4118 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
4121 var
= OMP_CLAUSE_DECL (c
);
4122 new_var
= lookup_decl (var
, ctx
);
4123 if (is_reference (var
))
4124 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4125 ref
= build_outer_var_ref (var
, ctx
);
4126 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4128 /* reduction(-:var) sums up the partial results, so it acts
4129 identically to reduction(+:var). */
4130 if (code
== MINUS_EXPR
)
4135 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
4137 addr
= save_expr (addr
);
4138 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
4139 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
4140 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
4141 gimplify_and_add (x
, stmt_seqp
);
4145 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4147 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4149 if (is_reference (var
)
4150 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4152 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
4153 SET_DECL_VALUE_EXPR (placeholder
, ref
);
4154 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4155 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
4156 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
4157 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4158 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
4162 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4163 ref
= build_outer_var_ref (var
, ctx
);
4164 gimplify_assign (ref
, x
, &sub_seq
);
4168 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4170 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4172 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4174 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4176 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4180 /* Generate code to implement the COPYPRIVATE clauses. */
4183 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4188 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4190 tree var
, new_var
, ref
, x
;
4192 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4194 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4197 var
= OMP_CLAUSE_DECL (c
);
4198 by_ref
= use_pointer_for_field (var
, NULL
);
4200 ref
= build_sender_ref (var
, ctx
);
4201 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4204 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4205 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4207 gimplify_assign (ref
, x
, slist
);
4209 ref
= build_receiver_ref (var
, false, ctx
);
4212 ref
= fold_convert_loc (clause_loc
,
4213 build_pointer_type (TREE_TYPE (new_var
)),
4215 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4217 if (is_reference (var
))
4219 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4220 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4221 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4223 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4224 gimplify_and_add (x
, rlist
);
4229 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4230 and REDUCTION from the sender (aka parent) side. */
4233 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4238 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4240 tree val
, ref
, x
, var
;
4241 bool by_ref
, do_in
= false, do_out
= false;
4242 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4244 switch (OMP_CLAUSE_CODE (c
))
4246 case OMP_CLAUSE_PRIVATE
:
4247 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4250 case OMP_CLAUSE_FIRSTPRIVATE
:
4251 case OMP_CLAUSE_COPYIN
:
4252 case OMP_CLAUSE_LASTPRIVATE
:
4253 case OMP_CLAUSE_REDUCTION
:
4254 case OMP_CLAUSE__LOOPTEMP_
:
4260 val
= OMP_CLAUSE_DECL (c
);
4261 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4263 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4264 && is_global_var (var
))
4266 if (is_variable_sized (val
))
4268 by_ref
= use_pointer_for_field (val
, NULL
);
4270 switch (OMP_CLAUSE_CODE (c
))
4272 case OMP_CLAUSE_PRIVATE
:
4273 case OMP_CLAUSE_FIRSTPRIVATE
:
4274 case OMP_CLAUSE_COPYIN
:
4275 case OMP_CLAUSE__LOOPTEMP_
:
4279 case OMP_CLAUSE_LASTPRIVATE
:
4280 if (by_ref
|| is_reference (val
))
4282 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4289 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4294 case OMP_CLAUSE_REDUCTION
:
4296 do_out
= !(by_ref
|| is_reference (val
));
4305 ref
= build_sender_ref (val
, ctx
);
4306 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4307 gimplify_assign (ref
, x
, ilist
);
4308 if (is_task_ctx (ctx
))
4309 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4314 ref
= build_sender_ref (val
, ctx
);
4315 gimplify_assign (var
, ref
, olist
);
4320 /* Generate code to implement SHARED from the sender (aka parent)
4321 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4322 list things that got automatically shared. */
4325 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4327 tree var
, ovar
, nvar
, f
, x
, record_type
;
4329 if (ctx
->record_type
== NULL
)
4332 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4333 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4335 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4336 nvar
= maybe_lookup_decl (ovar
, ctx
);
4337 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4340 /* If CTX is a nested parallel directive. Find the immediately
4341 enclosing parallel or workshare construct that contains a
4342 mapping for OVAR. */
4343 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4345 if (use_pointer_for_field (ovar
, ctx
))
4347 x
= build_sender_ref (ovar
, ctx
);
4348 var
= build_fold_addr_expr (var
);
4349 gimplify_assign (x
, var
, ilist
);
4353 x
= build_sender_ref (ovar
, ctx
);
4354 gimplify_assign (x
, var
, ilist
);
4356 if (!TREE_READONLY (var
)
4357 /* We don't need to receive a new reference to a result
4358 or parm decl. In fact we may not store to it as we will
4359 invalidate any pending RSO and generate wrong gimple
4361 && !((TREE_CODE (var
) == RESULT_DECL
4362 || TREE_CODE (var
) == PARM_DECL
)
4363 && DECL_BY_REFERENCE (var
)))
4365 x
= build_sender_ref (ovar
, ctx
);
4366 gimplify_assign (var
, x
, olist
);
4373 /* A convenience function to build an empty GIMPLE_COND with just the
4377 gimple_build_cond_empty (tree cond
)
4379 enum tree_code pred_code
;
4382 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4383 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4387 /* Build the function calls to GOMP_parallel_start etc to actually
4388 generate the parallel operation. REGION is the parallel region
4389 being expanded. BB is the block where to insert the code. WS_ARGS
4390 will be set if this is a call to a combined parallel+workshare
4391 construct, it contains the list of additional arguments needed by
4392 the workshare construct. */
4395 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4396 gomp_parallel
*entry_stmt
,
4397 vec
<tree
, va_gc
> *ws_args
)
4399 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4400 gimple_stmt_iterator gsi
;
4402 enum built_in_function start_ix
;
4404 location_t clause_loc
;
4405 vec
<tree
, va_gc
> *args
;
4407 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4409 /* Determine what flavor of GOMP_parallel we will be
4411 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4412 if (is_combined_parallel (region
))
4414 switch (region
->inner
->type
)
4416 case GIMPLE_OMP_FOR
:
4417 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4418 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4419 + (region
->inner
->sched_kind
4420 == OMP_CLAUSE_SCHEDULE_RUNTIME
4421 ? 3 : region
->inner
->sched_kind
));
4422 start_ix
= (enum built_in_function
)start_ix2
;
4424 case GIMPLE_OMP_SECTIONS
:
4425 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4432 /* By default, the value of NUM_THREADS is zero (selected at run time)
4433 and there is no conditional. */
4435 val
= build_int_cst (unsigned_type_node
, 0);
4436 flags
= build_int_cst (unsigned_type_node
, 0);
4438 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4440 cond
= OMP_CLAUSE_IF_EXPR (c
);
4442 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4445 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4446 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4449 clause_loc
= gimple_location (entry_stmt
);
4451 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4453 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4455 /* Ensure 'val' is of the correct type. */
4456 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4458 /* If we found the clause 'if (cond)', build either
4459 (cond != 0) or (cond ? val : 1u). */
4462 cond
= gimple_boolify (cond
);
4464 if (integer_zerop (val
))
4465 val
= fold_build2_loc (clause_loc
,
4466 EQ_EXPR
, unsigned_type_node
, cond
,
4467 build_int_cst (TREE_TYPE (cond
), 0));
4470 basic_block cond_bb
, then_bb
, else_bb
;
4471 edge e
, e_then
, e_else
;
4472 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4474 tmp_var
= create_tmp_var (TREE_TYPE (val
));
4475 if (gimple_in_ssa_p (cfun
))
4477 tmp_then
= make_ssa_name (tmp_var
);
4478 tmp_else
= make_ssa_name (tmp_var
);
4479 tmp_join
= make_ssa_name (tmp_var
);
4488 e
= split_block (bb
, NULL
);
4493 then_bb
= create_empty_bb (cond_bb
);
4494 else_bb
= create_empty_bb (then_bb
);
4495 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4496 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4498 stmt
= gimple_build_cond_empty (cond
);
4499 gsi
= gsi_start_bb (cond_bb
);
4500 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4502 gsi
= gsi_start_bb (then_bb
);
4503 stmt
= gimple_build_assign (tmp_then
, val
);
4504 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4506 gsi
= gsi_start_bb (else_bb
);
4507 stmt
= gimple_build_assign
4508 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4509 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4511 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4512 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4513 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4514 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4515 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4516 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4518 if (gimple_in_ssa_p (cfun
))
4520 gphi
*phi
= create_phi_node (tmp_join
, bb
);
4521 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4522 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4528 gsi
= gsi_start_bb (bb
);
4529 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4530 false, GSI_CONTINUE_LINKING
);
4533 gsi
= gsi_last_bb (bb
);
4534 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4536 t1
= null_pointer_node
;
4538 t1
= build_fold_addr_expr (t
);
4539 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4541 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4542 args
->quick_push (t2
);
4543 args
->quick_push (t1
);
4544 args
->quick_push (val
);
4546 args
->splice (*ws_args
);
4547 args
->quick_push (flags
);
4549 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4550 builtin_decl_explicit (start_ix
), args
);
4552 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4553 false, GSI_CONTINUE_LINKING
);
4556 /* Insert a function call whose name is FUNC_NAME with the information from
4557 ENTRY_STMT into the basic_block BB. */
4560 expand_cilk_for_call (basic_block bb
, gomp_parallel
*entry_stmt
,
4561 vec
<tree
, va_gc
> *ws_args
)
4564 gimple_stmt_iterator gsi
;
4565 vec
<tree
, va_gc
> *args
;
4567 gcc_assert (vec_safe_length (ws_args
) == 2);
4568 tree func_name
= (*ws_args
)[0];
4569 tree grain
= (*ws_args
)[1];
4571 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4572 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
4573 gcc_assert (count
!= NULL_TREE
);
4574 count
= OMP_CLAUSE_OPERAND (count
, 0);
4576 gsi
= gsi_last_bb (bb
);
4577 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4579 t1
= null_pointer_node
;
4581 t1
= build_fold_addr_expr (t
);
4582 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4584 vec_alloc (args
, 4);
4585 args
->quick_push (t2
);
4586 args
->quick_push (t1
);
4587 args
->quick_push (count
);
4588 args
->quick_push (grain
);
4589 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
4591 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
4592 GSI_CONTINUE_LINKING
);
4595 /* Build the function call to GOMP_task to actually
4596 generate the task operation. BB is the block where to insert the code. */
4599 expand_task_call (basic_block bb
, gomp_task
*entry_stmt
)
4601 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
4602 gimple_stmt_iterator gsi
;
4603 location_t loc
= gimple_location (entry_stmt
);
4605 clauses
= gimple_omp_task_clauses (entry_stmt
);
4607 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4609 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
4611 cond
= boolean_true_node
;
4613 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
4614 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
4615 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
4616 flags
= build_int_cst (unsigned_type_node
,
4617 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
4619 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
4622 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
4623 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
4624 build_int_cst (unsigned_type_node
, 2),
4625 build_int_cst (unsigned_type_node
, 0));
4626 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
4629 depend
= OMP_CLAUSE_DECL (depend
);
4631 depend
= build_int_cst (ptr_type_node
, 0);
4633 gsi
= gsi_last_bb (bb
);
4634 t
= gimple_omp_task_data_arg (entry_stmt
);
4636 t2
= null_pointer_node
;
4638 t2
= build_fold_addr_expr_loc (loc
, t
);
4639 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
4640 t
= gimple_omp_task_copy_fn (entry_stmt
);
4642 t3
= null_pointer_node
;
4644 t3
= build_fold_addr_expr_loc (loc
, t
);
4646 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
4648 gimple_omp_task_arg_size (entry_stmt
),
4649 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
4652 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4653 false, GSI_CONTINUE_LINKING
);
4657 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4658 catch handler and return it. This prevents programs from violating the
4659 structured block semantics with throws. */
4662 maybe_catch_exception (gimple_seq body
)
4667 if (!flag_exceptions
)
4670 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
4671 decl
= lang_hooks
.eh_protect_cleanup_actions ();
4673 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
4675 g
= gimple_build_eh_must_not_throw (decl
);
4676 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
4679 return gimple_seq_alloc_with_stmt (g
);
4682 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4685 vec2chain (vec
<tree
, va_gc
> *v
)
4687 tree chain
= NULL_TREE
, t
;
4690 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
4692 DECL_CHAIN (t
) = chain
;
4700 /* Remove barriers in REGION->EXIT's block. Note that this is only
4701 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4702 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4703 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4707 remove_exit_barrier (struct omp_region
*region
)
4709 gimple_stmt_iterator gsi
;
4710 basic_block exit_bb
;
4714 int any_addressable_vars
= -1;
4716 exit_bb
= region
->exit
;
4718 /* If the parallel region doesn't return, we don't have REGION->EXIT
4723 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4724 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4725 statements that can appear in between are extremely limited -- no
4726 memory operations at all. Here, we allow nothing at all, so the
4727 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4728 gsi
= gsi_last_bb (exit_bb
);
4729 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
4731 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
4734 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
4736 gsi
= gsi_last_bb (e
->src
);
4737 if (gsi_end_p (gsi
))
4739 stmt
= gsi_stmt (gsi
);
4740 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
4741 && !gimple_omp_return_nowait_p (stmt
))
4743 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4744 in many cases. If there could be tasks queued, the barrier
4745 might be needed to let the tasks run before some local
4746 variable of the parallel that the task uses as shared
4747 runs out of scope. The task can be spawned either
4748 from within current function (this would be easy to check)
4749 or from some function it calls and gets passed an address
4750 of such a variable. */
4751 if (any_addressable_vars
< 0)
4753 gomp_parallel
*parallel_stmt
4754 = as_a
<gomp_parallel
*> (last_stmt (region
->entry
));
4755 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
4756 tree local_decls
, block
, decl
;
4759 any_addressable_vars
= 0;
4760 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
4761 if (TREE_ADDRESSABLE (decl
))
4763 any_addressable_vars
= 1;
4766 for (block
= gimple_block (stmt
);
4767 !any_addressable_vars
4769 && TREE_CODE (block
) == BLOCK
;
4770 block
= BLOCK_SUPERCONTEXT (block
))
4772 for (local_decls
= BLOCK_VARS (block
);
4774 local_decls
= DECL_CHAIN (local_decls
))
4775 if (TREE_ADDRESSABLE (local_decls
))
4777 any_addressable_vars
= 1;
4780 if (block
== gimple_block (parallel_stmt
))
4784 if (!any_addressable_vars
)
4785 gimple_omp_return_set_nowait (stmt
);
4791 remove_exit_barriers (struct omp_region
*region
)
4793 if (region
->type
== GIMPLE_OMP_PARALLEL
)
4794 remove_exit_barrier (region
);
4798 region
= region
->inner
;
4799 remove_exit_barriers (region
);
4800 while (region
->next
)
4802 region
= region
->next
;
4803 remove_exit_barriers (region
);
4808 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4809 calls. These can't be declared as const functions, but
4810 within one parallel body they are constant, so they can be
4811 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4812 which are declared const. Similarly for task body, except
4813 that in untied task omp_get_thread_num () can change at any task
4814 scheduling point. */
4817 optimize_omp_library_calls (gimple entry_stmt
)
4820 gimple_stmt_iterator gsi
;
4821 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4822 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
4823 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4824 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
4825 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
4826 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
4827 OMP_CLAUSE_UNTIED
) != NULL
);
4829 FOR_EACH_BB_FN (bb
, cfun
)
4830 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4832 gimple call
= gsi_stmt (gsi
);
4835 if (is_gimple_call (call
)
4836 && (decl
= gimple_call_fndecl (call
))
4837 && DECL_EXTERNAL (decl
)
4838 && TREE_PUBLIC (decl
)
4839 && DECL_INITIAL (decl
) == NULL
)
4843 if (DECL_NAME (decl
) == thr_num_id
)
4845 /* In #pragma omp task untied omp_get_thread_num () can change
4846 during the execution of the task region. */
4849 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
4851 else if (DECL_NAME (decl
) == num_thr_id
)
4852 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
4856 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
4857 || gimple_call_num_args (call
) != 0)
4860 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
4863 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
4864 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
4865 TREE_TYPE (TREE_TYPE (built_in
))))
4868 gimple_call_set_fndecl (call
, built_in
);
4873 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4877 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
4881 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4882 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
4885 if (TREE_CODE (t
) == ADDR_EXPR
)
4886 recompute_tree_invariant_for_addr_expr (t
);
4888 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
4892 /* Prepend TO = FROM assignment before *GSI_P. */
4895 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
4897 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
4898 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
4899 true, GSI_SAME_STMT
);
4900 gimple stmt
= gimple_build_assign (to
, from
);
4901 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
4902 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
4903 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
4905 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
4906 gimple_regimplify_operands (stmt
, &gsi
);
4910 /* Expand the OpenMP parallel or task directive starting at REGION. */
4913 expand_omp_taskreg (struct omp_region
*region
)
4915 basic_block entry_bb
, exit_bb
, new_bb
;
4916 struct function
*child_cfun
;
4917 tree child_fn
, block
, t
;
4918 gimple_stmt_iterator gsi
;
4919 gimple entry_stmt
, stmt
;
4921 vec
<tree
, va_gc
> *ws_args
;
4923 entry_stmt
= last_stmt (region
->entry
);
4924 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
4925 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
4927 entry_bb
= region
->entry
;
4928 exit_bb
= region
->exit
;
4932 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
4933 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
4934 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
4937 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4938 and the inner statement contains the name of the built-in function
4940 ws_args
= region
->inner
->ws_args
;
4941 else if (is_combined_parallel (region
))
4942 ws_args
= region
->ws_args
;
4946 if (child_cfun
->cfg
)
4948 /* Due to inlining, it may happen that we have already outlined
4949 the region, in which case all we need to do is make the
4950 sub-graph unreachable and emit the parallel call. */
4951 edge entry_succ_e
, exit_succ_e
;
4953 entry_succ_e
= single_succ_edge (entry_bb
);
4955 gsi
= gsi_last_bb (entry_bb
);
4956 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
4957 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
4958 gsi_remove (&gsi
, true);
4963 exit_succ_e
= single_succ_edge (exit_bb
);
4964 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
4966 remove_edge_and_dominated_blocks (entry_succ_e
);
4970 unsigned srcidx
, dstidx
, num
;
4972 /* If the parallel region needs data sent from the parent
4973 function, then the very first statement (except possible
4974 tree profile counter updates) of the parallel body
4975 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4976 &.OMP_DATA_O is passed as an argument to the child function,
4977 we need to replace it with the argument as seen by the child
4980 In most cases, this will end up being the identity assignment
4981 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4982 a function call that has been inlined, the original PARM_DECL
4983 .OMP_DATA_I may have been converted into a different local
4984 variable. In which case, we need to keep the assignment. */
4985 if (gimple_omp_taskreg_data_arg (entry_stmt
))
4987 basic_block entry_succ_bb
= single_succ (entry_bb
);
4989 gimple parcopy_stmt
= NULL
;
4991 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
4995 gcc_assert (!gsi_end_p (gsi
));
4996 stmt
= gsi_stmt (gsi
);
4997 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
5000 if (gimple_num_ops (stmt
) == 2)
5002 tree arg
= gimple_assign_rhs1 (stmt
);
5004 /* We're ignore the subcode because we're
5005 effectively doing a STRIP_NOPS. */
5007 if (TREE_CODE (arg
) == ADDR_EXPR
5008 && TREE_OPERAND (arg
, 0)
5009 == gimple_omp_taskreg_data_arg (entry_stmt
))
5011 parcopy_stmt
= stmt
;
5017 gcc_assert (parcopy_stmt
!= NULL
);
5018 arg
= DECL_ARGUMENTS (child_fn
);
5020 if (!gimple_in_ssa_p (cfun
))
5022 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
5023 gsi_remove (&gsi
, true);
5026 /* ?? Is setting the subcode really necessary ?? */
5027 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
5028 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
5033 /* If we are in ssa form, we must load the value from the default
5034 definition of the argument. That should not be defined now,
5035 since the argument is not used uninitialized. */
5036 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
5037 narg
= make_ssa_name (arg
, gimple_build_nop ());
5038 set_ssa_default_def (cfun
, arg
, narg
);
5039 /* ?? Is setting the subcode really necessary ?? */
5040 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
5041 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
5042 update_stmt (parcopy_stmt
);
5046 /* Declare local variables needed in CHILD_CFUN. */
5047 block
= DECL_INITIAL (child_fn
);
5048 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
5049 /* The gimplifier could record temporaries in parallel/task block
5050 rather than in containing function's local_decls chain,
5051 which would mean cgraph missed finalizing them. Do it now. */
5052 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
5053 if (TREE_CODE (t
) == VAR_DECL
5055 && !DECL_EXTERNAL (t
))
5056 varpool_node::finalize_decl (t
);
5057 DECL_SAVED_TREE (child_fn
) = NULL
;
5058 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5059 gimple_set_body (child_fn
, NULL
);
5060 TREE_USED (block
) = 1;
5062 /* Reset DECL_CONTEXT on function arguments. */
5063 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
5064 DECL_CONTEXT (t
) = child_fn
;
5066 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5067 so that it can be moved to the child function. */
5068 gsi
= gsi_last_bb (entry_bb
);
5069 stmt
= gsi_stmt (gsi
);
5070 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
5071 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
5072 gsi_remove (&gsi
, true);
5073 e
= split_block (entry_bb
, stmt
);
5075 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5077 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5080 gsi
= gsi_last_bb (exit_bb
);
5081 gcc_assert (!gsi_end_p (gsi
)
5082 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5083 stmt
= gimple_build_return (NULL
);
5084 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5085 gsi_remove (&gsi
, true);
5088 /* Move the parallel region into CHILD_CFUN. */
5090 if (gimple_in_ssa_p (cfun
))
5092 init_tree_ssa (child_cfun
);
5093 init_ssa_operands (child_cfun
);
5094 child_cfun
->gimple_df
->in_ssa_p
= true;
5098 block
= gimple_block (entry_stmt
);
5100 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
5102 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
5103 /* When the OMP expansion process cannot guarantee an up-to-date
5104 loop tree arrange for the child function to fixup loops. */
5105 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5106 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
5108 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5109 num
= vec_safe_length (child_cfun
->local_decls
);
5110 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
5112 t
= (*child_cfun
->local_decls
)[srcidx
];
5113 if (DECL_CONTEXT (t
) == cfun
->decl
)
5115 if (srcidx
!= dstidx
)
5116 (*child_cfun
->local_decls
)[dstidx
] = t
;
5120 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
5122 /* Inform the callgraph about the new function. */
5123 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
5124 cgraph_node::add_new_function (child_fn
, true);
5126 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5127 fixed in a following pass. */
5128 push_cfun (child_cfun
);
5130 optimize_omp_library_calls (entry_stmt
);
5131 cgraph_edge::rebuild_edges ();
5133 /* Some EH regions might become dead, see PR34608. If
5134 pass_cleanup_cfg isn't the first pass to happen with the
5135 new child, these dead EH edges might cause problems.
5136 Clean them up now. */
5137 if (flag_exceptions
)
5140 bool changed
= false;
5142 FOR_EACH_BB_FN (bb
, cfun
)
5143 changed
|= gimple_purge_dead_eh_edges (bb
);
5145 cleanup_tree_cfg ();
5147 if (gimple_in_ssa_p (cfun
))
5148 update_ssa (TODO_update_ssa
);
5152 /* Emit a library call to launch the children threads. */
5154 expand_cilk_for_call (new_bb
,
5155 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5156 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5157 expand_parallel_call (region
, new_bb
,
5158 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5160 expand_task_call (new_bb
, as_a
<gomp_task
*> (entry_stmt
));
5161 if (gimple_in_ssa_p (cfun
))
5162 update_ssa (TODO_update_ssa_only_virtuals
);
5166 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5167 of the combined collapse > 1 loop constructs, generate code like:
5168 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5173 count3 = (adj + N32 - N31) / STEP3;
5174 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5179 count2 = (adj + N22 - N21) / STEP2;
5180 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5185 count1 = (adj + N12 - N11) / STEP1;
5186 count = count1 * count2 * count3;
5187 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5189 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5190 of the combined loop constructs, just initialize COUNTS array
5191 from the _looptemp_ clauses. */
5193 /* NOTE: It *could* be better to moosh all of the BBs together,
5194 creating one larger BB with all the computation and the unexpected
5195 jump at the end. I.e.
5197 bool zero3, zero2, zero1, zero;
5200 count3 = (N32 - N31) /[cl] STEP3;
5202 count2 = (N22 - N21) /[cl] STEP2;
5204 count1 = (N12 - N11) /[cl] STEP1;
5205 zero = zero3 || zero2 || zero1;
5206 count = count1 * count2 * count3;
5207 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5209 After all, we expect the zero=false, and thus we expect to have to
5210 evaluate all of the comparison expressions, so short-circuiting
5211 oughtn't be a win. Since the condition isn't protecting a
5212 denominator, we're not concerned about divide-by-zero, so we can
5213 fully evaluate count even if a numerator turned out to be wrong.
5215 It seems like putting this all together would create much better
5216 scheduling opportunities, and less pressure on the chip's branch
5220 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5221 basic_block
&entry_bb
, tree
*counts
,
5222 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5223 basic_block
&l2_dom_bb
)
5225 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5229 /* Collapsed loops need work for expansion into SSA form. */
5230 gcc_assert (!gimple_in_ssa_p (cfun
));
5232 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5233 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5235 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5236 isn't supposed to be handled, as the inner loop doesn't
5238 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5239 OMP_CLAUSE__LOOPTEMP_
);
5240 gcc_assert (innerc
);
5241 for (i
= 0; i
< fd
->collapse
; i
++)
5243 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5244 OMP_CLAUSE__LOOPTEMP_
);
5245 gcc_assert (innerc
);
5247 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5249 counts
[0] = NULL_TREE
;
5254 for (i
= 0; i
< fd
->collapse
; i
++)
5256 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5258 if (SSA_VAR_P (fd
->loop
.n2
)
5259 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5260 fold_convert (itype
, fd
->loops
[i
].n1
),
5261 fold_convert (itype
, fd
->loops
[i
].n2
)))
5262 == NULL_TREE
|| !integer_onep (t
)))
5266 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5267 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5268 true, GSI_SAME_STMT
);
5269 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5270 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5271 true, GSI_SAME_STMT
);
5272 cond_stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5273 NULL_TREE
, NULL_TREE
);
5274 gsi_insert_before (gsi
, cond_stmt
, GSI_SAME_STMT
);
5275 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
5276 expand_omp_regimplify_p
, NULL
, NULL
)
5277 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
5278 expand_omp_regimplify_p
, NULL
, NULL
))
5280 *gsi
= gsi_for_stmt (cond_stmt
);
5281 gimple_regimplify_operands (cond_stmt
, gsi
);
5283 e
= split_block (entry_bb
, cond_stmt
);
5284 if (zero_iter_bb
== NULL
)
5286 gassign
*assign_stmt
;
5287 first_zero_iter
= i
;
5288 zero_iter_bb
= create_empty_bb (entry_bb
);
5289 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5290 *gsi
= gsi_after_labels (zero_iter_bb
);
5291 assign_stmt
= gimple_build_assign (fd
->loop
.n2
,
5292 build_zero_cst (type
));
5293 gsi_insert_before (gsi
, assign_stmt
, GSI_SAME_STMT
);
5294 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5297 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5298 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5299 e
->flags
= EDGE_TRUE_VALUE
;
5300 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5301 if (l2_dom_bb
== NULL
)
5302 l2_dom_bb
= entry_bb
;
5304 *gsi
= gsi_last_bb (entry_bb
);
5307 if (POINTER_TYPE_P (itype
))
5308 itype
= signed_type_for (itype
);
5309 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5311 t
= fold_build2 (PLUS_EXPR
, itype
,
5312 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5313 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5314 fold_convert (itype
, fd
->loops
[i
].n2
));
5315 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5316 fold_convert (itype
, fd
->loops
[i
].n1
));
5317 /* ?? We could probably use CEIL_DIV_EXPR instead of
5318 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5319 generate the same code in the end because generically we
5320 don't know that the values involved must be negative for
5322 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5323 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5324 fold_build1 (NEGATE_EXPR
, itype
, t
),
5325 fold_build1 (NEGATE_EXPR
, itype
,
5326 fold_convert (itype
,
5327 fd
->loops
[i
].step
)));
5329 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5330 fold_convert (itype
, fd
->loops
[i
].step
));
5331 t
= fold_convert (type
, t
);
5332 if (TREE_CODE (t
) == INTEGER_CST
)
5336 counts
[i
] = create_tmp_reg (type
, ".count");
5337 expand_omp_build_assign (gsi
, counts
[i
], t
);
5339 if (SSA_VAR_P (fd
->loop
.n2
))
5344 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5345 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5351 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5353 V3 = N31 + (T % count3) * STEP3;
5355 V2 = N21 + (T % count2) * STEP2;
5357 V1 = N11 + T * STEP1;
5358 if this loop doesn't have an inner loop construct combined with it.
5359 If it does have an inner loop construct combined with it and the
5360 iteration count isn't known constant, store values from counts array
5361 into its _looptemp_ temporaries instead. */
5364 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5365 tree
*counts
, gimple inner_stmt
, tree startvar
)
5368 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5370 /* If fd->loop.n2 is constant, then no propagation of the counts
5371 is needed, they are constant. */
5372 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5375 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5376 ? gimple_omp_parallel_clauses (inner_stmt
)
5377 : gimple_omp_for_clauses (inner_stmt
);
5378 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5379 isn't supposed to be handled, as the inner loop doesn't
5381 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5382 gcc_assert (innerc
);
5383 for (i
= 0; i
< fd
->collapse
; i
++)
5385 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5386 OMP_CLAUSE__LOOPTEMP_
);
5387 gcc_assert (innerc
);
5390 tree tem
= OMP_CLAUSE_DECL (innerc
);
5391 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5392 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5393 false, GSI_CONTINUE_LINKING
);
5394 gassign
*stmt
= gimple_build_assign (tem
, t
);
5395 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5401 tree type
= TREE_TYPE (fd
->loop
.v
);
5402 tree tem
= create_tmp_reg (type
, ".tem");
5403 gassign
*stmt
= gimple_build_assign (tem
, startvar
);
5404 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5406 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5408 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5410 if (POINTER_TYPE_P (vtype
))
5411 itype
= signed_type_for (vtype
);
5413 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5416 t
= fold_convert (itype
, t
);
5417 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5418 fold_convert (itype
, fd
->loops
[i
].step
));
5419 if (POINTER_TYPE_P (vtype
))
5420 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5422 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5423 t
= force_gimple_operand_gsi (gsi
, t
,
5424 DECL_P (fd
->loops
[i
].v
)
5425 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5427 GSI_CONTINUE_LINKING
);
5428 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5429 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5432 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5433 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5434 false, GSI_CONTINUE_LINKING
);
5435 stmt
= gimple_build_assign (tem
, t
);
5436 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5442 /* Helper function for expand_omp_for_*. Generate code like:
5445 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5449 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5456 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5457 basic_block body_bb
)
5459 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5461 gimple_stmt_iterator gsi
;
5467 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5469 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5471 bb
= create_empty_bb (last_bb
);
5472 add_bb_to_loop (bb
, last_bb
->loop_father
);
5473 gsi
= gsi_start_bb (bb
);
5475 if (i
< fd
->collapse
- 1)
5477 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5478 e
->probability
= REG_BR_PROB_BASE
/ 8;
5480 t
= fd
->loops
[i
+ 1].n1
;
5481 t
= force_gimple_operand_gsi (&gsi
, t
,
5482 DECL_P (fd
->loops
[i
+ 1].v
)
5483 && TREE_ADDRESSABLE (fd
->loops
[i
5486 GSI_CONTINUE_LINKING
);
5487 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5488 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5493 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5495 if (POINTER_TYPE_P (vtype
))
5496 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5498 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5499 t
= force_gimple_operand_gsi (&gsi
, t
,
5500 DECL_P (fd
->loops
[i
].v
)
5501 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5502 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5503 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5504 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5508 t
= fd
->loops
[i
].n2
;
5509 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5510 false, GSI_CONTINUE_LINKING
);
5511 tree v
= fd
->loops
[i
].v
;
5512 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5513 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5514 false, GSI_CONTINUE_LINKING
);
5515 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5516 stmt
= gimple_build_cond_empty (t
);
5517 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5518 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5519 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5522 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5530 /* A subroutine of expand_omp_for. Generate code for a parallel
5531 loop with any schedule. Given parameters:
5533 for (V = N1; V cond N2; V += STEP) BODY;
5535 where COND is "<" or ">", we generate pseudocode
5537 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5538 if (more) goto L0; else goto L3;
5545 if (V cond iend) goto L1; else goto L2;
5547 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5550 If this is a combined omp parallel loop, instead of the call to
5551 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5552 If this is gimple_omp_for_combined_p loop, then instead of assigning
5553 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5554 inner GIMPLE_OMP_FOR and V += STEP; and
5555 if (V cond iend) goto L1; else goto L2; are removed.
5557 For collapsed loops, given parameters:
5559 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5560 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5561 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5564 we generate pseudocode
5566 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5571 count3 = (adj + N32 - N31) / STEP3;
5572 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5577 count2 = (adj + N22 - N21) / STEP2;
5578 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5583 count1 = (adj + N12 - N11) / STEP1;
5584 count = count1 * count2 * count3;
5589 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5590 if (more) goto L0; else goto L3;
5594 V3 = N31 + (T % count3) * STEP3;
5596 V2 = N21 + (T % count2) * STEP2;
5598 V1 = N11 + T * STEP1;
5603 if (V < iend) goto L10; else goto L2;
5606 if (V3 cond3 N32) goto L1; else goto L11;
5610 if (V2 cond2 N22) goto L1; else goto L12;
5616 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5622 expand_omp_for_generic (struct omp_region
*region
,
5623 struct omp_for_data
*fd
,
5624 enum built_in_function start_fn
,
5625 enum built_in_function next_fn
,
5628 tree type
, istart0
, iend0
, iend
;
5629 tree t
, vmain
, vback
, bias
= NULL_TREE
;
5630 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
5631 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
5632 gimple_stmt_iterator gsi
;
5633 gassign
*assign_stmt
;
5634 bool in_combined_parallel
= is_combined_parallel (region
);
5635 bool broken_loop
= region
->cont
== NULL
;
5637 tree
*counts
= NULL
;
5640 gcc_assert (!broken_loop
|| !in_combined_parallel
);
5641 gcc_assert (fd
->iter_type
== long_integer_type_node
5642 || !in_combined_parallel
);
5644 type
= TREE_TYPE (fd
->loop
.v
);
5645 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
5646 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
5647 TREE_ADDRESSABLE (istart0
) = 1;
5648 TREE_ADDRESSABLE (iend0
) = 1;
5650 /* See if we need to bias by LLONG_MIN. */
5651 if (fd
->iter_type
== long_long_unsigned_type_node
5652 && TREE_CODE (type
) == INTEGER_TYPE
5653 && !TYPE_UNSIGNED (type
))
5657 if (fd
->loop
.cond_code
== LT_EXPR
)
5660 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5664 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
5667 if (TREE_CODE (n1
) != INTEGER_CST
5668 || TREE_CODE (n2
) != INTEGER_CST
5669 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
5670 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
5673 entry_bb
= region
->entry
;
5674 cont_bb
= region
->cont
;
5676 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5677 gcc_assert (broken_loop
5678 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
5679 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
5680 l1_bb
= single_succ (l0_bb
);
5683 l2_bb
= create_empty_bb (cont_bb
);
5684 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
5685 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5689 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5690 exit_bb
= region
->exit
;
5692 gsi
= gsi_last_bb (entry_bb
);
5694 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5695 if (fd
->collapse
> 1)
5697 int first_zero_iter
= -1;
5698 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
5700 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5701 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5702 zero_iter_bb
, first_zero_iter
,
5707 /* Some counts[i] vars might be uninitialized if
5708 some loop has zero iterations. But the body shouldn't
5709 be executed in that case, so just avoid uninit warnings. */
5710 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
5711 if (SSA_VAR_P (counts
[i
]))
5712 TREE_NO_WARNING (counts
[i
]) = 1;
5714 e
= split_block (entry_bb
, gsi_stmt (gsi
));
5716 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
5717 gsi
= gsi_last_bb (entry_bb
);
5718 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
5719 get_immediate_dominator (CDI_DOMINATORS
,
5723 if (in_combined_parallel
)
5725 /* In a combined parallel loop, emit a call to
5726 GOMP_loop_foo_next. */
5727 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5728 build_fold_addr_expr (istart0
),
5729 build_fold_addr_expr (iend0
));
5733 tree t0
, t1
, t2
, t3
, t4
;
5734 /* If this is not a combined parallel loop, emit a call to
5735 GOMP_loop_foo_start in ENTRY_BB. */
5736 t4
= build_fold_addr_expr (iend0
);
5737 t3
= build_fold_addr_expr (istart0
);
5738 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
5741 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
5743 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5744 OMP_CLAUSE__LOOPTEMP_
);
5745 gcc_assert (innerc
);
5746 t0
= OMP_CLAUSE_DECL (innerc
);
5747 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5748 OMP_CLAUSE__LOOPTEMP_
);
5749 gcc_assert (innerc
);
5750 t1
= OMP_CLAUSE_DECL (innerc
);
5752 if (POINTER_TYPE_P (TREE_TYPE (t0
))
5753 && TYPE_PRECISION (TREE_TYPE (t0
))
5754 != TYPE_PRECISION (fd
->iter_type
))
5756 /* Avoid casting pointers to integer of a different size. */
5757 tree itype
= signed_type_for (type
);
5758 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
5759 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
5763 t1
= fold_convert (fd
->iter_type
, t1
);
5764 t0
= fold_convert (fd
->iter_type
, t0
);
5768 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
5769 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
5771 if (fd
->iter_type
== long_integer_type_node
)
5775 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5776 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5777 6, t0
, t1
, t2
, t
, t3
, t4
);
5780 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5781 5, t0
, t1
, t2
, t3
, t4
);
5789 /* The GOMP_loop_ull_*start functions have additional boolean
5790 argument, true for < loops and false for > loops.
5791 In Fortran, the C bool type can be different from
5792 boolean_type_node. */
5793 bfn_decl
= builtin_decl_explicit (start_fn
);
5794 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
5795 t5
= build_int_cst (c_bool_type
,
5796 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
5799 tree bfn_decl
= builtin_decl_explicit (start_fn
);
5800 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
5801 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
5804 t
= build_call_expr (builtin_decl_explicit (start_fn
),
5805 6, t5
, t0
, t1
, t2
, t3
, t4
);
5808 if (TREE_TYPE (t
) != boolean_type_node
)
5809 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5810 t
, build_int_cst (TREE_TYPE (t
), 0));
5811 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5812 true, GSI_SAME_STMT
);
5813 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5815 /* Remove the GIMPLE_OMP_FOR statement. */
5816 gsi_remove (&gsi
, true);
5818 /* Iteration setup for sequential loop goes in L0_BB. */
5819 tree startvar
= fd
->loop
.v
;
5820 tree endvar
= NULL_TREE
;
5822 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5824 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
5825 && gimple_omp_for_kind (inner_stmt
)
5826 == GF_OMP_FOR_KIND_SIMD
);
5827 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
5828 OMP_CLAUSE__LOOPTEMP_
);
5829 gcc_assert (innerc
);
5830 startvar
= OMP_CLAUSE_DECL (innerc
);
5831 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5832 OMP_CLAUSE__LOOPTEMP_
);
5833 gcc_assert (innerc
);
5834 endvar
= OMP_CLAUSE_DECL (innerc
);
5837 gsi
= gsi_start_bb (l0_bb
);
5840 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5841 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5842 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5843 t
= fold_convert (TREE_TYPE (startvar
), t
);
5844 t
= force_gimple_operand_gsi (&gsi
, t
,
5846 && TREE_ADDRESSABLE (startvar
),
5847 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5848 assign_stmt
= gimple_build_assign (startvar
, t
);
5849 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
5853 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
5854 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
5855 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
5856 t
= fold_convert (TREE_TYPE (startvar
), t
);
5857 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5858 false, GSI_CONTINUE_LINKING
);
5861 assign_stmt
= gimple_build_assign (endvar
, iend
);
5862 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
5863 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
5864 assign_stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
5866 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, iend
);
5867 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
5869 if (fd
->collapse
> 1)
5870 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
5874 /* Code to control the increment and predicate for the sequential
5875 loop goes in the CONT_BB. */
5876 gsi
= gsi_last_bb (cont_bb
);
5877 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
5878 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
5879 vmain
= gimple_omp_continue_control_use (cont_stmt
);
5880 vback
= gimple_omp_continue_control_def (cont_stmt
);
5882 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
5884 if (POINTER_TYPE_P (type
))
5885 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
5887 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
5888 t
= force_gimple_operand_gsi (&gsi
, t
,
5890 && TREE_ADDRESSABLE (vback
),
5891 NULL_TREE
, true, GSI_SAME_STMT
);
5892 assign_stmt
= gimple_build_assign (vback
, t
);
5893 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
5895 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
5896 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
5898 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
5899 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
5902 /* Remove GIMPLE_OMP_CONTINUE. */
5903 gsi_remove (&gsi
, true);
5905 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
5906 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
5908 /* Emit code to get the next parallel iteration in L2_BB. */
5909 gsi
= gsi_start_bb (l2_bb
);
5911 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
5912 build_fold_addr_expr (istart0
),
5913 build_fold_addr_expr (iend0
));
5914 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5915 false, GSI_CONTINUE_LINKING
);
5916 if (TREE_TYPE (t
) != boolean_type_node
)
5917 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
5918 t
, build_int_cst (TREE_TYPE (t
), 0));
5919 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
5920 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
5923 /* Add the loop cleanup function. */
5924 gsi
= gsi_last_bb (exit_bb
);
5925 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
5926 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
5927 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5928 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
5930 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
5931 gcall
*call_stmt
= gimple_build_call (t
, 0);
5932 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
5933 gimple_call_set_lhs (call_stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
5934 gsi_insert_after (&gsi
, call_stmt
, GSI_SAME_STMT
);
5935 gsi_remove (&gsi
, true);
5937 /* Connect the new blocks. */
5938 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
5939 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
5945 e
= find_edge (cont_bb
, l3_bb
);
5946 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
5948 phis
= phi_nodes (l3_bb
);
5949 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5951 gimple phi
= gsi_stmt (gsi
);
5952 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
5953 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
5957 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
5958 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
5959 e
= find_edge (cont_bb
, l1_bb
);
5960 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5965 else if (fd
->collapse
> 1)
5968 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
5971 e
->flags
= EDGE_TRUE_VALUE
;
5974 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5975 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
5979 e
= find_edge (cont_bb
, l2_bb
);
5980 e
->flags
= EDGE_FALLTHRU
;
5982 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
5984 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
5985 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
5986 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
5987 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
5988 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
5989 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
5990 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
5991 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
5993 struct loop
*outer_loop
= alloc_loop ();
5994 outer_loop
->header
= l0_bb
;
5995 outer_loop
->latch
= l2_bb
;
5996 add_loop (outer_loop
, l0_bb
->loop_father
);
5998 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6000 struct loop
*loop
= alloc_loop ();
6001 loop
->header
= l1_bb
;
6002 /* The loop may have multiple latches. */
6003 add_loop (loop
, outer_loop
);
6009 /* A subroutine of expand_omp_for. Generate code for a parallel
6010 loop with static schedule and no specified chunk size. Given
6013 for (V = N1; V cond N2; V += STEP) BODY;
6015 where COND is "<" or ">", we generate pseudocode
6017 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6022 if ((__typeof (V)) -1 > 0 && cond is >)
6023 n = -(adj + N2 - N1) / -STEP;
6025 n = (adj + N2 - N1) / STEP;
6028 if (threadid < tt) goto L3; else goto L4;
6033 s0 = q * threadid + tt;
6036 if (s0 >= e0) goto L2; else goto L0;
6042 if (V cond e) goto L1;
6047 expand_omp_for_static_nochunk (struct omp_region
*region
,
6048 struct omp_for_data
*fd
,
6051 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
6052 tree type
, itype
, vmain
, vback
;
6053 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
6054 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
6056 gimple_stmt_iterator gsi
;
6058 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6059 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6060 bool broken_loop
= region
->cont
== NULL
;
6061 tree
*counts
= NULL
;
6064 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6065 if (POINTER_TYPE_P (type
))
6066 itype
= signed_type_for (type
);
6068 entry_bb
= region
->entry
;
6069 cont_bb
= region
->cont
;
6070 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6071 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6072 gcc_assert (broken_loop
6073 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
6074 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6075 body_bb
= single_succ (seq_start_bb
);
6078 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6079 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6081 exit_bb
= region
->exit
;
6083 /* Iteration space partitioning goes in ENTRY_BB. */
6084 gsi
= gsi_last_bb (entry_bb
);
6085 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6087 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6089 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6090 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6093 if (fd
->collapse
> 1)
6095 int first_zero_iter
= -1;
6096 basic_block l2_dom_bb
= NULL
;
6098 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6099 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6100 fin_bb
, first_zero_iter
,
6104 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6105 t
= integer_one_node
;
6107 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6108 fold_convert (type
, fd
->loop
.n1
),
6109 fold_convert (type
, fd
->loop
.n2
));
6110 if (fd
->collapse
== 1
6111 && TYPE_UNSIGNED (type
)
6112 && (t
== NULL_TREE
|| !integer_onep (t
)))
6114 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6115 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6116 true, GSI_SAME_STMT
);
6117 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6118 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6119 true, GSI_SAME_STMT
);
6120 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6121 NULL_TREE
, NULL_TREE
);
6122 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6123 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6124 expand_omp_regimplify_p
, NULL
, NULL
)
6125 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6126 expand_omp_regimplify_p
, NULL
, NULL
))
6128 gsi
= gsi_for_stmt (cond_stmt
);
6129 gimple_regimplify_operands (cond_stmt
, &gsi
);
6131 ep
= split_block (entry_bb
, cond_stmt
);
6132 ep
->flags
= EDGE_TRUE_VALUE
;
6133 entry_bb
= ep
->dest
;
6134 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6135 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6136 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6137 if (gimple_in_ssa_p (cfun
))
6139 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6140 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6141 !gsi_end_p (gpi
); gsi_next (&gpi
))
6143 gphi
*phi
= gpi
.phi ();
6144 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6145 ep
, UNKNOWN_LOCATION
);
6148 gsi
= gsi_last_bb (entry_bb
);
6151 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6152 t
= fold_convert (itype
, t
);
6153 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6154 true, GSI_SAME_STMT
);
6156 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6157 t
= fold_convert (itype
, t
);
6158 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6159 true, GSI_SAME_STMT
);
6163 step
= fd
->loop
.step
;
6164 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6166 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6167 OMP_CLAUSE__LOOPTEMP_
);
6168 gcc_assert (innerc
);
6169 n1
= OMP_CLAUSE_DECL (innerc
);
6170 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6171 OMP_CLAUSE__LOOPTEMP_
);
6172 gcc_assert (innerc
);
6173 n2
= OMP_CLAUSE_DECL (innerc
);
6175 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6176 true, NULL_TREE
, true, GSI_SAME_STMT
);
6177 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6178 true, NULL_TREE
, true, GSI_SAME_STMT
);
6179 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6180 true, NULL_TREE
, true, GSI_SAME_STMT
);
6182 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6183 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6184 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6185 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6186 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6187 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6188 fold_build1 (NEGATE_EXPR
, itype
, t
),
6189 fold_build1 (NEGATE_EXPR
, itype
, step
));
6191 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6192 t
= fold_convert (itype
, t
);
6193 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6195 q
= create_tmp_reg (itype
, "q");
6196 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
6197 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6198 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
6200 tt
= create_tmp_reg (itype
, "tt");
6201 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
6202 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6203 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
6205 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
6206 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6207 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6209 second_bb
= split_block (entry_bb
, cond_stmt
)->dest
;
6210 gsi
= gsi_last_bb (second_bb
);
6211 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6213 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
6215 gassign
*assign_stmt
6216 = gimple_build_assign (q
, PLUS_EXPR
, q
, build_int_cst (itype
, 1));
6217 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6219 third_bb
= split_block (second_bb
, assign_stmt
)->dest
;
6220 gsi
= gsi_last_bb (third_bb
);
6221 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6223 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6224 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6225 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6227 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6228 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6230 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6231 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6233 /* Remove the GIMPLE_OMP_FOR statement. */
6234 gsi_remove (&gsi
, true);
6236 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6237 gsi
= gsi_start_bb (seq_start_bb
);
6239 tree startvar
= fd
->loop
.v
;
6240 tree endvar
= NULL_TREE
;
6242 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6244 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6245 ? gimple_omp_parallel_clauses (inner_stmt
)
6246 : gimple_omp_for_clauses (inner_stmt
);
6247 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6248 gcc_assert (innerc
);
6249 startvar
= OMP_CLAUSE_DECL (innerc
);
6250 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6251 OMP_CLAUSE__LOOPTEMP_
);
6252 gcc_assert (innerc
);
6253 endvar
= OMP_CLAUSE_DECL (innerc
);
6255 t
= fold_convert (itype
, s0
);
6256 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6257 if (POINTER_TYPE_P (type
))
6258 t
= fold_build_pointer_plus (n1
, t
);
6260 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6261 t
= fold_convert (TREE_TYPE (startvar
), t
);
6262 t
= force_gimple_operand_gsi (&gsi
, t
,
6264 && TREE_ADDRESSABLE (startvar
),
6265 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6266 assign_stmt
= gimple_build_assign (startvar
, t
);
6267 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6269 t
= fold_convert (itype
, e0
);
6270 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6271 if (POINTER_TYPE_P (type
))
6272 t
= fold_build_pointer_plus (n1
, t
);
6274 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6275 t
= fold_convert (TREE_TYPE (startvar
), t
);
6276 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6277 false, GSI_CONTINUE_LINKING
);
6280 assign_stmt
= gimple_build_assign (endvar
, e
);
6281 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6282 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6283 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6285 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
6286 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6288 if (fd
->collapse
> 1)
6289 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6293 /* The code controlling the sequential loop replaces the
6294 GIMPLE_OMP_CONTINUE. */
6295 gsi
= gsi_last_bb (cont_bb
);
6296 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6297 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6298 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6299 vback
= gimple_omp_continue_control_def (cont_stmt
);
6301 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6303 if (POINTER_TYPE_P (type
))
6304 t
= fold_build_pointer_plus (vmain
, step
);
6306 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6307 t
= force_gimple_operand_gsi (&gsi
, t
,
6309 && TREE_ADDRESSABLE (vback
),
6310 NULL_TREE
, true, GSI_SAME_STMT
);
6311 assign_stmt
= gimple_build_assign (vback
, t
);
6312 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6314 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6315 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6317 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6320 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6321 gsi_remove (&gsi
, true);
6323 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6324 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6327 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6328 gsi
= gsi_last_bb (exit_bb
);
6329 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6331 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6332 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6334 gsi_remove (&gsi
, true);
6336 /* Connect all the blocks. */
6337 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6338 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6339 ep
= find_edge (entry_bb
, second_bb
);
6340 ep
->flags
= EDGE_TRUE_VALUE
;
6341 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6342 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6343 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6347 ep
= find_edge (cont_bb
, body_bb
);
6348 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6353 else if (fd
->collapse
> 1)
6356 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6359 ep
->flags
= EDGE_TRUE_VALUE
;
6360 find_edge (cont_bb
, fin_bb
)->flags
6361 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6364 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6365 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6366 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6368 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6369 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6370 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6371 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6373 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6375 struct loop
*loop
= alloc_loop ();
6376 loop
->header
= body_bb
;
6377 if (collapse_bb
== NULL
)
6378 loop
->latch
= cont_bb
;
6379 add_loop (loop
, body_bb
->loop_father
);
6384 /* A subroutine of expand_omp_for. Generate code for a parallel
6385 loop with static schedule and a specified chunk size. Given
6388 for (V = N1; V cond N2; V += STEP) BODY;
6390 where COND is "<" or ">", we generate pseudocode
6392 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6397 if ((__typeof (V)) -1 > 0 && cond is >)
6398 n = -(adj + N2 - N1) / -STEP;
6400 n = (adj + N2 - N1) / STEP;
6402 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6403 here so that V is defined
6404 if the loop is not entered
6406 s0 = (trip * nthreads + threadid) * CHUNK;
6407 e0 = min(s0 + CHUNK, n);
6408 if (s0 < n) goto L1; else goto L4;
6415 if (V cond e) goto L2; else goto L3;
6423 expand_omp_for_static_chunk (struct omp_region
*region
,
6424 struct omp_for_data
*fd
, gimple inner_stmt
)
6426 tree n
, s0
, e0
, e
, t
;
6427 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6428 tree type
, itype
, vmain
, vback
, vextra
;
6429 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6430 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6431 gimple_stmt_iterator gsi
;
6433 enum built_in_function get_num_threads
= BUILT_IN_OMP_GET_NUM_THREADS
;
6434 enum built_in_function get_thread_num
= BUILT_IN_OMP_GET_THREAD_NUM
;
6435 bool broken_loop
= region
->cont
== NULL
;
6436 tree
*counts
= NULL
;
6439 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6440 if (POINTER_TYPE_P (type
))
6441 itype
= signed_type_for (type
);
6443 entry_bb
= region
->entry
;
6444 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6446 iter_part_bb
= se
->dest
;
6447 cont_bb
= region
->cont
;
6448 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6449 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6450 gcc_assert (broken_loop
6451 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6452 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6453 body_bb
= single_succ (seq_start_bb
);
6456 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6457 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6458 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6460 exit_bb
= region
->exit
;
6462 /* Trip and adjustment setup goes in ENTRY_BB. */
6463 gsi
= gsi_last_bb (entry_bb
);
6464 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6466 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
6468 get_num_threads
= BUILT_IN_OMP_GET_NUM_TEAMS
;
6469 get_thread_num
= BUILT_IN_OMP_GET_TEAM_NUM
;
6472 if (fd
->collapse
> 1)
6474 int first_zero_iter
= -1;
6475 basic_block l2_dom_bb
= NULL
;
6477 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6478 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6479 fin_bb
, first_zero_iter
,
6483 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6484 t
= integer_one_node
;
6486 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6487 fold_convert (type
, fd
->loop
.n1
),
6488 fold_convert (type
, fd
->loop
.n2
));
6489 if (fd
->collapse
== 1
6490 && TYPE_UNSIGNED (type
)
6491 && (t
== NULL_TREE
|| !integer_onep (t
)))
6493 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6494 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6495 true, GSI_SAME_STMT
);
6496 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6497 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6498 true, GSI_SAME_STMT
);
6499 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6500 NULL_TREE
, NULL_TREE
);
6501 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6502 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6503 expand_omp_regimplify_p
, NULL
, NULL
)
6504 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6505 expand_omp_regimplify_p
, NULL
, NULL
))
6507 gsi
= gsi_for_stmt (cond_stmt
);
6508 gimple_regimplify_operands (cond_stmt
, &gsi
);
6510 se
= split_block (entry_bb
, cond_stmt
);
6511 se
->flags
= EDGE_TRUE_VALUE
;
6512 entry_bb
= se
->dest
;
6513 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6514 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6515 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6516 if (gimple_in_ssa_p (cfun
))
6518 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6519 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6520 !gsi_end_p (gpi
); gsi_next (&gpi
))
6522 gphi
*phi
= gpi
.phi ();
6523 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6524 se
, UNKNOWN_LOCATION
);
6527 gsi
= gsi_last_bb (entry_bb
);
6530 t
= build_call_expr (builtin_decl_explicit (get_num_threads
), 0);
6531 t
= fold_convert (itype
, t
);
6532 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6533 true, GSI_SAME_STMT
);
6535 t
= build_call_expr (builtin_decl_explicit (get_thread_num
), 0);
6536 t
= fold_convert (itype
, t
);
6537 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6538 true, GSI_SAME_STMT
);
6542 step
= fd
->loop
.step
;
6543 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6545 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6546 OMP_CLAUSE__LOOPTEMP_
);
6547 gcc_assert (innerc
);
6548 n1
= OMP_CLAUSE_DECL (innerc
);
6549 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6550 OMP_CLAUSE__LOOPTEMP_
);
6551 gcc_assert (innerc
);
6552 n2
= OMP_CLAUSE_DECL (innerc
);
6554 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6555 true, NULL_TREE
, true, GSI_SAME_STMT
);
6556 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6557 true, NULL_TREE
, true, GSI_SAME_STMT
);
6558 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6559 true, NULL_TREE
, true, GSI_SAME_STMT
);
6561 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
6562 true, NULL_TREE
, true, GSI_SAME_STMT
);
6564 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6565 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6566 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6567 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6568 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6569 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6570 fold_build1 (NEGATE_EXPR
, itype
, t
),
6571 fold_build1 (NEGATE_EXPR
, itype
, step
));
6573 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6574 t
= fold_convert (itype
, t
);
6575 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6576 true, GSI_SAME_STMT
);
6578 trip_var
= create_tmp_reg (itype
, ".trip");
6579 if (gimple_in_ssa_p (cfun
))
6581 trip_init
= make_ssa_name (trip_var
);
6582 trip_main
= make_ssa_name (trip_var
);
6583 trip_back
= make_ssa_name (trip_var
);
6587 trip_init
= trip_var
;
6588 trip_main
= trip_var
;
6589 trip_back
= trip_var
;
6592 gassign
*assign_stmt
6593 = gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
6594 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6596 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
6597 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6598 if (POINTER_TYPE_P (type
))
6599 t
= fold_build_pointer_plus (n1
, t
);
6601 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6602 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6603 true, GSI_SAME_STMT
);
6605 /* Remove the GIMPLE_OMP_FOR. */
6606 gsi_remove (&gsi
, true);
6608 /* Iteration space partitioning goes in ITER_PART_BB. */
6609 gsi
= gsi_last_bb (iter_part_bb
);
6611 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
6612 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
6613 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
6614 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6615 false, GSI_CONTINUE_LINKING
);
6617 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
6618 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
6619 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6620 false, GSI_CONTINUE_LINKING
);
6622 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
6623 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
6625 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6626 gsi
= gsi_start_bb (seq_start_bb
);
6628 tree startvar
= fd
->loop
.v
;
6629 tree endvar
= NULL_TREE
;
6631 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6633 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6634 ? gimple_omp_parallel_clauses (inner_stmt
)
6635 : gimple_omp_for_clauses (inner_stmt
);
6636 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6637 gcc_assert (innerc
);
6638 startvar
= OMP_CLAUSE_DECL (innerc
);
6639 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6640 OMP_CLAUSE__LOOPTEMP_
);
6641 gcc_assert (innerc
);
6642 endvar
= OMP_CLAUSE_DECL (innerc
);
6645 t
= fold_convert (itype
, s0
);
6646 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6647 if (POINTER_TYPE_P (type
))
6648 t
= fold_build_pointer_plus (n1
, t
);
6650 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6651 t
= fold_convert (TREE_TYPE (startvar
), t
);
6652 t
= force_gimple_operand_gsi (&gsi
, t
,
6654 && TREE_ADDRESSABLE (startvar
),
6655 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6656 assign_stmt
= gimple_build_assign (startvar
, t
);
6657 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6659 t
= fold_convert (itype
, e0
);
6660 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6661 if (POINTER_TYPE_P (type
))
6662 t
= fold_build_pointer_plus (n1
, t
);
6664 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6665 t
= fold_convert (TREE_TYPE (startvar
), t
);
6666 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6667 false, GSI_CONTINUE_LINKING
);
6670 assign_stmt
= gimple_build_assign (endvar
, e
);
6671 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6672 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6673 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6675 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
6676 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6678 if (fd
->collapse
> 1)
6679 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6683 /* The code controlling the sequential loop goes in CONT_BB,
6684 replacing the GIMPLE_OMP_CONTINUE. */
6685 gsi
= gsi_last_bb (cont_bb
);
6686 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6687 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6688 vback
= gimple_omp_continue_control_def (cont_stmt
);
6690 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6692 if (POINTER_TYPE_P (type
))
6693 t
= fold_build_pointer_plus (vmain
, step
);
6695 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6696 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
6697 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6698 true, GSI_SAME_STMT
);
6699 assign_stmt
= gimple_build_assign (vback
, t
);
6700 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6702 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6703 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6705 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6708 /* Remove GIMPLE_OMP_CONTINUE. */
6709 gsi_remove (&gsi
, true);
6711 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6712 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6714 /* Trip update code goes into TRIP_UPDATE_BB. */
6715 gsi
= gsi_start_bb (trip_update_bb
);
6717 t
= build_int_cst (itype
, 1);
6718 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
6719 assign_stmt
= gimple_build_assign (trip_back
, t
);
6720 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6723 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6724 gsi
= gsi_last_bb (exit_bb
);
6725 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6727 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6728 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6730 gsi_remove (&gsi
, true);
6732 /* Connect the new blocks. */
6733 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
6734 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
6738 se
= find_edge (cont_bb
, body_bb
);
6739 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6744 else if (fd
->collapse
> 1)
6747 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6750 se
->flags
= EDGE_TRUE_VALUE
;
6751 find_edge (cont_bb
, trip_update_bb
)->flags
6752 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6754 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
6757 if (gimple_in_ssa_p (cfun
))
6765 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
6767 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6768 remove arguments of the phi nodes in fin_bb. We need to create
6769 appropriate phi nodes in iter_part_bb instead. */
6770 se
= single_pred_edge (fin_bb
);
6771 re
= single_succ_edge (trip_update_bb
);
6772 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
6773 ene
= single_succ_edge (entry_bb
);
6775 psi
= gsi_start_phis (fin_bb
);
6776 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
6777 gsi_next (&psi
), ++i
)
6780 source_location locus
;
6783 t
= gimple_phi_result (phi
);
6784 gcc_assert (t
== redirect_edge_var_map_result (vm
));
6785 nphi
= create_phi_node (t
, iter_part_bb
);
6787 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
6788 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
6790 /* A special case -- fd->loop.v is not yet computed in
6791 iter_part_bb, we need to use vextra instead. */
6792 if (t
== fd
->loop
.v
)
6794 add_phi_arg (nphi
, t
, ene
, locus
);
6795 locus
= redirect_edge_var_map_location (vm
);
6796 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
6798 gcc_assert (gsi_end_p (psi
) && i
== head
->length ());
6799 redirect_edge_var_map_clear (re
);
6802 psi
= gsi_start_phis (fin_bb
);
6803 if (gsi_end_p (psi
))
6805 remove_phi_node (&psi
, false);
6808 /* Make phi node for trip. */
6809 phi
= create_phi_node (trip_main
, iter_part_bb
);
6810 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
6812 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
6817 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
6818 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
6819 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
6820 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6821 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6822 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
6823 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
6824 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6825 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6829 struct loop
*trip_loop
= alloc_loop ();
6830 trip_loop
->header
= iter_part_bb
;
6831 trip_loop
->latch
= trip_update_bb
;
6832 add_loop (trip_loop
, iter_part_bb
->loop_father
);
6834 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6836 struct loop
*loop
= alloc_loop ();
6837 loop
->header
= body_bb
;
6838 if (collapse_bb
== NULL
)
6839 loop
->latch
= cont_bb
;
6840 add_loop (loop
, trip_loop
);
6845 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6847 for (V = N1; V cond N2; V += STEP) BODY;
6849 where COND is "<" or ">" or "!=", we generate pseudocode
6851 for (ind_var = low; ind_var < high; ind_var++)
6853 V = n1 + (ind_var * STEP)
6858 In the above pseudocode, low and high are function parameters of the
6859 child function. In the function below, we are inserting a temp.
6860 variable that will be making a call to two OMP functions that will not be
6861 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6862 with _Cilk_for). These functions are replaced with low and high
6863 by the function that handles taskreg. */
6867 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
6869 bool broken_loop
= region
->cont
== NULL
;
6870 basic_block entry_bb
= region
->entry
;
6871 basic_block cont_bb
= region
->cont
;
6873 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6874 gcc_assert (broken_loop
6875 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6876 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
6877 basic_block l1_bb
, l2_bb
;
6881 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
6882 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6883 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
6884 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6888 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
6889 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
6890 l2_bb
= single_succ (l1_bb
);
6892 basic_block exit_bb
= region
->exit
;
6893 basic_block l2_dom_bb
= NULL
;
6895 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
6897 /* Below statements until the "tree high_val = ..." are pseudo statements
6898 used to pass information to be used by expand_omp_taskreg.
6899 low_val and high_val will be replaced by the __low and __high
6900 parameter from the child function.
6902 The call_exprs part is a place-holder, it is mainly used
6903 to distinctly identify to the top-level part that this is
6904 where we should put low and high (reasoning given in header
6908 = gimple_omp_parallel_child_fn (
6909 as_a
<gomp_parallel
*> (last_stmt (region
->outer
->entry
)));
6910 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
6911 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
6913 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
6915 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
6918 gcc_assert (low_val
&& high_val
);
6920 tree type
= TREE_TYPE (low_val
);
6921 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
6922 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6924 /* Not needed in SSA form right now. */
6925 gcc_assert (!gimple_in_ssa_p (cfun
));
6926 if (l2_dom_bb
== NULL
)
6932 gimple stmt
= gimple_build_assign (ind_var
, n1
);
6934 /* Replace the GIMPLE_OMP_FOR statement. */
6935 gsi_replace (&gsi
, stmt
, true);
6939 /* Code to control the increment goes in the CONT_BB. */
6940 gsi
= gsi_last_bb (cont_bb
);
6941 stmt
= gsi_stmt (gsi
);
6942 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
6943 stmt
= gimple_build_assign (ind_var
, PLUS_EXPR
, ind_var
,
6944 build_one_cst (type
));
6946 /* Replace GIMPLE_OMP_CONTINUE. */
6947 gsi_replace (&gsi
, stmt
, true);
6950 /* Emit the condition in L1_BB. */
6951 gsi
= gsi_after_labels (l1_bb
);
6952 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
6953 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
6955 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
6956 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
6957 fd
->loop
.n1
, fold_convert (sizetype
, t
));
6959 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
6960 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
6961 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
6962 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
6964 /* The condition is always '<' since the runtime will fill in the low
6966 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
6967 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
6969 /* Remove GIMPLE_OMP_RETURN. */
6970 gsi
= gsi_last_bb (exit_bb
);
6971 gsi_remove (&gsi
, true);
6973 /* Connect the new blocks. */
6974 remove_edge (FALLTHRU_EDGE (entry_bb
));
6979 remove_edge (BRANCH_EDGE (entry_bb
));
6980 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
6982 e
= BRANCH_EDGE (l1_bb
);
6983 ne
= FALLTHRU_EDGE (l1_bb
);
6984 e
->flags
= EDGE_TRUE_VALUE
;
6988 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6990 ne
= single_succ_edge (l1_bb
);
6991 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6994 ne
->flags
= EDGE_FALSE_VALUE
;
6995 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6996 ne
->probability
= REG_BR_PROB_BASE
/ 8;
6998 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
6999 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7000 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7004 struct loop
*loop
= alloc_loop ();
7005 loop
->header
= l1_bb
;
7006 loop
->latch
= cont_bb
;
7007 add_loop (loop
, l1_bb
->loop_father
);
7008 loop
->safelen
= INT_MAX
;
7011 /* Pick the correct library function based on the precision of the
7012 induction variable type. */
7013 tree lib_fun
= NULL_TREE
;
7014 if (TYPE_PRECISION (type
) == 32)
7015 lib_fun
= cilk_for_32_fndecl
;
7016 else if (TYPE_PRECISION (type
) == 64)
7017 lib_fun
= cilk_for_64_fndecl
;
7021 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
7023 /* WS_ARGS contains the library function flavor to call:
7024 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7025 user-defined grain value. If the user does not define one, then zero
7026 is passed in by the parser. */
7027 vec_alloc (region
->ws_args
, 2);
7028 region
->ws_args
->quick_push (lib_fun
);
7029 region
->ws_args
->quick_push (fd
->chunk_size
);
7032 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7033 loop. Given parameters:
7035 for (V = N1; V cond N2; V += STEP) BODY;
7037 where COND is "<" or ">", we generate pseudocode
7045 if (V cond N2) goto L0; else goto L2;
7048 For collapsed loops, given parameters:
7050 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7051 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7052 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7055 we generate pseudocode
7061 count3 = (adj + N32 - N31) / STEP3;
7066 count2 = (adj + N22 - N21) / STEP2;
7071 count1 = (adj + N12 - N11) / STEP1;
7072 count = count1 * count2 * count3;
7082 V2 += (V3 cond3 N32) ? 0 : STEP2;
7083 V3 = (V3 cond3 N32) ? V3 : N31;
7084 V1 += (V2 cond2 N22) ? 0 : STEP1;
7085 V2 = (V2 cond2 N22) ? V2 : N21;
7087 if (V < count) goto L0; else goto L2;
7093 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
7096 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
7097 gimple_stmt_iterator gsi
;
7100 bool broken_loop
= region
->cont
== NULL
;
7102 tree
*counts
= NULL
;
7104 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7105 OMP_CLAUSE_SAFELEN
);
7106 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7107 OMP_CLAUSE__SIMDUID_
);
7110 type
= TREE_TYPE (fd
->loop
.v
);
7111 entry_bb
= region
->entry
;
7112 cont_bb
= region
->cont
;
7113 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7114 gcc_assert (broken_loop
7115 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7116 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7119 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7120 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7121 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7122 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7126 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7127 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7128 l2_bb
= single_succ (l1_bb
);
7130 exit_bb
= region
->exit
;
7133 gsi
= gsi_last_bb (entry_bb
);
7135 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7136 /* Not needed in SSA form right now. */
7137 gcc_assert (!gimple_in_ssa_p (cfun
));
7138 if (fd
->collapse
> 1)
7140 int first_zero_iter
= -1;
7141 basic_block zero_iter_bb
= l2_bb
;
7143 counts
= XALLOCAVEC (tree
, fd
->collapse
);
7144 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7145 zero_iter_bb
, first_zero_iter
,
7148 if (l2_dom_bb
== NULL
)
7153 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7155 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7156 OMP_CLAUSE__LOOPTEMP_
);
7157 gcc_assert (innerc
);
7158 n1
= OMP_CLAUSE_DECL (innerc
);
7159 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7160 OMP_CLAUSE__LOOPTEMP_
);
7161 gcc_assert (innerc
);
7162 n2
= OMP_CLAUSE_DECL (innerc
);
7163 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7164 fold_convert (type
, n1
));
7165 if (fd
->collapse
> 1)
7168 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
7174 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7175 fold_convert (type
, fd
->loop
.n1
));
7176 if (fd
->collapse
> 1)
7177 for (i
= 0; i
< fd
->collapse
; i
++)
7179 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7180 if (POINTER_TYPE_P (itype
))
7181 itype
= signed_type_for (itype
);
7182 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
7183 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7187 /* Remove the GIMPLE_OMP_FOR statement. */
7188 gsi_remove (&gsi
, true);
7192 /* Code to control the increment goes in the CONT_BB. */
7193 gsi
= gsi_last_bb (cont_bb
);
7194 stmt
= gsi_stmt (gsi
);
7195 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7197 if (POINTER_TYPE_P (type
))
7198 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
7200 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
7201 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7203 if (fd
->collapse
> 1)
7205 i
= fd
->collapse
- 1;
7206 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7208 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
7209 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
7213 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
7215 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7218 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7220 for (i
= fd
->collapse
- 1; i
> 0; i
--)
7222 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7223 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
7224 if (POINTER_TYPE_P (itype2
))
7225 itype2
= signed_type_for (itype2
);
7226 t
= build3 (COND_EXPR
, itype2
,
7227 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7229 fold_convert (itype
, fd
->loops
[i
].n2
)),
7230 build_int_cst (itype2
, 0),
7231 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
7232 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
7233 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
7235 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
7236 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
7238 t
= build3 (COND_EXPR
, itype
,
7239 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7241 fold_convert (itype
, fd
->loops
[i
].n2
)),
7243 fold_convert (itype
, fd
->loops
[i
].n1
));
7244 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7248 /* Remove GIMPLE_OMP_CONTINUE. */
7249 gsi_remove (&gsi
, true);
7252 /* Emit the condition in L1_BB. */
7253 gsi
= gsi_start_bb (l1_bb
);
7255 t
= fold_convert (type
, n2
);
7256 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7257 false, GSI_CONTINUE_LINKING
);
7258 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
7259 cond_stmt
= gimple_build_cond_empty (t
);
7260 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
7261 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7263 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7266 gsi
= gsi_for_stmt (cond_stmt
);
7267 gimple_regimplify_operands (cond_stmt
, &gsi
);
7270 /* Remove GIMPLE_OMP_RETURN. */
7271 gsi
= gsi_last_bb (exit_bb
);
7272 gsi_remove (&gsi
, true);
7274 /* Connect the new blocks. */
7275 remove_edge (FALLTHRU_EDGE (entry_bb
));
7279 remove_edge (BRANCH_EDGE (entry_bb
));
7280 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7282 e
= BRANCH_EDGE (l1_bb
);
7283 ne
= FALLTHRU_EDGE (l1_bb
);
7284 e
->flags
= EDGE_TRUE_VALUE
;
7288 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7290 ne
= single_succ_edge (l1_bb
);
7291 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7294 ne
->flags
= EDGE_FALSE_VALUE
;
7295 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7296 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7298 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7299 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7300 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7304 struct loop
*loop
= alloc_loop ();
7305 loop
->header
= l1_bb
;
7306 loop
->latch
= cont_bb
;
7307 add_loop (loop
, l1_bb
->loop_father
);
7308 if (safelen
== NULL_TREE
)
7309 loop
->safelen
= INT_MAX
;
7312 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
7313 if (TREE_CODE (safelen
) != INTEGER_CST
)
7315 else if (!tree_fits_uhwi_p (safelen
)
7316 || tree_to_uhwi (safelen
) > INT_MAX
)
7317 loop
->safelen
= INT_MAX
;
7319 loop
->safelen
= tree_to_uhwi (safelen
);
7320 if (loop
->safelen
== 1)
7325 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
7326 cfun
->has_simduid_loops
= true;
7328 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7330 if ((flag_tree_loop_vectorize
7331 || (!global_options_set
.x_flag_tree_loop_vectorize
7332 && !global_options_set
.x_flag_tree_vectorize
))
7333 && flag_tree_loop_optimize
7334 && loop
->safelen
> 1)
7336 loop
->force_vectorize
= true;
7337 cfun
->has_force_vectorize_loops
= true;
7343 /* Expand the OpenMP loop defined by REGION. */
7346 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
7348 struct omp_for_data fd
;
7349 struct omp_for_data_loop
*loops
;
7352 = (struct omp_for_data_loop
*)
7353 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
7354 * sizeof (struct omp_for_data_loop
));
7355 extract_omp_for_data (as_a
<gomp_for
*> (last_stmt (region
->entry
)),
7357 region
->sched_kind
= fd
.sched_kind
;
7359 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
7360 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7361 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7364 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
7365 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7366 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7369 /* If there isn't a continue then this is a degerate case where
7370 the introduction of abnormal edges during lowering will prevent
7371 original loops from being detected. Fix that up. */
7372 loops_state_set (LOOPS_NEED_FIXUP
);
7374 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
7375 expand_omp_simd (region
, &fd
);
7376 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
7377 expand_cilk_for (region
, &fd
);
7378 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
7379 && !fd
.have_ordered
)
7381 if (fd
.chunk_size
== NULL
)
7382 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
7384 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
7388 int fn_index
, start_ix
, next_ix
;
7390 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
7391 == GF_OMP_FOR_KIND_FOR
);
7392 if (fd
.chunk_size
== NULL
7393 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
7394 fd
.chunk_size
= integer_zero_node
;
7395 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
7396 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
7397 ? 3 : fd
.sched_kind
;
7398 fn_index
+= fd
.have_ordered
* 4;
7399 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
7400 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
7401 if (fd
.iter_type
== long_long_unsigned_type_node
)
7403 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7404 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
7405 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7406 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7408 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7409 (enum built_in_function
) next_ix
, inner_stmt
);
7412 if (gimple_in_ssa_p (cfun
))
7413 update_ssa (TODO_update_ssa_only_virtuals
);
7417 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7419 v = GOMP_sections_start (n);
7436 v = GOMP_sections_next ();
7441 If this is a combined parallel sections, replace the call to
7442 GOMP_sections_start with call to GOMP_sections_next. */
7445 expand_omp_sections (struct omp_region
*region
)
7447 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7449 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7450 gimple_stmt_iterator si
, switch_si
;
7451 gomp_sections
*sections_stmt
;
7453 gomp_continue
*cont
;
7456 struct omp_region
*inner
;
7458 bool exit_reachable
= region
->cont
!= NULL
;
7460 gcc_assert (region
->exit
!= NULL
);
7461 entry_bb
= region
->entry
;
7462 l0_bb
= single_succ (entry_bb
);
7463 l1_bb
= region
->cont
;
7464 l2_bb
= region
->exit
;
7465 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7466 l2
= gimple_block_label (l2_bb
);
7469 /* This can happen if there are reductions. */
7470 len
= EDGE_COUNT (l0_bb
->succs
);
7471 gcc_assert (len
> 0);
7472 e
= EDGE_SUCC (l0_bb
, len
- 1);
7473 si
= gsi_last_bb (e
->dest
);
7476 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7477 l2
= gimple_block_label (e
->dest
);
7479 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7481 si
= gsi_last_bb (e
->dest
);
7483 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7485 l2
= gimple_block_label (e
->dest
);
7491 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7493 default_bb
= create_empty_bb (l0_bb
);
7495 /* We will build a switch() with enough cases for all the
7496 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7497 and a default case to abort if something goes wrong. */
7498 len
= EDGE_COUNT (l0_bb
->succs
);
7500 /* Use vec::quick_push on label_vec throughout, since we know the size
7502 auto_vec
<tree
> label_vec (len
);
7504 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7505 GIMPLE_OMP_SECTIONS statement. */
7506 si
= gsi_last_bb (entry_bb
);
7507 sections_stmt
= as_a
<gomp_sections
*> (gsi_stmt (si
));
7508 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
7509 vin
= gimple_omp_sections_control (sections_stmt
);
7510 if (!is_combined_parallel (region
))
7512 /* If we are not inside a combined parallel+sections region,
7513 call GOMP_sections_start. */
7514 t
= build_int_cst (unsigned_type_node
, len
- 1);
7515 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
7516 stmt
= gimple_build_call (u
, 1, t
);
7520 /* Otherwise, call GOMP_sections_next. */
7521 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7522 stmt
= gimple_build_call (u
, 0);
7524 gimple_call_set_lhs (stmt
, vin
);
7525 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7526 gsi_remove (&si
, true);
7528 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7530 switch_si
= gsi_last_bb (l0_bb
);
7531 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
7534 cont
= as_a
<gomp_continue
*> (last_stmt (l1_bb
));
7535 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
7536 vmain
= gimple_omp_continue_control_use (cont
);
7537 vnext
= gimple_omp_continue_control_def (cont
);
7545 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
7546 label_vec
.quick_push (t
);
7549 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7550 for (inner
= region
->inner
, casei
= 1;
7552 inner
= inner
->next
, i
++, casei
++)
7554 basic_block s_entry_bb
, s_exit_bb
;
7556 /* Skip optional reduction region. */
7557 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
7564 s_entry_bb
= inner
->entry
;
7565 s_exit_bb
= inner
->exit
;
7567 t
= gimple_block_label (s_entry_bb
);
7568 u
= build_int_cst (unsigned_type_node
, casei
);
7569 u
= build_case_label (u
, NULL
, t
);
7570 label_vec
.quick_push (u
);
7572 si
= gsi_last_bb (s_entry_bb
);
7573 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
7574 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
7575 gsi_remove (&si
, true);
7576 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
7578 if (s_exit_bb
== NULL
)
7581 si
= gsi_last_bb (s_exit_bb
);
7582 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7583 gsi_remove (&si
, true);
7585 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
7588 /* Error handling code goes in DEFAULT_BB. */
7589 t
= gimple_block_label (default_bb
);
7590 u
= build_case_label (NULL
, NULL
, t
);
7591 make_edge (l0_bb
, default_bb
, 0);
7592 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
7594 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
7595 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
7596 gsi_remove (&switch_si
, true);
7598 si
= gsi_start_bb (default_bb
);
7599 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
7600 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
7606 /* Code to get the next section goes in L1_BB. */
7607 si
= gsi_last_bb (l1_bb
);
7608 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
7610 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
7611 stmt
= gimple_build_call (bfn_decl
, 0);
7612 gimple_call_set_lhs (stmt
, vnext
);
7613 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7614 gsi_remove (&si
, true);
7616 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
7619 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7620 si
= gsi_last_bb (l2_bb
);
7621 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
7622 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
7623 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
7624 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
7626 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
7627 stmt
= gimple_build_call (t
, 0);
7628 if (gimple_omp_return_lhs (gsi_stmt (si
)))
7629 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
7630 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
7631 gsi_remove (&si
, true);
7633 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
7637 /* Expand code for an OpenMP single directive. We've already expanded
7638 much of the code, here we simply place the GOMP_barrier call. */
7641 expand_omp_single (struct omp_region
*region
)
7643 basic_block entry_bb
, exit_bb
;
7644 gimple_stmt_iterator si
;
7646 entry_bb
= region
->entry
;
7647 exit_bb
= region
->exit
;
7649 si
= gsi_last_bb (entry_bb
);
7650 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
7651 gsi_remove (&si
, true);
7652 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7654 si
= gsi_last_bb (exit_bb
);
7655 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
7657 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
7658 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
7660 gsi_remove (&si
, true);
7661 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7665 /* Generic expansion for OpenMP synchronization directives: master,
7666 ordered and critical. All we need to do here is remove the entry
7667 and exit markers for REGION. */
7670 expand_omp_synch (struct omp_region
*region
)
7672 basic_block entry_bb
, exit_bb
;
7673 gimple_stmt_iterator si
;
7675 entry_bb
= region
->entry
;
7676 exit_bb
= region
->exit
;
7678 si
= gsi_last_bb (entry_bb
);
7679 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
7680 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
7681 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
7682 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
7683 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
7684 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
7685 gsi_remove (&si
, true);
7686 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7690 si
= gsi_last_bb (exit_bb
);
7691 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
7692 gsi_remove (&si
, true);
7693 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
7697 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7698 operation as a normal volatile load. */
7701 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
7702 tree loaded_val
, int index
)
7704 enum built_in_function tmpbase
;
7705 gimple_stmt_iterator gsi
;
7706 basic_block store_bb
;
7709 tree decl
, call
, type
, itype
;
7711 gsi
= gsi_last_bb (load_bb
);
7712 stmt
= gsi_stmt (gsi
);
7713 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7714 loc
= gimple_location (stmt
);
7716 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7717 is smaller than word size, then expand_atomic_load assumes that the load
7718 is atomic. We could avoid the builtin entirely in this case. */
7720 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
7721 decl
= builtin_decl_explicit (tmpbase
);
7722 if (decl
== NULL_TREE
)
7725 type
= TREE_TYPE (loaded_val
);
7726 itype
= TREE_TYPE (TREE_TYPE (decl
));
7728 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
7729 build_int_cst (NULL
,
7730 gimple_omp_atomic_seq_cst_p (stmt
)
7732 : MEMMODEL_RELAXED
));
7733 if (!useless_type_conversion_p (type
, itype
))
7734 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7735 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7737 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7738 gsi_remove (&gsi
, true);
7740 store_bb
= single_succ (load_bb
);
7741 gsi
= gsi_last_bb (store_bb
);
7742 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7743 gsi_remove (&gsi
, true);
7745 if (gimple_in_ssa_p (cfun
))
7746 update_ssa (TODO_update_ssa_no_phi
);
7751 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7752 operation as a normal volatile store. */
7755 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
7756 tree loaded_val
, tree stored_val
, int index
)
7758 enum built_in_function tmpbase
;
7759 gimple_stmt_iterator gsi
;
7760 basic_block store_bb
= single_succ (load_bb
);
7763 tree decl
, call
, type
, itype
;
7767 gsi
= gsi_last_bb (load_bb
);
7768 stmt
= gsi_stmt (gsi
);
7769 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
7771 /* If the load value is needed, then this isn't a store but an exchange. */
7772 exchange
= gimple_omp_atomic_need_value_p (stmt
);
7774 gsi
= gsi_last_bb (store_bb
);
7775 stmt
= gsi_stmt (gsi
);
7776 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
7777 loc
= gimple_location (stmt
);
7779 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7780 is smaller than word size, then expand_atomic_store assumes that the store
7781 is atomic. We could avoid the builtin entirely in this case. */
7783 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
7784 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
7785 decl
= builtin_decl_explicit (tmpbase
);
7786 if (decl
== NULL_TREE
)
7789 type
= TREE_TYPE (stored_val
);
7791 /* Dig out the type of the function's second argument. */
7792 itype
= TREE_TYPE (decl
);
7793 itype
= TYPE_ARG_TYPES (itype
);
7794 itype
= TREE_CHAIN (itype
);
7795 itype
= TREE_VALUE (itype
);
7796 imode
= TYPE_MODE (itype
);
7798 if (exchange
&& !can_atomic_exchange_p (imode
, true))
7801 if (!useless_type_conversion_p (itype
, type
))
7802 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
7803 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
7804 build_int_cst (NULL
,
7805 gimple_omp_atomic_seq_cst_p (stmt
)
7807 : MEMMODEL_RELAXED
));
7810 if (!useless_type_conversion_p (type
, itype
))
7811 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
7812 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
7815 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7816 gsi_remove (&gsi
, true);
7818 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7819 gsi
= gsi_last_bb (load_bb
);
7820 gsi_remove (&gsi
, true);
7822 if (gimple_in_ssa_p (cfun
))
7823 update_ssa (TODO_update_ssa_no_phi
);
7828 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7829 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7830 size of the data type, and thus usable to find the index of the builtin
7831 decl. Returns false if the expression is not of the proper form. */
7834 expand_omp_atomic_fetch_op (basic_block load_bb
,
7835 tree addr
, tree loaded_val
,
7836 tree stored_val
, int index
)
7838 enum built_in_function oldbase
, newbase
, tmpbase
;
7839 tree decl
, itype
, call
;
7841 basic_block store_bb
= single_succ (load_bb
);
7842 gimple_stmt_iterator gsi
;
7845 enum tree_code code
;
7846 bool need_old
, need_new
;
7850 /* We expect to find the following sequences:
7853 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7856 val = tmp OP something; (or: something OP tmp)
7857 GIMPLE_OMP_STORE (val)
7859 ???FIXME: Allow a more flexible sequence.
7860 Perhaps use data flow to pick the statements.
7864 gsi
= gsi_after_labels (store_bb
);
7865 stmt
= gsi_stmt (gsi
);
7866 loc
= gimple_location (stmt
);
7867 if (!is_gimple_assign (stmt
))
7870 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
7872 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
7873 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
7874 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
7875 gcc_checking_assert (!need_old
|| !need_new
);
7877 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
7880 /* Check for one of the supported fetch-op operations. */
7881 code
= gimple_assign_rhs_code (stmt
);
7885 case POINTER_PLUS_EXPR
:
7886 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
7887 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
7890 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
7891 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
7894 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
7895 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
7898 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
7899 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
7902 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
7903 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
7909 /* Make sure the expression is of the proper form. */
7910 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
7911 rhs
= gimple_assign_rhs2 (stmt
);
7912 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
7913 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
7914 rhs
= gimple_assign_rhs1 (stmt
);
7918 tmpbase
= ((enum built_in_function
)
7919 ((need_new
? newbase
: oldbase
) + index
+ 1));
7920 decl
= builtin_decl_explicit (tmpbase
);
7921 if (decl
== NULL_TREE
)
7923 itype
= TREE_TYPE (TREE_TYPE (decl
));
7924 imode
= TYPE_MODE (itype
);
7926 /* We could test all of the various optabs involved, but the fact of the
7927 matter is that (with the exception of i486 vs i586 and xadd) all targets
7928 that support any atomic operaton optab also implements compare-and-swap.
7929 Let optabs.c take care of expanding any compare-and-swap loop. */
7930 if (!can_compare_and_swap_p (imode
, true))
7933 gsi
= gsi_last_bb (load_bb
);
7934 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
7936 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7937 It only requires that the operation happen atomically. Thus we can
7938 use the RELAXED memory model. */
7939 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
7940 fold_convert_loc (loc
, itype
, rhs
),
7941 build_int_cst (NULL
,
7942 seq_cst
? MEMMODEL_SEQ_CST
7943 : MEMMODEL_RELAXED
));
7945 if (need_old
|| need_new
)
7947 lhs
= need_old
? loaded_val
: stored_val
;
7948 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
7949 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
7952 call
= fold_convert_loc (loc
, void_type_node
, call
);
7953 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7954 gsi_remove (&gsi
, true);
7956 gsi
= gsi_last_bb (store_bb
);
7957 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
7958 gsi_remove (&gsi
, true);
7959 gsi
= gsi_last_bb (store_bb
);
7960 gsi_remove (&gsi
, true);
7962 if (gimple_in_ssa_p (cfun
))
7963 update_ssa (TODO_update_ssa_no_phi
);
7968 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7972 newval = rhs; // with oldval replacing *addr in rhs
7973 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7974 if (oldval != newval)
7977 INDEX is log2 of the size of the data type, and thus usable to find the
7978 index of the builtin decl. */
7981 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
7982 tree addr
, tree loaded_val
, tree stored_val
,
7985 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
7986 tree type
, itype
, cmpxchg
, iaddr
;
7987 gimple_stmt_iterator si
;
7988 basic_block loop_header
= single_succ (load_bb
);
7991 enum built_in_function fncode
;
7993 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7994 order to use the RELAXED memory model effectively. */
7995 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7997 cmpxchg
= builtin_decl_explicit (fncode
);
7998 if (cmpxchg
== NULL_TREE
)
8000 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8001 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
8003 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
8006 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8007 si
= gsi_last_bb (load_bb
);
8008 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8010 /* For floating-point values, we'll need to view-convert them to integers
8011 so that we can perform the atomic compare and swap. Simplify the
8012 following code by always setting up the "i"ntegral variables. */
8013 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
8017 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
8020 = force_gimple_operand_gsi (&si
,
8021 fold_convert (TREE_TYPE (iaddr
), addr
),
8022 false, NULL_TREE
, true, GSI_SAME_STMT
);
8023 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
8024 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8025 loadedi
= create_tmp_var (itype
);
8026 if (gimple_in_ssa_p (cfun
))
8027 loadedi
= make_ssa_name (loadedi
);
8032 loadedi
= loaded_val
;
8035 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8036 tree loaddecl
= builtin_decl_explicit (fncode
);
8039 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
8040 build_call_expr (loaddecl
, 2, iaddr
,
8041 build_int_cst (NULL_TREE
,
8042 MEMMODEL_RELAXED
)));
8044 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
8045 build_int_cst (TREE_TYPE (iaddr
), 0));
8048 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
8051 /* Move the value to the LOADEDI temporary. */
8052 if (gimple_in_ssa_p (cfun
))
8054 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
8055 phi
= create_phi_node (loadedi
, loop_header
);
8056 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
8060 gsi_insert_before (&si
,
8061 gimple_build_assign (loadedi
, initial
),
8063 if (loadedi
!= loaded_val
)
8065 gimple_stmt_iterator gsi2
;
8068 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
8069 gsi2
= gsi_start_bb (loop_header
);
8070 if (gimple_in_ssa_p (cfun
))
8073 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8074 true, GSI_SAME_STMT
);
8075 stmt
= gimple_build_assign (loaded_val
, x
);
8076 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
8080 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
8081 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8082 true, GSI_SAME_STMT
);
8085 gsi_remove (&si
, true);
8087 si
= gsi_last_bb (store_bb
);
8088 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8091 storedi
= stored_val
;
8094 force_gimple_operand_gsi (&si
,
8095 build1 (VIEW_CONVERT_EXPR
, itype
,
8096 stored_val
), true, NULL_TREE
, true,
8099 /* Build the compare&swap statement. */
8100 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
8101 new_storedi
= force_gimple_operand_gsi (&si
,
8102 fold_convert (TREE_TYPE (loadedi
),
8105 true, GSI_SAME_STMT
);
8107 if (gimple_in_ssa_p (cfun
))
8111 old_vali
= create_tmp_var (TREE_TYPE (loadedi
));
8112 stmt
= gimple_build_assign (old_vali
, loadedi
);
8113 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8115 stmt
= gimple_build_assign (loadedi
, new_storedi
);
8116 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8119 /* Note that we always perform the comparison as an integer, even for
8120 floating point. This allows the atomic operation to properly
8121 succeed even with NaNs and -0.0. */
8122 stmt
= gimple_build_cond_empty
8123 (build2 (NE_EXPR
, boolean_type_node
,
8124 new_storedi
, old_vali
));
8125 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8128 e
= single_succ_edge (store_bb
);
8129 e
->flags
&= ~EDGE_FALLTHRU
;
8130 e
->flags
|= EDGE_FALSE_VALUE
;
8132 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
8134 /* Copy the new value to loadedi (we already did that before the condition
8135 if we are not in SSA). */
8136 if (gimple_in_ssa_p (cfun
))
8138 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
8139 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
8142 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8143 gsi_remove (&si
, true);
8145 struct loop
*loop
= alloc_loop ();
8146 loop
->header
= loop_header
;
8147 loop
->latch
= store_bb
;
8148 add_loop (loop
, loop_header
->loop_father
);
8150 if (gimple_in_ssa_p (cfun
))
8151 update_ssa (TODO_update_ssa_no_phi
);
8156 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8158 GOMP_atomic_start ();
8162 The result is not globally atomic, but works so long as all parallel
8163 references are within #pragma omp atomic directives. According to
8164 responses received from omp@openmp.org, appears to be within spec.
8165 Which makes sense, since that's how several other compilers handle
8166 this situation as well.
8167 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8168 expanding. STORED_VAL is the operand of the matching
8169 GIMPLE_OMP_ATOMIC_STORE.
8172 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8176 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8181 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
8182 tree addr
, tree loaded_val
, tree stored_val
)
8184 gimple_stmt_iterator si
;
8188 si
= gsi_last_bb (load_bb
);
8189 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8191 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
8192 t
= build_call_expr (t
, 0);
8193 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8195 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
8196 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8197 gsi_remove (&si
, true);
8199 si
= gsi_last_bb (store_bb
);
8200 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8202 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
8204 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8206 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
8207 t
= build_call_expr (t
, 0);
8208 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8209 gsi_remove (&si
, true);
8211 if (gimple_in_ssa_p (cfun
))
8212 update_ssa (TODO_update_ssa_no_phi
);
8216 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8217 using expand_omp_atomic_fetch_op. If it failed, we try to
8218 call expand_omp_atomic_pipeline, and if it fails too, the
8219 ultimate fallback is wrapping the operation in a mutex
8220 (expand_omp_atomic_mutex). REGION is the atomic region built
8221 by build_omp_regions_1(). */
8224 expand_omp_atomic (struct omp_region
*region
)
8226 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
8227 gomp_atomic_load
*load
= as_a
<gomp_atomic_load
*> (last_stmt (load_bb
));
8228 gomp_atomic_store
*store
= as_a
<gomp_atomic_store
*> (last_stmt (store_bb
));
8229 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
8230 tree addr
= gimple_omp_atomic_load_rhs (load
);
8231 tree stored_val
= gimple_omp_atomic_store_val (store
);
8232 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8233 HOST_WIDE_INT index
;
8235 /* Make sure the type is one of the supported sizes. */
8236 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
8237 index
= exact_log2 (index
);
8238 if (index
>= 0 && index
<= 4)
8240 unsigned int align
= TYPE_ALIGN_UNIT (type
);
8242 /* __sync builtins require strict data alignment. */
8243 if (exact_log2 (align
) >= index
)
8246 if (loaded_val
== stored_val
8247 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8248 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8249 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8250 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
8254 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8255 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8256 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8257 && store_bb
== single_succ (load_bb
)
8258 && first_stmt (store_bb
) == store
8259 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
8263 /* When possible, use specialized atomic update functions. */
8264 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
8265 && store_bb
== single_succ (load_bb
)
8266 && expand_omp_atomic_fetch_op (load_bb
, addr
,
8267 loaded_val
, stored_val
, index
))
8270 /* If we don't have specialized __sync builtins, try and implement
8271 as a compare and swap loop. */
8272 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
8273 loaded_val
, stored_val
, index
))
8278 /* The ultimate fallback is wrapping the operation in a mutex. */
8279 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
8283 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8286 expand_omp_target (struct omp_region
*region
)
8288 basic_block entry_bb
, exit_bb
, new_bb
;
8289 struct function
*child_cfun
= NULL
;
8290 tree child_fn
= NULL_TREE
, block
, t
;
8291 gimple_stmt_iterator gsi
;
8292 gomp_target
*entry_stmt
;
8296 entry_stmt
= as_a
<gomp_target
*> (last_stmt (region
->entry
));
8297 new_bb
= region
->entry
;
8298 int kind
= gimple_omp_target_kind (entry_stmt
);
8299 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8301 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
8302 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
8305 entry_bb
= region
->entry
;
8306 exit_bb
= region
->exit
;
8308 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8310 unsigned srcidx
, dstidx
, num
;
8312 /* If the target region needs data sent from the parent
8313 function, then the very first statement (except possible
8314 tree profile counter updates) of the parallel body
8315 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8316 &.OMP_DATA_O is passed as an argument to the child function,
8317 we need to replace it with the argument as seen by the child
8320 In most cases, this will end up being the identity assignment
8321 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8322 a function call that has been inlined, the original PARM_DECL
8323 .OMP_DATA_I may have been converted into a different local
8324 variable. In which case, we need to keep the assignment. */
8325 if (gimple_omp_target_data_arg (entry_stmt
))
8327 basic_block entry_succ_bb
= single_succ (entry_bb
);
8328 gimple_stmt_iterator gsi
;
8330 gimple tgtcopy_stmt
= NULL
;
8332 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt
), 0);
8334 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
8336 gcc_assert (!gsi_end_p (gsi
));
8337 stmt
= gsi_stmt (gsi
);
8338 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
8341 if (gimple_num_ops (stmt
) == 2)
8343 tree arg
= gimple_assign_rhs1 (stmt
);
8345 /* We're ignoring the subcode because we're
8346 effectively doing a STRIP_NOPS. */
8348 if (TREE_CODE (arg
) == ADDR_EXPR
8349 && TREE_OPERAND (arg
, 0) == sender
)
8351 tgtcopy_stmt
= stmt
;
8357 gcc_assert (tgtcopy_stmt
!= NULL
);
8358 arg
= DECL_ARGUMENTS (child_fn
);
8360 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
8361 gsi_remove (&gsi
, true);
8364 /* Declare local variables needed in CHILD_CFUN. */
8365 block
= DECL_INITIAL (child_fn
);
8366 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
8367 /* The gimplifier could record temporaries in target block
8368 rather than in containing function's local_decls chain,
8369 which would mean cgraph missed finalizing them. Do it now. */
8370 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
8371 if (TREE_CODE (t
) == VAR_DECL
8373 && !DECL_EXTERNAL (t
))
8374 varpool_node::finalize_decl (t
);
8375 DECL_SAVED_TREE (child_fn
) = NULL
;
8376 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8377 gimple_set_body (child_fn
, NULL
);
8378 TREE_USED (block
) = 1;
8380 /* Reset DECL_CONTEXT on function arguments. */
8381 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
8382 DECL_CONTEXT (t
) = child_fn
;
8384 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8385 so that it can be moved to the child function. */
8386 gsi
= gsi_last_bb (entry_bb
);
8387 stmt
= gsi_stmt (gsi
);
8388 gcc_assert (stmt
&& gimple_code (stmt
) == GIMPLE_OMP_TARGET
8389 && gimple_omp_target_kind (stmt
)
8390 == GF_OMP_TARGET_KIND_REGION
);
8391 gsi_remove (&gsi
, true);
8392 e
= split_block (entry_bb
, stmt
);
8394 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8396 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8399 gsi
= gsi_last_bb (exit_bb
);
8400 gcc_assert (!gsi_end_p (gsi
)
8401 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
8402 stmt
= gimple_build_return (NULL
);
8403 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
8404 gsi_remove (&gsi
, true);
8407 /* Move the target region into CHILD_CFUN. */
8409 block
= gimple_block (entry_stmt
);
8411 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
8413 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
8414 /* When the OMP expansion process cannot guarantee an up-to-date
8415 loop tree arrange for the child function to fixup loops. */
8416 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
8417 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
8419 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8420 num
= vec_safe_length (child_cfun
->local_decls
);
8421 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
8423 t
= (*child_cfun
->local_decls
)[srcidx
];
8424 if (DECL_CONTEXT (t
) == cfun
->decl
)
8426 if (srcidx
!= dstidx
)
8427 (*child_cfun
->local_decls
)[dstidx
] = t
;
8431 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
8433 /* Inform the callgraph about the new function. */
8434 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
8435 cgraph_node::add_new_function (child_fn
, true);
8437 #ifdef ENABLE_OFFLOADING
8438 /* Add the new function to the offload table. */
8439 vec_safe_push (offload_funcs
, child_fn
);
8442 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8443 fixed in a following pass. */
8444 push_cfun (child_cfun
);
8445 cgraph_edge::rebuild_edges ();
8447 #ifdef ENABLE_OFFLOADING
8448 /* Prevent IPA from removing child_fn as unreachable, since there are no
8449 refs from the parent function to child_fn in offload LTO mode. */
8450 struct cgraph_node
*node
= cgraph_node::get (child_fn
);
8451 node
->mark_force_output ();
8454 /* Some EH regions might become dead, see PR34608. If
8455 pass_cleanup_cfg isn't the first pass to happen with the
8456 new child, these dead EH edges might cause problems.
8457 Clean them up now. */
8458 if (flag_exceptions
)
8461 bool changed
= false;
8463 FOR_EACH_BB_FN (bb
, cfun
)
8464 changed
|= gimple_purge_dead_eh_edges (bb
);
8466 cleanup_tree_cfg ();
8471 /* Emit a library call to launch the target region, or do data
8473 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
8474 enum built_in_function start_ix
;
8475 location_t clause_loc
;
8477 clauses
= gimple_omp_target_clauses (entry_stmt
);
8479 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8480 start_ix
= BUILT_IN_GOMP_TARGET
;
8481 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
8482 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
8484 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
8486 /* By default, the value of DEVICE is -1 (let runtime library choose)
8487 and there is no conditional. */
8489 device
= build_int_cst (integer_type_node
, -1);
8491 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
8493 cond
= OMP_CLAUSE_IF_EXPR (c
);
8495 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
8498 device
= OMP_CLAUSE_DEVICE_ID (c
);
8499 clause_loc
= OMP_CLAUSE_LOCATION (c
);
8502 clause_loc
= gimple_location (entry_stmt
);
8504 /* Ensure 'device' is of the correct type. */
8505 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
8507 /* If we found the clause 'if (cond)', build
8508 (cond ? device : -2). */
8511 cond
= gimple_boolify (cond
);
8513 basic_block cond_bb
, then_bb
, else_bb
;
8517 tmp_var
= create_tmp_var (TREE_TYPE (device
));
8518 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8520 gsi
= gsi_last_bb (new_bb
);
8522 e
= split_block (new_bb
, gsi_stmt (gsi
));
8525 e
= split_block (new_bb
, NULL
);
8530 then_bb
= create_empty_bb (cond_bb
);
8531 else_bb
= create_empty_bb (then_bb
);
8532 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
8533 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
8535 stmt
= gimple_build_cond_empty (cond
);
8536 gsi
= gsi_last_bb (cond_bb
);
8537 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8539 gsi
= gsi_start_bb (then_bb
);
8540 stmt
= gimple_build_assign (tmp_var
, device
);
8541 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8543 gsi
= gsi_start_bb (else_bb
);
8544 stmt
= gimple_build_assign (tmp_var
,
8545 build_int_cst (integer_type_node
, -2));
8546 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
8548 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
8549 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
8550 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
8551 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
8552 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
8553 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
8558 gsi
= gsi_last_bb (new_bb
);
8559 t
= gimple_omp_target_data_arg (entry_stmt
);
8562 t1
= size_zero_node
;
8563 t2
= build_zero_cst (ptr_type_node
);
8569 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
8570 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
8571 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
8572 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
8573 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
8577 /* FIXME: This will be address of
8578 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8579 symbol, as soon as the linker plugin is able to create it for us. */
8580 tree openmp_target
= build_zero_cst (ptr_type_node
);
8581 if (kind
== GF_OMP_TARGET_KIND_REGION
)
8583 tree fnaddr
= build_fold_addr_expr (child_fn
);
8584 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 7,
8585 device
, fnaddr
, openmp_target
, t1
, t2
, t3
, t4
);
8588 g
= gimple_build_call (builtin_decl_explicit (start_ix
), 6,
8589 device
, openmp_target
, t1
, t2
, t3
, t4
);
8590 gimple_set_location (g
, gimple_location (entry_stmt
));
8591 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
8592 if (kind
!= GF_OMP_TARGET_KIND_REGION
)
8595 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
8596 gsi_remove (&gsi
, true);
8598 if (kind
== GF_OMP_TARGET_KIND_DATA
&& region
->exit
)
8600 gsi
= gsi_last_bb (region
->exit
);
8602 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
8603 gsi_remove (&gsi
, true);
8608 /* Expand the parallel region tree rooted at REGION. Expansion
8609 proceeds in depth-first order. Innermost regions are expanded
8610 first. This way, parallel regions that require a new function to
8611 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8612 internal dependencies in their body. */
8615 expand_omp (struct omp_region
*region
)
8619 location_t saved_location
;
8620 gimple inner_stmt
= NULL
;
8622 /* First, determine whether this is a combined parallel+workshare
8624 if (region
->type
== GIMPLE_OMP_PARALLEL
)
8625 determine_parallel_type (region
);
8627 if (region
->type
== GIMPLE_OMP_FOR
8628 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
8629 inner_stmt
= last_stmt (region
->inner
->entry
);
8632 expand_omp (region
->inner
);
8634 saved_location
= input_location
;
8635 if (gimple_has_location (last_stmt (region
->entry
)))
8636 input_location
= gimple_location (last_stmt (region
->entry
));
8638 switch (region
->type
)
8640 case GIMPLE_OMP_PARALLEL
:
8641 case GIMPLE_OMP_TASK
:
8642 expand_omp_taskreg (region
);
8645 case GIMPLE_OMP_FOR
:
8646 expand_omp_for (region
, inner_stmt
);
8649 case GIMPLE_OMP_SECTIONS
:
8650 expand_omp_sections (region
);
8653 case GIMPLE_OMP_SECTION
:
8654 /* Individual omp sections are handled together with their
8655 parent GIMPLE_OMP_SECTIONS region. */
8658 case GIMPLE_OMP_SINGLE
:
8659 expand_omp_single (region
);
8662 case GIMPLE_OMP_MASTER
:
8663 case GIMPLE_OMP_TASKGROUP
:
8664 case GIMPLE_OMP_ORDERED
:
8665 case GIMPLE_OMP_CRITICAL
:
8666 case GIMPLE_OMP_TEAMS
:
8667 expand_omp_synch (region
);
8670 case GIMPLE_OMP_ATOMIC_LOAD
:
8671 expand_omp_atomic (region
);
8674 case GIMPLE_OMP_TARGET
:
8675 expand_omp_target (region
);
8682 input_location
= saved_location
;
8683 region
= region
->next
;
8688 /* Helper for build_omp_regions. Scan the dominator tree starting at
8689 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8690 true, the function ends once a single tree is built (otherwise, whole
8691 forest of OMP constructs may be built). */
8694 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
8697 gimple_stmt_iterator gsi
;
8701 gsi
= gsi_last_bb (bb
);
8702 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
8704 struct omp_region
*region
;
8705 enum gimple_code code
;
8707 stmt
= gsi_stmt (gsi
);
8708 code
= gimple_code (stmt
);
8709 if (code
== GIMPLE_OMP_RETURN
)
8711 /* STMT is the return point out of region PARENT. Mark it
8712 as the exit point and make PARENT the immediately
8713 enclosing region. */
8714 gcc_assert (parent
);
8717 parent
= parent
->outer
;
8719 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
8721 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8722 GIMPLE_OMP_RETURN, but matches with
8723 GIMPLE_OMP_ATOMIC_LOAD. */
8724 gcc_assert (parent
);
8725 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
8728 parent
= parent
->outer
;
8731 else if (code
== GIMPLE_OMP_CONTINUE
)
8733 gcc_assert (parent
);
8736 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
8738 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8739 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8742 else if (code
== GIMPLE_OMP_TARGET
8743 && gimple_omp_target_kind (stmt
) == GF_OMP_TARGET_KIND_UPDATE
)
8744 new_omp_region (bb
, code
, parent
);
8747 /* Otherwise, this directive becomes the parent for a new
8749 region
= new_omp_region (bb
, code
, parent
);
8754 if (single_tree
&& !parent
)
8757 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
8759 son
= next_dom_son (CDI_DOMINATORS
, son
))
8760 build_omp_regions_1 (son
, parent
, single_tree
);
8763 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8767 build_omp_regions_root (basic_block root
)
8769 gcc_assert (root_omp_region
== NULL
);
8770 build_omp_regions_1 (root
, NULL
, true);
8771 gcc_assert (root_omp_region
!= NULL
);
8774 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8777 omp_expand_local (basic_block head
)
8779 build_omp_regions_root (head
);
8780 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
8782 fprintf (dump_file
, "\nOMP region tree\n\n");
8783 dump_omp_region (dump_file
, root_omp_region
, 0);
8784 fprintf (dump_file
, "\n");
8787 remove_exit_barriers (root_omp_region
);
8788 expand_omp (root_omp_region
);
8790 free_omp_regions ();
8793 /* Scan the CFG and build a tree of OMP regions. Return the root of
8794 the OMP region tree. */
8797 build_omp_regions (void)
8799 gcc_assert (root_omp_region
== NULL
);
8800 calculate_dominance_info (CDI_DOMINATORS
);
8801 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
8804 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8807 execute_expand_omp (void)
8809 build_omp_regions ();
8811 if (!root_omp_region
)
8816 fprintf (dump_file
, "\nOMP region tree\n\n");
8817 dump_omp_region (dump_file
, root_omp_region
, 0);
8818 fprintf (dump_file
, "\n");
8821 remove_exit_barriers (root_omp_region
);
8823 expand_omp (root_omp_region
);
8825 cleanup_tree_cfg ();
8827 free_omp_regions ();
8832 /* OMP expansion -- the default pass, run before creation of SSA form. */
8836 const pass_data pass_data_expand_omp
=
8838 GIMPLE_PASS
, /* type */
8839 "ompexp", /* name */
8840 OPTGROUP_NONE
, /* optinfo_flags */
8841 TV_NONE
, /* tv_id */
8842 PROP_gimple_any
, /* properties_required */
8843 PROP_gimple_eomp
, /* properties_provided */
8844 0, /* properties_destroyed */
8845 0, /* todo_flags_start */
8846 0, /* todo_flags_finish */
8849 class pass_expand_omp
: public gimple_opt_pass
8852 pass_expand_omp (gcc::context
*ctxt
)
8853 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
8856 /* opt_pass methods: */
8857 virtual unsigned int execute (function
*)
8859 bool gate
= ((flag_openmp
!= 0 || flag_openmp_simd
!= 0
8860 || flag_cilkplus
!= 0) && !seen_error ());
8862 /* This pass always runs, to provide PROP_gimple_eomp.
8863 But there is nothing to do unless -fopenmp is given. */
8867 return execute_expand_omp ();
8870 }; // class pass_expand_omp
8875 make_pass_expand_omp (gcc::context
*ctxt
)
8877 return new pass_expand_omp (ctxt
);
8882 const pass_data pass_data_expand_omp_ssa
=
8884 GIMPLE_PASS
, /* type */
8885 "ompexpssa", /* name */
8886 OPTGROUP_NONE
, /* optinfo_flags */
8887 TV_NONE
, /* tv_id */
8888 PROP_cfg
| PROP_ssa
, /* properties_required */
8889 PROP_gimple_eomp
, /* properties_provided */
8890 0, /* properties_destroyed */
8891 0, /* todo_flags_start */
8892 TODO_cleanup_cfg
| TODO_rebuild_alias
, /* todo_flags_finish */
8895 class pass_expand_omp_ssa
: public gimple_opt_pass
8898 pass_expand_omp_ssa (gcc::context
*ctxt
)
8899 : gimple_opt_pass (pass_data_expand_omp_ssa
, ctxt
)
8902 /* opt_pass methods: */
8903 virtual bool gate (function
*fun
)
8905 return !(fun
->curr_properties
& PROP_gimple_eomp
);
8907 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
8909 }; // class pass_expand_omp_ssa
8914 make_pass_expand_omp_ssa (gcc::context
*ctxt
)
8916 return new pass_expand_omp_ssa (ctxt
);
8919 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8921 /* If ctx is a worksharing context inside of a cancellable parallel
8922 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8923 and conditional branch to parallel's cancel_label to handle
8924 cancellation in the implicit barrier. */
8927 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
8929 gimple omp_return
= gimple_seq_last_stmt (*body
);
8930 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
8931 if (gimple_omp_return_nowait_p (omp_return
))
8934 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
8935 && ctx
->outer
->cancellable
)
8937 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
8938 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
8939 tree lhs
= create_tmp_var (c_bool_type
);
8940 gimple_omp_return_set_lhs (omp_return
, lhs
);
8941 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
8942 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
8943 fold_convert (c_bool_type
,
8944 boolean_false_node
),
8945 ctx
->outer
->cancel_label
, fallthru_label
);
8946 gimple_seq_add_stmt (body
, g
);
8947 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
8951 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8952 CTX is the enclosing OMP context for the current statement. */
8955 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
8957 tree block
, control
;
8958 gimple_stmt_iterator tgsi
;
8959 gomp_sections
*stmt
;
8961 gbind
*new_stmt
, *bind
;
8962 gimple_seq ilist
, dlist
, olist
, new_body
;
8964 stmt
= as_a
<gomp_sections
*> (gsi_stmt (*gsi_p
));
8966 push_gimplify_context ();
8970 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
8971 &ilist
, &dlist
, ctx
, NULL
);
8973 new_body
= gimple_omp_body (stmt
);
8974 gimple_omp_set_body (stmt
, NULL
);
8975 tgsi
= gsi_start (new_body
);
8976 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
8981 sec_start
= gsi_stmt (tgsi
);
8982 sctx
= maybe_lookup_ctx (sec_start
);
8985 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
8986 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
8987 GSI_CONTINUE_LINKING
);
8988 gimple_omp_set_body (sec_start
, NULL
);
8990 if (gsi_one_before_end_p (tgsi
))
8992 gimple_seq l
= NULL
;
8993 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
8995 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
8996 gimple_omp_section_set_last (sec_start
);
8999 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
9000 GSI_CONTINUE_LINKING
);
9003 block
= make_node (BLOCK
);
9004 bind
= gimple_build_bind (NULL
, new_body
, block
);
9007 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
9009 block
= make_node (BLOCK
);
9010 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
9011 gsi_replace (gsi_p
, new_stmt
, true);
9013 pop_gimplify_context (new_stmt
);
9014 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
9015 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
9016 if (BLOCK_VARS (block
))
9017 TREE_USED (block
) = 1;
9020 gimple_seq_add_seq (&new_body
, ilist
);
9021 gimple_seq_add_stmt (&new_body
, stmt
);
9022 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
9023 gimple_seq_add_stmt (&new_body
, bind
);
9025 control
= create_tmp_var (unsigned_type_node
, ".section");
9026 t
= gimple_build_omp_continue (control
, control
);
9027 gimple_omp_sections_set_control (stmt
, control
);
9028 gimple_seq_add_stmt (&new_body
, t
);
9030 gimple_seq_add_seq (&new_body
, olist
);
9031 if (ctx
->cancellable
)
9032 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
9033 gimple_seq_add_seq (&new_body
, dlist
);
9035 new_body
= maybe_catch_exception (new_body
);
9037 t
= gimple_build_omp_return
9038 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
9039 OMP_CLAUSE_NOWAIT
));
9040 gimple_seq_add_stmt (&new_body
, t
);
9041 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
9043 gimple_bind_set_body (new_stmt
, new_body
);
9047 /* A subroutine of lower_omp_single. Expand the simple form of
9048 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
9050 if (GOMP_single_start ())
9052 [ GOMP_barrier (); ] -> unless 'nowait' is present.
9054 FIXME. It may be better to delay expanding the logic of this until
9055 pass_expand_omp. The expanded logic may make the job more difficult
9056 to a synchronization analysis pass. */
9059 lower_omp_single_simple (gomp_single
*single_stmt
, gimple_seq
*pre_p
)
9061 location_t loc
= gimple_location (single_stmt
);
9062 tree tlabel
= create_artificial_label (loc
);
9063 tree flabel
= create_artificial_label (loc
);
9067 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
9068 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)));
9069 call
= gimple_build_call (decl
, 0);
9070 gimple_call_set_lhs (call
, lhs
);
9071 gimple_seq_add_stmt (pre_p
, call
);
9073 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
9074 fold_convert_loc (loc
, TREE_TYPE (lhs
),
9077 gimple_seq_add_stmt (pre_p
, cond
);
9078 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
9079 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
9080 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
9084 /* A subroutine of lower_omp_single. Expand the simple form of
9085 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9087 #pragma omp single copyprivate (a, b, c)
9089 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9092 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9098 GOMP_single_copy_end (©out);
9109 FIXME. It may be better to delay expanding the logic of this until
9110 pass_expand_omp. The expanded logic may make the job more difficult
9111 to a synchronization analysis pass. */
9114 lower_omp_single_copy (gomp_single
*single_stmt
, gimple_seq
*pre_p
,
9117 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
9118 gimple_seq copyin_seq
;
9119 location_t loc
= gimple_location (single_stmt
);
9121 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
9123 ptr_type
= build_pointer_type (ctx
->record_type
);
9124 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
9126 l0
= create_artificial_label (loc
);
9127 l1
= create_artificial_label (loc
);
9128 l2
= create_artificial_label (loc
);
9130 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
9131 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
9132 t
= fold_convert_loc (loc
, ptr_type
, t
);
9133 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
9135 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
9136 build_int_cst (ptr_type
, 0));
9137 t
= build3 (COND_EXPR
, void_type_node
, t
,
9138 build_and_jump (&l0
), build_and_jump (&l1
));
9139 gimplify_and_add (t
, pre_p
);
9141 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
9143 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
9146 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
9149 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
9150 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
9151 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
9152 gimplify_and_add (t
, pre_p
);
9154 t
= build_and_jump (&l2
);
9155 gimplify_and_add (t
, pre_p
);
9157 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
9159 gimple_seq_add_seq (pre_p
, copyin_seq
);
9161 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
9165 /* Expand code for an OpenMP single directive. */
9168 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9172 gomp_single
*single_stmt
= as_a
<gomp_single
*> (gsi_stmt (*gsi_p
));
9174 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
9176 push_gimplify_context ();
9178 block
= make_node (BLOCK
);
9179 bind
= gimple_build_bind (NULL
, NULL
, block
);
9180 gsi_replace (gsi_p
, bind
, true);
9183 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
9184 &bind_body
, &dlist
, ctx
, NULL
);
9185 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
9187 gimple_seq_add_stmt (&bind_body
, single_stmt
);
9189 if (ctx
->record_type
)
9190 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
9192 lower_omp_single_simple (single_stmt
, &bind_body
);
9194 gimple_omp_set_body (single_stmt
, NULL
);
9196 gimple_seq_add_seq (&bind_body
, dlist
);
9198 bind_body
= maybe_catch_exception (bind_body
);
9200 t
= gimple_build_omp_return
9201 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
9202 OMP_CLAUSE_NOWAIT
));
9203 gimple_seq_add_stmt (&bind_body_tail
, t
);
9204 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
9205 if (ctx
->record_type
)
9207 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
9208 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
9209 TREE_THIS_VOLATILE (clobber
) = 1;
9210 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
9211 clobber
), GSI_SAME_STMT
);
9213 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
9214 gimple_bind_set_body (bind
, bind_body
);
9216 pop_gimplify_context (bind
);
9218 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9219 BLOCK_VARS (block
) = ctx
->block_vars
;
9220 if (BLOCK_VARS (block
))
9221 TREE_USED (block
) = 1;
9225 /* Expand code for an OpenMP master directive. */
9228 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9230 tree block
, lab
= NULL
, x
, bfn_decl
;
9231 gimple stmt
= gsi_stmt (*gsi_p
);
9233 location_t loc
= gimple_location (stmt
);
9236 push_gimplify_context ();
9238 block
= make_node (BLOCK
);
9239 bind
= gimple_build_bind (NULL
, NULL
, block
);
9240 gsi_replace (gsi_p
, bind
, true);
9241 gimple_bind_add_stmt (bind
, stmt
);
9243 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
9244 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
9245 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
9246 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
9248 gimplify_and_add (x
, &tseq
);
9249 gimple_bind_add_seq (bind
, tseq
);
9251 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9252 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9253 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9254 gimple_omp_set_body (stmt
, NULL
);
9256 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
9258 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9260 pop_gimplify_context (bind
);
9262 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9263 BLOCK_VARS (block
) = ctx
->block_vars
;
9267 /* Expand code for an OpenMP taskgroup directive. */
9270 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9272 gimple stmt
= gsi_stmt (*gsi_p
);
9275 tree block
= make_node (BLOCK
);
9277 bind
= gimple_build_bind (NULL
, NULL
, block
);
9278 gsi_replace (gsi_p
, bind
, true);
9279 gimple_bind_add_stmt (bind
, stmt
);
9281 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
9283 gimple_bind_add_stmt (bind
, x
);
9285 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9286 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9287 gimple_omp_set_body (stmt
, NULL
);
9289 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9291 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9292 BLOCK_VARS (block
) = ctx
->block_vars
;
9296 /* Expand code for an OpenMP ordered directive. */
9299 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9302 gimple stmt
= gsi_stmt (*gsi_p
);
9306 push_gimplify_context ();
9308 block
= make_node (BLOCK
);
9309 bind
= gimple_build_bind (NULL
, NULL
, block
);
9310 gsi_replace (gsi_p
, bind
, true);
9311 gimple_bind_add_stmt (bind
, stmt
);
9313 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
9315 gimple_bind_add_stmt (bind
, x
);
9317 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9318 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9319 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9320 gimple_omp_set_body (stmt
, NULL
);
9322 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
9323 gimple_bind_add_stmt (bind
, x
);
9325 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9327 pop_gimplify_context (bind
);
9329 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9330 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
9334 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9335 substitution of a couple of function calls. But in the NAMED case,
9336 requires that languages coordinate a symbol name. It is therefore
9337 best put here in common code. */
9339 static GTY(()) hash_map
<tree
, tree
> *critical_name_mutexes
;
9342 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9345 tree name
, lock
, unlock
;
9346 gomp_critical
*stmt
= as_a
<gomp_critical
*> (gsi_stmt (*gsi_p
));
9348 location_t loc
= gimple_location (stmt
);
9351 name
= gimple_omp_critical_name (stmt
);
9356 if (!critical_name_mutexes
)
9357 critical_name_mutexes
= hash_map
<tree
, tree
>::create_ggc (10);
9359 tree
*n
= critical_name_mutexes
->get (name
);
9364 decl
= create_tmp_var_raw (ptr_type_node
);
9366 new_str
= ACONCAT ((".gomp_critical_user_",
9367 IDENTIFIER_POINTER (name
), NULL
));
9368 DECL_NAME (decl
) = get_identifier (new_str
);
9369 TREE_PUBLIC (decl
) = 1;
9370 TREE_STATIC (decl
) = 1;
9371 DECL_COMMON (decl
) = 1;
9372 DECL_ARTIFICIAL (decl
) = 1;
9373 DECL_IGNORED_P (decl
) = 1;
9375 varpool_node::finalize_decl (decl
);
9377 critical_name_mutexes
->put (name
, decl
);
9382 /* If '#pragma omp critical' is inside target region or
9383 inside function marked as offloadable, the symbol must be
9384 marked as offloadable too. */
9386 if (cgraph_node::get (current_function_decl
)->offloadable
)
9387 varpool_node::get_create (decl
)->offloadable
= 1;
9389 for (octx
= ctx
->outer
; octx
; octx
= octx
->outer
)
9390 if (is_targetreg_ctx (octx
))
9392 varpool_node::get_create (decl
)->offloadable
= 1;
9396 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
9397 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
9399 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
9400 unlock
= build_call_expr_loc (loc
, unlock
, 1,
9401 build_fold_addr_expr_loc (loc
, decl
));
9405 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
9406 lock
= build_call_expr_loc (loc
, lock
, 0);
9408 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
9409 unlock
= build_call_expr_loc (loc
, unlock
, 0);
9412 push_gimplify_context ();
9414 block
= make_node (BLOCK
);
9415 bind
= gimple_build_bind (NULL
, NULL
, block
);
9416 gsi_replace (gsi_p
, bind
, true);
9417 gimple_bind_add_stmt (bind
, stmt
);
9419 tbody
= gimple_bind_body (bind
);
9420 gimplify_and_add (lock
, &tbody
);
9421 gimple_bind_set_body (bind
, tbody
);
9423 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9424 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
9425 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
9426 gimple_omp_set_body (stmt
, NULL
);
9428 tbody
= gimple_bind_body (bind
);
9429 gimplify_and_add (unlock
, &tbody
);
9430 gimple_bind_set_body (bind
, tbody
);
9432 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
9434 pop_gimplify_context (bind
);
9435 gimple_bind_append_vars (bind
, ctx
->block_vars
);
9436 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
9440 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9441 for a lastprivate clause. Given a loop control predicate of (V
9442 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9443 is appended to *DLIST, iterator initialization is appended to
9447 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
9448 gimple_seq
*dlist
, struct omp_context
*ctx
)
9450 tree clauses
, cond
, vinit
;
9451 enum tree_code cond_code
;
9454 cond_code
= fd
->loop
.cond_code
;
9455 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
9457 /* When possible, use a strict equality expression. This can let VRP
9458 type optimizations deduce the value and remove a copy. */
9459 if (tree_fits_shwi_p (fd
->loop
.step
))
9461 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
9462 if (step
== 1 || step
== -1)
9463 cond_code
= EQ_EXPR
;
9466 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, fd
->loop
.n2
);
9468 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
9470 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
9471 if (!gimple_seq_empty_p (stmts
))
9473 gimple_seq_add_seq (&stmts
, *dlist
);
9476 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9477 vinit
= fd
->loop
.n1
;
9478 if (cond_code
== EQ_EXPR
9479 && tree_fits_shwi_p (fd
->loop
.n2
)
9480 && ! integer_zerop (fd
->loop
.n2
))
9481 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
9483 vinit
= unshare_expr (vinit
);
9485 /* Initialize the iterator variable, so that threads that don't execute
9486 any iterations don't execute the lastprivate clauses by accident. */
9487 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
9492 /* Lower code for an OpenMP loop directive. */
9495 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
9498 struct omp_for_data fd
, *fdp
= NULL
;
9499 gomp_for
*stmt
= as_a
<gomp_for
*> (gsi_stmt (*gsi_p
));
9501 gimple_seq omp_for_body
, body
, dlist
;
9504 push_gimplify_context ();
9506 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
9508 block
= make_node (BLOCK
);
9509 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
9510 /* Replace at gsi right away, so that 'stmt' is no member
9511 of a sequence anymore as we're going to add to to a different
9513 gsi_replace (gsi_p
, new_stmt
, true);
9515 /* Move declaration of temporaries in the loop body before we make
9517 omp_for_body
= gimple_omp_body (stmt
);
9518 if (!gimple_seq_empty_p (omp_for_body
)
9519 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
9522 = as_a
<gbind
*> (gimple_seq_first_stmt (omp_for_body
));
9523 tree vars
= gimple_bind_vars (inner_bind
);
9524 gimple_bind_append_vars (new_stmt
, vars
);
9525 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9526 keep them on the inner_bind and it's block. */
9527 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
9528 if (gimple_bind_block (inner_bind
))
9529 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
9532 if (gimple_omp_for_combined_into_p (stmt
))
9534 extract_omp_for_data (stmt
, &fd
, NULL
);
9537 /* We need two temporaries with fd.loop.v type (istart/iend)
9538 and then (fd.collapse - 1) temporaries with the same
9539 type for count2 ... countN-1 vars if not constant. */
9541 tree type
= fd
.iter_type
;
9543 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
9544 count
+= fd
.collapse
- 1;
9545 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
9546 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
9550 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
9551 OMP_CLAUSE__LOOPTEMP_
);
9552 for (i
= 0; i
< count
; i
++)
9557 gcc_assert (outerc
);
9558 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
9559 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
9560 OMP_CLAUSE__LOOPTEMP_
);
9564 temp
= create_tmp_var (type
);
9565 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
9567 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
9568 OMP_CLAUSE_DECL (*pc
) = temp
;
9569 pc
= &OMP_CLAUSE_CHAIN (*pc
);
9574 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9577 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
9579 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
9581 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
9583 /* Lower the header expressions. At this point, we can assume that
9584 the header is of the form:
9586 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9588 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9589 using the .omp_data_s mapping, if needed. */
9590 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
9592 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
9593 if (!is_gimple_min_invariant (*rhs_p
))
9594 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9596 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
9597 if (!is_gimple_min_invariant (*rhs_p
))
9598 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9600 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
9601 if (!is_gimple_min_invariant (*rhs_p
))
9602 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
9605 /* Once lowered, extract the bounds and clauses. */
9606 extract_omp_for_data (stmt
, &fd
, NULL
);
9608 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
9610 gimple_seq_add_stmt (&body
, stmt
);
9611 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
9613 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
9616 /* After the loop, add exit clauses. */
9617 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
9619 if (ctx
->cancellable
)
9620 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
9622 gimple_seq_add_seq (&body
, dlist
);
9624 body
= maybe_catch_exception (body
);
9626 /* Region exit marker goes at the end of the loop body. */
9627 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
9628 maybe_add_implicit_barrier_cancel (ctx
, &body
);
9629 pop_gimplify_context (new_stmt
);
9631 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
9632 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
9633 if (BLOCK_VARS (block
))
9634 TREE_USED (block
) = 1;
9636 gimple_bind_set_body (new_stmt
, body
);
9637 gimple_omp_set_body (stmt
, NULL
);
9638 gimple_omp_for_set_pre_body (stmt
, NULL
);
9641 /* Callback for walk_stmts. Check if the current statement only contains
9642 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9645 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
9646 bool *handled_ops_p
,
9647 struct walk_stmt_info
*wi
)
9649 int *info
= (int *) wi
->info
;
9650 gimple stmt
= gsi_stmt (*gsi_p
);
9652 *handled_ops_p
= true;
9653 switch (gimple_code (stmt
))
9657 case GIMPLE_OMP_FOR
:
9658 case GIMPLE_OMP_SECTIONS
:
9659 *info
= *info
== 0 ? 1 : -1;
9668 struct omp_taskcopy_context
9670 /* This field must be at the beginning, as we do "inheritance": Some
9671 callback functions for tree-inline.c (e.g., omp_copy_decl)
9672 receive a copy_body_data pointer that is up-casted to an
9673 omp_context pointer. */
9679 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
9681 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
9683 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
9684 return create_tmp_var (TREE_TYPE (var
));
9690 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
9692 tree name
, new_fields
= NULL
, type
, f
;
9694 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
9695 name
= DECL_NAME (TYPE_NAME (orig_type
));
9696 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
9697 TYPE_DECL
, name
, type
);
9698 TYPE_NAME (type
) = name
;
9700 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
9702 tree new_f
= copy_node (f
);
9703 DECL_CONTEXT (new_f
) = type
;
9704 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
9705 TREE_CHAIN (new_f
) = new_fields
;
9706 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9707 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
9708 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
9711 tcctx
->cb
.decl_map
->put (f
, new_f
);
9713 TYPE_FIELDS (type
) = nreverse (new_fields
);
9718 /* Create task copyfn. */
9721 create_task_copyfn (gomp_task
*task_stmt
, omp_context
*ctx
)
9723 struct function
*child_cfun
;
9724 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
9725 tree record_type
, srecord_type
, bind
, list
;
9726 bool record_needs_remap
= false, srecord_needs_remap
= false;
9728 struct omp_taskcopy_context tcctx
;
9729 location_t loc
= gimple_location (task_stmt
);
9731 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
9732 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
9733 gcc_assert (child_cfun
->cfg
== NULL
);
9734 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
9736 /* Reset DECL_CONTEXT on function arguments. */
9737 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
9738 DECL_CONTEXT (t
) = child_fn
;
9740 /* Populate the function. */
9741 push_gimplify_context ();
9742 push_cfun (child_cfun
);
9744 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
9745 TREE_SIDE_EFFECTS (bind
) = 1;
9747 DECL_SAVED_TREE (child_fn
) = bind
;
9748 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
9750 /* Remap src and dst argument types if needed. */
9751 record_type
= ctx
->record_type
;
9752 srecord_type
= ctx
->srecord_type
;
9753 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
9754 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9756 record_needs_remap
= true;
9759 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
9760 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
9762 srecord_needs_remap
= true;
9766 if (record_needs_remap
|| srecord_needs_remap
)
9768 memset (&tcctx
, '\0', sizeof (tcctx
));
9769 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
9770 tcctx
.cb
.dst_fn
= child_fn
;
9771 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
9772 gcc_checking_assert (tcctx
.cb
.src_node
);
9773 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
9774 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
9775 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
9776 tcctx
.cb
.eh_lp_nr
= 0;
9777 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
9778 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
9781 if (record_needs_remap
)
9782 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
9783 if (srecord_needs_remap
)
9784 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
9787 tcctx
.cb
.decl_map
= NULL
;
9789 arg
= DECL_ARGUMENTS (child_fn
);
9790 TREE_TYPE (arg
) = build_pointer_type (record_type
);
9791 sarg
= DECL_CHAIN (arg
);
9792 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
9794 /* First pass: initialize temporaries used in record_type and srecord_type
9795 sizes and field offsets. */
9796 if (tcctx
.cb
.decl_map
)
9797 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9798 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9802 decl
= OMP_CLAUSE_DECL (c
);
9803 p
= tcctx
.cb
.decl_map
->get (decl
);
9806 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9807 sf
= (tree
) n
->value
;
9808 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9809 src
= build_simple_mem_ref_loc (loc
, sarg
);
9810 src
= omp_build_component_ref (src
, sf
);
9811 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
9812 append_to_statement_list (t
, &list
);
9815 /* Second pass: copy shared var pointers and copy construct non-VLA
9816 firstprivate vars. */
9817 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9818 switch (OMP_CLAUSE_CODE (c
))
9820 case OMP_CLAUSE_SHARED
:
9821 decl
= OMP_CLAUSE_DECL (c
);
9822 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9825 f
= (tree
) n
->value
;
9826 if (tcctx
.cb
.decl_map
)
9827 f
= *tcctx
.cb
.decl_map
->get (f
);
9828 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9829 sf
= (tree
) n
->value
;
9830 if (tcctx
.cb
.decl_map
)
9831 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9832 src
= build_simple_mem_ref_loc (loc
, sarg
);
9833 src
= omp_build_component_ref (src
, sf
);
9834 dst
= build_simple_mem_ref_loc (loc
, arg
);
9835 dst
= omp_build_component_ref (dst
, f
);
9836 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9837 append_to_statement_list (t
, &list
);
9839 case OMP_CLAUSE_FIRSTPRIVATE
:
9840 decl
= OMP_CLAUSE_DECL (c
);
9841 if (is_variable_sized (decl
))
9843 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9846 f
= (tree
) n
->value
;
9847 if (tcctx
.cb
.decl_map
)
9848 f
= *tcctx
.cb
.decl_map
->get (f
);
9849 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9852 sf
= (tree
) n
->value
;
9853 if (tcctx
.cb
.decl_map
)
9854 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9855 src
= build_simple_mem_ref_loc (loc
, sarg
);
9856 src
= omp_build_component_ref (src
, sf
);
9857 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
9858 src
= build_simple_mem_ref_loc (loc
, src
);
9862 dst
= build_simple_mem_ref_loc (loc
, arg
);
9863 dst
= omp_build_component_ref (dst
, f
);
9864 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9865 append_to_statement_list (t
, &list
);
9867 case OMP_CLAUSE_PRIVATE
:
9868 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
9870 decl
= OMP_CLAUSE_DECL (c
);
9871 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9872 f
= (tree
) n
->value
;
9873 if (tcctx
.cb
.decl_map
)
9874 f
= *tcctx
.cb
.decl_map
->get (f
);
9875 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
9878 sf
= (tree
) n
->value
;
9879 if (tcctx
.cb
.decl_map
)
9880 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9881 src
= build_simple_mem_ref_loc (loc
, sarg
);
9882 src
= omp_build_component_ref (src
, sf
);
9883 if (use_pointer_for_field (decl
, NULL
))
9884 src
= build_simple_mem_ref_loc (loc
, src
);
9888 dst
= build_simple_mem_ref_loc (loc
, arg
);
9889 dst
= omp_build_component_ref (dst
, f
);
9890 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
9891 append_to_statement_list (t
, &list
);
9897 /* Last pass: handle VLA firstprivates. */
9898 if (tcctx
.cb
.decl_map
)
9899 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
9900 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
9904 decl
= OMP_CLAUSE_DECL (c
);
9905 if (!is_variable_sized (decl
))
9907 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
9910 f
= (tree
) n
->value
;
9911 f
= *tcctx
.cb
.decl_map
->get (f
);
9912 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
9913 ind
= DECL_VALUE_EXPR (decl
);
9914 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
9915 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
9916 n
= splay_tree_lookup (ctx
->sfield_map
,
9917 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9918 sf
= (tree
) n
->value
;
9919 sf
= *tcctx
.cb
.decl_map
->get (sf
);
9920 src
= build_simple_mem_ref_loc (loc
, sarg
);
9921 src
= omp_build_component_ref (src
, sf
);
9922 src
= build_simple_mem_ref_loc (loc
, src
);
9923 dst
= build_simple_mem_ref_loc (loc
, arg
);
9924 dst
= omp_build_component_ref (dst
, f
);
9925 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
9926 append_to_statement_list (t
, &list
);
9927 n
= splay_tree_lookup (ctx
->field_map
,
9928 (splay_tree_key
) TREE_OPERAND (ind
, 0));
9929 df
= (tree
) n
->value
;
9930 df
= *tcctx
.cb
.decl_map
->get (df
);
9931 ptr
= build_simple_mem_ref_loc (loc
, arg
);
9932 ptr
= omp_build_component_ref (ptr
, df
);
9933 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
9934 build_fold_addr_expr_loc (loc
, dst
));
9935 append_to_statement_list (t
, &list
);
9938 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
9939 append_to_statement_list (t
, &list
);
9941 if (tcctx
.cb
.decl_map
)
9942 delete tcctx
.cb
.decl_map
;
9943 pop_gimplify_context (NULL
);
9944 BIND_EXPR_BODY (bind
) = list
;
9949 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
9953 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
9955 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
9957 gcc_assert (clauses
);
9958 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9959 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
9960 switch (OMP_CLAUSE_DEPEND_KIND (c
))
9962 case OMP_CLAUSE_DEPEND_IN
:
9965 case OMP_CLAUSE_DEPEND_OUT
:
9966 case OMP_CLAUSE_DEPEND_INOUT
:
9972 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
9973 tree array
= create_tmp_var (type
);
9974 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
9976 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
9977 gimple_seq_add_stmt (iseq
, g
);
9978 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
9980 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
9981 gimple_seq_add_stmt (iseq
, g
);
9982 for (i
= 0; i
< 2; i
++)
9984 if ((i
? n_in
: n_out
) == 0)
9986 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9987 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
9988 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
9990 tree t
= OMP_CLAUSE_DECL (c
);
9991 t
= fold_convert (ptr_type_node
, t
);
9992 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
9993 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
9994 NULL_TREE
, NULL_TREE
);
9995 g
= gimple_build_assign (r
, t
);
9996 gimple_seq_add_stmt (iseq
, g
);
9999 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
10000 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
10001 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
10002 OMP_CLAUSE_CHAIN (c
) = *p
;
10004 tree clobber
= build_constructor (type
, NULL
);
10005 TREE_THIS_VOLATILE (clobber
) = 1;
10006 g
= gimple_build_assign (array
, clobber
);
10007 gimple_seq_add_stmt (oseq
, g
);
10010 /* Lower the OpenMP parallel or task directive in the current statement
10011 in GSI_P. CTX holds context information for the directive. */
10014 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10018 gimple stmt
= gsi_stmt (*gsi_p
);
10019 gbind
*par_bind
, *bind
, *dep_bind
= NULL
;
10020 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
10021 location_t loc
= gimple_location (stmt
);
10023 clauses
= gimple_omp_taskreg_clauses (stmt
);
10025 = as_a
<gbind
*> (gimple_seq_first_stmt (gimple_omp_body (stmt
)));
10026 par_body
= gimple_bind_body (par_bind
);
10027 child_fn
= ctx
->cb
.dst_fn
;
10028 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
10029 && !gimple_omp_parallel_combined_p (stmt
))
10031 struct walk_stmt_info wi
;
10034 memset (&wi
, 0, sizeof (wi
));
10036 wi
.val_only
= true;
10037 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
10039 gimple_omp_parallel_set_combined_p (stmt
, true);
10041 gimple_seq dep_ilist
= NULL
;
10042 gimple_seq dep_olist
= NULL
;
10043 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
10044 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
10046 push_gimplify_context ();
10047 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
10048 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
10051 if (ctx
->srecord_type
)
10052 create_task_copyfn (as_a
<gomp_task
*> (stmt
), ctx
);
10054 push_gimplify_context ();
10059 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
10060 lower_omp (&par_body
, ctx
);
10061 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
10062 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
10064 /* Declare all the variables created by mapping and the variables
10065 declared in the scope of the parallel body. */
10066 record_vars_into (ctx
->block_vars
, child_fn
);
10067 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
10069 if (ctx
->record_type
)
10072 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
10073 : ctx
->record_type
, ".omp_data_o");
10074 DECL_NAMELESS (ctx
->sender_decl
) = 1;
10075 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
10076 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
10081 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
10082 lower_send_shared_vars (&ilist
, &olist
, ctx
);
10084 if (ctx
->record_type
)
10086 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
10087 TREE_THIS_VOLATILE (clobber
) = 1;
10088 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
10092 /* Once all the expansions are done, sequence all the different
10093 fragments inside gimple_omp_body. */
10097 if (ctx
->record_type
)
10099 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10100 /* fixup_child_record_type might have changed receiver_decl's type. */
10101 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
10102 gimple_seq_add_stmt (&new_body
,
10103 gimple_build_assign (ctx
->receiver_decl
, t
));
10106 gimple_seq_add_seq (&new_body
, par_ilist
);
10107 gimple_seq_add_seq (&new_body
, par_body
);
10108 gimple_seq_add_seq (&new_body
, par_rlist
);
10109 if (ctx
->cancellable
)
10110 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
10111 gimple_seq_add_seq (&new_body
, par_olist
);
10112 new_body
= maybe_catch_exception (new_body
);
10113 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
10114 gimple_omp_set_body (stmt
, new_body
);
10116 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
10117 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
10118 gimple_bind_add_seq (bind
, ilist
);
10119 gimple_bind_add_stmt (bind
, stmt
);
10120 gimple_bind_add_seq (bind
, olist
);
10122 pop_gimplify_context (NULL
);
10126 gimple_bind_add_seq (dep_bind
, dep_ilist
);
10127 gimple_bind_add_stmt (dep_bind
, bind
);
10128 gimple_bind_add_seq (dep_bind
, dep_olist
);
10129 pop_gimplify_context (dep_bind
);
10133 /* Lower the OpenMP target directive in the current statement
10134 in GSI_P. CTX holds context information for the directive. */
10137 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10140 tree child_fn
, t
, c
;
10141 gomp_target
*stmt
= as_a
<gomp_target
*> (gsi_stmt (*gsi_p
));
10142 gbind
*tgt_bind
= NULL
, *bind
;
10143 gimple_seq tgt_body
= NULL
, olist
, ilist
, new_body
;
10144 location_t loc
= gimple_location (stmt
);
10145 int kind
= gimple_omp_target_kind (stmt
);
10146 unsigned int map_cnt
= 0;
10148 clauses
= gimple_omp_target_clauses (stmt
);
10149 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10151 tgt_bind
= gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt
));
10152 tgt_body
= gimple_bind_body (tgt_bind
);
10154 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10155 tgt_body
= gimple_omp_body (stmt
);
10156 child_fn
= ctx
->cb
.dst_fn
;
10158 push_gimplify_context ();
10160 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
10161 switch (OMP_CLAUSE_CODE (c
))
10167 case OMP_CLAUSE_MAP
:
10168 case OMP_CLAUSE_TO
:
10169 case OMP_CLAUSE_FROM
:
10170 var
= OMP_CLAUSE_DECL (c
);
10173 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
10174 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
10179 if (DECL_SIZE (var
)
10180 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
10182 tree var2
= DECL_VALUE_EXPR (var
);
10183 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
10184 var2
= TREE_OPERAND (var2
, 0);
10185 gcc_assert (DECL_P (var2
));
10189 if (!maybe_lookup_field (var
, ctx
))
10192 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10194 x
= build_receiver_ref (var
, true, ctx
);
10195 tree new_var
= lookup_decl (var
, ctx
);
10196 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10197 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
10198 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
10199 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
10200 x
= build_simple_mem_ref (x
);
10201 SET_DECL_VALUE_EXPR (new_var
, x
);
10202 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
10207 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10209 target_nesting_level
++;
10210 lower_omp (&tgt_body
, ctx
);
10211 target_nesting_level
--;
10213 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10214 lower_omp (&tgt_body
, ctx
);
10216 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10218 /* Declare all the variables created by mapping and the variables
10219 declared in the scope of the target body. */
10220 record_vars_into (ctx
->block_vars
, child_fn
);
10221 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
10226 if (ctx
->record_type
)
10229 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
10230 DECL_NAMELESS (ctx
->sender_decl
) = 1;
10231 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
10232 t
= make_tree_vec (3);
10233 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
10234 TREE_VEC_ELT (t
, 1)
10235 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
10236 ".omp_data_sizes");
10237 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
10238 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
10239 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
10240 TREE_VEC_ELT (t
, 2)
10241 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node
,
10243 ".omp_data_kinds");
10244 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
10245 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
10246 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
10247 gimple_omp_target_set_data_arg (stmt
, t
);
10249 vec
<constructor_elt
, va_gc
> *vsize
;
10250 vec
<constructor_elt
, va_gc
> *vkind
;
10251 vec_alloc (vsize
, map_cnt
);
10252 vec_alloc (vkind
, map_cnt
);
10253 unsigned int map_idx
= 0;
10255 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
10256 switch (OMP_CLAUSE_CODE (c
))
10262 case OMP_CLAUSE_MAP
:
10263 case OMP_CLAUSE_TO
:
10264 case OMP_CLAUSE_FROM
:
10266 ovar
= OMP_CLAUSE_DECL (c
);
10267 if (!DECL_P (ovar
))
10269 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10270 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
10272 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
10273 == get_base_address (ovar
));
10274 nc
= OMP_CLAUSE_CHAIN (c
);
10275 ovar
= OMP_CLAUSE_DECL (nc
);
10279 tree x
= build_sender_ref (ovar
, ctx
);
10281 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
10282 gimplify_assign (x
, v
, &ilist
);
10288 if (DECL_SIZE (ovar
)
10289 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
10291 tree ovar2
= DECL_VALUE_EXPR (ovar
);
10292 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
10293 ovar2
= TREE_OPERAND (ovar2
, 0);
10294 gcc_assert (DECL_P (ovar2
));
10297 if (!maybe_lookup_field (ovar
, ctx
))
10301 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
10302 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
10303 talign
= DECL_ALIGN_UNIT (ovar
);
10306 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
10307 tree x
= build_sender_ref (ovar
, ctx
);
10308 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
10309 && OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_POINTER
10310 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
10311 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
10313 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
10315 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)));
10316 mark_addressable (avar
);
10317 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
10318 talign
= DECL_ALIGN_UNIT (avar
);
10319 avar
= build_fold_addr_expr (avar
);
10320 gimplify_assign (x
, avar
, &ilist
);
10322 else if (is_gimple_reg (var
))
10324 gcc_assert (kind
== GF_OMP_TARGET_KIND_REGION
);
10325 tree avar
= create_tmp_var (TREE_TYPE (var
));
10326 mark_addressable (avar
);
10327 if (OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_ALLOC
10328 && OMP_CLAUSE_MAP_KIND (c
) != OMP_CLAUSE_MAP_FROM
)
10329 gimplify_assign (avar
, var
, &ilist
);
10330 avar
= build_fold_addr_expr (avar
);
10331 gimplify_assign (x
, avar
, &ilist
);
10332 if ((OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_FROM
10333 || OMP_CLAUSE_MAP_KIND (c
) == OMP_CLAUSE_MAP_TOFROM
)
10334 && !TYPE_READONLY (TREE_TYPE (var
)))
10336 x
= build_sender_ref (ovar
, ctx
);
10337 x
= build_simple_mem_ref (x
);
10338 gimplify_assign (var
, x
, &olist
);
10343 var
= build_fold_addr_expr (var
);
10344 gimplify_assign (x
, var
, &ilist
);
10347 tree s
= OMP_CLAUSE_SIZE (c
);
10348 if (s
== NULL_TREE
)
10349 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
10350 s
= fold_convert (size_type_node
, s
);
10351 tree purpose
= size_int (map_idx
++);
10352 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
10353 if (TREE_CODE (s
) != INTEGER_CST
)
10354 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
10356 unsigned char tkind
= 0;
10357 switch (OMP_CLAUSE_CODE (c
))
10359 case OMP_CLAUSE_MAP
:
10360 tkind
= OMP_CLAUSE_MAP_KIND (c
);
10362 case OMP_CLAUSE_TO
:
10363 tkind
= OMP_CLAUSE_MAP_TO
;
10365 case OMP_CLAUSE_FROM
:
10366 tkind
= OMP_CLAUSE_MAP_FROM
;
10369 gcc_unreachable ();
10371 talign
= ceil_log2 (talign
);
10372 tkind
|= talign
<< 3;
10373 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
10374 build_int_cst (unsigned_char_type_node
,
10380 gcc_assert (map_idx
== map_cnt
);
10382 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
10383 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
10384 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
10385 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
10386 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
10388 gimple_seq initlist
= NULL
;
10389 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
10390 TREE_VEC_ELT (t
, 1)),
10391 &initlist
, true, NULL_TREE
);
10392 gimple_seq_add_seq (&ilist
, initlist
);
10394 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
10396 TREE_THIS_VOLATILE (clobber
) = 1;
10397 gimple_seq_add_stmt (&olist
,
10398 gimple_build_assign (TREE_VEC_ELT (t
, 1),
10402 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
10403 TREE_THIS_VOLATILE (clobber
) = 1;
10404 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
10408 /* Once all the expansions are done, sequence all the different
10409 fragments inside gimple_omp_body. */
10413 if (ctx
->record_type
&& kind
== GF_OMP_TARGET_KIND_REGION
)
10415 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10416 /* fixup_child_record_type might have changed receiver_decl's type. */
10417 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
10418 gimple_seq_add_stmt (&new_body
,
10419 gimple_build_assign (ctx
->receiver_decl
, t
));
10422 if (kind
== GF_OMP_TARGET_KIND_REGION
)
10424 gimple_seq_add_seq (&new_body
, tgt_body
);
10425 new_body
= maybe_catch_exception (new_body
);
10427 else if (kind
== GF_OMP_TARGET_KIND_DATA
)
10428 new_body
= tgt_body
;
10429 if (kind
!= GF_OMP_TARGET_KIND_UPDATE
)
10431 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
10432 gimple_omp_set_body (stmt
, new_body
);
10435 bind
= gimple_build_bind (NULL
, NULL
,
10436 tgt_bind
? gimple_bind_block (tgt_bind
)
10438 gsi_replace (gsi_p
, bind
, true);
10439 gimple_bind_add_seq (bind
, ilist
);
10440 gimple_bind_add_stmt (bind
, stmt
);
10441 gimple_bind_add_seq (bind
, olist
);
10443 pop_gimplify_context (NULL
);
10446 /* Expand code for an OpenMP teams directive. */
10449 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10451 gomp_teams
*teams_stmt
= as_a
<gomp_teams
*> (gsi_stmt (*gsi_p
));
10452 push_gimplify_context ();
10454 tree block
= make_node (BLOCK
);
10455 gbind
*bind
= gimple_build_bind (NULL
, NULL
, block
);
10456 gsi_replace (gsi_p
, bind
, true);
10457 gimple_seq bind_body
= NULL
;
10458 gimple_seq dlist
= NULL
;
10459 gimple_seq olist
= NULL
;
10461 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
10462 OMP_CLAUSE_NUM_TEAMS
);
10463 if (num_teams
== NULL_TREE
)
10464 num_teams
= build_int_cst (unsigned_type_node
, 0);
10467 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
10468 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
10469 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
10471 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
10472 OMP_CLAUSE_THREAD_LIMIT
);
10473 if (thread_limit
== NULL_TREE
)
10474 thread_limit
= build_int_cst (unsigned_type_node
, 0);
10477 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
10478 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
10479 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
10483 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
10484 &bind_body
, &dlist
, ctx
, NULL
);
10485 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
10486 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
10487 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
10489 location_t loc
= gimple_location (teams_stmt
);
10490 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
10491 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
10492 gimple_set_location (call
, loc
);
10493 gimple_seq_add_stmt (&bind_body
, call
);
10495 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
10496 gimple_omp_set_body (teams_stmt
, NULL
);
10497 gimple_seq_add_seq (&bind_body
, olist
);
10498 gimple_seq_add_seq (&bind_body
, dlist
);
10499 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
10500 gimple_bind_set_body (bind
, bind_body
);
10502 pop_gimplify_context (bind
);
10504 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10505 BLOCK_VARS (block
) = ctx
->block_vars
;
10506 if (BLOCK_VARS (block
))
10507 TREE_USED (block
) = 1;
10511 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10512 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10513 of OpenMP context, but with task_shared_vars set. */
10516 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
10521 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10522 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
10525 if (task_shared_vars
10527 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
10530 /* If a global variable has been privatized, TREE_CONSTANT on
10531 ADDR_EXPR might be wrong. */
10532 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
10533 recompute_tree_invariant_for_addr_expr (t
);
10535 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
10540 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10542 gimple stmt
= gsi_stmt (*gsi_p
);
10543 struct walk_stmt_info wi
;
10546 if (gimple_has_location (stmt
))
10547 input_location
= gimple_location (stmt
);
10549 if (task_shared_vars
)
10550 memset (&wi
, '\0', sizeof (wi
));
10552 /* If we have issued syntax errors, avoid doing any heavy lifting.
10553 Just replace the OpenMP directives with a NOP to avoid
10554 confusing RTL expansion. */
10555 if (seen_error () && is_gimple_omp (stmt
))
10557 gsi_replace (gsi_p
, gimple_build_nop (), true);
10561 switch (gimple_code (stmt
))
10565 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
10566 if ((ctx
|| task_shared_vars
)
10567 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
10568 lower_omp_regimplify_p
,
10569 ctx
? NULL
: &wi
, NULL
)
10570 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
10571 lower_omp_regimplify_p
,
10572 ctx
? NULL
: &wi
, NULL
)))
10573 gimple_regimplify_operands (cond_stmt
, gsi_p
);
10577 lower_omp (gimple_catch_handler_ptr (as_a
<gcatch
*> (stmt
)), ctx
);
10579 case GIMPLE_EH_FILTER
:
10580 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
10583 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
10584 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
10586 case GIMPLE_TRANSACTION
:
10587 lower_omp (gimple_transaction_body_ptr (
10588 as_a
<gtransaction
*> (stmt
)),
10592 lower_omp (gimple_bind_body_ptr (as_a
<gbind
*> (stmt
)), ctx
);
10594 case GIMPLE_OMP_PARALLEL
:
10595 case GIMPLE_OMP_TASK
:
10596 ctx
= maybe_lookup_ctx (stmt
);
10598 if (ctx
->cancellable
)
10599 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10600 lower_omp_taskreg (gsi_p
, ctx
);
10602 case GIMPLE_OMP_FOR
:
10603 ctx
= maybe_lookup_ctx (stmt
);
10605 if (ctx
->cancellable
)
10606 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10607 lower_omp_for (gsi_p
, ctx
);
10609 case GIMPLE_OMP_SECTIONS
:
10610 ctx
= maybe_lookup_ctx (stmt
);
10612 if (ctx
->cancellable
)
10613 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
10614 lower_omp_sections (gsi_p
, ctx
);
10616 case GIMPLE_OMP_SINGLE
:
10617 ctx
= maybe_lookup_ctx (stmt
);
10619 lower_omp_single (gsi_p
, ctx
);
10621 case GIMPLE_OMP_MASTER
:
10622 ctx
= maybe_lookup_ctx (stmt
);
10624 lower_omp_master (gsi_p
, ctx
);
10626 case GIMPLE_OMP_TASKGROUP
:
10627 ctx
= maybe_lookup_ctx (stmt
);
10629 lower_omp_taskgroup (gsi_p
, ctx
);
10631 case GIMPLE_OMP_ORDERED
:
10632 ctx
= maybe_lookup_ctx (stmt
);
10634 lower_omp_ordered (gsi_p
, ctx
);
10636 case GIMPLE_OMP_CRITICAL
:
10637 ctx
= maybe_lookup_ctx (stmt
);
10639 lower_omp_critical (gsi_p
, ctx
);
10641 case GIMPLE_OMP_ATOMIC_LOAD
:
10642 if ((ctx
|| task_shared_vars
)
10643 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
10644 as_a
<gomp_atomic_load
*> (stmt
)),
10645 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
10646 gimple_regimplify_operands (stmt
, gsi_p
);
10648 case GIMPLE_OMP_TARGET
:
10649 ctx
= maybe_lookup_ctx (stmt
);
10651 lower_omp_target (gsi_p
, ctx
);
10653 case GIMPLE_OMP_TEAMS
:
10654 ctx
= maybe_lookup_ctx (stmt
);
10656 lower_omp_teams (gsi_p
, ctx
);
10660 call_stmt
= as_a
<gcall
*> (stmt
);
10661 fndecl
= gimple_call_fndecl (call_stmt
);
10663 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
10664 switch (DECL_FUNCTION_CODE (fndecl
))
10666 case BUILT_IN_GOMP_BARRIER
:
10670 case BUILT_IN_GOMP_CANCEL
:
10671 case BUILT_IN_GOMP_CANCELLATION_POINT
:
10674 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
10675 cctx
= cctx
->outer
;
10676 gcc_assert (gimple_call_lhs (call_stmt
) == NULL_TREE
);
10677 if (!cctx
->cancellable
)
10679 if (DECL_FUNCTION_CODE (fndecl
)
10680 == BUILT_IN_GOMP_CANCELLATION_POINT
)
10682 stmt
= gimple_build_nop ();
10683 gsi_replace (gsi_p
, stmt
, false);
10687 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
10689 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
10690 gimple_call_set_fndecl (call_stmt
, fndecl
);
10691 gimple_call_set_fntype (call_stmt
, TREE_TYPE (fndecl
));
10694 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)));
10695 gimple_call_set_lhs (call_stmt
, lhs
);
10696 tree fallthru_label
;
10697 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
10699 g
= gimple_build_label (fallthru_label
);
10700 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10701 g
= gimple_build_cond (NE_EXPR
, lhs
,
10702 fold_convert (TREE_TYPE (lhs
),
10703 boolean_false_node
),
10704 cctx
->cancel_label
, fallthru_label
);
10705 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
10712 if ((ctx
|| task_shared_vars
)
10713 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
10716 /* Just remove clobbers, this should happen only if we have
10717 "privatized" local addressable variables in SIMD regions,
10718 the clobber isn't needed in that case and gimplifying address
10719 of the ARRAY_REF into a pointer and creating MEM_REF based
10720 clobber would create worse code than we get with the clobber
10722 if (gimple_clobber_p (stmt
))
10724 gsi_replace (gsi_p
, gimple_build_nop (), true);
10727 gimple_regimplify_operands (stmt
, gsi_p
);
10734 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
10736 location_t saved_location
= input_location
;
10737 gimple_stmt_iterator gsi
;
10738 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10739 lower_omp_1 (&gsi
, ctx
);
10740 /* During gimplification, we have not always invoked fold_stmt
10741 (gimplify.c:maybe_fold_stmt); call it now. */
10742 if (target_nesting_level
)
10743 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
10745 input_location
= saved_location
;
10748 /* Main entry point. */
10750 static unsigned int
10751 execute_lower_omp (void)
10757 /* This pass always runs, to provide PROP_gimple_lomp.
10758 But there is nothing to do unless -fopenmp is given. */
10759 if (flag_openmp
== 0 && flag_openmp_simd
== 0 && flag_cilkplus
== 0)
10762 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
10763 delete_omp_context
);
10765 body
= gimple_body (current_function_decl
);
10766 scan_omp (&body
, NULL
);
10767 gcc_assert (taskreg_nesting_level
== 0);
10768 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
10769 finish_taskreg_scan (ctx
);
10770 taskreg_contexts
.release ();
10772 if (all_contexts
->root
)
10774 if (task_shared_vars
)
10775 push_gimplify_context ();
10776 lower_omp (&body
, NULL
);
10777 if (task_shared_vars
)
10778 pop_gimplify_context (NULL
);
10783 splay_tree_delete (all_contexts
);
10784 all_contexts
= NULL
;
10786 BITMAP_FREE (task_shared_vars
);
10792 const pass_data pass_data_lower_omp
=
10794 GIMPLE_PASS
, /* type */
10795 "omplower", /* name */
10796 OPTGROUP_NONE
, /* optinfo_flags */
10797 TV_NONE
, /* tv_id */
10798 PROP_gimple_any
, /* properties_required */
10799 PROP_gimple_lomp
, /* properties_provided */
10800 0, /* properties_destroyed */
10801 0, /* todo_flags_start */
10802 0, /* todo_flags_finish */
10805 class pass_lower_omp
: public gimple_opt_pass
10808 pass_lower_omp (gcc::context
*ctxt
)
10809 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
10812 /* opt_pass methods: */
10813 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
10815 }; // class pass_lower_omp
10817 } // anon namespace
10820 make_pass_lower_omp (gcc::context
*ctxt
)
10822 return new pass_lower_omp (ctxt
);
10825 /* The following is a utility to diagnose OpenMP structured block violations.
10826 It is not part of the "omplower" pass, as that's invoked too late. It
10827 should be invoked by the respective front ends after gimplification. */
10829 static splay_tree all_labels
;
10831 /* Check for mismatched contexts and generate an error if needed. Return
10832 true if an error is detected. */
10835 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
10836 gimple branch_ctx
, gimple label_ctx
)
10838 if (label_ctx
== branch_ctx
)
10843 Previously we kept track of the label's entire context in diagnose_sb_[12]
10844 so we could traverse it and issue a correct "exit" or "enter" error
10845 message upon a structured block violation.
10847 We built the context by building a list with tree_cons'ing, but there is
10848 no easy counterpart in gimple tuples. It seems like far too much work
10849 for issuing exit/enter error messages. If someone really misses the
10850 distinct error message... patches welcome.
10854 /* Try to avoid confusing the user by producing and error message
10855 with correct "exit" or "enter" verbiage. We prefer "exit"
10856 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10857 if (branch_ctx
== NULL
)
10863 if (TREE_VALUE (label_ctx
) == branch_ctx
)
10868 label_ctx
= TREE_CHAIN (label_ctx
);
10873 error ("invalid exit from OpenMP structured block");
10875 error ("invalid entry to OpenMP structured block");
10878 bool cilkplus_block
= false;
10882 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
10883 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
10885 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
10886 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
10887 cilkplus_block
= true;
10890 /* If it's obvious we have an invalid entry, be specific about the error. */
10891 if (branch_ctx
== NULL
)
10893 if (cilkplus_block
)
10894 error ("invalid entry to Cilk Plus structured block");
10896 error ("invalid entry to OpenMP structured block");
10900 /* Otherwise, be vague and lazy, but efficient. */
10901 if (cilkplus_block
)
10902 error ("invalid branch to/from a Cilk Plus structured block");
10904 error ("invalid branch to/from an OpenMP structured block");
10907 gsi_replace (gsi_p
, gimple_build_nop (), false);
10911 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10912 where each label is found. */
10915 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10916 struct walk_stmt_info
*wi
)
10918 gimple context
= (gimple
) wi
->info
;
10919 gimple inner_context
;
10920 gimple stmt
= gsi_stmt (*gsi_p
);
10922 *handled_ops_p
= true;
10924 switch (gimple_code (stmt
))
10928 case GIMPLE_OMP_PARALLEL
:
10929 case GIMPLE_OMP_TASK
:
10930 case GIMPLE_OMP_SECTIONS
:
10931 case GIMPLE_OMP_SINGLE
:
10932 case GIMPLE_OMP_SECTION
:
10933 case GIMPLE_OMP_MASTER
:
10934 case GIMPLE_OMP_ORDERED
:
10935 case GIMPLE_OMP_CRITICAL
:
10936 case GIMPLE_OMP_TARGET
:
10937 case GIMPLE_OMP_TEAMS
:
10938 case GIMPLE_OMP_TASKGROUP
:
10939 /* The minimal context here is just the current OMP construct. */
10940 inner_context
= stmt
;
10941 wi
->info
= inner_context
;
10942 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10943 wi
->info
= context
;
10946 case GIMPLE_OMP_FOR
:
10947 inner_context
= stmt
;
10948 wi
->info
= inner_context
;
10949 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10951 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
10952 diagnose_sb_1
, NULL
, wi
);
10953 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
10954 wi
->info
= context
;
10958 splay_tree_insert (all_labels
,
10959 (splay_tree_key
) gimple_label_label (
10960 as_a
<glabel
*> (stmt
)),
10961 (splay_tree_value
) context
);
10971 /* Pass 2: Check each branch and see if its context differs from that of
10972 the destination label's context. */
10975 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
10976 struct walk_stmt_info
*wi
)
10978 gimple context
= (gimple
) wi
->info
;
10980 gimple stmt
= gsi_stmt (*gsi_p
);
10982 *handled_ops_p
= true;
10984 switch (gimple_code (stmt
))
10988 case GIMPLE_OMP_PARALLEL
:
10989 case GIMPLE_OMP_TASK
:
10990 case GIMPLE_OMP_SECTIONS
:
10991 case GIMPLE_OMP_SINGLE
:
10992 case GIMPLE_OMP_SECTION
:
10993 case GIMPLE_OMP_MASTER
:
10994 case GIMPLE_OMP_ORDERED
:
10995 case GIMPLE_OMP_CRITICAL
:
10996 case GIMPLE_OMP_TARGET
:
10997 case GIMPLE_OMP_TEAMS
:
10998 case GIMPLE_OMP_TASKGROUP
:
11000 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
11001 wi
->info
= context
;
11004 case GIMPLE_OMP_FOR
:
11006 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11008 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
11009 diagnose_sb_2
, NULL
, wi
);
11010 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
11011 wi
->info
= context
;
11016 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
11017 tree lab
= gimple_cond_true_label (cond_stmt
);
11020 n
= splay_tree_lookup (all_labels
,
11021 (splay_tree_key
) lab
);
11022 diagnose_sb_0 (gsi_p
, context
,
11023 n
? (gimple
) n
->value
: NULL
);
11025 lab
= gimple_cond_false_label (cond_stmt
);
11028 n
= splay_tree_lookup (all_labels
,
11029 (splay_tree_key
) lab
);
11030 diagnose_sb_0 (gsi_p
, context
,
11031 n
? (gimple
) n
->value
: NULL
);
11038 tree lab
= gimple_goto_dest (stmt
);
11039 if (TREE_CODE (lab
) != LABEL_DECL
)
11042 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
11043 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
11047 case GIMPLE_SWITCH
:
11049 gswitch
*switch_stmt
= as_a
<gswitch
*> (stmt
);
11051 for (i
= 0; i
< gimple_switch_num_labels (switch_stmt
); ++i
)
11053 tree lab
= CASE_LABEL (gimple_switch_label (switch_stmt
, i
));
11054 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
11055 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
11061 case GIMPLE_RETURN
:
11062 diagnose_sb_0 (gsi_p
, context
, NULL
);
11072 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
11075 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
11078 gimple last
= last_stmt (bb
);
11079 enum gimple_code code
= gimple_code (last
);
11080 struct omp_region
*cur_region
= *region
;
11081 bool fallthru
= false;
11085 case GIMPLE_OMP_PARALLEL
:
11086 case GIMPLE_OMP_TASK
:
11087 case GIMPLE_OMP_FOR
:
11088 case GIMPLE_OMP_SINGLE
:
11089 case GIMPLE_OMP_TEAMS
:
11090 case GIMPLE_OMP_MASTER
:
11091 case GIMPLE_OMP_TASKGROUP
:
11092 case GIMPLE_OMP_ORDERED
:
11093 case GIMPLE_OMP_CRITICAL
:
11094 case GIMPLE_OMP_SECTION
:
11095 cur_region
= new_omp_region (bb
, code
, cur_region
);
11099 case GIMPLE_OMP_TARGET
:
11100 cur_region
= new_omp_region (bb
, code
, cur_region
);
11102 if (gimple_omp_target_kind (last
) == GF_OMP_TARGET_KIND_UPDATE
)
11103 cur_region
= cur_region
->outer
;
11106 case GIMPLE_OMP_SECTIONS
:
11107 cur_region
= new_omp_region (bb
, code
, cur_region
);
11111 case GIMPLE_OMP_SECTIONS_SWITCH
:
11115 case GIMPLE_OMP_ATOMIC_LOAD
:
11116 case GIMPLE_OMP_ATOMIC_STORE
:
11120 case GIMPLE_OMP_RETURN
:
11121 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11122 somewhere other than the next block. This will be
11124 cur_region
->exit
= bb
;
11125 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
11126 cur_region
= cur_region
->outer
;
11129 case GIMPLE_OMP_CONTINUE
:
11130 cur_region
->cont
= bb
;
11131 switch (cur_region
->type
)
11133 case GIMPLE_OMP_FOR
:
11134 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11135 succs edges as abnormal to prevent splitting
11137 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
11138 /* Make the loopback edge. */
11139 make_edge (bb
, single_succ (cur_region
->entry
),
11142 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11143 corresponds to the case that the body of the loop
11144 is not executed at all. */
11145 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
11146 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
11150 case GIMPLE_OMP_SECTIONS
:
11151 /* Wire up the edges into and out of the nested sections. */
11153 basic_block switch_bb
= single_succ (cur_region
->entry
);
11155 struct omp_region
*i
;
11156 for (i
= cur_region
->inner
; i
; i
= i
->next
)
11158 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
11159 make_edge (switch_bb
, i
->entry
, 0);
11160 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
11163 /* Make the loopback edge to the block with
11164 GIMPLE_OMP_SECTIONS_SWITCH. */
11165 make_edge (bb
, switch_bb
, 0);
11167 /* Make the edge from the switch to exit. */
11168 make_edge (switch_bb
, bb
->next_bb
, 0);
11174 gcc_unreachable ();
11179 gcc_unreachable ();
11182 if (*region
!= cur_region
)
11184 *region
= cur_region
;
11186 *region_idx
= cur_region
->entry
->index
;
11194 static unsigned int
11195 diagnose_omp_structured_block_errors (void)
11197 struct walk_stmt_info wi
;
11198 gimple_seq body
= gimple_body (current_function_decl
);
11200 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
11202 memset (&wi
, 0, sizeof (wi
));
11203 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
11205 memset (&wi
, 0, sizeof (wi
));
11206 wi
.want_locations
= true;
11207 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
11209 gimple_set_body (current_function_decl
, body
);
11211 splay_tree_delete (all_labels
);
11219 const pass_data pass_data_diagnose_omp_blocks
=
11221 GIMPLE_PASS
, /* type */
11222 "*diagnose_omp_blocks", /* name */
11223 OPTGROUP_NONE
, /* optinfo_flags */
11224 TV_NONE
, /* tv_id */
11225 PROP_gimple_any
, /* properties_required */
11226 0, /* properties_provided */
11227 0, /* properties_destroyed */
11228 0, /* todo_flags_start */
11229 0, /* todo_flags_finish */
11232 class pass_diagnose_omp_blocks
: public gimple_opt_pass
11235 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
11236 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
11239 /* opt_pass methods: */
11240 virtual bool gate (function
*) { return flag_openmp
|| flag_cilkplus
; }
11241 virtual unsigned int execute (function
*)
11243 return diagnose_omp_structured_block_errors ();
11246 }; // class pass_diagnose_omp_blocks
11248 } // anon namespace
11251 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
11253 return new pass_diagnose_omp_blocks (ctxt
);
11256 /* SIMD clone supporting code. */
11258 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11259 of arguments to reserve space for. */
11261 static struct cgraph_simd_clone
*
11262 simd_clone_struct_alloc (int nargs
)
11264 struct cgraph_simd_clone
*clone_info
;
11265 size_t len
= (sizeof (struct cgraph_simd_clone
)
11266 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
11267 clone_info
= (struct cgraph_simd_clone
*)
11268 ggc_internal_cleared_alloc (len
);
11272 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11275 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
11276 struct cgraph_simd_clone
*from
)
11278 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
11279 + ((from
->nargs
- from
->inbranch
)
11280 * sizeof (struct cgraph_simd_clone_arg
))));
11283 /* Return vector of parameter types of function FNDECL. This uses
11284 TYPE_ARG_TYPES if available, otherwise falls back to types of
11285 DECL_ARGUMENTS types. */
11288 simd_clone_vector_of_formal_parm_types (tree fndecl
)
11290 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
11291 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
11292 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
11295 FOR_EACH_VEC_ELT (args
, i
, arg
)
11296 args
[i
] = TREE_TYPE (args
[i
]);
11300 /* Given a simd function in NODE, extract the simd specific
11301 information from the OMP clauses passed in CLAUSES, and return
11302 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11303 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11304 otherwise set to FALSE. */
11306 static struct cgraph_simd_clone
*
11307 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
11308 bool *inbranch_specified
)
11310 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11313 *inbranch_specified
= false;
11315 n
= args
.length ();
11316 if (n
> 0 && args
.last () == void_type_node
)
11319 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11320 be cloned have a distinctive artificial label in addition to "omp
11324 && lookup_attribute ("cilk simd function",
11325 DECL_ATTRIBUTES (node
->decl
)));
11327 /* Allocate one more than needed just in case this is an in-branch
11328 clone which will require a mask argument. */
11329 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
11330 clone_info
->nargs
= n
;
11331 clone_info
->cilk_elemental
= cilk_clone
;
11338 clauses
= TREE_VALUE (clauses
);
11339 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
11342 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
11344 switch (OMP_CLAUSE_CODE (t
))
11346 case OMP_CLAUSE_INBRANCH
:
11347 clone_info
->inbranch
= 1;
11348 *inbranch_specified
= true;
11350 case OMP_CLAUSE_NOTINBRANCH
:
11351 clone_info
->inbranch
= 0;
11352 *inbranch_specified
= true;
11354 case OMP_CLAUSE_SIMDLEN
:
11355 clone_info
->simdlen
11356 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
11358 case OMP_CLAUSE_LINEAR
:
11360 tree decl
= OMP_CLAUSE_DECL (t
);
11361 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
11362 int argno
= TREE_INT_CST_LOW (decl
);
11363 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
11365 clone_info
->args
[argno
].arg_type
11366 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
11367 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
11368 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
11369 && clone_info
->args
[argno
].linear_step
< n
);
11373 if (POINTER_TYPE_P (args
[argno
]))
11374 step
= fold_convert (ssizetype
, step
);
11375 if (!tree_fits_shwi_p (step
))
11377 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
11378 "ignoring large linear step");
11382 else if (integer_zerop (step
))
11384 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
11385 "ignoring zero linear step");
11391 clone_info
->args
[argno
].arg_type
11392 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
11393 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
11398 case OMP_CLAUSE_UNIFORM
:
11400 tree decl
= OMP_CLAUSE_DECL (t
);
11401 int argno
= tree_to_uhwi (decl
);
11402 clone_info
->args
[argno
].arg_type
11403 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
11406 case OMP_CLAUSE_ALIGNED
:
11408 tree decl
= OMP_CLAUSE_DECL (t
);
11409 int argno
= tree_to_uhwi (decl
);
11410 clone_info
->args
[argno
].alignment
11411 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
11422 /* Given a SIMD clone in NODE, calculate the characteristic data
11423 type and return the coresponding type. The characteristic data
11424 type is computed as described in the Intel Vector ABI. */
11427 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
11428 struct cgraph_simd_clone
*clone_info
)
11430 tree type
= integer_type_node
;
11431 tree fndecl
= node
->decl
;
11433 /* a) For non-void function, the characteristic data type is the
11435 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
11436 type
= TREE_TYPE (TREE_TYPE (fndecl
));
11438 /* b) If the function has any non-uniform, non-linear parameters,
11439 then the characteristic data type is the type of the first
11443 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
11444 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
11445 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
11453 /* c) If the characteristic data type determined by a) or b) above
11454 is struct, union, or class type which is pass-by-value (except
11455 for the type that maps to the built-in complex data type), the
11456 characteristic data type is int. */
11457 if (RECORD_OR_UNION_TYPE_P (type
)
11458 && !aggregate_value_p (type
, NULL
)
11459 && TREE_CODE (type
) != COMPLEX_TYPE
)
11460 return integer_type_node
;
11462 /* d) If none of the above three classes is applicable, the
11463 characteristic data type is int. */
11467 /* e) For Intel Xeon Phi native and offload compilation, if the
11468 resulting characteristic data type is 8-bit or 16-bit integer
11469 data type, the characteristic data type is int. */
11470 /* Well, we don't handle Xeon Phi yet. */
11474 simd_clone_mangle (struct cgraph_node
*node
,
11475 struct cgraph_simd_clone
*clone_info
)
11477 char vecsize_mangle
= clone_info
->vecsize_mangle
;
11478 char mask
= clone_info
->inbranch
? 'M' : 'N';
11479 unsigned int simdlen
= clone_info
->simdlen
;
11483 gcc_assert (vecsize_mangle
&& simdlen
);
11485 pp_string (&pp
, "_ZGV");
11486 pp_character (&pp
, vecsize_mangle
);
11487 pp_character (&pp
, mask
);
11488 pp_decimal_int (&pp
, simdlen
);
11490 for (n
= 0; n
< clone_info
->nargs
; ++n
)
11492 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
11494 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
11495 pp_character (&pp
, 'u');
11496 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
11498 gcc_assert (arg
.linear_step
!= 0);
11499 pp_character (&pp
, 'l');
11500 if (arg
.linear_step
> 1)
11501 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
11502 else if (arg
.linear_step
< 0)
11504 pp_character (&pp
, 'n');
11505 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
11509 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
11511 pp_character (&pp
, 's');
11512 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
11515 pp_character (&pp
, 'v');
11518 pp_character (&pp
, 'a');
11519 pp_decimal_int (&pp
, arg
.alignment
);
11523 pp_underscore (&pp
);
11525 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
)));
11526 const char *str
= pp_formatted_text (&pp
);
11528 /* If there already is a SIMD clone with the same mangled name, don't
11529 add another one. This can happen e.g. for
11530 #pragma omp declare simd
11531 #pragma omp declare simd simdlen(8)
11532 int foo (int, int);
11533 if the simdlen is assumed to be 8 for the first one, etc. */
11534 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
11535 clone
= clone
->simdclone
->next_clone
)
11536 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
11540 return get_identifier (str
);
11543 /* Create a simd clone of OLD_NODE and return it. */
11545 static struct cgraph_node
*
11546 simd_clone_create (struct cgraph_node
*old_node
)
11548 struct cgraph_node
*new_node
;
11549 if (old_node
->definition
)
11551 if (!old_node
->has_gimple_body_p ())
11553 old_node
->get_body ();
11554 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
11560 tree old_decl
= old_node
->decl
;
11561 tree new_decl
= copy_node (old_node
->decl
);
11562 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
11563 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
11564 SET_DECL_RTL (new_decl
, NULL
);
11565 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
11566 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
11567 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
11568 symtab
->call_cgraph_insertion_hooks (new_node
);
11570 if (new_node
== NULL
)
11573 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
11575 /* The function cgraph_function_versioning () will force the new
11576 symbol local. Undo this, and inherit external visability from
11578 new_node
->local
.local
= old_node
->local
.local
;
11579 new_node
->externally_visible
= old_node
->externally_visible
;
11584 /* Adjust the return type of the given function to its appropriate
11585 vector counterpart. Returns a simd array to be used throughout the
11586 function as a return value. */
11589 simd_clone_adjust_return_type (struct cgraph_node
*node
)
11591 tree fndecl
= node
->decl
;
11592 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
11593 unsigned int veclen
;
11596 /* Adjust the function return type. */
11597 if (orig_rettype
== void_type_node
)
11599 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
11600 t
= TREE_TYPE (TREE_TYPE (fndecl
));
11601 if (INTEGRAL_TYPE_P (t
) || POINTER_TYPE_P (t
))
11602 veclen
= node
->simdclone
->vecsize_int
;
11604 veclen
= node
->simdclone
->vecsize_float
;
11605 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (t
));
11606 if (veclen
> node
->simdclone
->simdlen
)
11607 veclen
= node
->simdclone
->simdlen
;
11608 if (POINTER_TYPE_P (t
))
11609 t
= pointer_sized_int_node
;
11610 if (veclen
== node
->simdclone
->simdlen
)
11611 t
= build_vector_type (t
, node
->simdclone
->simdlen
);
11614 t
= build_vector_type (t
, veclen
);
11615 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
11617 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
11618 if (!node
->definition
)
11621 t
= DECL_RESULT (fndecl
);
11622 /* Adjust the DECL_RESULT. */
11623 gcc_assert (TREE_TYPE (t
) != void_type_node
);
11624 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
11627 tree atype
= build_array_type_nelts (orig_rettype
,
11628 node
->simdclone
->simdlen
);
11629 if (veclen
!= node
->simdclone
->simdlen
)
11630 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
11632 /* Set up a SIMD array to use as the return value. */
11633 tree retval
= create_tmp_var_raw (atype
, "retval");
11634 gimple_add_tmp_var (retval
);
11638 /* Each vector argument has a corresponding array to be used locally
11639 as part of the eventual loop. Create such temporary array and
11642 PREFIX is the prefix to be used for the temporary.
11644 TYPE is the inner element type.
11646 SIMDLEN is the number of elements. */
11649 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
11651 tree atype
= build_array_type_nelts (type
, simdlen
);
11652 tree avar
= create_tmp_var_raw (atype
, prefix
);
11653 gimple_add_tmp_var (avar
);
11657 /* Modify the function argument types to their corresponding vector
11658 counterparts if appropriate. Also, create one array for each simd
11659 argument to be used locally when using the function arguments as
11662 NODE is the function whose arguments are to be adjusted.
11664 Returns an adjustment vector that will be filled describing how the
11665 argument types will be adjusted. */
11667 static ipa_parm_adjustment_vec
11668 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
11671 ipa_parm_adjustment_vec adjustments
;
11673 if (node
->definition
)
11674 args
= ipa_get_vector_of_formal_parms (node
->decl
);
11676 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
11677 adjustments
.create (args
.length ());
11678 unsigned i
, j
, veclen
;
11679 struct ipa_parm_adjustment adj
;
11680 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
11682 memset (&adj
, 0, sizeof (adj
));
11683 tree parm
= args
[i
];
11684 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
11685 adj
.base_index
= i
;
11688 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
11689 node
->simdclone
->args
[i
].orig_type
= parm_type
;
11691 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
11693 /* No adjustment necessary for scalar arguments. */
11694 adj
.op
= IPA_PARM_OP_COPY
;
11698 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
11699 veclen
= node
->simdclone
->vecsize_int
;
11701 veclen
= node
->simdclone
->vecsize_float
;
11702 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
11703 if (veclen
> node
->simdclone
->simdlen
)
11704 veclen
= node
->simdclone
->simdlen
;
11705 adj
.arg_prefix
= "simd";
11706 if (POINTER_TYPE_P (parm_type
))
11707 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
11709 adj
.type
= build_vector_type (parm_type
, veclen
);
11710 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
11711 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11713 adjustments
.safe_push (adj
);
11716 memset (&adj
, 0, sizeof (adj
));
11717 adj
.op
= IPA_PARM_OP_NEW
;
11718 adj
.arg_prefix
= "simd";
11719 adj
.base_index
= i
;
11720 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
11724 if (node
->definition
)
11725 node
->simdclone
->args
[i
].simd_array
11726 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
11727 parm_type
, node
->simdclone
->simdlen
);
11729 adjustments
.safe_push (adj
);
11732 if (node
->simdclone
->inbranch
)
11735 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
11738 memset (&adj
, 0, sizeof (adj
));
11739 adj
.op
= IPA_PARM_OP_NEW
;
11740 adj
.arg_prefix
= "mask";
11742 adj
.base_index
= i
;
11743 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
11744 veclen
= node
->simdclone
->vecsize_int
;
11746 veclen
= node
->simdclone
->vecsize_float
;
11747 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
11748 if (veclen
> node
->simdclone
->simdlen
)
11749 veclen
= node
->simdclone
->simdlen
;
11750 if (POINTER_TYPE_P (base_type
))
11751 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
11753 adj
.type
= build_vector_type (base_type
, veclen
);
11754 adjustments
.safe_push (adj
);
11756 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
11757 adjustments
.safe_push (adj
);
11759 /* We have previously allocated one extra entry for the mask. Use
11761 struct cgraph_simd_clone
*sc
= node
->simdclone
;
11763 if (node
->definition
)
11765 sc
->args
[i
].orig_arg
11766 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
11767 sc
->args
[i
].simd_array
11768 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
11770 sc
->args
[i
].orig_type
= base_type
;
11771 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
11774 if (node
->definition
)
11775 ipa_modify_formal_parameters (node
->decl
, adjustments
);
11778 tree new_arg_types
= NULL_TREE
, new_reversed
;
11779 bool last_parm_void
= false;
11780 if (args
.length () > 0 && args
.last () == void_type_node
)
11781 last_parm_void
= true;
11783 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
11784 j
= adjustments
.length ();
11785 for (i
= 0; i
< j
; i
++)
11787 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
11789 if (adj
->op
== IPA_PARM_OP_COPY
)
11790 ptype
= args
[adj
->base_index
];
11793 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
11795 new_reversed
= nreverse (new_arg_types
);
11796 if (last_parm_void
)
11799 TREE_CHAIN (new_arg_types
) = void_list_node
;
11801 new_reversed
= void_list_node
;
11804 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
11805 TYPE_ARG_TYPES (new_type
) = new_reversed
;
11806 TREE_TYPE (node
->decl
) = new_type
;
11808 adjustments
.release ();
11811 return adjustments
;
11814 /* Initialize and copy the function arguments in NODE to their
11815 corresponding local simd arrays. Returns a fresh gimple_seq with
11816 the instruction sequence generated. */
11819 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
11820 ipa_parm_adjustment_vec adjustments
)
11822 gimple_seq seq
= NULL
;
11823 unsigned i
= 0, j
= 0, k
;
11825 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
11827 arg
= DECL_CHAIN (arg
), i
++, j
++)
11829 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
11832 node
->simdclone
->args
[i
].vector_arg
= arg
;
11834 tree array
= node
->simdclone
->args
[i
].simd_array
;
11835 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
11837 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11838 tree ptr
= build_fold_addr_expr (array
);
11839 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11840 build_int_cst (ptype
, 0));
11841 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11842 gimplify_and_add (t
, &seq
);
11846 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
11847 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
11848 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
11850 tree ptr
= build_fold_addr_expr (array
);
11854 arg
= DECL_CHAIN (arg
);
11858 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
11859 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
11860 build_int_cst (ptype
, k
* elemsize
));
11861 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
11862 gimplify_and_add (t
, &seq
);
11869 /* Callback info for ipa_simd_modify_stmt_ops below. */
11871 struct modify_stmt_info
{
11872 ipa_parm_adjustment_vec adjustments
;
11874 /* True if the parent statement was modified by
11875 ipa_simd_modify_stmt_ops. */
11879 /* Callback for walk_gimple_op.
11881 Adjust operands from a given statement as specified in the
11882 adjustments vector in the callback data. */
11885 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
11887 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
11888 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
11889 tree
*orig_tp
= tp
;
11890 if (TREE_CODE (*tp
) == ADDR_EXPR
)
11891 tp
= &TREE_OPERAND (*tp
, 0);
11892 struct ipa_parm_adjustment
*cand
= NULL
;
11893 if (TREE_CODE (*tp
) == PARM_DECL
)
11894 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
11898 *walk_subtrees
= 0;
11901 tree repl
= NULL_TREE
;
11903 repl
= unshare_expr (cand
->new_decl
);
11908 *walk_subtrees
= 0;
11909 bool modified
= info
->modified
;
11910 info
->modified
= false;
11911 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
11912 if (!info
->modified
)
11914 info
->modified
= modified
;
11917 info
->modified
= modified
;
11926 repl
= build_fold_addr_expr (repl
);
11928 if (is_gimple_debug (info
->stmt
))
11930 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
11931 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
11932 DECL_ARTIFICIAL (vexpr
) = 1;
11933 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
11934 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
11939 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
)), repl
);
11940 repl
= gimple_assign_lhs (stmt
);
11942 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
11943 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11946 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
11948 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
11954 info
->modified
= true;
11958 /* Traverse the function body and perform all modifications as
11959 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11960 modified such that the replacement/reduction value will now be an
11961 offset into the corresponding simd_array.
11963 This function will replace all function argument uses with their
11964 corresponding simd array elements, and ajust the return values
11968 ipa_simd_modify_function_body (struct cgraph_node
*node
,
11969 ipa_parm_adjustment_vec adjustments
,
11970 tree retval_array
, tree iter
)
11973 unsigned int i
, j
, l
;
11975 /* Re-use the adjustments array, but this time use it to replace
11976 every function argument use to an offset into the corresponding
11978 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
11980 if (!node
->simdclone
->args
[i
].vector_arg
)
11983 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
11984 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
11985 adjustments
[j
].new_decl
11986 = build4 (ARRAY_REF
,
11988 node
->simdclone
->args
[i
].simd_array
,
11990 NULL_TREE
, NULL_TREE
);
11991 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
11992 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
11993 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
11996 l
= adjustments
.length ();
11997 for (i
= 1; i
< num_ssa_names
; i
++)
11999 tree name
= ssa_name (i
);
12001 && SSA_NAME_VAR (name
)
12002 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
12004 for (j
= 0; j
< l
; j
++)
12005 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
12006 && adjustments
[j
].new_decl
)
12009 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
12012 = copy_var_decl (adjustments
[j
].base
,
12013 DECL_NAME (adjustments
[j
].base
),
12014 TREE_TYPE (adjustments
[j
].base
));
12015 adjustments
[j
].new_ssa_base
= base_var
;
12018 base_var
= adjustments
[j
].new_ssa_base
;
12019 if (SSA_NAME_IS_DEFAULT_DEF (name
))
12021 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
12022 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
12023 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
12024 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
12025 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
12026 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
12027 gimple stmt
= gimple_build_assign (name
, new_decl
);
12028 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
12031 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
12036 struct modify_stmt_info info
;
12037 info
.adjustments
= adjustments
;
12039 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
12041 gimple_stmt_iterator gsi
;
12043 gsi
= gsi_start_bb (bb
);
12044 while (!gsi_end_p (gsi
))
12046 gimple stmt
= gsi_stmt (gsi
);
12048 struct walk_stmt_info wi
;
12050 memset (&wi
, 0, sizeof (wi
));
12051 info
.modified
= false;
12053 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
12055 if (greturn
*return_stmt
= dyn_cast
<greturn
*> (stmt
))
12057 tree retval
= gimple_return_retval (return_stmt
);
12060 gsi_remove (&gsi
, true);
12064 /* Replace `return foo' with `retval_array[iter] = foo'. */
12065 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
12066 retval_array
, iter
, NULL
, NULL
);
12067 stmt
= gimple_build_assign (ref
, retval
);
12068 gsi_replace (&gsi
, stmt
, true);
12069 info
.modified
= true;
12074 update_stmt (stmt
);
12075 if (maybe_clean_eh_stmt (stmt
))
12076 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
12083 /* Adjust the argument types in NODE to their appropriate vector
12087 simd_clone_adjust (struct cgraph_node
*node
)
12089 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
12091 targetm
.simd_clone
.adjust (node
);
12093 tree retval
= simd_clone_adjust_return_type (node
);
12094 ipa_parm_adjustment_vec adjustments
12095 = simd_clone_adjust_argument_types (node
);
12097 push_gimplify_context ();
12099 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
12101 /* Adjust all uses of vector arguments accordingly. Adjust all
12102 return values accordingly. */
12103 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
12104 tree iter1
= make_ssa_name (iter
);
12105 tree iter2
= make_ssa_name (iter
);
12106 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
12108 /* Initialize the iteration variable. */
12109 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
12110 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
12111 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
12112 /* Insert the SIMD array and iv initialization at function
12114 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
12116 pop_gimplify_context (NULL
);
12118 /* Create a new BB right before the original exit BB, to hold the
12119 iteration increment and the condition/branch. */
12120 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
12121 basic_block incr_bb
= create_empty_bb (orig_exit
);
12122 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
12123 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12124 flag. Set it now to be a FALLTHRU_EDGE. */
12125 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
12126 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
12127 for (unsigned i
= 0;
12128 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
12130 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
12131 redirect_edge_succ (e
, incr_bb
);
12133 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
12134 e
->probability
= REG_BR_PROB_BASE
;
12135 gsi
= gsi_last_bb (incr_bb
);
12136 gimple g
= gimple_build_assign (iter2
, PLUS_EXPR
, iter1
,
12137 build_int_cst (unsigned_type_node
, 1));
12138 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12140 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12141 struct loop
*loop
= alloc_loop ();
12142 cfun
->has_force_vectorize_loops
= true;
12143 loop
->safelen
= node
->simdclone
->simdlen
;
12144 loop
->force_vectorize
= true;
12145 loop
->header
= body_bb
;
12147 /* Branch around the body if the mask applies. */
12148 if (node
->simdclone
->inbranch
)
12150 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
12152 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
12153 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)));
12154 tree aref
= build4 (ARRAY_REF
,
12155 TREE_TYPE (TREE_TYPE (mask_array
)),
12158 g
= gimple_build_assign (mask
, aref
);
12159 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12160 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
12161 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
12163 aref
= build1 (VIEW_CONVERT_EXPR
,
12164 build_nonstandard_integer_type (bitsize
, 0), mask
);
12165 mask
= make_ssa_name (TREE_TYPE (aref
));
12166 g
= gimple_build_assign (mask
, aref
);
12167 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12170 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
12172 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12173 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
12174 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
12177 /* Generate the condition. */
12178 g
= gimple_build_cond (LT_EXPR
,
12180 build_int_cst (unsigned_type_node
,
12181 node
->simdclone
->simdlen
),
12183 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12184 e
= split_block (incr_bb
, gsi_stmt (gsi
));
12185 basic_block latch_bb
= e
->dest
;
12186 basic_block new_exit_bb
;
12187 new_exit_bb
= split_block (latch_bb
, NULL
)->dest
;
12188 loop
->latch
= latch_bb
;
12190 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
12192 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
12193 /* The successor of incr_bb is already pointing to latch_bb; just
12195 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12196 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
12198 gphi
*phi
= create_phi_node (iter1
, body_bb
);
12199 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
12200 edge latch_edge
= single_succ_edge (latch_bb
);
12201 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
12203 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
12205 /* Generate the new return. */
12206 gsi
= gsi_last_bb (new_exit_bb
);
12208 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
12209 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
12210 retval
= TREE_OPERAND (retval
, 0);
12213 retval
= build1 (VIEW_CONVERT_EXPR
,
12214 TREE_TYPE (TREE_TYPE (node
->decl
)),
12216 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
12217 false, GSI_CONTINUE_LINKING
);
12219 g
= gimple_build_return (retval
);
12220 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
12222 /* Handle aligned clauses by replacing default defs of the aligned
12223 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12224 lhs. Handle linear by adding PHIs. */
12225 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
12226 if (node
->simdclone
->args
[i
].alignment
12227 && node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
12228 && (node
->simdclone
->args
[i
].alignment
12229 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
12230 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
12233 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
12234 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
12235 tree def
= ssa_default_def (cfun
, orig_arg
);
12236 if (def
&& !has_zero_uses (def
))
12238 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
12239 gimple_seq seq
= NULL
;
12240 bool need_cvt
= false;
12242 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
12244 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
12247 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
);
12248 gimple_call_set_lhs (g
, t
);
12249 gimple_seq_add_stmt_without_update (&seq
, g
);
12252 t
= make_ssa_name (orig_arg
);
12253 g
= gimple_build_assign (t
, NOP_EXPR
, gimple_call_lhs (g
));
12254 gimple_seq_add_stmt_without_update (&seq
, g
);
12256 gsi_insert_seq_on_edge_immediate
12257 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
12259 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
12260 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
12262 node
->create_edge (cgraph_node::get_create (fn
),
12263 call
, entry_bb
->count
, freq
);
12265 imm_use_iterator iter
;
12266 use_operand_p use_p
;
12268 tree repl
= gimple_get_lhs (g
);
12269 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
12270 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
12273 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
12274 SET_USE (use_p
, repl
);
12277 else if (node
->simdclone
->args
[i
].arg_type
12278 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
12280 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
12281 tree def
= ssa_default_def (cfun
, orig_arg
);
12282 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12283 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
12284 if (def
&& !has_zero_uses (def
))
12286 iter1
= make_ssa_name (orig_arg
);
12287 iter2
= make_ssa_name (orig_arg
);
12288 phi
= create_phi_node (iter1
, body_bb
);
12289 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
12290 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
12291 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12292 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
12293 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
12294 ? TREE_TYPE (orig_arg
) : sizetype
;
12296 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
12297 g
= gimple_build_assign (iter2
, code
, iter1
, addcst
);
12298 gsi
= gsi_last_bb (incr_bb
);
12299 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
12301 imm_use_iterator iter
;
12302 use_operand_p use_p
;
12304 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
12305 if (use_stmt
== phi
)
12308 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
12309 SET_USE (use_p
, iter1
);
12313 calculate_dominance_info (CDI_DOMINATORS
);
12314 add_loop (loop
, loop
->header
->loop_father
);
12315 update_ssa (TODO_update_ssa
);
12320 /* If the function in NODE is tagged as an elemental SIMD function,
12321 create the appropriate SIMD clones. */
12324 expand_simd_clones (struct cgraph_node
*node
)
12326 tree attr
= lookup_attribute ("omp declare simd",
12327 DECL_ATTRIBUTES (node
->decl
));
12328 if (attr
== NULL_TREE
12329 || node
->global
.inlined_to
12330 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
12334 #pragma omp declare simd
12336 in C, there we don't know the argument types at all. */
12337 if (!node
->definition
12338 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
12343 /* Start with parsing the "omp declare simd" attribute(s). */
12344 bool inbranch_clause_specified
;
12345 struct cgraph_simd_clone
*clone_info
12346 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
12347 &inbranch_clause_specified
);
12348 if (clone_info
== NULL
)
12351 int orig_simdlen
= clone_info
->simdlen
;
12352 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
12353 /* The target can return 0 (no simd clones should be created),
12354 1 (just one ISA of simd clones should be created) or higher
12355 count of ISA variants. In that case, clone_info is initialized
12356 for the first ISA variant. */
12358 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
12363 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12364 also create one inbranch and one !inbranch clone of it. */
12365 for (int i
= 0; i
< count
* 2; i
++)
12367 struct cgraph_simd_clone
*clone
= clone_info
;
12368 if (inbranch_clause_specified
&& (i
& 1) != 0)
12373 clone
= simd_clone_struct_alloc (clone_info
->nargs
12375 simd_clone_struct_copy (clone
, clone_info
);
12376 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12377 and simd_clone_adjust_argument_types did to the first
12379 clone
->nargs
-= clone_info
->inbranch
;
12380 clone
->simdlen
= orig_simdlen
;
12381 /* And call the target hook again to get the right ISA. */
12382 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
12386 clone
->inbranch
= 1;
12389 /* simd_clone_mangle might fail if such a clone has been created
12391 tree id
= simd_clone_mangle (node
, clone
);
12392 if (id
== NULL_TREE
)
12395 /* Only when we are sure we want to create the clone actually
12396 clone the function (or definitions) or create another
12397 extern FUNCTION_DECL (for prototypes without definitions). */
12398 struct cgraph_node
*n
= simd_clone_create (node
);
12402 n
->simdclone
= clone
;
12403 clone
->origin
= node
;
12404 clone
->next_clone
= NULL
;
12405 if (node
->simd_clones
== NULL
)
12407 clone
->prev_clone
= n
;
12408 node
->simd_clones
= n
;
12412 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
12413 clone
->prev_clone
->simdclone
->next_clone
= n
;
12414 node
->simd_clones
->simdclone
->prev_clone
= n
;
12416 symtab
->change_decl_assembler_name (n
->decl
, id
);
12417 /* And finally adjust the return type, parameters and for
12418 definitions also function body. */
12419 if (node
->definition
)
12420 simd_clone_adjust (n
);
12423 simd_clone_adjust_return_type (n
);
12424 simd_clone_adjust_argument_types (n
);
12428 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
12431 /* Entry point for IPA simd clone creation pass. */
12433 static unsigned int
12434 ipa_omp_simd_clone (void)
12436 struct cgraph_node
*node
;
12437 FOR_EACH_FUNCTION (node
)
12438 expand_simd_clones (node
);
12444 const pass_data pass_data_omp_simd_clone
=
12446 SIMPLE_IPA_PASS
, /* type */
12447 "simdclone", /* name */
12448 OPTGROUP_NONE
, /* optinfo_flags */
12449 TV_NONE
, /* tv_id */
12450 ( PROP_ssa
| PROP_cfg
), /* properties_required */
12451 0, /* properties_provided */
12452 0, /* properties_destroyed */
12453 0, /* todo_flags_start */
12454 0, /* todo_flags_finish */
12457 class pass_omp_simd_clone
: public simple_ipa_opt_pass
12460 pass_omp_simd_clone(gcc::context
*ctxt
)
12461 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
12464 /* opt_pass methods: */
12465 virtual bool gate (function
*);
12466 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
12470 pass_omp_simd_clone::gate (function
*)
12472 return ((flag_openmp
|| flag_openmp_simd
12474 || (in_lto_p
&& !flag_wpa
))
12475 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
12478 } // anon namespace
12480 simple_ipa_opt_pass
*
12481 make_pass_omp_simd_clone (gcc::context
*ctxt
)
12483 return new pass_omp_simd_clone (ctxt
);
12486 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
12487 adds their addresses and sizes to constructor-vector V_CTOR. */
12489 add_decls_addresses_to_decl_constructor (vec
<tree
, va_gc
> *v_decls
,
12490 vec
<constructor_elt
, va_gc
> *v_ctor
)
12492 unsigned len
= vec_safe_length (v_decls
);
12493 for (unsigned i
= 0; i
< len
; i
++)
12495 tree it
= (*v_decls
)[i
];
12496 bool is_function
= TREE_CODE (it
) != VAR_DECL
;
12498 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, build_fold_addr_expr (it
));
12500 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
,
12501 fold_convert (const_ptr_type_node
,
12502 DECL_SIZE_UNIT (it
)));
12506 /* Create new symbols containing (address, size) pairs for global variables,
12507 marked with "omp declare target" attribute, as well as addresses for the
12508 functions, which are outlined target regions. */
12510 omp_finish_file (void)
12512 unsigned num_funcs
= vec_safe_length (offload_funcs
);
12513 unsigned num_vars
= vec_safe_length (offload_vars
);
12515 if (num_funcs
== 0 && num_vars
== 0)
12518 if (targetm_common
.have_named_sections
)
12520 vec
<constructor_elt
, va_gc
> *v_f
, *v_v
;
12521 vec_alloc (v_f
, num_funcs
);
12522 vec_alloc (v_v
, num_vars
* 2);
12524 add_decls_addresses_to_decl_constructor (offload_funcs
, v_f
);
12525 add_decls_addresses_to_decl_constructor (offload_vars
, v_v
);
12527 tree vars_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
12529 tree funcs_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
12531 TYPE_ALIGN (vars_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
12532 TYPE_ALIGN (funcs_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
12533 tree ctor_v
= build_constructor (vars_decl_type
, v_v
);
12534 tree ctor_f
= build_constructor (funcs_decl_type
, v_f
);
12535 TREE_CONSTANT (ctor_v
) = TREE_CONSTANT (ctor_f
) = 1;
12536 TREE_STATIC (ctor_v
) = TREE_STATIC (ctor_f
) = 1;
12537 tree funcs_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
12538 get_identifier (".offload_func_table"),
12540 tree vars_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
12541 get_identifier (".offload_var_table"),
12543 TREE_STATIC (funcs_decl
) = TREE_STATIC (vars_decl
) = 1;
12544 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
12545 otherwise a joint table in a binary will contain padding between
12546 tables from multiple object files. */
12547 DECL_USER_ALIGN (funcs_decl
) = DECL_USER_ALIGN (vars_decl
) = 1;
12548 DECL_ALIGN (funcs_decl
) = TYPE_ALIGN (funcs_decl_type
);
12549 DECL_ALIGN (vars_decl
) = TYPE_ALIGN (vars_decl_type
);
12550 DECL_INITIAL (funcs_decl
) = ctor_f
;
12551 DECL_INITIAL (vars_decl
) = ctor_v
;
12552 set_decl_section_name (funcs_decl
, OFFLOAD_FUNC_TABLE_SECTION_NAME
);
12553 set_decl_section_name (vars_decl
, OFFLOAD_VAR_TABLE_SECTION_NAME
);
12555 varpool_node::finalize_decl (vars_decl
);
12556 varpool_node::finalize_decl (funcs_decl
);
12560 for (unsigned i
= 0; i
< num_funcs
; i
++)
12562 tree it
= (*offload_funcs
)[i
];
12563 targetm
.record_offload_symbol (it
);
12565 for (unsigned i
= 0; i
< num_vars
; i
++)
12567 tree it
= (*offload_vars
)[i
];
12568 targetm
.record_offload_symbol (it
);
12573 #include "gt-omp-low.h"