1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
27 #include "coretypes.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
38 #include "internal-fn.h"
39 #include "gimple-fold.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
50 #include "tree-into-ssa.h"
52 #include "insn-config.h"
63 #include "tree-pass.h"
65 #include "splay-tree.h"
66 #include "insn-codes.h"
70 #include "common/common-target.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "pretty-print.h"
75 #include "alloc-pool.h"
76 #include "symbol-summary.h"
78 #include "tree-nested.h"
82 #include "lto-section-names.h"
83 #include "gomp-constants.h"
85 /* Lowering of OMP parallel and workshare constructs proceeds in two
86 phases. The first phase scans the function looking for OMP statements
87 and then for variables that must be replaced to satisfy data sharing
88 clauses. The second phase expands code for the constructs, as well as
89 re-gimplifying things when variables have been replaced with complex
92 Final code generation is done by pass_expand_omp. The flowgraph is
93 scanned for regions which are then moved to a new
94 function, to be invoked by the thread library, or offloaded. */
96 /* OMP region information. Every parallel and workshare
97 directive is enclosed between two markers, the OMP_* directive
98 and a corresponding GIMPLE_OMP_RETURN statement. */
102 /* The enclosing region. */
103 struct omp_region
*outer
;
105 /* First child region. */
106 struct omp_region
*inner
;
108 /* Next peer region. */
109 struct omp_region
*next
;
111 /* Block containing the omp directive as its last stmt. */
114 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
117 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
120 /* If this is a combined parallel+workshare region, this is a list
121 of additional arguments needed by the combined parallel+workshare
123 vec
<tree
, va_gc
> *ws_args
;
125 /* The code for the omp directive of this region. */
126 enum gimple_code type
;
128 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
129 enum omp_clause_schedule_kind sched_kind
;
131 /* True if this is a combined parallel+workshare region. */
132 bool is_combined_parallel
;
134 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
136 gomp_ordered
*ord_stmt
;
139 /* Levels of parallelism as defined by OpenACC. Increasing numbers
140 correspond to deeper loop nesting levels. */
142 #define MASK_WORKER 2
143 #define MASK_VECTOR 4
145 /* Context structure. Used to store information about each parallel
146 directive in the code. */
150 /* This field must be at the beginning, as we do "inheritance": Some
151 callback functions for tree-inline.c (e.g., omp_copy_decl)
152 receive a copy_body_data pointer that is up-casted to an
153 omp_context pointer. */
156 /* The tree of contexts corresponding to the encountered constructs. */
157 struct omp_context
*outer
;
160 /* Map variables to fields in a structure that allows communication
161 between sending and receiving threads. */
162 splay_tree field_map
;
167 /* These are used just by task contexts, if task firstprivate fn is
168 needed. srecord_type is used to communicate from the thread
169 that encountered the task construct to task firstprivate fn,
170 record_type is allocated by GOMP_task, initialized by task firstprivate
171 fn and passed to the task body fn. */
172 splay_tree sfield_map
;
175 /* A chain of variables to add to the top-level block surrounding the
176 construct. In the case of a parallel, this is in the child function. */
179 /* A map of reduction pointer variables. For accelerators, each
180 reduction variable is replaced with an array. Each thread, in turn,
181 is assigned to a slot on that array. */
182 splay_tree reduction_map
;
184 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
185 barriers should jump to during omplower pass. */
188 /* What to do with variables with implicitly determined sharing
190 enum omp_clause_default_kind default_kind
;
192 /* Nesting depth of this context. Used to beautify error messages re
193 invalid gotos. The outermost ctx is depth 1, with depth 0 being
194 reserved for the main body of the function. */
197 /* True if this parallel directive is nested within another. */
200 /* True if this construct can be cancelled. */
203 /* For OpenACC loops, a mask of gang, worker and vector used at
204 levels below this one. */
206 /* For OpenACC loops, a mask of gang, worker and vector used at
207 this level and above. For parallel and kernels clauses, a mask
208 indicating which of num_gangs/num_workers/num_vectors was used. */
212 /* A structure holding the elements of:
213 for (V = N1; V cond N2; V += STEP) [...] */
215 struct omp_for_data_loop
217 tree v
, n1
, n2
, step
;
218 enum tree_code cond_code
;
221 /* A structure describing the main elements of a parallel loop. */
225 struct omp_for_data_loop loop
;
231 bool have_nowait
, have_ordered
, simd_schedule
;
232 enum omp_clause_schedule_kind sched_kind
;
233 struct omp_for_data_loop
*loops
;
237 static splay_tree all_contexts
;
238 static int taskreg_nesting_level
;
239 static int target_nesting_level
;
240 static struct omp_region
*root_omp_region
;
241 static bitmap task_shared_vars
;
242 static vec
<omp_context
*> taskreg_contexts
;
244 static void scan_omp (gimple_seq
*, omp_context
*);
245 static tree
scan_omp_1_op (tree
*, int *, void *);
246 static gphi
*find_phi_with_arg_on_edge (tree
, edge
);
248 #define WALK_SUBSTMTS \
252 case GIMPLE_EH_FILTER: \
253 case GIMPLE_TRANSACTION: \
254 /* The sub-statements for these should be walked. */ \
255 *handled_ops_p = false; \
258 /* Helper function to get the name of the array containing the partial
259 reductions for OpenACC reductions. */
261 oacc_get_reduction_array_id (tree node
)
263 const char *id
= IDENTIFIER_POINTER (DECL_NAME (node
));
264 int len
= strlen ("OACC") + strlen (id
);
265 char *temp_name
= XALLOCAVEC (char, len
+ 1);
266 snprintf (temp_name
, len
+ 1, "OACC%s", id
);
267 return IDENTIFIER_POINTER (get_identifier (temp_name
));
270 /* Determine the number of threads OpenACC threads used to determine the
271 size of the array of partial reductions. Currently, this is num_gangs
272 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
273 because it is independed of the device used. */
276 oacc_max_threads (omp_context
*ctx
)
278 tree nthreads
, vector_length
, gangs
, clauses
;
280 gangs
= fold_convert (sizetype
, integer_one_node
);
281 vector_length
= gangs
;
283 /* The reduction clause may be nested inside a loop directive.
284 Scan for the innermost vector_length clause. */
285 for (omp_context
*oc
= ctx
; oc
; oc
= oc
->outer
)
287 if (gimple_code (oc
->stmt
) != GIMPLE_OMP_TARGET
288 || (gimple_omp_target_kind (oc
->stmt
)
289 != GF_OMP_TARGET_KIND_OACC_PARALLEL
))
292 clauses
= gimple_omp_target_clauses (oc
->stmt
);
294 vector_length
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
296 vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length
),
298 OMP_CLAUSE_VECTOR_LENGTH_EXPR
301 vector_length
= fold_convert (sizetype
, integer_one_node
);
303 gangs
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
305 gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (gangs
), sizetype
,
306 OMP_CLAUSE_NUM_GANGS_EXPR (gangs
));
308 gangs
= fold_convert (sizetype
, integer_one_node
);
313 nthreads
= fold_build2 (MULT_EXPR
, sizetype
, gangs
, vector_length
);
318 /* If DECL is the artificial dummy VAR_DECL created for non-static
319 data member privatization, return the underlying "this" parameter,
320 otherwise return NULL. */
323 omp_member_access_dummy_var (tree decl
)
326 || !DECL_ARTIFICIAL (decl
)
327 || !DECL_IGNORED_P (decl
)
328 || !DECL_HAS_VALUE_EXPR_P (decl
)
329 || !lang_hooks
.decls
.omp_disregard_value_expr (decl
, false))
332 tree v
= DECL_VALUE_EXPR (decl
);
333 if (TREE_CODE (v
) != COMPONENT_REF
)
337 switch (TREE_CODE (v
))
343 case POINTER_PLUS_EXPR
:
344 v
= TREE_OPERAND (v
, 0);
347 if (DECL_CONTEXT (v
) == current_function_decl
348 && DECL_ARTIFICIAL (v
)
349 && TREE_CODE (TREE_TYPE (v
)) == POINTER_TYPE
)
357 /* Helper for unshare_and_remap, called through walk_tree. */
360 unshare_and_remap_1 (tree
*tp
, int *walk_subtrees
, void *data
)
362 tree
*pair
= (tree
*) data
;
365 *tp
= unshare_expr (pair
[1]);
368 else if (IS_TYPE_OR_DECL_P (*tp
))
373 /* Return unshare_expr (X) with all occurrences of FROM
377 unshare_and_remap (tree x
, tree from
, tree to
)
379 tree pair
[2] = { from
, to
};
380 x
= unshare_expr (x
);
381 walk_tree (&x
, unshare_and_remap_1
, pair
, NULL
);
385 /* Holds offload tables with decls. */
386 vec
<tree
, va_gc
> *offload_funcs
, *offload_vars
;
388 /* Convenience function for calling scan_omp_1_op on tree operands. */
391 scan_omp_op (tree
*tp
, omp_context
*ctx
)
393 struct walk_stmt_info wi
;
395 memset (&wi
, 0, sizeof (wi
));
397 wi
.want_locations
= true;
399 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
402 static void lower_omp (gimple_seq
*, omp_context
*);
403 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
404 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
406 /* Find an OMP clause of type KIND within CLAUSES. */
409 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
411 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
412 if (OMP_CLAUSE_CODE (clauses
) == kind
)
418 /* Return true if CTX is for an omp parallel. */
421 is_parallel_ctx (omp_context
*ctx
)
423 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
427 /* Return true if CTX is for an omp task. */
430 is_task_ctx (omp_context
*ctx
)
432 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
436 /* Return true if CTX is for an omp taskloop. */
439 is_taskloop_ctx (omp_context
*ctx
)
441 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
442 && gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_TASKLOOP
;
446 /* Return true if CTX is for an omp parallel or omp task. */
449 is_taskreg_ctx (omp_context
*ctx
)
451 return is_parallel_ctx (ctx
) || is_task_ctx (ctx
);
455 /* Return true if REGION is a combined parallel+workshare region. */
458 is_combined_parallel (struct omp_region
*region
)
460 return region
->is_combined_parallel
;
464 /* Extract the header elements of parallel loop FOR_STMT and store
468 extract_omp_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
469 struct omp_for_data_loop
*loops
)
471 tree t
, var
, *collapse_iter
, *collapse_count
;
472 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
473 struct omp_for_data_loop
*loop
;
475 struct omp_for_data_loop dummy_loop
;
476 location_t loc
= gimple_location (for_stmt
);
477 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
478 bool distribute
= gimple_omp_for_kind (for_stmt
)
479 == GF_OMP_FOR_KIND_DISTRIBUTE
;
480 bool taskloop
= gimple_omp_for_kind (for_stmt
)
481 == GF_OMP_FOR_KIND_TASKLOOP
;
484 fd
->for_stmt
= for_stmt
;
486 if (gimple_omp_for_collapse (for_stmt
) > 1)
489 fd
->loops
= &fd
->loop
;
491 fd
->have_nowait
= distribute
|| simd
;
492 fd
->have_ordered
= false;
495 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
496 fd
->chunk_size
= NULL_TREE
;
497 fd
->simd_schedule
= false;
498 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
499 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
500 collapse_iter
= NULL
;
501 collapse_count
= NULL
;
503 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
504 switch (OMP_CLAUSE_CODE (t
))
506 case OMP_CLAUSE_NOWAIT
:
507 fd
->have_nowait
= true;
509 case OMP_CLAUSE_ORDERED
:
510 fd
->have_ordered
= true;
511 if (OMP_CLAUSE_ORDERED_EXPR (t
))
512 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
514 case OMP_CLAUSE_SCHEDULE
:
515 gcc_assert (!distribute
&& !taskloop
);
516 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
517 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
518 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
520 case OMP_CLAUSE_DIST_SCHEDULE
:
521 gcc_assert (distribute
);
522 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
524 case OMP_CLAUSE_COLLAPSE
:
525 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
526 if (fd
->collapse
> 1)
528 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
529 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
535 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
540 collapse_iter
= &iterv
;
541 collapse_count
= &countv
;
544 /* FIXME: for now map schedule(auto) to schedule(static).
545 There should be analysis to determine whether all iterations
546 are approximately the same amount of work (then schedule(static)
547 is best) or if it varies (then schedule(dynamic,N) is better). */
548 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
550 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
551 gcc_assert (fd
->chunk_size
== NULL
);
553 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
555 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
556 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
557 gcc_assert (fd
->chunk_size
== NULL
);
558 else if (fd
->chunk_size
== NULL
)
560 /* We only need to compute a default chunk size for ordered
561 static loops and dynamic loops. */
562 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
564 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
565 ? integer_zero_node
: integer_one_node
;
568 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
569 for (i
= 0; i
< cnt
; i
++)
571 if (i
== 0 && fd
->collapse
== 1 && (fd
->ordered
== 0 || loops
== NULL
))
573 else if (loops
!= NULL
)
578 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
579 gcc_assert (SSA_VAR_P (loop
->v
));
580 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
581 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
582 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
583 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
585 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
586 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
587 switch (loop
->cond_code
)
593 gcc_assert (gimple_omp_for_kind (for_stmt
)
594 == GF_OMP_FOR_KIND_CILKSIMD
595 || (gimple_omp_for_kind (for_stmt
)
596 == GF_OMP_FOR_KIND_CILKFOR
));
599 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
600 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
602 loop
->n2
= fold_build2_loc (loc
,
603 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
604 build_int_cst (TREE_TYPE (loop
->n2
), 1));
605 loop
->cond_code
= LT_EXPR
;
608 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
609 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
611 loop
->n2
= fold_build2_loc (loc
,
612 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
613 build_int_cst (TREE_TYPE (loop
->n2
), 1));
614 loop
->cond_code
= GT_EXPR
;
620 t
= gimple_omp_for_incr (for_stmt
, i
);
621 gcc_assert (TREE_OPERAND (t
, 0) == var
);
622 switch (TREE_CODE (t
))
625 loop
->step
= TREE_OPERAND (t
, 1);
627 case POINTER_PLUS_EXPR
:
628 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
631 loop
->step
= TREE_OPERAND (t
, 1);
632 loop
->step
= fold_build1_loc (loc
,
633 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
641 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
642 && !fd
->have_ordered
))
644 if (fd
->collapse
== 1)
645 iter_type
= TREE_TYPE (loop
->v
);
647 || TYPE_PRECISION (iter_type
)
648 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
650 = build_nonstandard_integer_type
651 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
653 else if (iter_type
!= long_long_unsigned_type_node
)
655 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
656 iter_type
= long_long_unsigned_type_node
;
657 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
658 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
659 >= TYPE_PRECISION (iter_type
))
663 if (loop
->cond_code
== LT_EXPR
)
664 n
= fold_build2_loc (loc
,
665 PLUS_EXPR
, TREE_TYPE (loop
->v
),
666 loop
->n2
, loop
->step
);
669 if (TREE_CODE (n
) != INTEGER_CST
670 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
671 iter_type
= long_long_unsigned_type_node
;
673 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
674 > TYPE_PRECISION (iter_type
))
678 if (loop
->cond_code
== LT_EXPR
)
681 n2
= fold_build2_loc (loc
,
682 PLUS_EXPR
, TREE_TYPE (loop
->v
),
683 loop
->n2
, loop
->step
);
687 n1
= fold_build2_loc (loc
,
688 MINUS_EXPR
, TREE_TYPE (loop
->v
),
689 loop
->n2
, loop
->step
);
692 if (TREE_CODE (n1
) != INTEGER_CST
693 || TREE_CODE (n2
) != INTEGER_CST
694 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
695 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
696 iter_type
= long_long_unsigned_type_node
;
700 if (i
>= fd
->collapse
)
703 if (collapse_count
&& *collapse_count
== NULL
)
705 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
706 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
707 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
708 if (t
&& integer_zerop (t
))
709 count
= build_zero_cst (long_long_unsigned_type_node
);
710 else if ((i
== 0 || count
!= NULL_TREE
)
711 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
712 && TREE_CONSTANT (loop
->n1
)
713 && TREE_CONSTANT (loop
->n2
)
714 && TREE_CODE (loop
->step
) == INTEGER_CST
)
716 tree itype
= TREE_TYPE (loop
->v
);
718 if (POINTER_TYPE_P (itype
))
719 itype
= signed_type_for (itype
);
720 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
721 t
= fold_build2_loc (loc
,
723 fold_convert_loc (loc
, itype
, loop
->step
), t
);
724 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
725 fold_convert_loc (loc
, itype
, loop
->n2
));
726 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
727 fold_convert_loc (loc
, itype
, loop
->n1
));
728 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
729 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
730 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
731 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
732 fold_convert_loc (loc
, itype
,
735 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
736 fold_convert_loc (loc
, itype
, loop
->step
));
737 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
738 if (count
!= NULL_TREE
)
739 count
= fold_build2_loc (loc
,
740 MULT_EXPR
, long_long_unsigned_type_node
,
744 if (TREE_CODE (count
) != INTEGER_CST
)
747 else if (count
&& !integer_zerop (count
))
754 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
755 || fd
->have_ordered
))
757 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
758 iter_type
= long_long_unsigned_type_node
;
760 iter_type
= long_integer_type_node
;
762 else if (collapse_iter
&& *collapse_iter
!= NULL
)
763 iter_type
= TREE_TYPE (*collapse_iter
);
764 fd
->iter_type
= iter_type
;
765 if (collapse_iter
&& *collapse_iter
== NULL
)
766 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
767 if (collapse_count
&& *collapse_count
== NULL
)
770 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
772 *collapse_count
= create_tmp_var (iter_type
, ".count");
775 if (fd
->collapse
> 1 || (fd
->ordered
&& loops
))
777 fd
->loop
.v
= *collapse_iter
;
778 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
779 fd
->loop
.n2
= *collapse_count
;
780 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
781 fd
->loop
.cond_code
= LT_EXPR
;
786 /* For OpenACC loops, force a chunk size of one, as this avoids the default
787 scheduling where several subsequent iterations are being executed by the
789 if (gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
791 gcc_assert (fd
->chunk_size
== NULL_TREE
);
792 fd
->chunk_size
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
797 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
798 is the immediate dominator of PAR_ENTRY_BB, return true if there
799 are no data dependencies that would prevent expanding the parallel
800 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
802 When expanding a combined parallel+workshare region, the call to
803 the child function may need additional arguments in the case of
804 GIMPLE_OMP_FOR regions. In some cases, these arguments are
805 computed out of variables passed in from the parent to the child
806 via 'struct .omp_data_s'. For instance:
808 #pragma omp parallel for schedule (guided, i * 4)
813 # BLOCK 2 (PAR_ENTRY_BB)
815 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
817 # BLOCK 3 (WS_ENTRY_BB)
818 .omp_data_i = &.omp_data_o;
819 D.1667 = .omp_data_i->i;
821 #pragma omp for schedule (guided, D.1598)
823 When we outline the parallel region, the call to the child function
824 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
825 that value is computed *after* the call site. So, in principle we
826 cannot do the transformation.
828 To see whether the code in WS_ENTRY_BB blocks the combined
829 parallel+workshare call, we collect all the variables used in the
830 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
831 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
834 FIXME. If we had the SSA form built at this point, we could merely
835 hoist the code in block 3 into block 2 and be done with it. But at
836 this point we don't have dataflow information and though we could
837 hack something up here, it is really not worth the aggravation. */
840 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
842 struct omp_for_data fd
;
843 gimple
*ws_stmt
= last_stmt (ws_entry_bb
);
845 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
848 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
850 extract_omp_for_data (as_a
<gomp_for
*> (ws_stmt
), &fd
, NULL
);
852 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
854 if (fd
.iter_type
!= long_integer_type_node
)
857 /* FIXME. We give up too easily here. If any of these arguments
858 are not constants, they will likely involve variables that have
859 been mapped into fields of .omp_data_s for sharing with the child
860 function. With appropriate data flow, it would be possible to
862 if (!is_gimple_min_invariant (fd
.loop
.n1
)
863 || !is_gimple_min_invariant (fd
.loop
.n2
)
864 || !is_gimple_min_invariant (fd
.loop
.step
)
865 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
872 static int omp_max_vf (void);
874 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
875 presence (SIMD_SCHEDULE). */
878 omp_adjust_chunk_size (tree chunk_size
, bool simd_schedule
)
883 int vf
= omp_max_vf ();
887 tree type
= TREE_TYPE (chunk_size
);
888 chunk_size
= fold_build2 (PLUS_EXPR
, type
, chunk_size
,
889 build_int_cst (type
, vf
- 1));
890 return fold_build2 (BIT_AND_EXPR
, type
, chunk_size
,
891 build_int_cst (type
, -vf
));
895 /* Collect additional arguments needed to emit a combined
896 parallel+workshare call. WS_STMT is the workshare directive being
899 static vec
<tree
, va_gc
> *
900 get_ws_args_for (gimple
*par_stmt
, gimple
*ws_stmt
)
903 location_t loc
= gimple_location (ws_stmt
);
904 vec
<tree
, va_gc
> *ws_args
;
906 if (gomp_for
*for_stmt
= dyn_cast
<gomp_for
*> (ws_stmt
))
908 struct omp_for_data fd
;
911 extract_omp_for_data (for_stmt
, &fd
, NULL
);
915 if (gimple_omp_for_combined_into_p (for_stmt
))
918 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
919 OMP_CLAUSE__LOOPTEMP_
);
921 n1
= OMP_CLAUSE_DECL (innerc
);
922 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
923 OMP_CLAUSE__LOOPTEMP_
);
925 n2
= OMP_CLAUSE_DECL (innerc
);
928 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
930 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
931 ws_args
->quick_push (t
);
933 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
934 ws_args
->quick_push (t
);
936 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
937 ws_args
->quick_push (t
);
941 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
942 t
= omp_adjust_chunk_size (t
, fd
.simd_schedule
);
943 ws_args
->quick_push (t
);
948 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
950 /* Number of sections is equal to the number of edges from the
951 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
952 the exit of the sections region. */
953 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
954 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
955 vec_alloc (ws_args
, 1);
956 ws_args
->quick_push (t
);
964 /* Discover whether REGION is a combined parallel+workshare region. */
967 determine_parallel_type (struct omp_region
*region
)
969 basic_block par_entry_bb
, par_exit_bb
;
970 basic_block ws_entry_bb
, ws_exit_bb
;
972 if (region
== NULL
|| region
->inner
== NULL
973 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
974 || region
->inner
->cont
== NULL
)
977 /* We only support parallel+for and parallel+sections. */
978 if (region
->type
!= GIMPLE_OMP_PARALLEL
979 || (region
->inner
->type
!= GIMPLE_OMP_FOR
980 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
983 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
984 WS_EXIT_BB -> PAR_EXIT_BB. */
985 par_entry_bb
= region
->entry
;
986 par_exit_bb
= region
->exit
;
987 ws_entry_bb
= region
->inner
->entry
;
988 ws_exit_bb
= region
->inner
->exit
;
990 if (single_succ (par_entry_bb
) == ws_entry_bb
991 && single_succ (ws_exit_bb
) == par_exit_bb
992 && workshare_safe_to_combine_p (ws_entry_bb
)
993 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
994 || (last_and_only_stmt (ws_entry_bb
)
995 && last_and_only_stmt (par_exit_bb
))))
997 gimple
*par_stmt
= last_stmt (par_entry_bb
);
998 gimple
*ws_stmt
= last_stmt (ws_entry_bb
);
1000 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
1002 /* If this is a combined parallel loop, we need to determine
1003 whether or not to use the combined library calls. There
1004 are two cases where we do not apply the transformation:
1005 static loops and any kind of ordered loop. In the first
1006 case, we already open code the loop so there is no need
1007 to do anything else. In the latter case, the combined
1008 parallel loop call would still need extra synchronization
1009 to implement ordered semantics, so there would not be any
1010 gain in using the combined call. */
1011 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
1012 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
1014 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
1015 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
1017 region
->is_combined_parallel
= false;
1018 region
->inner
->is_combined_parallel
= false;
1023 region
->is_combined_parallel
= true;
1024 region
->inner
->is_combined_parallel
= true;
1025 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
1030 /* Return true if EXPR is variable sized. */
1033 is_variable_sized (const_tree expr
)
1035 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
1038 /* Return true if DECL is a reference type. */
1041 is_reference (tree decl
)
1043 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
1046 /* Return the type of a decl. If the decl is reference type,
1047 return its base type. */
1049 get_base_type (tree decl
)
1051 tree type
= TREE_TYPE (decl
);
1052 if (is_reference (decl
))
1053 type
= TREE_TYPE (type
);
1057 /* Lookup variables. The "maybe" form
1058 allows for the variable form to not have been entered, otherwise we
1059 assert that the variable must have been entered. */
1062 lookup_decl (tree var
, omp_context
*ctx
)
1064 tree
*n
= ctx
->cb
.decl_map
->get (var
);
1069 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
1071 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
1072 return n
? *n
: NULL_TREE
;
1076 lookup_field (tree var
, omp_context
*ctx
)
1079 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
1080 return (tree
) n
->value
;
1084 lookup_sfield (splay_tree_key key
, omp_context
*ctx
)
1087 n
= splay_tree_lookup (ctx
->sfield_map
1088 ? ctx
->sfield_map
: ctx
->field_map
, key
);
1089 return (tree
) n
->value
;
1093 lookup_sfield (tree var
, omp_context
*ctx
)
1095 return lookup_sfield ((splay_tree_key
) var
, ctx
);
1099 maybe_lookup_field (splay_tree_key key
, omp_context
*ctx
)
1102 n
= splay_tree_lookup (ctx
->field_map
, key
);
1103 return n
? (tree
) n
->value
: NULL_TREE
;
1107 maybe_lookup_field (tree var
, omp_context
*ctx
)
1109 return maybe_lookup_field ((splay_tree_key
) var
, ctx
);
1113 lookup_oacc_reduction (const char *id
, omp_context
*ctx
)
1116 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) id
);
1117 return (tree
) n
->value
;
1121 maybe_lookup_oacc_reduction (tree var
, omp_context
*ctx
)
1123 splay_tree_node n
= NULL
;
1124 if (ctx
->reduction_map
)
1125 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) var
);
1126 return n
? (tree
) n
->value
: NULL_TREE
;
1129 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1130 the parallel context if DECL is to be shared. */
1133 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
1135 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
1138 /* We can only use copy-in/copy-out semantics for shared variables
1139 when we know the value is not accessible from an outer scope. */
1142 gcc_assert (!is_gimple_omp_oacc (shared_ctx
->stmt
));
1144 /* ??? Trivially accessible from anywhere. But why would we even
1145 be passing an address in this case? Should we simply assert
1146 this to be false, or should we have a cleanup pass that removes
1147 these from the list of mappings? */
1148 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
1151 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1152 without analyzing the expression whether or not its location
1153 is accessible to anyone else. In the case of nested parallel
1154 regions it certainly may be. */
1155 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
1158 /* Do not use copy-in/copy-out for variables that have their
1160 if (TREE_ADDRESSABLE (decl
))
1163 /* lower_send_shared_vars only uses copy-in, but not copy-out
1165 if (TREE_READONLY (decl
)
1166 || ((TREE_CODE (decl
) == RESULT_DECL
1167 || TREE_CODE (decl
) == PARM_DECL
)
1168 && DECL_BY_REFERENCE (decl
)))
1171 /* Disallow copy-in/out in nested parallel if
1172 decl is shared in outer parallel, otherwise
1173 each thread could store the shared variable
1174 in its own copy-in location, making the
1175 variable no longer really shared. */
1176 if (shared_ctx
->is_nested
)
1180 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
1181 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
1188 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
1189 c
; c
= OMP_CLAUSE_CHAIN (c
))
1190 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1191 && OMP_CLAUSE_DECL (c
) == decl
)
1195 goto maybe_mark_addressable_and_ret
;
1199 /* For tasks avoid using copy-in/out. As tasks can be
1200 deferred or executed in different thread, when GOMP_task
1201 returns, the task hasn't necessarily terminated. */
1202 if (is_task_ctx (shared_ctx
))
1205 maybe_mark_addressable_and_ret
:
1206 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
1207 if (is_gimple_reg (outer
) && !omp_member_access_dummy_var (outer
))
1209 /* Taking address of OUTER in lower_send_shared_vars
1210 might need regimplification of everything that uses the
1212 if (!task_shared_vars
)
1213 task_shared_vars
= BITMAP_ALLOC (NULL
);
1214 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
1215 TREE_ADDRESSABLE (outer
) = 1;
1224 /* Construct a new automatic decl similar to VAR. */
1227 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
1229 tree copy
= copy_var_decl (var
, name
, type
);
1231 DECL_CONTEXT (copy
) = current_function_decl
;
1232 DECL_CHAIN (copy
) = ctx
->block_vars
;
1233 /* If VAR is listed in task_shared_vars, it means it wasn't
1234 originally addressable and is just because task needs to take
1235 it's address. But we don't need to take address of privatizations
1237 if (TREE_ADDRESSABLE (var
)
1239 && bitmap_bit_p (task_shared_vars
, DECL_UID (var
)))
1240 TREE_ADDRESSABLE (copy
) = 0;
1241 ctx
->block_vars
= copy
;
1247 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
1249 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
1252 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1255 omp_build_component_ref (tree obj
, tree field
)
1257 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
1258 if (TREE_THIS_VOLATILE (field
))
1259 TREE_THIS_VOLATILE (ret
) |= 1;
1260 if (TREE_READONLY (field
))
1261 TREE_READONLY (ret
) |= 1;
1265 /* Build tree nodes to access the field for VAR on the receiver side. */
1268 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1270 tree x
, field
= lookup_field (var
, ctx
);
1272 /* If the receiver record type was remapped in the child function,
1273 remap the field into the new record type. */
1274 x
= maybe_lookup_field (field
, ctx
);
1278 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1279 TREE_THIS_NOTRAP (x
) = 1;
1280 x
= omp_build_component_ref (x
, field
);
1282 x
= build_simple_mem_ref (x
);
1287 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1288 of a parallel, this is a component reference; for workshare constructs
1289 this is some variable. */
1292 build_outer_var_ref (tree var
, omp_context
*ctx
, bool lastprivate
= false)
1296 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1298 else if (is_variable_sized (var
))
1300 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1301 x
= build_outer_var_ref (x
, ctx
, lastprivate
);
1302 x
= build_simple_mem_ref (x
);
1304 else if (is_taskreg_ctx (ctx
))
1306 bool by_ref
= use_pointer_for_field (var
, NULL
);
1307 x
= build_receiver_ref (var
, by_ref
, ctx
);
1309 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1310 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1312 /* #pragma omp simd isn't a worksharing construct, and can reference even
1313 private vars in its linear etc. clauses. */
1315 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1316 x
= lookup_decl (var
, ctx
->outer
);
1317 else if (ctx
->outer
)
1318 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1322 else if (lastprivate
&& is_taskloop_ctx (ctx
))
1324 gcc_assert (ctx
->outer
);
1326 = splay_tree_lookup (ctx
->outer
->field_map
,
1327 (splay_tree_key
) &DECL_UID (var
));
1330 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
->outer
)))
1333 x
= lookup_decl (var
, ctx
->outer
);
1337 tree field
= (tree
) n
->value
;
1338 /* If the receiver record type was remapped in the child function,
1339 remap the field into the new record type. */
1340 x
= maybe_lookup_field (field
, ctx
->outer
);
1344 x
= build_simple_mem_ref (ctx
->outer
->receiver_decl
);
1345 x
= omp_build_component_ref (x
, field
);
1346 if (use_pointer_for_field (var
, ctx
->outer
))
1347 x
= build_simple_mem_ref (x
);
1350 else if (ctx
->outer
)
1351 x
= lookup_decl (var
, ctx
->outer
);
1352 else if (is_reference (var
))
1353 /* This can happen with orphaned constructs. If var is reference, it is
1354 possible it is shared and as such valid. */
1356 else if (omp_member_access_dummy_var (var
))
1363 tree t
= omp_member_access_dummy_var (var
);
1366 x
= DECL_VALUE_EXPR (var
);
1367 tree o
= maybe_lookup_decl_in_outer_ctx (t
, ctx
);
1369 x
= unshare_and_remap (x
, t
, o
);
1371 x
= unshare_expr (x
);
1375 if (is_reference (var
))
1376 x
= build_simple_mem_ref (x
);
1381 /* Build tree nodes to access the field for VAR on the sender side. */
1384 build_sender_ref (splay_tree_key key
, omp_context
*ctx
)
1386 tree field
= lookup_sfield (key
, ctx
);
1387 return omp_build_component_ref (ctx
->sender_decl
, field
);
1391 build_sender_ref (tree var
, omp_context
*ctx
)
1393 return build_sender_ref ((splay_tree_key
) var
, ctx
);
1396 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1399 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1401 tree field
, type
, sfield
= NULL_TREE
;
1402 splay_tree_key key
= (splay_tree_key
) var
;
1404 if ((mask
& 8) != 0)
1406 key
= (splay_tree_key
) &DECL_UID (var
);
1407 gcc_checking_assert (key
!= (splay_tree_key
) var
);
1409 gcc_assert ((mask
& 1) == 0
1410 || !splay_tree_lookup (ctx
->field_map
, key
));
1411 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1412 || !splay_tree_lookup (ctx
->sfield_map
, key
));
1413 gcc_assert ((mask
& 3) == 3
1414 || !is_gimple_omp_oacc (ctx
->stmt
));
1416 type
= TREE_TYPE (var
);
1419 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1420 type
= build_pointer_type (build_pointer_type (type
));
1423 type
= build_pointer_type (type
);
1424 else if ((mask
& 3) == 1 && is_reference (var
))
1425 type
= TREE_TYPE (type
);
1427 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1428 FIELD_DECL
, DECL_NAME (var
), type
);
1430 /* Remember what variable this field was created for. This does have a
1431 side effect of making dwarf2out ignore this member, so for helpful
1432 debugging we clear it later in delete_omp_context. */
1433 DECL_ABSTRACT_ORIGIN (field
) = var
;
1434 if (type
== TREE_TYPE (var
))
1436 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1437 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1438 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1441 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1443 if ((mask
& 3) == 3)
1445 insert_field_into_struct (ctx
->record_type
, field
);
1446 if (ctx
->srecord_type
)
1448 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1449 FIELD_DECL
, DECL_NAME (var
), type
);
1450 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1451 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1452 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1453 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1454 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1459 if (ctx
->srecord_type
== NULL_TREE
)
1463 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1464 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1465 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1467 sfield
= build_decl (DECL_SOURCE_LOCATION (t
),
1468 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1469 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1470 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1471 splay_tree_insert (ctx
->sfield_map
,
1472 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1473 (splay_tree_value
) sfield
);
1477 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1478 : ctx
->srecord_type
, field
);
1482 splay_tree_insert (ctx
->field_map
, key
, (splay_tree_value
) field
);
1483 if ((mask
& 2) && ctx
->sfield_map
)
1484 splay_tree_insert (ctx
->sfield_map
, key
, (splay_tree_value
) sfield
);
1488 install_var_local (tree var
, omp_context
*ctx
)
1490 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1491 insert_decl_map (&ctx
->cb
, var
, new_var
);
1495 /* Adjust the replacement for DECL in CTX for the new context. This means
1496 copying the DECL_VALUE_EXPR, and fixing up the type. */
1499 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1501 tree new_decl
, size
;
1503 new_decl
= lookup_decl (decl
, ctx
);
1505 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1507 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1508 && DECL_HAS_VALUE_EXPR_P (decl
))
1510 tree ve
= DECL_VALUE_EXPR (decl
);
1511 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1512 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1513 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1516 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1518 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1519 if (size
== error_mark_node
)
1520 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1521 DECL_SIZE (new_decl
) = size
;
1523 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1524 if (size
== error_mark_node
)
1525 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1526 DECL_SIZE_UNIT (new_decl
) = size
;
1530 /* The callback for remap_decl. Search all containing contexts for a
1531 mapping of the variable; this avoids having to duplicate the splay
1532 tree ahead of time. We know a mapping doesn't already exist in the
1533 given context. Create new mappings to implement default semantics. */
1536 omp_copy_decl (tree var
, copy_body_data
*cb
)
1538 omp_context
*ctx
= (omp_context
*) cb
;
1541 if (TREE_CODE (var
) == LABEL_DECL
)
1543 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1544 DECL_CONTEXT (new_var
) = current_function_decl
;
1545 insert_decl_map (&ctx
->cb
, var
, new_var
);
1549 while (!is_taskreg_ctx (ctx
))
1554 new_var
= maybe_lookup_decl (var
, ctx
);
1559 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1562 return error_mark_node
;
1566 /* Debugging dumps for parallel regions. */
1567 void dump_omp_region (FILE *, struct omp_region
*, int);
1568 void debug_omp_region (struct omp_region
*);
1569 void debug_all_omp_regions (void);
1571 /* Dump the parallel region tree rooted at REGION. */
1574 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1576 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1577 gimple_code_name
[region
->type
]);
1580 dump_omp_region (file
, region
->inner
, indent
+ 4);
1584 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1585 region
->cont
->index
);
1589 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1590 region
->exit
->index
);
1592 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1595 dump_omp_region (file
, region
->next
, indent
);
1599 debug_omp_region (struct omp_region
*region
)
1601 dump_omp_region (stderr
, region
, 0);
1605 debug_all_omp_regions (void)
1607 dump_omp_region (stderr
, root_omp_region
, 0);
1611 /* Create a new parallel region starting at STMT inside region PARENT. */
1613 static struct omp_region
*
1614 new_omp_region (basic_block bb
, enum gimple_code type
,
1615 struct omp_region
*parent
)
1617 struct omp_region
*region
= XCNEW (struct omp_region
);
1619 region
->outer
= parent
;
1621 region
->type
= type
;
1625 /* This is a nested region. Add it to the list of inner
1626 regions in PARENT. */
1627 region
->next
= parent
->inner
;
1628 parent
->inner
= region
;
1632 /* This is a toplevel region. Add it to the list of toplevel
1633 regions in ROOT_OMP_REGION. */
1634 region
->next
= root_omp_region
;
1635 root_omp_region
= region
;
1641 /* Release the memory associated with the region tree rooted at REGION. */
1644 free_omp_region_1 (struct omp_region
*region
)
1646 struct omp_region
*i
, *n
;
1648 for (i
= region
->inner
; i
; i
= n
)
1651 free_omp_region_1 (i
);
1657 /* Release the memory for the entire omp region tree. */
1660 free_omp_regions (void)
1662 struct omp_region
*r
, *n
;
1663 for (r
= root_omp_region
; r
; r
= n
)
1666 free_omp_region_1 (r
);
1668 root_omp_region
= NULL
;
1672 /* Create a new context, with OUTER_CTX being the surrounding context. */
1674 static omp_context
*
1675 new_omp_context (gimple
*stmt
, omp_context
*outer_ctx
)
1677 omp_context
*ctx
= XCNEW (omp_context
);
1679 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1680 (splay_tree_value
) ctx
);
1685 ctx
->outer
= outer_ctx
;
1686 ctx
->cb
= outer_ctx
->cb
;
1687 ctx
->cb
.block
= NULL
;
1688 ctx
->depth
= outer_ctx
->depth
+ 1;
1689 ctx
->reduction_map
= outer_ctx
->reduction_map
;
1693 ctx
->cb
.src_fn
= current_function_decl
;
1694 ctx
->cb
.dst_fn
= current_function_decl
;
1695 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1696 gcc_checking_assert (ctx
->cb
.src_node
);
1697 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1698 ctx
->cb
.src_cfun
= cfun
;
1699 ctx
->cb
.copy_decl
= omp_copy_decl
;
1700 ctx
->cb
.eh_lp_nr
= 0;
1701 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1705 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1710 static gimple_seq
maybe_catch_exception (gimple_seq
);
1712 /* Finalize task copyfn. */
1715 finalize_task_copyfn (gomp_task
*task_stmt
)
1717 struct function
*child_cfun
;
1719 gimple_seq seq
= NULL
, new_seq
;
1722 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1723 if (child_fn
== NULL_TREE
)
1726 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1727 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1729 push_cfun (child_cfun
);
1730 bind
= gimplify_body (child_fn
, false);
1731 gimple_seq_add_stmt (&seq
, bind
);
1732 new_seq
= maybe_catch_exception (seq
);
1735 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1737 gimple_seq_add_stmt (&seq
, bind
);
1739 gimple_set_body (child_fn
, seq
);
1742 /* Inform the callgraph about the new function. */
1743 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
1744 node
->parallelized_function
= 1;
1745 cgraph_node::add_new_function (child_fn
, false);
1748 /* Destroy a omp_context data structures. Called through the splay tree
1749 value delete callback. */
1752 delete_omp_context (splay_tree_value value
)
1754 omp_context
*ctx
= (omp_context
*) value
;
1756 delete ctx
->cb
.decl_map
;
1759 splay_tree_delete (ctx
->field_map
);
1760 if (ctx
->sfield_map
)
1761 splay_tree_delete (ctx
->sfield_map
);
1762 /* Reduction map is copied to nested contexts, so only delete it in the
1764 if (ctx
->reduction_map
1765 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
1766 && is_gimple_omp_offloaded (ctx
->stmt
)
1767 && is_gimple_omp_oacc (ctx
->stmt
))
1768 splay_tree_delete (ctx
->reduction_map
);
1770 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1771 it produces corrupt debug information. */
1772 if (ctx
->record_type
)
1775 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1776 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1778 if (ctx
->srecord_type
)
1781 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1782 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1785 if (is_task_ctx (ctx
))
1786 finalize_task_copyfn (as_a
<gomp_task
*> (ctx
->stmt
));
1791 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1795 fixup_child_record_type (omp_context
*ctx
)
1797 tree f
, type
= ctx
->record_type
;
1799 /* ??? It isn't sufficient to just call remap_type here, because
1800 variably_modified_type_p doesn't work the way we expect for
1801 record types. Testing each field for whether it needs remapping
1802 and creating a new record by hand works, however. */
1803 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1804 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1808 tree name
, new_fields
= NULL
;
1810 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1811 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1812 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1813 TYPE_DECL
, name
, type
);
1814 TYPE_NAME (type
) = name
;
1816 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1818 tree new_f
= copy_node (f
);
1819 DECL_CONTEXT (new_f
) = type
;
1820 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1821 DECL_CHAIN (new_f
) = new_fields
;
1822 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1823 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1825 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1829 /* Arrange to be able to look up the receiver field
1830 given the sender field. */
1831 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1832 (splay_tree_value
) new_f
);
1834 TYPE_FIELDS (type
) = nreverse (new_fields
);
1838 /* In a target region we never modify any of the pointers in *.omp_data_i,
1839 so attempt to help the optimizers. */
1840 if (is_gimple_omp_offloaded (ctx
->stmt
))
1841 type
= build_qualified_type (type
, TYPE_QUAL_CONST
);
1843 TREE_TYPE (ctx
->receiver_decl
)
1844 = build_qualified_type (build_reference_type (type
), TYPE_QUAL_RESTRICT
);
1847 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1848 specified by CLAUSES. */
1851 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1854 bool scan_array_reductions
= false;
1856 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1860 switch (OMP_CLAUSE_CODE (c
))
1862 case OMP_CLAUSE_PRIVATE
:
1863 decl
= OMP_CLAUSE_DECL (c
);
1864 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1866 else if (!is_variable_sized (decl
))
1867 install_var_local (decl
, ctx
);
1870 case OMP_CLAUSE_SHARED
:
1871 decl
= OMP_CLAUSE_DECL (c
);
1872 /* Ignore shared directives in teams construct. */
1873 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1875 /* Global variables don't need to be copied,
1876 the receiver side will use them directly. */
1877 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1878 if (is_global_var (odecl
))
1880 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1883 gcc_assert (is_taskreg_ctx (ctx
));
1884 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1885 || !is_variable_sized (decl
));
1886 /* Global variables don't need to be copied,
1887 the receiver side will use them directly. */
1888 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1890 by_ref
= use_pointer_for_field (decl
, ctx
);
1891 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
1893 if (! TREE_READONLY (decl
)
1894 || TREE_ADDRESSABLE (decl
)
1896 || is_reference (decl
))
1898 install_var_field (decl
, by_ref
, 3, ctx
);
1899 install_var_local (decl
, ctx
);
1902 /* We don't need to copy const scalar vars back. */
1903 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1906 case OMP_CLAUSE_REDUCTION
:
1907 decl
= OMP_CLAUSE_DECL (c
);
1908 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1909 && TREE_CODE (decl
) == MEM_REF
)
1911 tree t
= TREE_OPERAND (decl
, 0);
1912 if (TREE_CODE (t
) == INDIRECT_REF
1913 || TREE_CODE (t
) == ADDR_EXPR
)
1914 t
= TREE_OPERAND (t
, 0);
1915 install_var_local (t
, ctx
);
1916 if (is_taskreg_ctx (ctx
)
1917 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t
, ctx
))
1918 && !is_variable_sized (t
))
1920 by_ref
= use_pointer_for_field (t
, ctx
);
1921 install_var_field (t
, by_ref
, 3, ctx
);
1927 case OMP_CLAUSE_LASTPRIVATE
:
1928 /* Let the corresponding firstprivate clause create
1930 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1934 case OMP_CLAUSE_FIRSTPRIVATE
:
1935 if (is_gimple_omp_oacc (ctx
->stmt
))
1937 sorry ("clause not supported yet");
1941 case OMP_CLAUSE_LINEAR
:
1942 decl
= OMP_CLAUSE_DECL (c
);
1944 if ((OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
1945 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_IS_DEVICE_PTR
)
1946 && is_gimple_omp_offloaded (ctx
->stmt
))
1948 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
1949 install_var_field (decl
, !is_reference (decl
), 3, ctx
);
1950 else if (TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1951 install_var_field (decl
, true, 3, ctx
);
1953 install_var_field (decl
, false, 3, ctx
);
1955 if (is_variable_sized (decl
))
1957 if (is_task_ctx (ctx
))
1958 install_var_field (decl
, false, 1, ctx
);
1961 else if (is_taskreg_ctx (ctx
))
1964 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1965 by_ref
= use_pointer_for_field (decl
, NULL
);
1967 if (is_task_ctx (ctx
)
1968 && (global
|| by_ref
|| is_reference (decl
)))
1970 install_var_field (decl
, false, 1, ctx
);
1972 install_var_field (decl
, by_ref
, 2, ctx
);
1975 install_var_field (decl
, by_ref
, 3, ctx
);
1977 install_var_local (decl
, ctx
);
1978 if (is_gimple_omp_oacc (ctx
->stmt
)
1979 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
1981 /* Create a decl for the reduction array. */
1982 tree var
= OMP_CLAUSE_DECL (c
);
1983 tree type
= get_base_type (var
);
1984 tree ptype
= build_pointer_type (type
);
1985 tree array
= create_tmp_var (ptype
,
1986 oacc_get_reduction_array_id (var
));
1987 omp_context
*octx
= (ctx
->field_map
? ctx
: ctx
->outer
);
1988 install_var_field (array
, true, 3, octx
);
1989 install_var_local (array
, octx
);
1991 /* Insert it into the current context. */
1992 splay_tree_insert (ctx
->reduction_map
, (splay_tree_key
)
1993 oacc_get_reduction_array_id (var
),
1994 (splay_tree_value
) array
);
1995 splay_tree_insert (ctx
->reduction_map
,
1996 (splay_tree_key
) array
,
1997 (splay_tree_value
) array
);
2001 case OMP_CLAUSE_USE_DEVICE_PTR
:
2002 decl
= OMP_CLAUSE_DECL (c
);
2003 if (TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2004 install_var_field (decl
, true, 3, ctx
);
2006 install_var_field (decl
, false, 3, ctx
);
2007 if (DECL_SIZE (decl
)
2008 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2010 tree decl2
= DECL_VALUE_EXPR (decl
);
2011 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2012 decl2
= TREE_OPERAND (decl2
, 0);
2013 gcc_assert (DECL_P (decl2
));
2014 install_var_local (decl2
, ctx
);
2016 install_var_local (decl
, ctx
);
2019 case OMP_CLAUSE_IS_DEVICE_PTR
:
2020 decl
= OMP_CLAUSE_DECL (c
);
2023 case OMP_CLAUSE__LOOPTEMP_
:
2024 gcc_assert (is_taskreg_ctx (ctx
));
2025 decl
= OMP_CLAUSE_DECL (c
);
2026 install_var_field (decl
, false, 3, ctx
);
2027 install_var_local (decl
, ctx
);
2030 case OMP_CLAUSE_COPYPRIVATE
:
2031 case OMP_CLAUSE_COPYIN
:
2032 decl
= OMP_CLAUSE_DECL (c
);
2033 by_ref
= use_pointer_for_field (decl
, NULL
);
2034 install_var_field (decl
, by_ref
, 3, ctx
);
2037 case OMP_CLAUSE_DEFAULT
:
2038 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
2041 case OMP_CLAUSE_FINAL
:
2043 case OMP_CLAUSE_NUM_THREADS
:
2044 case OMP_CLAUSE_NUM_TEAMS
:
2045 case OMP_CLAUSE_THREAD_LIMIT
:
2046 case OMP_CLAUSE_DEVICE
:
2047 case OMP_CLAUSE_SCHEDULE
:
2048 case OMP_CLAUSE_DIST_SCHEDULE
:
2049 case OMP_CLAUSE_DEPEND
:
2050 case OMP_CLAUSE_PRIORITY
:
2051 case OMP_CLAUSE_GRAINSIZE
:
2052 case OMP_CLAUSE_NUM_TASKS
:
2053 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2054 case OMP_CLAUSE_NUM_GANGS
:
2055 case OMP_CLAUSE_NUM_WORKERS
:
2056 case OMP_CLAUSE_VECTOR_LENGTH
:
2058 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
2062 case OMP_CLAUSE_FROM
:
2063 case OMP_CLAUSE_MAP
:
2065 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
2066 decl
= OMP_CLAUSE_DECL (c
);
2067 /* Global variables with "omp declare target" attribute
2068 don't need to be copied, the receiver side will use them
2070 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2072 && (OMP_CLAUSE_MAP_KIND (c
) != GOMP_MAP_FIRSTPRIVATE_POINTER
2073 || TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2074 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
2075 && varpool_node::get_create (decl
)->offloadable
)
2077 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2078 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
)
2080 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2081 not offloaded; there is nothing to map for those. */
2082 if (!is_gimple_omp_offloaded (ctx
->stmt
)
2083 && !POINTER_TYPE_P (TREE_TYPE (decl
))
2084 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
2087 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2088 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
)
2090 if (TREE_CODE (decl
) == COMPONENT_REF
2091 || (TREE_CODE (decl
) == INDIRECT_REF
2092 && TREE_CODE (TREE_OPERAND (decl
, 0)) == COMPONENT_REF
2093 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl
, 0)))
2094 == REFERENCE_TYPE
)))
2096 if (DECL_SIZE (decl
)
2097 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2099 tree decl2
= DECL_VALUE_EXPR (decl
);
2100 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2101 decl2
= TREE_OPERAND (decl2
, 0);
2102 gcc_assert (DECL_P (decl2
));
2103 install_var_local (decl2
, ctx
);
2105 install_var_local (decl
, ctx
);
2110 if (DECL_SIZE (decl
)
2111 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2113 tree decl2
= DECL_VALUE_EXPR (decl
);
2114 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2115 decl2
= TREE_OPERAND (decl2
, 0);
2116 gcc_assert (DECL_P (decl2
));
2117 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2118 && OMP_CLAUSE_MAP_PRIVATE (c
))
2119 install_var_field (decl2
, true, 11, ctx
);
2121 install_var_field (decl2
, true, 3, ctx
);
2122 install_var_local (decl2
, ctx
);
2123 install_var_local (decl
, ctx
);
2127 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2128 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
2129 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
2130 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2131 install_var_field (decl
, true, 7, ctx
);
2132 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2133 && OMP_CLAUSE_MAP_PRIVATE (c
))
2134 install_var_field (decl
, true, 11, ctx
);
2136 install_var_field (decl
, true, 3, ctx
);
2137 if (is_gimple_omp_offloaded (ctx
->stmt
))
2138 install_var_local (decl
, ctx
);
2143 tree base
= get_base_address (decl
);
2144 tree nc
= OMP_CLAUSE_CHAIN (c
);
2147 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
2148 && OMP_CLAUSE_DECL (nc
) == base
2149 && OMP_CLAUSE_MAP_KIND (nc
) == GOMP_MAP_POINTER
2150 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
2152 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
2153 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
2159 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
2160 decl
= OMP_CLAUSE_DECL (c
);
2162 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
2163 (splay_tree_key
) decl
));
2165 = build_decl (OMP_CLAUSE_LOCATION (c
),
2166 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
2167 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
2168 insert_field_into_struct (ctx
->record_type
, field
);
2169 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
2170 (splay_tree_value
) field
);
2175 case OMP_CLAUSE_NOWAIT
:
2176 case OMP_CLAUSE_ORDERED
:
2177 case OMP_CLAUSE_COLLAPSE
:
2178 case OMP_CLAUSE_UNTIED
:
2179 case OMP_CLAUSE_MERGEABLE
:
2180 case OMP_CLAUSE_PROC_BIND
:
2181 case OMP_CLAUSE_SAFELEN
:
2182 case OMP_CLAUSE_SIMDLEN
:
2183 case OMP_CLAUSE_THREADS
:
2184 case OMP_CLAUSE_SIMD
:
2185 case OMP_CLAUSE_NOGROUP
:
2186 case OMP_CLAUSE_DEFAULTMAP
:
2187 case OMP_CLAUSE_ASYNC
:
2188 case OMP_CLAUSE_WAIT
:
2189 case OMP_CLAUSE_GANG
:
2190 case OMP_CLAUSE_WORKER
:
2191 case OMP_CLAUSE_VECTOR
:
2194 case OMP_CLAUSE_ALIGNED
:
2195 decl
= OMP_CLAUSE_DECL (c
);
2196 if (is_global_var (decl
)
2197 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2198 install_var_local (decl
, ctx
);
2201 case OMP_CLAUSE_DEVICE_RESIDENT
:
2202 case OMP_CLAUSE_USE_DEVICE
:
2203 case OMP_CLAUSE__CACHE_
:
2204 case OMP_CLAUSE_INDEPENDENT
:
2205 case OMP_CLAUSE_AUTO
:
2206 case OMP_CLAUSE_SEQ
:
2207 sorry ("Clause not supported yet");
2215 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2217 switch (OMP_CLAUSE_CODE (c
))
2219 case OMP_CLAUSE_LASTPRIVATE
:
2220 /* Let the corresponding firstprivate clause create
2222 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2223 scan_array_reductions
= true;
2224 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
2228 case OMP_CLAUSE_FIRSTPRIVATE
:
2229 if (is_gimple_omp_oacc (ctx
->stmt
))
2231 sorry ("clause not supported yet");
2235 case OMP_CLAUSE_PRIVATE
:
2236 case OMP_CLAUSE_LINEAR
:
2237 case OMP_CLAUSE_IS_DEVICE_PTR
:
2238 decl
= OMP_CLAUSE_DECL (c
);
2239 if (is_variable_sized (decl
))
2241 if ((OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
2242 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_IS_DEVICE_PTR
)
2243 && is_gimple_omp_offloaded (ctx
->stmt
))
2245 tree decl2
= DECL_VALUE_EXPR (decl
);
2246 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2247 decl2
= TREE_OPERAND (decl2
, 0);
2248 gcc_assert (DECL_P (decl2
));
2249 install_var_local (decl2
, ctx
);
2250 fixup_remapped_decl (decl2
, ctx
, false);
2252 install_var_local (decl
, ctx
);
2254 fixup_remapped_decl (decl
, ctx
,
2255 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
2256 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
2257 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2258 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2259 scan_array_reductions
= true;
2262 case OMP_CLAUSE_REDUCTION
:
2263 decl
= OMP_CLAUSE_DECL (c
);
2264 if (TREE_CODE (decl
) != MEM_REF
)
2266 if (is_variable_sized (decl
))
2267 install_var_local (decl
, ctx
);
2268 fixup_remapped_decl (decl
, ctx
, false);
2270 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2271 scan_array_reductions
= true;
2274 case OMP_CLAUSE_SHARED
:
2275 /* Ignore shared directives in teams construct. */
2276 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2278 decl
= OMP_CLAUSE_DECL (c
);
2279 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2281 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
2283 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
,
2286 bool by_ref
= use_pointer_for_field (decl
, ctx
);
2287 install_var_field (decl
, by_ref
, 11, ctx
);
2290 fixup_remapped_decl (decl
, ctx
, false);
2293 case OMP_CLAUSE_MAP
:
2294 if (!is_gimple_omp_offloaded (ctx
->stmt
))
2296 decl
= OMP_CLAUSE_DECL (c
);
2298 && (OMP_CLAUSE_MAP_KIND (c
) != GOMP_MAP_FIRSTPRIVATE_POINTER
2299 || TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2300 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
2301 && varpool_node::get_create (decl
)->offloadable
)
2305 if ((OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
2306 || OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
)
2307 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
2308 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
2310 tree new_decl
= lookup_decl (decl
, ctx
);
2311 TREE_TYPE (new_decl
)
2312 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
2314 else if (DECL_SIZE (decl
)
2315 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2317 tree decl2
= DECL_VALUE_EXPR (decl
);
2318 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2319 decl2
= TREE_OPERAND (decl2
, 0);
2320 gcc_assert (DECL_P (decl2
));
2321 fixup_remapped_decl (decl2
, ctx
, false);
2322 fixup_remapped_decl (decl
, ctx
, true);
2325 fixup_remapped_decl (decl
, ctx
, false);
2329 case OMP_CLAUSE_COPYPRIVATE
:
2330 case OMP_CLAUSE_COPYIN
:
2331 case OMP_CLAUSE_DEFAULT
:
2333 case OMP_CLAUSE_NUM_THREADS
:
2334 case OMP_CLAUSE_NUM_TEAMS
:
2335 case OMP_CLAUSE_THREAD_LIMIT
:
2336 case OMP_CLAUSE_DEVICE
:
2337 case OMP_CLAUSE_SCHEDULE
:
2338 case OMP_CLAUSE_DIST_SCHEDULE
:
2339 case OMP_CLAUSE_NOWAIT
:
2340 case OMP_CLAUSE_ORDERED
:
2341 case OMP_CLAUSE_COLLAPSE
:
2342 case OMP_CLAUSE_UNTIED
:
2343 case OMP_CLAUSE_FINAL
:
2344 case OMP_CLAUSE_MERGEABLE
:
2345 case OMP_CLAUSE_PROC_BIND
:
2346 case OMP_CLAUSE_SAFELEN
:
2347 case OMP_CLAUSE_SIMDLEN
:
2348 case OMP_CLAUSE_ALIGNED
:
2349 case OMP_CLAUSE_DEPEND
:
2350 case OMP_CLAUSE__LOOPTEMP_
:
2352 case OMP_CLAUSE_FROM
:
2353 case OMP_CLAUSE_PRIORITY
:
2354 case OMP_CLAUSE_GRAINSIZE
:
2355 case OMP_CLAUSE_NUM_TASKS
:
2356 case OMP_CLAUSE_THREADS
:
2357 case OMP_CLAUSE_SIMD
:
2358 case OMP_CLAUSE_NOGROUP
:
2359 case OMP_CLAUSE_DEFAULTMAP
:
2360 case OMP_CLAUSE_USE_DEVICE_PTR
:
2361 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2362 case OMP_CLAUSE_ASYNC
:
2363 case OMP_CLAUSE_WAIT
:
2364 case OMP_CLAUSE_NUM_GANGS
:
2365 case OMP_CLAUSE_NUM_WORKERS
:
2366 case OMP_CLAUSE_VECTOR_LENGTH
:
2367 case OMP_CLAUSE_GANG
:
2368 case OMP_CLAUSE_WORKER
:
2369 case OMP_CLAUSE_VECTOR
:
2372 case OMP_CLAUSE_DEVICE_RESIDENT
:
2373 case OMP_CLAUSE_USE_DEVICE
:
2374 case OMP_CLAUSE__CACHE_
:
2375 case OMP_CLAUSE_INDEPENDENT
:
2376 case OMP_CLAUSE_AUTO
:
2377 case OMP_CLAUSE_SEQ
:
2378 sorry ("Clause not supported yet");
2386 gcc_checking_assert (!scan_array_reductions
2387 || !is_gimple_omp_oacc (ctx
->stmt
));
2388 if (scan_array_reductions
)
2389 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2390 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
2391 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2393 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
2394 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
2396 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2397 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2398 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
2399 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2400 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2401 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
2404 /* Create a new name for omp child function. Returns an identifier. If
2405 IS_CILK_FOR is true then the suffix for the child function is
2409 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
2412 return clone_function_name (current_function_decl
, "_cilk_for_fn");
2413 return clone_function_name (current_function_decl
,
2414 task_copy
? "_omp_cpyfn" : "_omp_fn");
2417 /* Returns the type of the induction variable for the child function for
2418 _Cilk_for and the types for _high and _low variables based on TYPE. */
2421 cilk_for_check_loop_diff_type (tree type
)
2423 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
2425 if (TYPE_UNSIGNED (type
))
2426 return uint32_type_node
;
2428 return integer_type_node
;
2432 if (TYPE_UNSIGNED (type
))
2433 return uint64_type_node
;
2435 return long_long_integer_type_node
;
2439 /* Build a decl for the omp child function. It'll not contain a body
2440 yet, just the bare decl. */
2443 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
2445 tree decl
, type
, name
, t
;
2448 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2449 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2450 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
2451 tree cilk_var_type
= NULL_TREE
;
2453 name
= create_omp_child_function_name (task_copy
,
2454 cilk_for_count
!= NULL_TREE
);
2456 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2457 ptr_type_node
, NULL_TREE
);
2458 else if (cilk_for_count
)
2460 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
2461 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
2462 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2463 cilk_var_type
, cilk_var_type
, NULL_TREE
);
2466 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
2468 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
2470 gcc_checking_assert (!is_gimple_omp_oacc (ctx
->stmt
)
2473 ctx
->cb
.dst_fn
= decl
;
2475 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
2477 TREE_STATIC (decl
) = 1;
2478 TREE_USED (decl
) = 1;
2479 DECL_ARTIFICIAL (decl
) = 1;
2480 DECL_IGNORED_P (decl
) = 0;
2481 TREE_PUBLIC (decl
) = 0;
2482 DECL_UNINLINABLE (decl
) = 1;
2483 DECL_EXTERNAL (decl
) = 0;
2484 DECL_CONTEXT (decl
) = NULL_TREE
;
2485 DECL_INITIAL (decl
) = make_node (BLOCK
);
2486 if (cgraph_node::get (current_function_decl
)->offloadable
)
2487 cgraph_node::get_create (decl
)->offloadable
= 1;
2491 for (octx
= ctx
; octx
; octx
= octx
->outer
)
2492 if (is_gimple_omp_offloaded (octx
->stmt
))
2494 cgraph_node::get_create (decl
)->offloadable
= 1;
2495 #ifdef ENABLE_OFFLOADING
2496 g
->have_offload
= true;
2502 if (cgraph_node::get_create (decl
)->offloadable
2503 && !lookup_attribute ("omp declare target",
2504 DECL_ATTRIBUTES (current_function_decl
)))
2505 DECL_ATTRIBUTES (decl
)
2506 = tree_cons (get_identifier ("omp target entrypoint"),
2507 NULL_TREE
, DECL_ATTRIBUTES (decl
));
2509 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2510 RESULT_DECL
, NULL_TREE
, void_type_node
);
2511 DECL_ARTIFICIAL (t
) = 1;
2512 DECL_IGNORED_P (t
) = 1;
2513 DECL_CONTEXT (t
) = decl
;
2514 DECL_RESULT (decl
) = t
;
2516 /* _Cilk_for's child function requires two extra parameters called
2517 __low and __high that are set the by Cilk runtime when it calls this
2521 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2522 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
2523 DECL_ARTIFICIAL (t
) = 1;
2524 DECL_NAMELESS (t
) = 1;
2525 DECL_ARG_TYPE (t
) = ptr_type_node
;
2526 DECL_CONTEXT (t
) = current_function_decl
;
2528 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2529 DECL_ARGUMENTS (decl
) = t
;
2531 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2532 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
2533 DECL_ARTIFICIAL (t
) = 1;
2534 DECL_NAMELESS (t
) = 1;
2535 DECL_ARG_TYPE (t
) = ptr_type_node
;
2536 DECL_CONTEXT (t
) = current_function_decl
;
2538 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2539 DECL_ARGUMENTS (decl
) = t
;
2542 tree data_name
= get_identifier (".omp_data_i");
2543 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
2545 DECL_ARTIFICIAL (t
) = 1;
2546 DECL_NAMELESS (t
) = 1;
2547 DECL_ARG_TYPE (t
) = ptr_type_node
;
2548 DECL_CONTEXT (t
) = current_function_decl
;
2550 TREE_READONLY (t
) = 1;
2552 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2553 DECL_ARGUMENTS (decl
) = t
;
2555 ctx
->receiver_decl
= t
;
2558 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2559 PARM_DECL
, get_identifier (".omp_data_o"),
2561 DECL_ARTIFICIAL (t
) = 1;
2562 DECL_NAMELESS (t
) = 1;
2563 DECL_ARG_TYPE (t
) = ptr_type_node
;
2564 DECL_CONTEXT (t
) = current_function_decl
;
2566 TREE_ADDRESSABLE (t
) = 1;
2567 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2568 DECL_ARGUMENTS (decl
) = t
;
2571 /* Allocate memory for the function structure. The call to
2572 allocate_struct_function clobbers CFUN, so we need to restore
2574 push_struct_function (decl
);
2575 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2579 /* Callback for walk_gimple_seq. Check if combined parallel
2580 contains gimple_omp_for_combined_into_p OMP_FOR. */
2583 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2584 bool *handled_ops_p
,
2585 struct walk_stmt_info
*wi
)
2587 gimple
*stmt
= gsi_stmt (*gsi_p
);
2589 *handled_ops_p
= true;
2590 switch (gimple_code (stmt
))
2594 case GIMPLE_OMP_FOR
:
2595 if (gimple_omp_for_combined_into_p (stmt
)
2596 && gimple_omp_for_kind (stmt
)
2597 == *(const enum gf_mask
*) (wi
->info
))
2600 return integer_zero_node
;
2609 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2612 add_taskreg_looptemp_clauses (enum gf_mask msk
, gimple
*stmt
,
2613 omp_context
*outer_ctx
)
2615 struct walk_stmt_info wi
;
2617 memset (&wi
, 0, sizeof (wi
));
2619 wi
.info
= (void *) &msk
;
2620 walk_gimple_seq (gimple_omp_body (stmt
), find_combined_for
, NULL
, &wi
);
2621 if (wi
.info
!= (void *) &msk
)
2623 gomp_for
*for_stmt
= as_a
<gomp_for
*> ((gimple
*) wi
.info
);
2624 struct omp_for_data fd
;
2625 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2626 /* We need two temporaries with fd.loop.v type (istart/iend)
2627 and then (fd.collapse - 1) temporaries with the same
2628 type for count2 ... countN-1 vars if not constant. */
2629 size_t count
= 2, i
;
2630 tree type
= fd
.iter_type
;
2632 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2634 count
+= fd
.collapse
- 1;
2635 /* For taskloop, if there are lastprivate clauses on the inner
2636 GIMPLE_OMP_FOR, add one more temporaries for the total number
2637 of iterations (product of count1 ... countN-1). */
2638 if (msk
== GF_OMP_FOR_KIND_TASKLOOP
2639 && find_omp_clause (gimple_omp_for_clauses (for_stmt
),
2640 OMP_CLAUSE_LASTPRIVATE
))
2643 for (i
= 0; i
< count
; i
++)
2645 tree temp
= create_tmp_var (type
);
2646 tree c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
2647 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2648 OMP_CLAUSE_DECL (c
) = temp
;
2649 OMP_CLAUSE_CHAIN (c
) = gimple_omp_taskreg_clauses (stmt
);
2650 gimple_omp_taskreg_set_clauses (stmt
, c
);
2655 /* Scan an OpenMP parallel directive. */
2658 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2662 gomp_parallel
*stmt
= as_a
<gomp_parallel
*> (gsi_stmt (*gsi
));
2664 /* Ignore parallel directives with empty bodies, unless there
2665 are copyin clauses. */
2667 && empty_body_p (gimple_omp_body (stmt
))
2668 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2669 OMP_CLAUSE_COPYIN
) == NULL
)
2671 gsi_replace (gsi
, gimple_build_nop (), false);
2675 if (gimple_omp_parallel_combined_p (stmt
))
2676 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR
, stmt
, outer_ctx
);
2678 ctx
= new_omp_context (stmt
, outer_ctx
);
2679 taskreg_contexts
.safe_push (ctx
);
2680 if (taskreg_nesting_level
> 1)
2681 ctx
->is_nested
= true;
2682 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2683 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2684 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2685 name
= create_tmp_var_name (".omp_data_s");
2686 name
= build_decl (gimple_location (stmt
),
2687 TYPE_DECL
, name
, ctx
->record_type
);
2688 DECL_ARTIFICIAL (name
) = 1;
2689 DECL_NAMELESS (name
) = 1;
2690 TYPE_NAME (ctx
->record_type
) = name
;
2691 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2692 create_omp_child_function (ctx
, false);
2693 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2695 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2696 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2698 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2699 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2702 /* Scan an OpenMP task directive. */
2705 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2709 gomp_task
*stmt
= as_a
<gomp_task
*> (gsi_stmt (*gsi
));
2711 /* Ignore task directives with empty bodies. */
2713 && empty_body_p (gimple_omp_body (stmt
)))
2715 gsi_replace (gsi
, gimple_build_nop (), false);
2719 if (gimple_omp_task_taskloop_p (stmt
))
2720 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP
, stmt
, outer_ctx
);
2722 ctx
= new_omp_context (stmt
, outer_ctx
);
2723 taskreg_contexts
.safe_push (ctx
);
2724 if (taskreg_nesting_level
> 1)
2725 ctx
->is_nested
= true;
2726 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2727 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2728 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2729 name
= create_tmp_var_name (".omp_data_s");
2730 name
= build_decl (gimple_location (stmt
),
2731 TYPE_DECL
, name
, ctx
->record_type
);
2732 DECL_ARTIFICIAL (name
) = 1;
2733 DECL_NAMELESS (name
) = 1;
2734 TYPE_NAME (ctx
->record_type
) = name
;
2735 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2736 create_omp_child_function (ctx
, false);
2737 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2739 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2741 if (ctx
->srecord_type
)
2743 name
= create_tmp_var_name (".omp_data_a");
2744 name
= build_decl (gimple_location (stmt
),
2745 TYPE_DECL
, name
, ctx
->srecord_type
);
2746 DECL_ARTIFICIAL (name
) = 1;
2747 DECL_NAMELESS (name
) = 1;
2748 TYPE_NAME (ctx
->srecord_type
) = name
;
2749 TYPE_ARTIFICIAL (ctx
->srecord_type
) = 1;
2750 create_omp_child_function (ctx
, true);
2753 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2755 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2757 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2758 t
= build_int_cst (long_integer_type_node
, 0);
2759 gimple_omp_task_set_arg_size (stmt
, t
);
2760 t
= build_int_cst (long_integer_type_node
, 1);
2761 gimple_omp_task_set_arg_align (stmt
, t
);
2766 /* If any decls have been made addressable during scan_omp,
2767 adjust their fields if needed, and layout record types
2768 of parallel/task constructs. */
2771 finish_taskreg_scan (omp_context
*ctx
)
2773 if (ctx
->record_type
== NULL_TREE
)
2776 /* If any task_shared_vars were needed, verify all
2777 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2778 statements if use_pointer_for_field hasn't changed
2779 because of that. If it did, update field types now. */
2780 if (task_shared_vars
)
2784 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2785 c
; c
= OMP_CLAUSE_CHAIN (c
))
2786 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
2787 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
2789 tree decl
= OMP_CLAUSE_DECL (c
);
2791 /* Global variables don't need to be copied,
2792 the receiver side will use them directly. */
2793 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2795 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2796 || !use_pointer_for_field (decl
, ctx
))
2798 tree field
= lookup_field (decl
, ctx
);
2799 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2800 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2802 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2803 TREE_THIS_VOLATILE (field
) = 0;
2804 DECL_USER_ALIGN (field
) = 0;
2805 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2806 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2807 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2808 if (ctx
->srecord_type
)
2810 tree sfield
= lookup_sfield (decl
, ctx
);
2811 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2812 TREE_THIS_VOLATILE (sfield
) = 0;
2813 DECL_USER_ALIGN (sfield
) = 0;
2814 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2815 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2816 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2821 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2823 layout_type (ctx
->record_type
);
2824 fixup_child_record_type (ctx
);
2828 location_t loc
= gimple_location (ctx
->stmt
);
2829 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2830 /* Move VLA fields to the end. */
2831 p
= &TYPE_FIELDS (ctx
->record_type
);
2833 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2834 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2837 *p
= TREE_CHAIN (*p
);
2838 TREE_CHAIN (*q
) = NULL_TREE
;
2839 q
= &TREE_CHAIN (*q
);
2842 p
= &DECL_CHAIN (*p
);
2844 if (gimple_omp_task_taskloop_p (ctx
->stmt
))
2846 /* Move fields corresponding to first and second _looptemp_
2847 clause first. There are filled by GOMP_taskloop
2848 and thus need to be in specific positions. */
2849 tree c1
= gimple_omp_task_clauses (ctx
->stmt
);
2850 c1
= find_omp_clause (c1
, OMP_CLAUSE__LOOPTEMP_
);
2851 tree c2
= find_omp_clause (OMP_CLAUSE_CHAIN (c1
),
2852 OMP_CLAUSE__LOOPTEMP_
);
2853 tree f1
= lookup_field (OMP_CLAUSE_DECL (c1
), ctx
);
2854 tree f2
= lookup_field (OMP_CLAUSE_DECL (c2
), ctx
);
2855 p
= &TYPE_FIELDS (ctx
->record_type
);
2857 if (*p
== f1
|| *p
== f2
)
2858 *p
= DECL_CHAIN (*p
);
2860 p
= &DECL_CHAIN (*p
);
2861 DECL_CHAIN (f1
) = f2
;
2862 DECL_CHAIN (f2
) = TYPE_FIELDS (ctx
->record_type
);
2863 TYPE_FIELDS (ctx
->record_type
) = f1
;
2864 if (ctx
->srecord_type
)
2866 f1
= lookup_sfield (OMP_CLAUSE_DECL (c1
), ctx
);
2867 f2
= lookup_sfield (OMP_CLAUSE_DECL (c2
), ctx
);
2868 p
= &TYPE_FIELDS (ctx
->srecord_type
);
2870 if (*p
== f1
|| *p
== f2
)
2871 *p
= DECL_CHAIN (*p
);
2873 p
= &DECL_CHAIN (*p
);
2874 DECL_CHAIN (f1
) = f2
;
2875 DECL_CHAIN (f2
) = TYPE_FIELDS (ctx
->srecord_type
);
2876 TYPE_FIELDS (ctx
->srecord_type
) = f1
;
2879 layout_type (ctx
->record_type
);
2880 fixup_child_record_type (ctx
);
2881 if (ctx
->srecord_type
)
2882 layout_type (ctx
->srecord_type
);
2883 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2884 TYPE_SIZE_UNIT (ctx
->record_type
));
2885 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2886 t
= build_int_cst (long_integer_type_node
,
2887 TYPE_ALIGN_UNIT (ctx
->record_type
));
2888 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2893 static omp_context
*
2894 enclosing_target_ctx (omp_context
*ctx
)
2897 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
2899 gcc_assert (ctx
!= NULL
);
2904 oacc_loop_or_target_p (gimple
*stmt
)
2906 enum gimple_code outer_type
= gimple_code (stmt
);
2907 return ((outer_type
== GIMPLE_OMP_TARGET
2908 && ((gimple_omp_target_kind (stmt
)
2909 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2910 || (gimple_omp_target_kind (stmt
)
2911 == GF_OMP_TARGET_KIND_OACC_KERNELS
)))
2912 || (outer_type
== GIMPLE_OMP_FOR
2913 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
));
2916 /* Scan a GIMPLE_OMP_FOR. */
2919 scan_omp_for (gomp_for
*stmt
, omp_context
*outer_ctx
)
2921 enum gimple_code outer_type
= GIMPLE_ERROR_MARK
;
2924 tree clauses
= gimple_omp_for_clauses (stmt
);
2927 outer_type
= gimple_code (outer_ctx
->stmt
);
2929 ctx
= new_omp_context (stmt
, outer_ctx
);
2931 if (is_gimple_omp_oacc (stmt
))
2933 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2934 ctx
->gwv_this
= outer_ctx
->gwv_this
;
2935 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2938 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_GANG
)
2940 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WORKER
)
2942 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR
)
2946 ctx
->gwv_this
|= val
;
2949 /* Skip; not nested inside a region. */
2952 if (!oacc_loop_or_target_p (outer_ctx
->stmt
))
2954 /* Skip; not nested inside an OpenACC region. */
2957 if (outer_type
== GIMPLE_OMP_FOR
)
2958 outer_ctx
->gwv_below
|= val
;
2959 if (OMP_CLAUSE_OPERAND (c
, 0) != NULL_TREE
)
2961 omp_context
*enclosing
= enclosing_target_ctx (outer_ctx
);
2962 if (gimple_omp_target_kind (enclosing
->stmt
)
2963 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2964 error_at (gimple_location (stmt
),
2965 "no arguments allowed to gang, worker and vector clauses inside parallel");
2970 scan_sharing_clauses (clauses
, ctx
);
2972 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2973 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2975 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2976 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2977 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2978 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2980 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2982 if (is_gimple_omp_oacc (stmt
))
2984 if (ctx
->gwv_this
& ctx
->gwv_below
)
2985 error_at (gimple_location (stmt
),
2986 "gang, worker and vector may occur only once in a loop nest");
2987 else if (ctx
->gwv_below
!= 0
2988 && ctx
->gwv_this
> ctx
->gwv_below
)
2989 error_at (gimple_location (stmt
),
2990 "gang, worker and vector must occur in this order in a loop nest");
2991 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2992 outer_ctx
->gwv_below
|= ctx
->gwv_below
;
2996 /* Scan an OpenMP sections directive. */
2999 scan_omp_sections (gomp_sections
*stmt
, omp_context
*outer_ctx
)
3003 ctx
= new_omp_context (stmt
, outer_ctx
);
3004 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
3005 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3008 /* Scan an OpenMP single directive. */
3011 scan_omp_single (gomp_single
*stmt
, omp_context
*outer_ctx
)
3016 ctx
= new_omp_context (stmt
, outer_ctx
);
3017 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
3018 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
3019 name
= create_tmp_var_name (".omp_copy_s");
3020 name
= build_decl (gimple_location (stmt
),
3021 TYPE_DECL
, name
, ctx
->record_type
);
3022 TYPE_NAME (ctx
->record_type
) = name
;
3024 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
3025 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3027 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
3028 ctx
->record_type
= NULL
;
3030 layout_type (ctx
->record_type
);
3033 /* Scan a GIMPLE_OMP_TARGET. */
3036 scan_omp_target (gomp_target
*stmt
, omp_context
*outer_ctx
)
3040 bool offloaded
= is_gimple_omp_offloaded (stmt
);
3041 tree clauses
= gimple_omp_target_clauses (stmt
);
3043 ctx
= new_omp_context (stmt
, outer_ctx
);
3044 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
3045 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
3046 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
3047 name
= create_tmp_var_name (".omp_data_t");
3048 name
= build_decl (gimple_location (stmt
),
3049 TYPE_DECL
, name
, ctx
->record_type
);
3050 DECL_ARTIFICIAL (name
) = 1;
3051 DECL_NAMELESS (name
) = 1;
3052 TYPE_NAME (ctx
->record_type
) = name
;
3053 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
3056 if (is_gimple_omp_oacc (stmt
))
3057 ctx
->reduction_map
= splay_tree_new (splay_tree_compare_pointers
,
3060 create_omp_child_function (ctx
, false);
3061 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
3064 if (is_gimple_omp_oacc (stmt
))
3066 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3068 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_GANGS
)
3069 ctx
->gwv_this
|= MASK_GANG
;
3070 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_WORKERS
)
3071 ctx
->gwv_this
|= MASK_WORKER
;
3072 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR_LENGTH
)
3073 ctx
->gwv_this
|= MASK_VECTOR
;
3077 scan_sharing_clauses (clauses
, ctx
);
3078 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3080 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
3081 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
3084 TYPE_FIELDS (ctx
->record_type
)
3085 = nreverse (TYPE_FIELDS (ctx
->record_type
));
3086 #ifdef ENABLE_CHECKING
3088 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
3089 for (field
= TYPE_FIELDS (ctx
->record_type
);
3091 field
= DECL_CHAIN (field
))
3092 gcc_assert (DECL_ALIGN (field
) == align
);
3094 layout_type (ctx
->record_type
);
3096 fixup_child_record_type (ctx
);
3100 /* Scan an OpenMP teams directive. */
3103 scan_omp_teams (gomp_teams
*stmt
, omp_context
*outer_ctx
)
3105 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
3106 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
3107 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3110 /* Check nesting restrictions. */
3112 check_omp_nesting_restrictions (gimple
*stmt
, omp_context
*ctx
)
3116 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3117 inside an OpenACC CTX. */
3118 if (!(is_gimple_omp (stmt
)
3119 && is_gimple_omp_oacc (stmt
)))
3121 for (omp_context
*ctx_
= ctx
; ctx_
!= NULL
; ctx_
= ctx_
->outer
)
3122 if (is_gimple_omp (ctx_
->stmt
)
3123 && is_gimple_omp_oacc (ctx_
->stmt
))
3125 error_at (gimple_location (stmt
),
3126 "non-OpenACC construct inside of OpenACC region");
3133 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3134 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3137 if (gimple_code (stmt
) == GIMPLE_OMP_ORDERED
)
3139 c
= gimple_omp_ordered_clauses (as_a
<gomp_ordered
*> (stmt
));
3140 if (c
&& OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SIMD
)
3143 error_at (gimple_location (stmt
),
3144 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3145 " may not be nested inside simd region");
3148 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3150 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
3151 || (gimple_omp_for_kind (stmt
)
3152 != GF_OMP_FOR_KIND_DISTRIBUTE
))
3153 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
3155 error_at (gimple_location (stmt
),
3156 "only distribute or parallel constructs are allowed to "
3157 "be closely nested inside teams construct");
3162 switch (gimple_code (stmt
))
3164 case GIMPLE_OMP_FOR
:
3165 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
3167 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
3169 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
3171 error_at (gimple_location (stmt
),
3172 "distribute construct must be closely nested inside "
3178 /* We split taskloop into task and nested taskloop in it. */
3179 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_TASKLOOP
)
3183 if (is_gimple_call (stmt
)
3184 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3185 == BUILT_IN_GOMP_CANCEL
3186 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3187 == BUILT_IN_GOMP_CANCELLATION_POINT
))
3189 const char *bad
= NULL
;
3190 const char *kind
= NULL
;
3193 error_at (gimple_location (stmt
), "orphaned %qs construct",
3194 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3195 == BUILT_IN_GOMP_CANCEL
3196 ? "#pragma omp cancel"
3197 : "#pragma omp cancellation point");
3200 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
3201 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
3205 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
3206 bad
= "#pragma omp parallel";
3207 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3208 == BUILT_IN_GOMP_CANCEL
3209 && !integer_zerop (gimple_call_arg (stmt
, 1)))
3210 ctx
->cancellable
= true;
3214 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3215 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
3216 bad
= "#pragma omp for";
3217 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3218 == BUILT_IN_GOMP_CANCEL
3219 && !integer_zerop (gimple_call_arg (stmt
, 1)))
3221 ctx
->cancellable
= true;
3222 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3224 warning_at (gimple_location (stmt
), 0,
3225 "%<#pragma omp cancel for%> inside "
3226 "%<nowait%> for construct");
3227 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3228 OMP_CLAUSE_ORDERED
))
3229 warning_at (gimple_location (stmt
), 0,
3230 "%<#pragma omp cancel for%> inside "
3231 "%<ordered%> for construct");
3236 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
3237 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
3238 bad
= "#pragma omp sections";
3239 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3240 == BUILT_IN_GOMP_CANCEL
3241 && !integer_zerop (gimple_call_arg (stmt
, 1)))
3243 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
3245 ctx
->cancellable
= true;
3246 if (find_omp_clause (gimple_omp_sections_clauses
3249 warning_at (gimple_location (stmt
), 0,
3250 "%<#pragma omp cancel sections%> inside "
3251 "%<nowait%> sections construct");
3255 gcc_assert (ctx
->outer
3256 && gimple_code (ctx
->outer
->stmt
)
3257 == GIMPLE_OMP_SECTIONS
);
3258 ctx
->outer
->cancellable
= true;
3259 if (find_omp_clause (gimple_omp_sections_clauses
3262 warning_at (gimple_location (stmt
), 0,
3263 "%<#pragma omp cancel sections%> inside "
3264 "%<nowait%> sections construct");
3270 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
3271 bad
= "#pragma omp task";
3273 ctx
->cancellable
= true;
3277 error_at (gimple_location (stmt
), "invalid arguments");
3282 error_at (gimple_location (stmt
),
3283 "%<%s %s%> construct not closely nested inside of %qs",
3284 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3285 == BUILT_IN_GOMP_CANCEL
3286 ? "#pragma omp cancel"
3287 : "#pragma omp cancellation point", kind
, bad
);
3292 case GIMPLE_OMP_SECTIONS
:
3293 case GIMPLE_OMP_SINGLE
:
3294 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3295 switch (gimple_code (ctx
->stmt
))
3297 case GIMPLE_OMP_FOR
:
3298 case GIMPLE_OMP_SECTIONS
:
3299 case GIMPLE_OMP_SINGLE
:
3300 case GIMPLE_OMP_ORDERED
:
3301 case GIMPLE_OMP_MASTER
:
3302 case GIMPLE_OMP_TASK
:
3303 case GIMPLE_OMP_CRITICAL
:
3304 if (is_gimple_call (stmt
))
3306 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3307 != BUILT_IN_GOMP_BARRIER
)
3309 error_at (gimple_location (stmt
),
3310 "barrier region may not be closely nested inside "
3311 "of work-sharing, critical, ordered, master or "
3312 "explicit task region");
3315 error_at (gimple_location (stmt
),
3316 "work-sharing region may not be closely nested inside "
3317 "of work-sharing, critical, ordered, master or explicit "
3320 case GIMPLE_OMP_PARALLEL
:
3326 case GIMPLE_OMP_MASTER
:
3327 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3328 switch (gimple_code (ctx
->stmt
))
3330 case GIMPLE_OMP_FOR
:
3331 case GIMPLE_OMP_SECTIONS
:
3332 case GIMPLE_OMP_SINGLE
:
3333 case GIMPLE_OMP_TASK
:
3334 error_at (gimple_location (stmt
),
3335 "master region may not be closely nested inside "
3336 "of work-sharing or explicit task region");
3338 case GIMPLE_OMP_PARALLEL
:
3344 case GIMPLE_OMP_TASK
:
3345 for (c
= gimple_omp_task_clauses (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
3346 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
3347 && (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SOURCE
3348 || OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
))
3350 enum omp_clause_depend_kind kind
= OMP_CLAUSE_DEPEND_KIND (c
);
3351 error_at (OMP_CLAUSE_LOCATION (c
),
3352 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3353 kind
== OMP_CLAUSE_DEPEND_SOURCE
? "source" : "sink");
3357 case GIMPLE_OMP_ORDERED
:
3358 for (c
= gimple_omp_ordered_clauses (as_a
<gomp_ordered
*> (stmt
));
3359 c
; c
= OMP_CLAUSE_CHAIN (c
))
3361 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_DEPEND
)
3363 gcc_assert (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_THREADS
3365 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SIMD
));
3368 enum omp_clause_depend_kind kind
= OMP_CLAUSE_DEPEND_KIND (c
);
3369 if (kind
== OMP_CLAUSE_DEPEND_SOURCE
3370 || kind
== OMP_CLAUSE_DEPEND_SINK
)
3373 /* Look for containing ordered(N) loop. */
3375 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3377 = find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3378 OMP_CLAUSE_ORDERED
)) == NULL_TREE
)
3380 error_at (OMP_CLAUSE_LOCATION (c
),
3381 "%<depend%> clause must be closely nested "
3382 "inside an ordered loop");
3385 else if (OMP_CLAUSE_ORDERED_EXPR (oclause
) == NULL_TREE
)
3387 error_at (OMP_CLAUSE_LOCATION (c
),
3388 "%<depend%> clause must be closely nested "
3389 "inside a loop with %<ordered%> clause with "
3396 error_at (OMP_CLAUSE_LOCATION (c
),
3397 "invalid depend kind in omp ordered depend");
3401 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3402 switch (gimple_code (ctx
->stmt
))
3404 case GIMPLE_OMP_CRITICAL
:
3405 case GIMPLE_OMP_TASK
:
3406 error_at (gimple_location (stmt
),
3407 "ordered region may not be closely nested inside "
3408 "of critical or explicit task region");
3410 case GIMPLE_OMP_FOR
:
3411 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3412 OMP_CLAUSE_ORDERED
) == NULL
)
3414 error_at (gimple_location (stmt
),
3415 "ordered region must be closely nested inside "
3416 "a loop region with an ordered clause");
3420 case GIMPLE_OMP_PARALLEL
:
3421 error_at (gimple_location (stmt
),
3422 "ordered region must be closely nested inside "
3423 "a loop region with an ordered clause");
3429 case GIMPLE_OMP_CRITICAL
:
3432 = gimple_omp_critical_name (as_a
<gomp_critical
*> (stmt
));
3433 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3434 if (gomp_critical
*other_crit
3435 = dyn_cast
<gomp_critical
*> (ctx
->stmt
))
3436 if (this_stmt_name
== gimple_omp_critical_name (other_crit
))
3438 error_at (gimple_location (stmt
),
3439 "critical region may not be nested inside a critical "
3440 "region with the same name");
3445 case GIMPLE_OMP_TEAMS
:
3447 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
3448 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
3450 error_at (gimple_location (stmt
),
3451 "teams construct not closely nested inside of target "
3456 case GIMPLE_OMP_TARGET
:
3457 for (c
= gimple_omp_target_clauses (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
3458 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
3459 && (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SOURCE
3460 || OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
))
3462 enum omp_clause_depend_kind kind
= OMP_CLAUSE_DEPEND_KIND (c
);
3463 error_at (OMP_CLAUSE_LOCATION (c
),
3464 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3465 kind
== OMP_CLAUSE_DEPEND_SOURCE
? "source" : "sink");
3468 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3470 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
3472 if (is_gimple_omp (stmt
)
3473 && is_gimple_omp_oacc (stmt
)
3474 && is_gimple_omp (ctx
->stmt
))
3476 error_at (gimple_location (stmt
),
3477 "OpenACC construct inside of non-OpenACC region");
3483 const char *stmt_name
, *ctx_stmt_name
;
3484 switch (gimple_omp_target_kind (stmt
))
3486 case GF_OMP_TARGET_KIND_REGION
: stmt_name
= "target"; break;
3487 case GF_OMP_TARGET_KIND_DATA
: stmt_name
= "target data"; break;
3488 case GF_OMP_TARGET_KIND_UPDATE
: stmt_name
= "target update"; break;
3489 case GF_OMP_TARGET_KIND_ENTER_DATA
:
3490 stmt_name
= "target enter data"; break;
3491 case GF_OMP_TARGET_KIND_EXIT_DATA
:
3492 stmt_name
= "target exit data"; break;
3493 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: stmt_name
= "parallel"; break;
3494 case GF_OMP_TARGET_KIND_OACC_KERNELS
: stmt_name
= "kernels"; break;
3495 case GF_OMP_TARGET_KIND_OACC_DATA
: stmt_name
= "data"; break;
3496 case GF_OMP_TARGET_KIND_OACC_UPDATE
: stmt_name
= "update"; break;
3497 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
3498 stmt_name
= "enter/exit data"; break;
3499 default: gcc_unreachable ();
3501 switch (gimple_omp_target_kind (ctx
->stmt
))
3503 case GF_OMP_TARGET_KIND_REGION
: ctx_stmt_name
= "target"; break;
3504 case GF_OMP_TARGET_KIND_DATA
: ctx_stmt_name
= "target data"; break;
3505 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
3506 ctx_stmt_name
= "parallel"; break;
3507 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
3508 ctx_stmt_name
= "kernels"; break;
3509 case GF_OMP_TARGET_KIND_OACC_DATA
: ctx_stmt_name
= "data"; break;
3510 default: gcc_unreachable ();
3513 /* OpenACC/OpenMP mismatch? */
3514 if (is_gimple_omp_oacc (stmt
)
3515 != is_gimple_omp_oacc (ctx
->stmt
))
3517 error_at (gimple_location (stmt
),
3518 "%s %s construct inside of %s %s region",
3519 (is_gimple_omp_oacc (stmt
)
3520 ? "OpenACC" : "OpenMP"), stmt_name
,
3521 (is_gimple_omp_oacc (ctx
->stmt
)
3522 ? "OpenACC" : "OpenMP"), ctx_stmt_name
);
3525 if (is_gimple_omp_offloaded (ctx
->stmt
))
3527 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3528 if (is_gimple_omp_oacc (ctx
->stmt
))
3530 error_at (gimple_location (stmt
),
3531 "%s construct inside of %s region",
3532 stmt_name
, ctx_stmt_name
);
3537 gcc_checking_assert (!is_gimple_omp_oacc (stmt
));
3538 warning_at (gimple_location (stmt
), 0,
3539 "%s construct inside of %s region",
3540 stmt_name
, ctx_stmt_name
);
3552 /* Helper function scan_omp.
3554 Callback for walk_tree or operators in walk_gimple_stmt used to
3555 scan for OMP directives in TP. */
3558 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
3560 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
3561 omp_context
*ctx
= (omp_context
*) wi
->info
;
3564 switch (TREE_CODE (t
))
3571 *tp
= remap_decl (t
, &ctx
->cb
);
3575 if (ctx
&& TYPE_P (t
))
3576 *tp
= remap_type (t
, &ctx
->cb
);
3577 else if (!DECL_P (t
))
3582 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
3583 if (tem
!= TREE_TYPE (t
))
3585 if (TREE_CODE (t
) == INTEGER_CST
)
3586 *tp
= wide_int_to_tree (tem
, t
);
3588 TREE_TYPE (t
) = tem
;
3598 /* Return true if FNDECL is a setjmp or a longjmp. */
3601 setjmp_or_longjmp_p (const_tree fndecl
)
3603 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
3604 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
3605 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
3608 tree declname
= DECL_NAME (fndecl
);
3611 const char *name
= IDENTIFIER_POINTER (declname
);
3612 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
3616 /* Helper function for scan_omp.
3618 Callback for walk_gimple_stmt used to scan for OMP directives in
3619 the current statement in GSI. */
3622 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
3623 struct walk_stmt_info
*wi
)
3625 gimple
*stmt
= gsi_stmt (*gsi
);
3626 omp_context
*ctx
= (omp_context
*) wi
->info
;
3628 if (gimple_has_location (stmt
))
3629 input_location
= gimple_location (stmt
);
3631 /* Check the nesting restrictions. */
3632 bool remove
= false;
3633 if (is_gimple_omp (stmt
))
3634 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3635 else if (is_gimple_call (stmt
))
3637 tree fndecl
= gimple_call_fndecl (stmt
);
3640 if (setjmp_or_longjmp_p (fndecl
)
3642 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3643 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3646 error_at (gimple_location (stmt
),
3647 "setjmp/longjmp inside simd construct");
3649 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
3650 switch (DECL_FUNCTION_CODE (fndecl
))
3652 case BUILT_IN_GOMP_BARRIER
:
3653 case BUILT_IN_GOMP_CANCEL
:
3654 case BUILT_IN_GOMP_CANCELLATION_POINT
:
3655 case BUILT_IN_GOMP_TASKYIELD
:
3656 case BUILT_IN_GOMP_TASKWAIT
:
3657 case BUILT_IN_GOMP_TASKGROUP_START
:
3658 case BUILT_IN_GOMP_TASKGROUP_END
:
3659 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3668 stmt
= gimple_build_nop ();
3669 gsi_replace (gsi
, stmt
, false);
3672 *handled_ops_p
= true;
3674 switch (gimple_code (stmt
))
3676 case GIMPLE_OMP_PARALLEL
:
3677 taskreg_nesting_level
++;
3678 scan_omp_parallel (gsi
, ctx
);
3679 taskreg_nesting_level
--;
3682 case GIMPLE_OMP_TASK
:
3683 taskreg_nesting_level
++;
3684 scan_omp_task (gsi
, ctx
);
3685 taskreg_nesting_level
--;
3688 case GIMPLE_OMP_FOR
:
3689 scan_omp_for (as_a
<gomp_for
*> (stmt
), ctx
);
3692 case GIMPLE_OMP_SECTIONS
:
3693 scan_omp_sections (as_a
<gomp_sections
*> (stmt
), ctx
);
3696 case GIMPLE_OMP_SINGLE
:
3697 scan_omp_single (as_a
<gomp_single
*> (stmt
), ctx
);
3700 case GIMPLE_OMP_SECTION
:
3701 case GIMPLE_OMP_MASTER
:
3702 case GIMPLE_OMP_TASKGROUP
:
3703 case GIMPLE_OMP_ORDERED
:
3704 case GIMPLE_OMP_CRITICAL
:
3705 ctx
= new_omp_context (stmt
, ctx
);
3706 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3709 case GIMPLE_OMP_TARGET
:
3710 scan_omp_target (as_a
<gomp_target
*> (stmt
), ctx
);
3713 case GIMPLE_OMP_TEAMS
:
3714 scan_omp_teams (as_a
<gomp_teams
*> (stmt
), ctx
);
3721 *handled_ops_p
= false;
3723 for (var
= gimple_bind_vars (as_a
<gbind
*> (stmt
));
3725 var
= DECL_CHAIN (var
))
3726 insert_decl_map (&ctx
->cb
, var
, var
);
3730 *handled_ops_p
= false;
3738 /* Scan all the statements starting at the current statement. CTX
3739 contains context information about the OMP directives and
3740 clauses found during the scan. */
3743 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
3745 location_t saved_location
;
3746 struct walk_stmt_info wi
;
3748 memset (&wi
, 0, sizeof (wi
));
3750 wi
.want_locations
= true;
3752 saved_location
= input_location
;
3753 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
3754 input_location
= saved_location
;
3757 /* Re-gimplification and code generation routines. */
3759 /* Build a call to GOMP_barrier. */
3762 build_omp_barrier (tree lhs
)
3764 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
3765 : BUILT_IN_GOMP_BARRIER
);
3766 gcall
*g
= gimple_build_call (fndecl
, 0);
3768 gimple_call_set_lhs (g
, lhs
);
3772 /* If a context was created for STMT when it was scanned, return it. */
3774 static omp_context
*
3775 maybe_lookup_ctx (gimple
*stmt
)
3778 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
3779 return n
? (omp_context
*) n
->value
: NULL
;
3783 /* Find the mapping for DECL in CTX or the immediately enclosing
3784 context that has a mapping for DECL.
3786 If CTX is a nested parallel directive, we may have to use the decl
3787 mappings created in CTX's parent context. Suppose that we have the
3788 following parallel nesting (variable UIDs showed for clarity):
3791 #omp parallel shared(iD.1562) -> outer parallel
3792 iD.1562 = iD.1562 + 1;
3794 #omp parallel shared (iD.1562) -> inner parallel
3795 iD.1562 = iD.1562 - 1;
3797 Each parallel structure will create a distinct .omp_data_s structure
3798 for copying iD.1562 in/out of the directive:
3800 outer parallel .omp_data_s.1.i -> iD.1562
3801 inner parallel .omp_data_s.2.i -> iD.1562
3803 A shared variable mapping will produce a copy-out operation before
3804 the parallel directive and a copy-in operation after it. So, in
3805 this case we would have:
3808 .omp_data_o.1.i = iD.1562;
3809 #omp parallel shared(iD.1562) -> outer parallel
3810 .omp_data_i.1 = &.omp_data_o.1
3811 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3813 .omp_data_o.2.i = iD.1562; -> **
3814 #omp parallel shared(iD.1562) -> inner parallel
3815 .omp_data_i.2 = &.omp_data_o.2
3816 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3819 ** This is a problem. The symbol iD.1562 cannot be referenced
3820 inside the body of the outer parallel region. But since we are
3821 emitting this copy operation while expanding the inner parallel
3822 directive, we need to access the CTX structure of the outer
3823 parallel directive to get the correct mapping:
3825 .omp_data_o.2.i = .omp_data_i.1->i
3827 Since there may be other workshare or parallel directives enclosing
3828 the parallel directive, it may be necessary to walk up the context
3829 parent chain. This is not a problem in general because nested
3830 parallelism happens only rarely. */
3833 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3838 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3839 t
= maybe_lookup_decl (decl
, up
);
3841 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
3843 return t
? t
: decl
;
3847 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3848 in outer contexts. */
3851 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3856 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3857 t
= maybe_lookup_decl (decl
, up
);
3859 return t
? t
: decl
;
3863 /* Construct the initialization value for reduction operation OP. */
3866 omp_reduction_init_op (location_t loc
, enum tree_code op
, tree type
)
3875 case TRUTH_ORIF_EXPR
:
3876 case TRUTH_XOR_EXPR
:
3878 return build_zero_cst (type
);
3881 case TRUTH_AND_EXPR
:
3882 case TRUTH_ANDIF_EXPR
:
3884 return fold_convert_loc (loc
, type
, integer_one_node
);
3887 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3890 if (SCALAR_FLOAT_TYPE_P (type
))
3892 REAL_VALUE_TYPE max
, min
;
3893 if (HONOR_INFINITIES (type
))
3896 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3899 real_maxval (&min
, 1, TYPE_MODE (type
));
3900 return build_real (type
, min
);
3902 else if (POINTER_TYPE_P (type
))
3905 = wi::min_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
3906 return wide_int_to_tree (type
, min
);
3910 gcc_assert (INTEGRAL_TYPE_P (type
));
3911 return TYPE_MIN_VALUE (type
);
3915 if (SCALAR_FLOAT_TYPE_P (type
))
3917 REAL_VALUE_TYPE max
;
3918 if (HONOR_INFINITIES (type
))
3921 real_maxval (&max
, 0, TYPE_MODE (type
));
3922 return build_real (type
, max
);
3924 else if (POINTER_TYPE_P (type
))
3927 = wi::max_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
3928 return wide_int_to_tree (type
, max
);
3932 gcc_assert (INTEGRAL_TYPE_P (type
));
3933 return TYPE_MAX_VALUE (type
);
3941 /* Construct the initialization value for reduction CLAUSE. */
3944 omp_reduction_init (tree clause
, tree type
)
3946 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause
),
3947 OMP_CLAUSE_REDUCTION_CODE (clause
), type
);
3950 /* Return alignment to be assumed for var in CLAUSE, which should be
3951 OMP_CLAUSE_ALIGNED. */
3954 omp_clause_aligned_alignment (tree clause
)
3956 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3957 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3959 /* Otherwise return implementation defined alignment. */
3960 unsigned int al
= 1;
3961 machine_mode mode
, vmode
;
3962 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3964 vs
= 1 << floor_log2 (vs
);
3965 static enum mode_class classes
[]
3966 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3967 for (int i
= 0; i
< 4; i
+= 2)
3968 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3970 mode
= GET_MODE_WIDER_MODE (mode
))
3972 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3973 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3976 && GET_MODE_SIZE (vmode
) < vs
3977 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3978 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3980 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3981 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3983 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3984 / GET_MODE_SIZE (mode
));
3985 if (TYPE_MODE (type
) != vmode
)
3987 if (TYPE_ALIGN_UNIT (type
) > al
)
3988 al
= TYPE_ALIGN_UNIT (type
);
3990 return build_int_cst (integer_type_node
, al
);
3993 /* Return maximum possible vectorization factor for the target. */
4000 || !flag_tree_loop_optimize
4001 || (!flag_tree_loop_vectorize
4002 && (global_options_set
.x_flag_tree_loop_vectorize
4003 || global_options_set
.x_flag_tree_vectorize
)))
4006 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
4009 vs
= 1 << floor_log2 (vs
);
4012 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
4013 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
4014 return GET_MODE_NUNITS (vqimode
);
4018 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4022 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
4023 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
4027 max_vf
= omp_max_vf ();
4030 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
4031 OMP_CLAUSE_SAFELEN
);
4032 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
4034 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
4036 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
4040 idx
= create_tmp_var (unsigned_type_node
);
4041 lane
= create_tmp_var (unsigned_type_node
);
4047 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
4048 tree avar
= create_tmp_var_raw (atype
);
4049 if (TREE_ADDRESSABLE (new_var
))
4050 TREE_ADDRESSABLE (avar
) = 1;
4051 DECL_ATTRIBUTES (avar
)
4052 = tree_cons (get_identifier ("omp simd array"), NULL
,
4053 DECL_ATTRIBUTES (avar
));
4054 gimple_add_tmp_var (avar
);
4055 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
4056 NULL_TREE
, NULL_TREE
);
4057 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
4058 NULL_TREE
, NULL_TREE
);
4059 if (DECL_P (new_var
))
4061 SET_DECL_VALUE_EXPR (new_var
, lvar
);
4062 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4067 /* Helper function of lower_rec_input_clauses. For a reference
4068 in simd reduction, add an underlying variable it will reference. */
4071 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
4073 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
4074 if (TREE_CONSTANT (z
))
4076 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)),
4077 get_name (new_vard
));
4078 gimple_add_tmp_var (z
);
4079 TREE_ADDRESSABLE (z
) = 1;
4080 z
= build_fold_addr_expr_loc (loc
, z
);
4081 gimplify_assign (new_vard
, z
, ilist
);
4085 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4086 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4087 private variables. Initialization statements go in ILIST, while calls
4088 to destructors go in DLIST. */
4091 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
4092 omp_context
*ctx
, struct omp_for_data
*fd
)
4094 tree c
, dtor
, copyin_seq
, x
, ptr
;
4095 bool copyin_by_ref
= false;
4096 bool lastprivate_firstprivate
= false;
4097 bool reduction_omp_orig_ref
= false;
4099 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4100 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
4102 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
4103 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
4104 gimple_seq llist
[2] = { NULL
, NULL
};
4108 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4109 with data sharing clauses referencing variable sized vars. That
4110 is unnecessarily hard to support and very unlikely to result in
4111 vectorized code anyway. */
4113 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4114 switch (OMP_CLAUSE_CODE (c
))
4116 case OMP_CLAUSE_LINEAR
:
4117 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
4120 case OMP_CLAUSE_PRIVATE
:
4121 case OMP_CLAUSE_FIRSTPRIVATE
:
4122 case OMP_CLAUSE_LASTPRIVATE
:
4123 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
4126 case OMP_CLAUSE_REDUCTION
:
4127 if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == MEM_REF
4128 || is_variable_sized (OMP_CLAUSE_DECL (c
)))
4135 /* Do all the fixed sized types in the first pass, and the variable sized
4136 types in the second pass. This makes sure that the scalar arguments to
4137 the variable sized types are processed before we use them in the
4138 variable sized operations. */
4139 for (pass
= 0; pass
< 2; ++pass
)
4141 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4143 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
4146 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4150 case OMP_CLAUSE_PRIVATE
:
4151 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
4154 case OMP_CLAUSE_SHARED
:
4155 /* Ignore shared directives in teams construct. */
4156 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
4158 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
4160 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
)
4161 || is_global_var (OMP_CLAUSE_DECL (c
)));
4164 case OMP_CLAUSE_FIRSTPRIVATE
:
4165 case OMP_CLAUSE_COPYIN
:
4167 case OMP_CLAUSE_LINEAR
:
4168 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
)
4169 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
4170 lastprivate_firstprivate
= true;
4172 case OMP_CLAUSE_REDUCTION
:
4173 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
4174 reduction_omp_orig_ref
= true;
4176 case OMP_CLAUSE__LOOPTEMP_
:
4177 /* Handle _looptemp_ clauses only on parallel/task. */
4181 case OMP_CLAUSE_LASTPRIVATE
:
4182 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4184 lastprivate_firstprivate
= true;
4185 if (pass
!= 0 || is_taskloop_ctx (ctx
))
4188 /* Even without corresponding firstprivate, if
4189 decl is Fortran allocatable, it needs outer var
4192 && lang_hooks
.decls
.omp_private_outer_ref
4193 (OMP_CLAUSE_DECL (c
)))
4194 lastprivate_firstprivate
= true;
4196 case OMP_CLAUSE_ALIGNED
:
4199 var
= OMP_CLAUSE_DECL (c
);
4200 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
4201 && !is_global_var (var
))
4203 new_var
= maybe_lookup_decl (var
, ctx
);
4204 if (new_var
== NULL_TREE
)
4205 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
4206 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
4207 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
4208 omp_clause_aligned_alignment (c
));
4209 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
4210 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
4211 gimplify_and_add (x
, ilist
);
4213 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
4214 && is_global_var (var
))
4216 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
4217 new_var
= lookup_decl (var
, ctx
);
4218 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
4219 t
= build_fold_addr_expr_loc (clause_loc
, t
);
4220 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
4221 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
4222 omp_clause_aligned_alignment (c
));
4223 t
= fold_convert_loc (clause_loc
, ptype
, t
);
4224 x
= create_tmp_var (ptype
);
4225 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
4226 gimplify_and_add (t
, ilist
);
4227 t
= build_simple_mem_ref_loc (clause_loc
, x
);
4228 SET_DECL_VALUE_EXPR (new_var
, t
);
4229 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4236 new_var
= var
= OMP_CLAUSE_DECL (c
);
4237 if (c_kind
== OMP_CLAUSE_REDUCTION
&& TREE_CODE (var
) == MEM_REF
)
4239 var
= TREE_OPERAND (var
, 0);
4240 if (TREE_CODE (var
) == INDIRECT_REF
4241 || TREE_CODE (var
) == ADDR_EXPR
)
4242 var
= TREE_OPERAND (var
, 0);
4243 if (is_variable_sized (var
))
4245 gcc_assert (DECL_HAS_VALUE_EXPR_P (var
));
4246 var
= DECL_VALUE_EXPR (var
);
4247 gcc_assert (TREE_CODE (var
) == INDIRECT_REF
);
4248 var
= TREE_OPERAND (var
, 0);
4249 gcc_assert (DECL_P (var
));
4253 if (c_kind
!= OMP_CLAUSE_COPYIN
)
4254 new_var
= lookup_decl (var
, ctx
);
4256 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
4261 /* C/C++ array section reductions. */
4262 else if (c_kind
== OMP_CLAUSE_REDUCTION
4263 && var
!= OMP_CLAUSE_DECL (c
))
4268 tree orig_var
= TREE_OPERAND (OMP_CLAUSE_DECL (c
), 0);
4269 if (TREE_CODE (orig_var
) == INDIRECT_REF
4270 || TREE_CODE (orig_var
) == ADDR_EXPR
)
4271 orig_var
= TREE_OPERAND (orig_var
, 0);
4272 tree d
= OMP_CLAUSE_DECL (c
);
4273 tree type
= TREE_TYPE (d
);
4274 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
4275 tree v
= TYPE_MAX_VALUE (TYPE_DOMAIN (type
));
4276 const char *name
= get_name (orig_var
);
4277 if (TREE_CONSTANT (v
))
4279 x
= create_tmp_var_raw (type
, name
);
4280 gimple_add_tmp_var (x
);
4281 TREE_ADDRESSABLE (x
) = 1;
4282 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4287 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
4288 tree t
= maybe_lookup_decl (v
, ctx
);
4292 v
= maybe_lookup_decl_in_outer_ctx (v
, ctx
);
4293 gimplify_expr (&v
, ilist
, NULL
, is_gimple_val
, fb_rvalue
);
4294 t
= fold_build2_loc (clause_loc
, PLUS_EXPR
,
4296 build_int_cst (TREE_TYPE (v
), 1));
4297 t
= fold_build2_loc (clause_loc
, MULT_EXPR
,
4299 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4300 tree al
= size_int (TYPE_ALIGN (TREE_TYPE (type
)));
4301 x
= build_call_expr_loc (clause_loc
, atmp
, 2, t
, al
);
4304 tree ptype
= build_pointer_type (TREE_TYPE (type
));
4305 x
= fold_convert_loc (clause_loc
, ptype
, x
);
4306 tree y
= create_tmp_var (ptype
, name
);
4307 gimplify_assign (y
, x
, ilist
);
4309 if (TREE_CODE (TREE_OPERAND (d
, 0)) == ADDR_EXPR
)
4311 if (orig_var
!= var
)
4313 gcc_assert (is_variable_sized (orig_var
));
4314 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
),
4316 gimplify_assign (new_var
, x
, ilist
);
4317 tree new_orig_var
= lookup_decl (orig_var
, ctx
);
4318 tree t
= build_fold_indirect_ref (new_var
);
4319 DECL_IGNORED_P (new_var
) = 0;
4320 TREE_THIS_NOTRAP (t
);
4321 SET_DECL_VALUE_EXPR (new_orig_var
, t
);
4322 DECL_HAS_VALUE_EXPR_P (new_orig_var
) = 1;
4326 x
= build2 (MEM_REF
, TREE_TYPE (new_var
), x
,
4327 build_int_cst (ptype
, 0));
4328 SET_DECL_VALUE_EXPR (new_var
, x
);
4329 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4334 gcc_assert (orig_var
== var
);
4335 if (TREE_CODE (TREE_OPERAND (d
, 0)) == INDIRECT_REF
)
4337 x
= create_tmp_var (ptype
, name
);
4338 TREE_ADDRESSABLE (x
) = 1;
4339 gimplify_assign (x
, y
, ilist
);
4340 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4342 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
4343 gimplify_assign (new_var
, x
, ilist
);
4345 tree y1
= create_tmp_var (ptype
, NULL
);
4346 gimplify_assign (y1
, y
, ilist
);
4347 tree i2
= NULL_TREE
, y2
= NULL_TREE
;
4348 tree body2
= NULL_TREE
, end2
= NULL_TREE
;
4349 tree y3
= NULL_TREE
, y4
= NULL_TREE
;
4350 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) || is_simd
)
4352 y2
= create_tmp_var (ptype
, NULL
);
4353 gimplify_assign (y2
, y
, ilist
);
4354 tree ref
= build_outer_var_ref (var
, ctx
);
4355 /* For ref build_outer_var_ref already performs this. */
4356 if (TREE_CODE (TREE_OPERAND (d
, 0)) == INDIRECT_REF
)
4357 gcc_assert (is_reference (var
));
4358 else if (TREE_CODE (TREE_OPERAND (d
, 0)) == ADDR_EXPR
)
4359 ref
= build_fold_addr_expr (ref
);
4360 else if (is_reference (var
))
4361 ref
= build_fold_addr_expr (ref
);
4362 ref
= fold_convert_loc (clause_loc
, ptype
, ref
);
4363 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
)
4364 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
4366 y3
= create_tmp_var (ptype
, NULL
);
4367 gimplify_assign (y3
, unshare_expr (ref
), ilist
);
4371 y4
= create_tmp_var (ptype
, NULL
);
4372 gimplify_assign (y4
, ref
, dlist
);
4375 tree i
= create_tmp_var (TREE_TYPE (v
), NULL
);
4376 gimplify_assign (i
, build_int_cst (TREE_TYPE (v
), 0), ilist
);
4377 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
4378 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
4379 gimple_seq_add_stmt (ilist
, gimple_build_label (body
));
4382 i2
= create_tmp_var (TREE_TYPE (v
), NULL
);
4383 gimplify_assign (i2
, build_int_cst (TREE_TYPE (v
), 0), dlist
);
4384 body2
= create_artificial_label (UNKNOWN_LOCATION
);
4385 end2
= create_artificial_label (UNKNOWN_LOCATION
);
4386 gimple_seq_add_stmt (dlist
, gimple_build_label (body2
));
4388 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4390 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4391 tree decl_placeholder
4392 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c
);
4393 SET_DECL_VALUE_EXPR (decl_placeholder
,
4394 build_simple_mem_ref (y1
));
4395 DECL_HAS_VALUE_EXPR_P (decl_placeholder
) = 1;
4396 SET_DECL_VALUE_EXPR (placeholder
,
4397 y3
? build_simple_mem_ref (y3
)
4399 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4400 x
= lang_hooks
.decls
.omp_clause_default_ctor
4401 (c
, build_simple_mem_ref (y1
),
4402 y3
? build_simple_mem_ref (y3
) : NULL_TREE
);
4404 gimplify_and_add (x
, ilist
);
4405 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4407 gimple_seq tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4408 lower_omp (&tseq
, ctx
);
4409 gimple_seq_add_seq (ilist
, tseq
);
4411 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4414 SET_DECL_VALUE_EXPR (decl_placeholder
,
4415 build_simple_mem_ref (y2
));
4416 SET_DECL_VALUE_EXPR (placeholder
,
4417 build_simple_mem_ref (y4
));
4418 gimple_seq tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4419 lower_omp (&tseq
, ctx
);
4420 gimple_seq_add_seq (dlist
, tseq
);
4421 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4423 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4424 DECL_HAS_VALUE_EXPR_P (decl_placeholder
) = 0;
4425 x
= lang_hooks
.decls
.omp_clause_dtor
4426 (c
, build_simple_mem_ref (y2
));
4429 gimple_seq tseq
= NULL
;
4431 gimplify_stmt (&dtor
, &tseq
);
4432 gimple_seq_add_seq (dlist
, tseq
);
4437 x
= omp_reduction_init (c
, TREE_TYPE (type
));
4438 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4440 /* reduction(-:var) sums up the partial results, so it
4441 acts identically to reduction(+:var). */
4442 if (code
== MINUS_EXPR
)
4445 gimplify_assign (build_simple_mem_ref (y1
), x
, ilist
);
4448 x
= build2 (code
, TREE_TYPE (type
),
4449 build_simple_mem_ref (y4
),
4450 build_simple_mem_ref (y2
));
4451 gimplify_assign (build_simple_mem_ref (y4
), x
, dlist
);
4455 = gimple_build_assign (y1
, POINTER_PLUS_EXPR
, y1
,
4456 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4457 gimple_seq_add_stmt (ilist
, g
);
4460 g
= gimple_build_assign (y3
, POINTER_PLUS_EXPR
, y3
,
4461 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4462 gimple_seq_add_stmt (ilist
, g
);
4464 g
= gimple_build_assign (i
, PLUS_EXPR
, i
,
4465 build_int_cst (TREE_TYPE (i
), 1));
4466 gimple_seq_add_stmt (ilist
, g
);
4467 g
= gimple_build_cond (LE_EXPR
, i
, v
, body
, end
);
4468 gimple_seq_add_stmt (ilist
, g
);
4469 gimple_seq_add_stmt (ilist
, gimple_build_label (end
));
4472 g
= gimple_build_assign (y2
, POINTER_PLUS_EXPR
, y2
,
4473 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4474 gimple_seq_add_stmt (dlist
, g
);
4477 g
= gimple_build_assign
4478 (y4
, POINTER_PLUS_EXPR
, y4
,
4479 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4480 gimple_seq_add_stmt (dlist
, g
);
4482 g
= gimple_build_assign (i2
, PLUS_EXPR
, i2
,
4483 build_int_cst (TREE_TYPE (i2
), 1));
4484 gimple_seq_add_stmt (dlist
, g
);
4485 g
= gimple_build_cond (LE_EXPR
, i2
, v
, body2
, end2
);
4486 gimple_seq_add_stmt (dlist
, g
);
4487 gimple_seq_add_stmt (dlist
, gimple_build_label (end2
));
4491 else if (is_variable_sized (var
))
4493 /* For variable sized types, we need to allocate the
4494 actual storage here. Call alloca and store the
4495 result in the pointer decl that we created elsewhere. */
4499 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
4504 ptr
= DECL_VALUE_EXPR (new_var
);
4505 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
4506 ptr
= TREE_OPERAND (ptr
, 0);
4507 gcc_assert (DECL_P (ptr
));
4508 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
4510 /* void *tmp = __builtin_alloca */
4511 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
4512 stmt
= gimple_build_call (atmp
, 2, x
,
4513 size_int (DECL_ALIGN (var
)));
4514 tmp
= create_tmp_var_raw (ptr_type_node
);
4515 gimple_add_tmp_var (tmp
);
4516 gimple_call_set_lhs (stmt
, tmp
);
4518 gimple_seq_add_stmt (ilist
, stmt
);
4520 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
4521 gimplify_assign (ptr
, x
, ilist
);
4524 else if (is_reference (var
))
4526 /* For references that are being privatized for Fortran,
4527 allocate new backing storage for the new pointer
4528 variable. This allows us to avoid changing all the
4529 code that expects a pointer to something that expects
4530 a direct variable. */
4534 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
4535 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
4537 x
= build_receiver_ref (var
, false, ctx
);
4538 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4540 else if (TREE_CONSTANT (x
))
4542 /* For reduction in SIMD loop, defer adding the
4543 initialization of the reference, because if we decide
4544 to use SIMD array for it, the initilization could cause
4546 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
4550 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
4552 gimple_add_tmp_var (x
);
4553 TREE_ADDRESSABLE (x
) = 1;
4554 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4560 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
4561 tree rtype
= TREE_TYPE (TREE_TYPE (new_var
));
4562 tree al
= size_int (TYPE_ALIGN (rtype
));
4563 x
= build_call_expr_loc (clause_loc
, atmp
, 2, x
, al
);
4568 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
4569 gimplify_assign (new_var
, x
, ilist
);
4572 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4574 else if (c_kind
== OMP_CLAUSE_REDUCTION
4575 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4583 switch (OMP_CLAUSE_CODE (c
))
4585 case OMP_CLAUSE_SHARED
:
4586 /* Ignore shared directives in teams construct. */
4587 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
4589 /* Shared global vars are just accessed directly. */
4590 if (is_global_var (new_var
))
4592 /* For taskloop firstprivate/lastprivate, represented
4593 as firstprivate and shared clause on the task, new_var
4594 is the firstprivate var. */
4595 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
4597 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4598 needs to be delayed until after fixup_child_record_type so
4599 that we get the correct type during the dereference. */
4600 by_ref
= use_pointer_for_field (var
, ctx
);
4601 x
= build_receiver_ref (var
, by_ref
, ctx
);
4602 SET_DECL_VALUE_EXPR (new_var
, x
);
4603 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4605 /* ??? If VAR is not passed by reference, and the variable
4606 hasn't been initialized yet, then we'll get a warning for
4607 the store into the omp_data_s structure. Ideally, we'd be
4608 able to notice this and not store anything at all, but
4609 we're generating code too early. Suppress the warning. */
4611 TREE_NO_WARNING (var
) = 1;
4614 case OMP_CLAUSE_LASTPRIVATE
:
4615 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4619 case OMP_CLAUSE_PRIVATE
:
4620 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
4621 x
= build_outer_var_ref (var
, ctx
);
4622 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4624 if (is_task_ctx (ctx
))
4625 x
= build_receiver_ref (var
, false, ctx
);
4627 x
= build_outer_var_ref (var
, ctx
);
4633 nx
= lang_hooks
.decls
.omp_clause_default_ctor
4634 (c
, unshare_expr (new_var
), x
);
4637 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
4638 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
4639 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
4640 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4641 idx
, lane
, ivar
, lvar
))
4644 x
= lang_hooks
.decls
.omp_clause_default_ctor
4645 (c
, unshare_expr (ivar
), x
);
4647 gimplify_and_add (x
, &llist
[0]);
4650 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4653 gimple_seq tseq
= NULL
;
4656 gimplify_stmt (&dtor
, &tseq
);
4657 gimple_seq_add_seq (&llist
[1], tseq
);
4664 gimplify_and_add (nx
, ilist
);
4668 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
4671 gimple_seq tseq
= NULL
;
4674 gimplify_stmt (&dtor
, &tseq
);
4675 gimple_seq_add_seq (dlist
, tseq
);
4679 case OMP_CLAUSE_LINEAR
:
4680 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
4681 goto do_firstprivate
;
4682 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
4685 x
= build_outer_var_ref (var
, ctx
);
4688 case OMP_CLAUSE_FIRSTPRIVATE
:
4689 if (is_task_ctx (ctx
))
4691 if (is_reference (var
) || is_variable_sized (var
))
4693 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
4695 || use_pointer_for_field (var
, NULL
))
4697 x
= build_receiver_ref (var
, false, ctx
);
4698 SET_DECL_VALUE_EXPR (new_var
, x
);
4699 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4704 x
= build_outer_var_ref (var
, ctx
);
4707 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4708 && gimple_omp_for_combined_into_p (ctx
->stmt
))
4710 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
4711 tree stept
= TREE_TYPE (t
);
4712 tree ct
= find_omp_clause (clauses
,
4713 OMP_CLAUSE__LOOPTEMP_
);
4715 tree l
= OMP_CLAUSE_DECL (ct
);
4716 tree n1
= fd
->loop
.n1
;
4717 tree step
= fd
->loop
.step
;
4718 tree itype
= TREE_TYPE (l
);
4719 if (POINTER_TYPE_P (itype
))
4720 itype
= signed_type_for (itype
);
4721 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
4722 if (TYPE_UNSIGNED (itype
)
4723 && fd
->loop
.cond_code
== GT_EXPR
)
4724 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
4725 fold_build1 (NEGATE_EXPR
, itype
, l
),
4726 fold_build1 (NEGATE_EXPR
,
4729 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
4730 t
= fold_build2 (MULT_EXPR
, stept
,
4731 fold_convert (stept
, l
), t
);
4733 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
4735 x
= lang_hooks
.decls
.omp_clause_linear_ctor
4737 gimplify_and_add (x
, ilist
);
4741 if (POINTER_TYPE_P (TREE_TYPE (x
)))
4742 x
= fold_build2 (POINTER_PLUS_EXPR
,
4743 TREE_TYPE (x
), x
, t
);
4745 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
4748 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
4749 || TREE_ADDRESSABLE (new_var
))
4750 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4751 idx
, lane
, ivar
, lvar
))
4753 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
4755 tree iv
= create_tmp_var (TREE_TYPE (new_var
));
4756 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
4757 gimplify_and_add (x
, ilist
);
4758 gimple_stmt_iterator gsi
4759 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4761 = gimple_build_assign (unshare_expr (lvar
), iv
);
4762 gsi_insert_before_without_update (&gsi
, g
,
4764 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
4765 enum tree_code code
= PLUS_EXPR
;
4766 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
4767 code
= POINTER_PLUS_EXPR
;
4768 g
= gimple_build_assign (iv
, code
, iv
, t
);
4769 gsi_insert_before_without_update (&gsi
, g
,
4773 x
= lang_hooks
.decls
.omp_clause_copy_ctor
4774 (c
, unshare_expr (ivar
), x
);
4775 gimplify_and_add (x
, &llist
[0]);
4776 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4779 gimple_seq tseq
= NULL
;
4782 gimplify_stmt (&dtor
, &tseq
);
4783 gimple_seq_add_seq (&llist
[1], tseq
);
4788 x
= lang_hooks
.decls
.omp_clause_copy_ctor
4789 (c
, unshare_expr (new_var
), x
);
4790 gimplify_and_add (x
, ilist
);
4793 case OMP_CLAUSE__LOOPTEMP_
:
4794 gcc_assert (is_taskreg_ctx (ctx
));
4795 x
= build_outer_var_ref (var
, ctx
);
4796 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
4797 gimplify_and_add (x
, ilist
);
4800 case OMP_CLAUSE_COPYIN
:
4801 by_ref
= use_pointer_for_field (var
, NULL
);
4802 x
= build_receiver_ref (var
, by_ref
, ctx
);
4803 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
4804 append_to_statement_list (x
, ©in_seq
);
4805 copyin_by_ref
|= by_ref
;
4808 case OMP_CLAUSE_REDUCTION
:
4809 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4811 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4813 x
= build_outer_var_ref (var
, ctx
);
4815 if (is_reference (var
)
4816 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4818 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4819 SET_DECL_VALUE_EXPR (placeholder
, x
);
4820 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4821 tree new_vard
= new_var
;
4822 if (is_reference (var
))
4824 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4825 new_vard
= TREE_OPERAND (new_var
, 0);
4826 gcc_assert (DECL_P (new_vard
));
4829 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4830 idx
, lane
, ivar
, lvar
))
4832 if (new_vard
== new_var
)
4834 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
4835 SET_DECL_VALUE_EXPR (new_var
, ivar
);
4839 SET_DECL_VALUE_EXPR (new_vard
,
4840 build_fold_addr_expr (ivar
));
4841 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4843 x
= lang_hooks
.decls
.omp_clause_default_ctor
4844 (c
, unshare_expr (ivar
),
4845 build_outer_var_ref (var
, ctx
));
4847 gimplify_and_add (x
, &llist
[0]);
4848 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4850 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4851 lower_omp (&tseq
, ctx
);
4852 gimple_seq_add_seq (&llist
[0], tseq
);
4854 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4855 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4856 lower_omp (&tseq
, ctx
);
4857 gimple_seq_add_seq (&llist
[1], tseq
);
4858 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4859 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4860 if (new_vard
== new_var
)
4861 SET_DECL_VALUE_EXPR (new_var
, lvar
);
4863 SET_DECL_VALUE_EXPR (new_vard
,
4864 build_fold_addr_expr (lvar
));
4865 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4870 gimplify_stmt (&dtor
, &tseq
);
4871 gimple_seq_add_seq (&llist
[1], tseq
);
4875 /* If this is a reference to constant size reduction var
4876 with placeholder, we haven't emitted the initializer
4877 for it because it is undesirable if SIMD arrays are used.
4878 But if they aren't used, we need to emit the deferred
4879 initialization now. */
4880 else if (is_reference (var
) && is_simd
)
4881 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4882 x
= lang_hooks
.decls
.omp_clause_default_ctor
4883 (c
, unshare_expr (new_var
),
4884 build_outer_var_ref (var
, ctx
));
4886 gimplify_and_add (x
, ilist
);
4887 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4889 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4890 lower_omp (&tseq
, ctx
);
4891 gimple_seq_add_seq (ilist
, tseq
);
4893 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4896 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4897 lower_omp (&tseq
, ctx
);
4898 gimple_seq_add_seq (dlist
, tseq
);
4899 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4901 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4906 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
4907 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
4908 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4910 /* reduction(-:var) sums up the partial results, so it
4911 acts identically to reduction(+:var). */
4912 if (code
== MINUS_EXPR
)
4915 tree new_vard
= new_var
;
4916 if (is_simd
&& is_reference (var
))
4918 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4919 new_vard
= TREE_OPERAND (new_var
, 0);
4920 gcc_assert (DECL_P (new_vard
));
4923 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4924 idx
, lane
, ivar
, lvar
))
4926 tree ref
= build_outer_var_ref (var
, ctx
);
4928 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
4930 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
4931 ref
= build_outer_var_ref (var
, ctx
);
4932 gimplify_assign (ref
, x
, &llist
[1]);
4934 if (new_vard
!= new_var
)
4936 SET_DECL_VALUE_EXPR (new_vard
,
4937 build_fold_addr_expr (lvar
));
4938 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4943 if (is_reference (var
) && is_simd
)
4944 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4945 gimplify_assign (new_var
, x
, ilist
);
4948 tree ref
= build_outer_var_ref (var
, ctx
);
4950 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4951 ref
= build_outer_var_ref (var
, ctx
);
4952 gimplify_assign (ref
, x
, dlist
);
4966 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
4967 /* Don't want uninit warnings on simduid, it is always uninitialized,
4968 but we use it not for the value, but for the DECL_UID only. */
4969 TREE_NO_WARNING (uid
) = 1;
4971 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
4972 gimple_call_set_lhs (g
, lane
);
4973 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4974 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
4975 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
4976 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
4977 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4978 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4979 g
= gimple_build_assign (lane
, INTEGER_CST
,
4980 build_int_cst (unsigned_type_node
, 0));
4981 gimple_seq_add_stmt (ilist
, g
);
4982 for (int i
= 0; i
< 2; i
++)
4985 tree vf
= create_tmp_var (unsigned_type_node
);
4986 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
4987 gimple_call_set_lhs (g
, vf
);
4988 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
4989 gimple_seq_add_stmt (seq
, g
);
4990 tree t
= build_int_cst (unsigned_type_node
, 0);
4991 g
= gimple_build_assign (idx
, INTEGER_CST
, t
);
4992 gimple_seq_add_stmt (seq
, g
);
4993 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
4994 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
4995 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
4996 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
4997 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
4998 gimple_seq_add_seq (seq
, llist
[i
]);
4999 t
= build_int_cst (unsigned_type_node
, 1);
5000 g
= gimple_build_assign (idx
, PLUS_EXPR
, idx
, t
);
5001 gimple_seq_add_stmt (seq
, g
);
5002 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
5003 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
5004 gimple_seq_add_stmt (seq
, g
);
5005 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
5009 /* The copyin sequence is not to be executed by the main thread, since
5010 that would result in self-copies. Perhaps not visible to scalars,
5011 but it certainly is to C++ operator=. */
5014 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
5016 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
5017 build_int_cst (TREE_TYPE (x
), 0));
5018 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
5019 gimplify_and_add (x
, ilist
);
5022 /* If any copyin variable is passed by reference, we must ensure the
5023 master thread doesn't modify it before it is copied over in all
5024 threads. Similarly for variables in both firstprivate and
5025 lastprivate clauses we need to ensure the lastprivate copying
5026 happens after firstprivate copying in all threads. And similarly
5027 for UDRs if initializer expression refers to omp_orig. */
5028 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
5030 /* Don't add any barrier for #pragma omp simd or
5031 #pragma omp distribute. */
5032 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
5033 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
5034 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
5037 /* If max_vf is non-zero, then we can use only a vectorization factor
5038 up to the max_vf we chose. So stick it into the safelen clause. */
5041 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
5042 OMP_CLAUSE_SAFELEN
);
5044 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
5045 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
5048 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
5049 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
5051 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
5052 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
5058 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5059 both parallel and workshare constructs. PREDICATE may be NULL if it's
5063 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
5066 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
5067 bool par_clauses
= false;
5068 tree simduid
= NULL
, lastlane
= NULL
;
5070 /* Early exit if there are no lastprivate or linear clauses. */
5071 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
5072 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
5073 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
5074 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
5076 if (clauses
== NULL
)
5078 /* If this was a workshare clause, see if it had been combined
5079 with its parallel. In that case, look for the clauses on the
5080 parallel statement itself. */
5081 if (is_parallel_ctx (ctx
))
5085 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
5088 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
5089 OMP_CLAUSE_LASTPRIVATE
);
5090 if (clauses
== NULL
)
5098 tree label_true
, arm1
, arm2
;
5100 label
= create_artificial_label (UNKNOWN_LOCATION
);
5101 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
5102 arm1
= TREE_OPERAND (predicate
, 0);
5103 arm2
= TREE_OPERAND (predicate
, 1);
5104 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
5105 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
5106 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
5108 gimple_seq_add_stmt (stmt_list
, stmt
);
5109 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
5112 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
5113 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
5115 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
5117 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
5120 for (c
= clauses
; c
;)
5123 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
5125 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5126 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
5127 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
5129 var
= OMP_CLAUSE_DECL (c
);
5130 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5131 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
)
5132 && is_taskloop_ctx (ctx
))
5134 gcc_checking_assert (ctx
->outer
&& is_task_ctx (ctx
->outer
));
5135 new_var
= lookup_decl (var
, ctx
->outer
);
5138 new_var
= lookup_decl (var
, ctx
);
5140 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
5142 tree val
= DECL_VALUE_EXPR (new_var
);
5143 if (TREE_CODE (val
) == ARRAY_REF
5144 && VAR_P (TREE_OPERAND (val
, 0))
5145 && lookup_attribute ("omp simd array",
5146 DECL_ATTRIBUTES (TREE_OPERAND (val
,
5149 if (lastlane
== NULL
)
5151 lastlane
= create_tmp_var (unsigned_type_node
);
5153 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
5155 TREE_OPERAND (val
, 1));
5156 gimple_call_set_lhs (g
, lastlane
);
5157 gimple_seq_add_stmt (stmt_list
, g
);
5159 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
5160 TREE_OPERAND (val
, 0), lastlane
,
5161 NULL_TREE
, NULL_TREE
);
5165 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5166 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
5168 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
5169 gimple_seq_add_seq (stmt_list
,
5170 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
5171 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
5173 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
5174 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
5176 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
5177 gimple_seq_add_seq (stmt_list
,
5178 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
5179 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
5183 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5184 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c
))
5186 gcc_checking_assert (is_taskloop_ctx (ctx
));
5187 tree ovar
= maybe_lookup_decl_in_outer_ctx (var
,
5189 if (is_global_var (ovar
))
5193 x
= build_outer_var_ref (var
, ctx
, true);
5194 if (is_reference (var
))
5195 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5196 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
5197 gimplify_and_add (x
, stmt_list
);
5199 c
= OMP_CLAUSE_CHAIN (c
);
5200 if (c
== NULL
&& !par_clauses
)
5202 /* If this was a workshare clause, see if it had been combined
5203 with its parallel. In that case, continue looking for the
5204 clauses also on the parallel statement itself. */
5205 if (is_parallel_ctx (ctx
))
5209 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
5212 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
5213 OMP_CLAUSE_LASTPRIVATE
);
5219 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
5223 oacc_lower_reduction_var_helper (gimple_seq
*stmt_seqp
, omp_context
*ctx
,
5224 tree tid
, tree var
, tree new_var
)
5226 /* The atomic add at the end of the sum creates unnecessary
5227 write contention on accelerators. To work around this,
5228 create an array to store the partial reductions. Later, in
5229 lower_omp_for (for openacc), the values of array will be
5232 tree t
= NULL_TREE
, array
, x
;
5233 tree type
= get_base_type (var
);
5236 /* Now insert the partial reductions into the array. */
5238 /* Find the reduction array. */
5240 tree ptype
= build_pointer_type (type
);
5242 t
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
), ctx
);
5243 t
= build_receiver_ref (t
, false, ctx
->outer
);
5245 array
= create_tmp_var (ptype
);
5246 gimplify_assign (array
, t
, stmt_seqp
);
5248 tree ptr
= create_tmp_var (TREE_TYPE (array
));
5250 /* Find the reduction array. */
5252 /* testing a unary conversion. */
5253 tree offset
= create_tmp_var (sizetype
);
5254 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
),
5256 t
= create_tmp_var (sizetype
);
5257 gimplify_assign (t
, unshare_expr (fold_build1 (NOP_EXPR
, sizetype
, tid
)),
5259 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, t
);
5260 gimple_seq_add_stmt (stmt_seqp
, stmt
);
5262 /* Offset expression. Does the POINTER_PLUS_EXPR take care
5263 of adding sizeof(var) to the array? */
5264 ptr
= create_tmp_var (ptype
);
5265 stmt
= gimple_build_assign (unshare_expr (ptr
), POINTER_PLUS_EXPR
, array
,
5267 gimple_seq_add_stmt (stmt_seqp
, stmt
);
5269 /* Move the local sum to gfc$sum[i]. */
5270 x
= unshare_expr (build_simple_mem_ref (ptr
));
5271 stmt
= gimplify_assign (x
, new_var
, stmt_seqp
);
5274 /* Generate code to implement the REDUCTION clauses. */
5277 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
5279 gimple_seq sub_seq
= NULL
;
5281 tree x
, c
, tid
= NULL_TREE
;
5284 /* SIMD reductions are handled in lower_rec_input_clauses. */
5285 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
5286 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
5289 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5290 update in that case, otherwise use a lock. */
5291 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
5292 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
5294 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
)
5295 || TREE_CODE (OMP_CLAUSE_DECL (c
)) == MEM_REF
)
5297 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5307 /* Initialize thread info for OpenACC. */
5308 if (is_gimple_omp_oacc (ctx
->stmt
))
5310 /* Get the current thread id. */
5311 tree call
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
5312 tid
= create_tmp_var (TREE_TYPE (TREE_TYPE (call
)));
5313 gimple
*stmt
= gimple_build_call (call
, 0);
5314 gimple_call_set_lhs (stmt
, tid
);
5315 gimple_seq_add_stmt (stmt_seqp
, stmt
);
5318 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
5320 tree var
, ref
, new_var
, orig_var
;
5321 enum tree_code code
;
5322 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
5324 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
5327 orig_var
= var
= OMP_CLAUSE_DECL (c
);
5328 if (TREE_CODE (var
) == MEM_REF
)
5330 var
= TREE_OPERAND (var
, 0);
5331 if (TREE_CODE (var
) == INDIRECT_REF
5332 || TREE_CODE (var
) == ADDR_EXPR
)
5333 var
= TREE_OPERAND (var
, 0);
5335 if (is_variable_sized (var
))
5337 gcc_assert (DECL_HAS_VALUE_EXPR_P (var
));
5338 var
= DECL_VALUE_EXPR (var
);
5339 gcc_assert (TREE_CODE (var
) == INDIRECT_REF
);
5340 var
= TREE_OPERAND (var
, 0);
5341 gcc_assert (DECL_P (var
));
5344 new_var
= lookup_decl (var
, ctx
);
5345 if (var
== OMP_CLAUSE_DECL (c
) && is_reference (var
))
5346 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5347 ref
= build_outer_var_ref (var
, ctx
);
5348 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
5350 /* reduction(-:var) sums up the partial results, so it acts
5351 identically to reduction(+:var). */
5352 if (code
== MINUS_EXPR
)
5355 if (is_gimple_omp_oacc (ctx
->stmt
))
5357 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
));
5359 oacc_lower_reduction_var_helper (stmt_seqp
, ctx
, tid
, var
, new_var
);
5361 else if (count
== 1)
5363 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
5365 addr
= save_expr (addr
);
5366 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
5367 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
5368 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
5369 gimplify_and_add (x
, stmt_seqp
);
5372 else if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == MEM_REF
)
5374 tree d
= OMP_CLAUSE_DECL (c
);
5375 tree type
= TREE_TYPE (d
);
5376 tree v
= TYPE_MAX_VALUE (TYPE_DOMAIN (type
));
5377 tree i
= create_tmp_var (TREE_TYPE (v
), NULL
);
5378 tree ptype
= build_pointer_type (TREE_TYPE (type
));
5379 /* For ref build_outer_var_ref already performs this, so
5380 only new_var needs a dereference. */
5381 if (TREE_CODE (TREE_OPERAND (d
, 0)) == INDIRECT_REF
)
5383 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5384 gcc_assert (is_reference (var
) && var
== orig_var
);
5386 else if (TREE_CODE (TREE_OPERAND (d
, 0)) == ADDR_EXPR
)
5388 if (orig_var
== var
)
5390 new_var
= build_fold_addr_expr (new_var
);
5391 ref
= build_fold_addr_expr (ref
);
5396 gcc_assert (orig_var
== var
);
5397 if (is_reference (var
))
5398 ref
= build_fold_addr_expr (ref
);
5402 tree t
= maybe_lookup_decl (v
, ctx
);
5406 v
= maybe_lookup_decl_in_outer_ctx (v
, ctx
);
5407 gimplify_expr (&v
, stmt_seqp
, NULL
, is_gimple_val
, fb_rvalue
);
5409 new_var
= fold_convert_loc (clause_loc
, ptype
, new_var
);
5410 ref
= fold_convert_loc (clause_loc
, ptype
, ref
);
5411 tree m
= create_tmp_var (ptype
, NULL
);
5412 gimplify_assign (m
, new_var
, stmt_seqp
);
5414 m
= create_tmp_var (ptype
, NULL
);
5415 gimplify_assign (m
, ref
, stmt_seqp
);
5417 gimplify_assign (i
, build_int_cst (TREE_TYPE (v
), 0), stmt_seqp
);
5418 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
5419 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
5420 gimple_seq_add_stmt (&sub_seq
, gimple_build_label (body
));
5421 tree priv
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5422 tree out
= build_simple_mem_ref_loc (clause_loc
, ref
);
5423 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
5425 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
5426 tree decl_placeholder
5427 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c
);
5428 SET_DECL_VALUE_EXPR (placeholder
, out
);
5429 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
5430 SET_DECL_VALUE_EXPR (decl_placeholder
, priv
);
5431 DECL_HAS_VALUE_EXPR_P (decl_placeholder
) = 1;
5432 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
5433 gimple_seq_add_seq (&sub_seq
,
5434 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
5435 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
5436 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
5437 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c
) = NULL
;
5441 x
= build2 (code
, TREE_TYPE (out
), out
, priv
);
5442 out
= unshare_expr (out
);
5443 gimplify_assign (out
, x
, &sub_seq
);
5445 gimple
*g
= gimple_build_assign (new_var
, POINTER_PLUS_EXPR
, new_var
,
5446 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
5447 gimple_seq_add_stmt (&sub_seq
, g
);
5448 g
= gimple_build_assign (ref
, POINTER_PLUS_EXPR
, ref
,
5449 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
5450 gimple_seq_add_stmt (&sub_seq
, g
);
5451 g
= gimple_build_assign (i
, PLUS_EXPR
, i
,
5452 build_int_cst (TREE_TYPE (i
), 1));
5453 gimple_seq_add_stmt (&sub_seq
, g
);
5454 g
= gimple_build_cond (LE_EXPR
, i
, v
, body
, end
);
5455 gimple_seq_add_stmt (&sub_seq
, g
);
5456 gimple_seq_add_stmt (&sub_seq
, gimple_build_label (end
));
5458 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
5460 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
5462 if (is_reference (var
)
5463 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
5465 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
5466 SET_DECL_VALUE_EXPR (placeholder
, ref
);
5467 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
5468 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
5469 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
5470 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
5471 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
5475 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
5476 ref
= build_outer_var_ref (var
, ctx
);
5477 gimplify_assign (ref
, x
, &sub_seq
);
5481 if (is_gimple_omp_oacc (ctx
->stmt
))
5484 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
5486 gimple_seq_add_stmt (stmt_seqp
, stmt
);
5488 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
5490 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
5492 gimple_seq_add_stmt (stmt_seqp
, stmt
);
5496 /* Generate code to implement the COPYPRIVATE clauses. */
5499 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
5504 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
5506 tree var
, new_var
, ref
, x
;
5508 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
5510 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
5513 var
= OMP_CLAUSE_DECL (c
);
5514 by_ref
= use_pointer_for_field (var
, NULL
);
5516 ref
= build_sender_ref (var
, ctx
);
5517 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
5520 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
5521 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
5523 gimplify_assign (ref
, x
, slist
);
5525 ref
= build_receiver_ref (var
, false, ctx
);
5528 ref
= fold_convert_loc (clause_loc
,
5529 build_pointer_type (TREE_TYPE (new_var
)),
5531 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
5533 if (is_reference (var
))
5535 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
5536 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
5537 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5539 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
5540 gimplify_and_add (x
, rlist
);
5545 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5546 and REDUCTION from the sender (aka parent) side. */
5549 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
5553 int ignored_looptemp
= 0;
5554 bool is_taskloop
= false;
5556 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5557 by GOMP_taskloop. */
5558 if (is_task_ctx (ctx
) && gimple_omp_task_taskloop_p (ctx
->stmt
))
5560 ignored_looptemp
= 2;
5564 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
5566 tree val
, ref
, x
, var
;
5567 bool by_ref
, do_in
= false, do_out
= false;
5568 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
5570 switch (OMP_CLAUSE_CODE (c
))
5572 case OMP_CLAUSE_PRIVATE
:
5573 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
5576 case OMP_CLAUSE_FIRSTPRIVATE
:
5577 case OMP_CLAUSE_COPYIN
:
5578 case OMP_CLAUSE_LASTPRIVATE
:
5579 case OMP_CLAUSE_REDUCTION
:
5581 case OMP_CLAUSE_SHARED
:
5582 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
5585 case OMP_CLAUSE__LOOPTEMP_
:
5586 if (ignored_looptemp
)
5596 val
= OMP_CLAUSE_DECL (c
);
5597 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
5598 && TREE_CODE (val
) == MEM_REF
)
5600 val
= TREE_OPERAND (val
, 0);
5601 if (TREE_CODE (val
) == INDIRECT_REF
5602 || TREE_CODE (val
) == ADDR_EXPR
)
5603 val
= TREE_OPERAND (val
, 0);
5604 if (is_variable_sized (val
))
5608 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5609 outer taskloop region. */
5610 omp_context
*ctx_for_o
= ctx
;
5612 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
5613 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
5614 ctx_for_o
= ctx
->outer
;
5616 var
= lookup_decl_in_outer_ctx (val
, ctx_for_o
);
5618 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
5619 && is_global_var (var
))
5622 t
= omp_member_access_dummy_var (var
);
5625 var
= DECL_VALUE_EXPR (var
);
5626 tree o
= maybe_lookup_decl_in_outer_ctx (t
, ctx_for_o
);
5628 var
= unshare_and_remap (var
, t
, o
);
5630 var
= unshare_expr (var
);
5633 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
5635 /* Handle taskloop firstprivate/lastprivate, where the
5636 lastprivate on GIMPLE_OMP_TASK is represented as
5637 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
5638 tree f
= lookup_sfield ((splay_tree_key
) &DECL_UID (val
), ctx
);
5639 x
= omp_build_component_ref (ctx
->sender_decl
, f
);
5640 if (use_pointer_for_field (val
, ctx
))
5641 var
= build_fold_addr_expr (var
);
5642 gimplify_assign (x
, var
, ilist
);
5643 DECL_ABSTRACT_ORIGIN (f
) = NULL
;
5647 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
5648 || val
== OMP_CLAUSE_DECL (c
))
5649 && is_variable_sized (val
))
5651 by_ref
= use_pointer_for_field (val
, NULL
);
5653 switch (OMP_CLAUSE_CODE (c
))
5655 case OMP_CLAUSE_PRIVATE
:
5656 case OMP_CLAUSE_FIRSTPRIVATE
:
5657 case OMP_CLAUSE_COPYIN
:
5658 case OMP_CLAUSE__LOOPTEMP_
:
5662 case OMP_CLAUSE_LASTPRIVATE
:
5663 if (by_ref
|| is_reference (val
))
5665 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
5672 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
5677 case OMP_CLAUSE_REDUCTION
:
5679 if (val
== OMP_CLAUSE_DECL (c
))
5680 do_out
= !(by_ref
|| is_reference (val
));
5682 by_ref
= TREE_CODE (TREE_TYPE (val
)) == ARRAY_TYPE
;
5691 ref
= build_sender_ref (val
, ctx
);
5692 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
5693 gimplify_assign (ref
, x
, ilist
);
5694 if (is_task_ctx (ctx
))
5695 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
5700 ref
= build_sender_ref (val
, ctx
);
5701 gimplify_assign (var
, ref
, olist
);
5706 /* Generate code to implement SHARED from the sender (aka parent)
5707 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
5708 list things that got automatically shared. */
5711 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
5713 tree var
, ovar
, nvar
, t
, f
, x
, record_type
;
5715 if (ctx
->record_type
== NULL
)
5718 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
5719 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
5721 ovar
= DECL_ABSTRACT_ORIGIN (f
);
5722 if (!ovar
|| TREE_CODE (ovar
) == FIELD_DECL
)
5725 nvar
= maybe_lookup_decl (ovar
, ctx
);
5726 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
5729 /* If CTX is a nested parallel directive. Find the immediately
5730 enclosing parallel or workshare construct that contains a
5731 mapping for OVAR. */
5732 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
5734 t
= omp_member_access_dummy_var (var
);
5737 var
= DECL_VALUE_EXPR (var
);
5738 tree o
= maybe_lookup_decl_in_outer_ctx (t
, ctx
);
5740 var
= unshare_and_remap (var
, t
, o
);
5742 var
= unshare_expr (var
);
5745 if (use_pointer_for_field (ovar
, ctx
))
5747 x
= build_sender_ref (ovar
, ctx
);
5748 var
= build_fold_addr_expr (var
);
5749 gimplify_assign (x
, var
, ilist
);
5753 x
= build_sender_ref (ovar
, ctx
);
5754 gimplify_assign (x
, var
, ilist
);
5756 if (!TREE_READONLY (var
)
5757 /* We don't need to receive a new reference to a result
5758 or parm decl. In fact we may not store to it as we will
5759 invalidate any pending RSO and generate wrong gimple
5761 && !((TREE_CODE (var
) == RESULT_DECL
5762 || TREE_CODE (var
) == PARM_DECL
)
5763 && DECL_BY_REFERENCE (var
)))
5765 x
= build_sender_ref (ovar
, ctx
);
5766 gimplify_assign (var
, x
, olist
);
5773 /* A convenience function to build an empty GIMPLE_COND with just the
5777 gimple_build_cond_empty (tree cond
)
5779 enum tree_code pred_code
;
5782 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
5783 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
5786 static void expand_omp_build_assign (gimple_stmt_iterator
*, tree
, tree
,
5789 /* Build the function calls to GOMP_parallel_start etc to actually
5790 generate the parallel operation. REGION is the parallel region
5791 being expanded. BB is the block where to insert the code. WS_ARGS
5792 will be set if this is a call to a combined parallel+workshare
5793 construct, it contains the list of additional arguments needed by
5794 the workshare construct. */
5797 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
5798 gomp_parallel
*entry_stmt
,
5799 vec
<tree
, va_gc
> *ws_args
)
5801 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
5802 gimple_stmt_iterator gsi
;
5804 enum built_in_function start_ix
;
5806 location_t clause_loc
;
5807 vec
<tree
, va_gc
> *args
;
5809 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
5811 /* Determine what flavor of GOMP_parallel we will be
5813 start_ix
= BUILT_IN_GOMP_PARALLEL
;
5814 if (is_combined_parallel (region
))
5816 switch (region
->inner
->type
)
5818 case GIMPLE_OMP_FOR
:
5819 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
5820 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
5821 + (region
->inner
->sched_kind
5822 == OMP_CLAUSE_SCHEDULE_RUNTIME
5823 ? 3 : region
->inner
->sched_kind
));
5824 start_ix
= (enum built_in_function
)start_ix2
;
5826 case GIMPLE_OMP_SECTIONS
:
5827 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
5834 /* By default, the value of NUM_THREADS is zero (selected at run time)
5835 and there is no conditional. */
5837 val
= build_int_cst (unsigned_type_node
, 0);
5838 flags
= build_int_cst (unsigned_type_node
, 0);
5840 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
5842 cond
= OMP_CLAUSE_IF_EXPR (c
);
5844 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
5847 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
5848 clause_loc
= OMP_CLAUSE_LOCATION (c
);
5851 clause_loc
= gimple_location (entry_stmt
);
5853 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
5855 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
5857 /* Ensure 'val' is of the correct type. */
5858 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
5860 /* If we found the clause 'if (cond)', build either
5861 (cond != 0) or (cond ? val : 1u). */
5864 cond
= gimple_boolify (cond
);
5866 if (integer_zerop (val
))
5867 val
= fold_build2_loc (clause_loc
,
5868 EQ_EXPR
, unsigned_type_node
, cond
,
5869 build_int_cst (TREE_TYPE (cond
), 0));
5872 basic_block cond_bb
, then_bb
, else_bb
;
5873 edge e
, e_then
, e_else
;
5874 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
5876 tmp_var
= create_tmp_var (TREE_TYPE (val
));
5877 if (gimple_in_ssa_p (cfun
))
5879 tmp_then
= make_ssa_name (tmp_var
);
5880 tmp_else
= make_ssa_name (tmp_var
);
5881 tmp_join
= make_ssa_name (tmp_var
);
5890 e
= split_block_after_labels (bb
);
5895 then_bb
= create_empty_bb (cond_bb
);
5896 else_bb
= create_empty_bb (then_bb
);
5897 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
5898 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
5900 stmt
= gimple_build_cond_empty (cond
);
5901 gsi
= gsi_start_bb (cond_bb
);
5902 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5904 gsi
= gsi_start_bb (then_bb
);
5905 expand_omp_build_assign (&gsi
, tmp_then
, val
, true);
5907 gsi
= gsi_start_bb (else_bb
);
5908 expand_omp_build_assign (&gsi
, tmp_else
,
5909 build_int_cst (unsigned_type_node
, 1),
5912 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
5913 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
5914 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
5915 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
5916 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
5917 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
5919 if (gimple_in_ssa_p (cfun
))
5921 gphi
*phi
= create_phi_node (tmp_join
, bb
);
5922 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
5923 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
5929 gsi
= gsi_start_bb (bb
);
5930 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
5931 false, GSI_CONTINUE_LINKING
);
5934 gsi
= gsi_last_bb (bb
);
5935 t
= gimple_omp_parallel_data_arg (entry_stmt
);
5937 t1
= null_pointer_node
;
5939 t1
= build_fold_addr_expr (t
);
5940 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
5942 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
5943 args
->quick_push (t2
);
5944 args
->quick_push (t1
);
5945 args
->quick_push (val
);
5947 args
->splice (*ws_args
);
5948 args
->quick_push (flags
);
5950 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
5951 builtin_decl_explicit (start_ix
), args
);
5953 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5954 false, GSI_CONTINUE_LINKING
);
5957 /* Insert a function call whose name is FUNC_NAME with the information from
5958 ENTRY_STMT into the basic_block BB. */
5961 expand_cilk_for_call (basic_block bb
, gomp_parallel
*entry_stmt
,
5962 vec
<tree
, va_gc
> *ws_args
)
5965 gimple_stmt_iterator gsi
;
5966 vec
<tree
, va_gc
> *args
;
5968 gcc_assert (vec_safe_length (ws_args
) == 2);
5969 tree func_name
= (*ws_args
)[0];
5970 tree grain
= (*ws_args
)[1];
5972 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
5973 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
5974 gcc_assert (count
!= NULL_TREE
);
5975 count
= OMP_CLAUSE_OPERAND (count
, 0);
5977 gsi
= gsi_last_bb (bb
);
5978 t
= gimple_omp_parallel_data_arg (entry_stmt
);
5980 t1
= null_pointer_node
;
5982 t1
= build_fold_addr_expr (t
);
5983 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
5985 vec_alloc (args
, 4);
5986 args
->quick_push (t2
);
5987 args
->quick_push (t1
);
5988 args
->quick_push (count
);
5989 args
->quick_push (grain
);
5990 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
5992 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
5993 GSI_CONTINUE_LINKING
);
5996 /* Build the function call to GOMP_task to actually
5997 generate the task operation. BB is the block where to insert the code. */
6000 expand_task_call (struct omp_region
*region
, basic_block bb
,
6001 gomp_task
*entry_stmt
)
6004 gimple_stmt_iterator gsi
;
6005 location_t loc
= gimple_location (entry_stmt
);
6007 tree clauses
= gimple_omp_task_clauses (entry_stmt
);
6009 tree ifc
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
6010 tree untied
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
6011 tree mergeable
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
6012 tree depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
6013 tree finalc
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
6014 tree priority
= find_omp_clause (clauses
, OMP_CLAUSE_PRIORITY
);
6017 = (untied
? GOMP_TASK_FLAG_UNTIED
: 0)
6018 | (mergeable
? GOMP_TASK_FLAG_MERGEABLE
: 0)
6019 | (depend
? GOMP_TASK_FLAG_DEPEND
: 0);
6021 bool taskloop_p
= gimple_omp_task_taskloop_p (entry_stmt
);
6022 tree startvar
= NULL_TREE
, endvar
= NULL_TREE
, step
= NULL_TREE
;
6023 tree num_tasks
= NULL_TREE
;
6027 gimple
*g
= last_stmt (region
->outer
->entry
);
6028 gcc_assert (gimple_code (g
) == GIMPLE_OMP_FOR
6029 && gimple_omp_for_kind (g
) == GF_OMP_FOR_KIND_TASKLOOP
);
6030 struct omp_for_data fd
;
6031 extract_omp_for_data (as_a
<gomp_for
*> (g
), &fd
, NULL
);
6032 startvar
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6033 endvar
= find_omp_clause (OMP_CLAUSE_CHAIN (startvar
),
6034 OMP_CLAUSE__LOOPTEMP_
);
6035 startvar
= OMP_CLAUSE_DECL (startvar
);
6036 endvar
= OMP_CLAUSE_DECL (endvar
);
6037 step
= fold_convert_loc (loc
, fd
.iter_type
, fd
.loop
.step
);
6038 if (fd
.loop
.cond_code
== LT_EXPR
)
6039 iflags
|= GOMP_TASK_FLAG_UP
;
6040 tree tclauses
= gimple_omp_for_clauses (g
);
6041 num_tasks
= find_omp_clause (tclauses
, OMP_CLAUSE_NUM_TASKS
);
6043 num_tasks
= OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks
);
6046 num_tasks
= find_omp_clause (tclauses
, OMP_CLAUSE_GRAINSIZE
);
6049 iflags
|= GOMP_TASK_FLAG_GRAINSIZE
;
6050 num_tasks
= OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks
);
6053 num_tasks
= integer_zero_node
;
6055 num_tasks
= fold_convert_loc (loc
, long_integer_type_node
, num_tasks
);
6056 if (ifc
== NULL_TREE
)
6057 iflags
|= GOMP_TASK_FLAG_IF
;
6058 if (find_omp_clause (tclauses
, OMP_CLAUSE_NOGROUP
))
6059 iflags
|= GOMP_TASK_FLAG_NOGROUP
;
6060 ull
= fd
.iter_type
== long_long_unsigned_type_node
;
6063 iflags
|= GOMP_TASK_FLAG_PRIORITY
;
6065 tree flags
= build_int_cst (unsigned_type_node
, iflags
);
6067 tree cond
= boolean_true_node
;
6072 tree t
= gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc
));
6073 t
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, t
,
6074 build_int_cst (unsigned_type_node
,
6076 build_int_cst (unsigned_type_node
, 0));
6077 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
,
6081 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc
));
6086 tree t
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc
));
6087 t
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, t
,
6088 build_int_cst (unsigned_type_node
,
6089 GOMP_TASK_FLAG_FINAL
),
6090 build_int_cst (unsigned_type_node
, 0));
6091 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, t
);
6094 depend
= OMP_CLAUSE_DECL (depend
);
6096 depend
= build_int_cst (ptr_type_node
, 0);
6098 priority
= fold_convert (integer_type_node
,
6099 OMP_CLAUSE_PRIORITY_EXPR (priority
));
6101 priority
= integer_zero_node
;
6103 gsi
= gsi_last_bb (bb
);
6104 tree t
= gimple_omp_task_data_arg (entry_stmt
);
6106 t2
= null_pointer_node
;
6108 t2
= build_fold_addr_expr_loc (loc
, t
);
6109 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
6110 t
= gimple_omp_task_copy_fn (entry_stmt
);
6112 t3
= null_pointer_node
;
6114 t3
= build_fold_addr_expr_loc (loc
, t
);
6117 t
= build_call_expr (ull
6118 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL
)
6119 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP
),
6121 gimple_omp_task_arg_size (entry_stmt
),
6122 gimple_omp_task_arg_align (entry_stmt
), flags
,
6123 num_tasks
, priority
, startvar
, endvar
, step
);
6125 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
6127 gimple_omp_task_arg_size (entry_stmt
),
6128 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
6131 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6132 false, GSI_CONTINUE_LINKING
);
6136 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6137 catch handler and return it. This prevents programs from violating the
6138 structured block semantics with throws. */
6141 maybe_catch_exception (gimple_seq body
)
6146 if (!flag_exceptions
)
6149 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
6150 decl
= lang_hooks
.eh_protect_cleanup_actions ();
6152 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
6154 g
= gimple_build_eh_must_not_throw (decl
);
6155 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
6158 return gimple_seq_alloc_with_stmt (g
);
6161 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6164 vec2chain (vec
<tree
, va_gc
> *v
)
6166 tree chain
= NULL_TREE
, t
;
6169 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
6171 DECL_CHAIN (t
) = chain
;
6179 /* Remove barriers in REGION->EXIT's block. Note that this is only
6180 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6181 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6182 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6186 remove_exit_barrier (struct omp_region
*region
)
6188 gimple_stmt_iterator gsi
;
6189 basic_block exit_bb
;
6193 int any_addressable_vars
= -1;
6195 exit_bb
= region
->exit
;
6197 /* If the parallel region doesn't return, we don't have REGION->EXIT
6202 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6203 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6204 statements that can appear in between are extremely limited -- no
6205 memory operations at all. Here, we allow nothing at all, so the
6206 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6207 gsi
= gsi_last_bb (exit_bb
);
6208 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
6210 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
6213 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
6215 gsi
= gsi_last_bb (e
->src
);
6216 if (gsi_end_p (gsi
))
6218 stmt
= gsi_stmt (gsi
);
6219 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
6220 && !gimple_omp_return_nowait_p (stmt
))
6222 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6223 in many cases. If there could be tasks queued, the barrier
6224 might be needed to let the tasks run before some local
6225 variable of the parallel that the task uses as shared
6226 runs out of scope. The task can be spawned either
6227 from within current function (this would be easy to check)
6228 or from some function it calls and gets passed an address
6229 of such a variable. */
6230 if (any_addressable_vars
< 0)
6232 gomp_parallel
*parallel_stmt
6233 = as_a
<gomp_parallel
*> (last_stmt (region
->entry
));
6234 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
6235 tree local_decls
, block
, decl
;
6238 any_addressable_vars
= 0;
6239 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
6240 if (TREE_ADDRESSABLE (decl
))
6242 any_addressable_vars
= 1;
6245 for (block
= gimple_block (stmt
);
6246 !any_addressable_vars
6248 && TREE_CODE (block
) == BLOCK
;
6249 block
= BLOCK_SUPERCONTEXT (block
))
6251 for (local_decls
= BLOCK_VARS (block
);
6253 local_decls
= DECL_CHAIN (local_decls
))
6254 if (TREE_ADDRESSABLE (local_decls
))
6256 any_addressable_vars
= 1;
6259 if (block
== gimple_block (parallel_stmt
))
6263 if (!any_addressable_vars
)
6264 gimple_omp_return_set_nowait (stmt
);
6270 remove_exit_barriers (struct omp_region
*region
)
6272 if (region
->type
== GIMPLE_OMP_PARALLEL
)
6273 remove_exit_barrier (region
);
6277 region
= region
->inner
;
6278 remove_exit_barriers (region
);
6279 while (region
->next
)
6281 region
= region
->next
;
6282 remove_exit_barriers (region
);
6287 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6288 calls. These can't be declared as const functions, but
6289 within one parallel body they are constant, so they can be
6290 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6291 which are declared const. Similarly for task body, except
6292 that in untied task omp_get_thread_num () can change at any task
6293 scheduling point. */
6296 optimize_omp_library_calls (gimple
*entry_stmt
)
6299 gimple_stmt_iterator gsi
;
6300 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
6301 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
6302 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
6303 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
6304 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
6305 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
6306 OMP_CLAUSE_UNTIED
) != NULL
);
6308 FOR_EACH_BB_FN (bb
, cfun
)
6309 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
6311 gimple
*call
= gsi_stmt (gsi
);
6314 if (is_gimple_call (call
)
6315 && (decl
= gimple_call_fndecl (call
))
6316 && DECL_EXTERNAL (decl
)
6317 && TREE_PUBLIC (decl
)
6318 && DECL_INITIAL (decl
) == NULL
)
6322 if (DECL_NAME (decl
) == thr_num_id
)
6324 /* In #pragma omp task untied omp_get_thread_num () can change
6325 during the execution of the task region. */
6328 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
6330 else if (DECL_NAME (decl
) == num_thr_id
)
6331 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
6335 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
6336 || gimple_call_num_args (call
) != 0)
6339 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
6342 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
6343 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
6344 TREE_TYPE (TREE_TYPE (built_in
))))
6347 gimple_call_set_fndecl (call
, built_in
);
6352 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6356 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
6360 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6361 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
6364 if (TREE_CODE (t
) == ADDR_EXPR
)
6365 recompute_tree_invariant_for_addr_expr (t
);
6367 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
6371 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
6374 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
,
6377 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
6378 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
6379 !after
, after
? GSI_CONTINUE_LINKING
6381 gimple
*stmt
= gimple_build_assign (to
, from
);
6383 gsi_insert_after (gsi_p
, stmt
, GSI_CONTINUE_LINKING
);
6385 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
6386 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
6387 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
6389 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
6390 gimple_regimplify_operands (stmt
, &gsi
);
6394 /* Expand the OpenMP parallel or task directive starting at REGION. */
6397 expand_omp_taskreg (struct omp_region
*region
)
6399 basic_block entry_bb
, exit_bb
, new_bb
;
6400 struct function
*child_cfun
;
6401 tree child_fn
, block
, t
;
6402 gimple_stmt_iterator gsi
;
6403 gimple
*entry_stmt
, *stmt
;
6405 vec
<tree
, va_gc
> *ws_args
;
6407 entry_stmt
= last_stmt (region
->entry
);
6408 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
6409 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
6411 entry_bb
= region
->entry
;
6412 if (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
)
6413 exit_bb
= region
->cont
;
6415 exit_bb
= region
->exit
;
6419 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
6420 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
6421 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
6424 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
6425 and the inner statement contains the name of the built-in function
6427 ws_args
= region
->inner
->ws_args
;
6428 else if (is_combined_parallel (region
))
6429 ws_args
= region
->ws_args
;
6433 if (child_cfun
->cfg
)
6435 /* Due to inlining, it may happen that we have already outlined
6436 the region, in which case all we need to do is make the
6437 sub-graph unreachable and emit the parallel call. */
6438 edge entry_succ_e
, exit_succ_e
;
6440 entry_succ_e
= single_succ_edge (entry_bb
);
6442 gsi
= gsi_last_bb (entry_bb
);
6443 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
6444 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
6445 gsi_remove (&gsi
, true);
6450 exit_succ_e
= single_succ_edge (exit_bb
);
6451 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
6453 remove_edge_and_dominated_blocks (entry_succ_e
);
6457 unsigned srcidx
, dstidx
, num
;
6459 /* If the parallel region needs data sent from the parent
6460 function, then the very first statement (except possible
6461 tree profile counter updates) of the parallel body
6462 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
6463 &.OMP_DATA_O is passed as an argument to the child function,
6464 we need to replace it with the argument as seen by the child
6467 In most cases, this will end up being the identity assignment
6468 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
6469 a function call that has been inlined, the original PARM_DECL
6470 .OMP_DATA_I may have been converted into a different local
6471 variable. In which case, we need to keep the assignment. */
6472 if (gimple_omp_taskreg_data_arg (entry_stmt
))
6474 basic_block entry_succ_bb
6475 = single_succ_p (entry_bb
) ? single_succ (entry_bb
)
6476 : FALLTHRU_EDGE (entry_bb
)->dest
;
6478 gimple
*parcopy_stmt
= NULL
;
6480 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
6484 gcc_assert (!gsi_end_p (gsi
));
6485 stmt
= gsi_stmt (gsi
);
6486 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
6489 if (gimple_num_ops (stmt
) == 2)
6491 tree arg
= gimple_assign_rhs1 (stmt
);
6493 /* We're ignore the subcode because we're
6494 effectively doing a STRIP_NOPS. */
6496 if (TREE_CODE (arg
) == ADDR_EXPR
6497 && TREE_OPERAND (arg
, 0)
6498 == gimple_omp_taskreg_data_arg (entry_stmt
))
6500 parcopy_stmt
= stmt
;
6506 gcc_assert (parcopy_stmt
!= NULL
);
6507 arg
= DECL_ARGUMENTS (child_fn
);
6509 if (!gimple_in_ssa_p (cfun
))
6511 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
6512 gsi_remove (&gsi
, true);
6515 /* ?? Is setting the subcode really necessary ?? */
6516 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
6517 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
6522 tree lhs
= gimple_assign_lhs (parcopy_stmt
);
6523 gcc_assert (SSA_NAME_VAR (lhs
) == arg
);
6524 /* We'd like to set the rhs to the default def in the child_fn,
6525 but it's too early to create ssa names in the child_fn.
6526 Instead, we set the rhs to the parm. In
6527 move_sese_region_to_fn, we introduce a default def for the
6528 parm, map the parm to it's default def, and once we encounter
6529 this stmt, replace the parm with the default def. */
6530 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
6531 update_stmt (parcopy_stmt
);
6535 /* Declare local variables needed in CHILD_CFUN. */
6536 block
= DECL_INITIAL (child_fn
);
6537 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
6538 /* The gimplifier could record temporaries in parallel/task block
6539 rather than in containing function's local_decls chain,
6540 which would mean cgraph missed finalizing them. Do it now. */
6541 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
6542 if (TREE_CODE (t
) == VAR_DECL
6544 && !DECL_EXTERNAL (t
))
6545 varpool_node::finalize_decl (t
);
6546 DECL_SAVED_TREE (child_fn
) = NULL
;
6547 /* We'll create a CFG for child_fn, so no gimple body is needed. */
6548 gimple_set_body (child_fn
, NULL
);
6549 TREE_USED (block
) = 1;
6551 /* Reset DECL_CONTEXT on function arguments. */
6552 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
6553 DECL_CONTEXT (t
) = child_fn
;
6555 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
6556 so that it can be moved to the child function. */
6557 gsi
= gsi_last_bb (entry_bb
);
6558 stmt
= gsi_stmt (gsi
);
6559 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
6560 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
6561 e
= split_block (entry_bb
, stmt
);
6562 gsi_remove (&gsi
, true);
6565 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
6566 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6569 e2
= make_edge (e
->src
, BRANCH_EDGE (entry_bb
)->dest
, EDGE_ABNORMAL
);
6570 gcc_assert (e2
->dest
== region
->exit
);
6571 remove_edge (BRANCH_EDGE (entry_bb
));
6572 set_immediate_dominator (CDI_DOMINATORS
, e2
->dest
, e
->src
);
6573 gsi
= gsi_last_bb (region
->exit
);
6574 gcc_assert (!gsi_end_p (gsi
)
6575 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
6576 gsi_remove (&gsi
, true);
6579 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
6582 gsi
= gsi_last_bb (exit_bb
);
6583 gcc_assert (!gsi_end_p (gsi
)
6584 && (gimple_code (gsi_stmt (gsi
))
6585 == (e2
? GIMPLE_OMP_CONTINUE
: GIMPLE_OMP_RETURN
)));
6586 stmt
= gimple_build_return (NULL
);
6587 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
6588 gsi_remove (&gsi
, true);
6591 /* Move the parallel region into CHILD_CFUN. */
6593 if (gimple_in_ssa_p (cfun
))
6595 init_tree_ssa (child_cfun
);
6596 init_ssa_operands (child_cfun
);
6597 child_cfun
->gimple_df
->in_ssa_p
= true;
6601 block
= gimple_block (entry_stmt
);
6603 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
6605 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
6608 basic_block dest_bb
= e2
->dest
;
6610 make_edge (new_bb
, dest_bb
, EDGE_FALLTHRU
);
6612 set_immediate_dominator (CDI_DOMINATORS
, dest_bb
, new_bb
);
6614 /* When the OMP expansion process cannot guarantee an up-to-date
6615 loop tree arrange for the child function to fixup loops. */
6616 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
6617 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
6619 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
6620 num
= vec_safe_length (child_cfun
->local_decls
);
6621 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
6623 t
= (*child_cfun
->local_decls
)[srcidx
];
6624 if (DECL_CONTEXT (t
) == cfun
->decl
)
6626 if (srcidx
!= dstidx
)
6627 (*child_cfun
->local_decls
)[dstidx
] = t
;
6631 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
6633 /* Inform the callgraph about the new function. */
6634 child_cfun
->curr_properties
= cfun
->curr_properties
;
6635 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
6636 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
6637 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
6638 node
->parallelized_function
= 1;
6639 cgraph_node::add_new_function (child_fn
, true);
6641 /* Fix the callgraph edges for child_cfun. Those for cfun will be
6642 fixed in a following pass. */
6643 push_cfun (child_cfun
);
6645 optimize_omp_library_calls (entry_stmt
);
6646 cgraph_edge::rebuild_edges ();
6648 /* Some EH regions might become dead, see PR34608. If
6649 pass_cleanup_cfg isn't the first pass to happen with the
6650 new child, these dead EH edges might cause problems.
6651 Clean them up now. */
6652 if (flag_exceptions
)
6655 bool changed
= false;
6657 FOR_EACH_BB_FN (bb
, cfun
)
6658 changed
|= gimple_purge_dead_eh_edges (bb
);
6660 cleanup_tree_cfg ();
6662 if (gimple_in_ssa_p (cfun
))
6663 update_ssa (TODO_update_ssa
);
6664 #ifdef ENABLE_CHECKING
6665 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
6666 verify_loop_structure ();
6671 /* Emit a library call to launch the children threads. */
6673 expand_cilk_for_call (new_bb
,
6674 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
6675 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
6676 expand_parallel_call (region
, new_bb
,
6677 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
6679 expand_task_call (region
, new_bb
, as_a
<gomp_task
*> (entry_stmt
));
6680 if (gimple_in_ssa_p (cfun
))
6681 update_ssa (TODO_update_ssa_only_virtuals
);
6685 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
6686 of the combined collapse > 1 loop constructs, generate code like:
6687 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
6692 count3 = (adj + N32 - N31) / STEP3;
6693 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
6698 count2 = (adj + N22 - N21) / STEP2;
6699 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
6704 count1 = (adj + N12 - N11) / STEP1;
6705 count = count1 * count2 * count3;
6706 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
6708 and set ZERO_ITER_BB to that bb. If this isn't the outermost
6709 of the combined loop constructs, just initialize COUNTS array
6710 from the _looptemp_ clauses. */
6712 /* NOTE: It *could* be better to moosh all of the BBs together,
6713 creating one larger BB with all the computation and the unexpected
6714 jump at the end. I.e.
6716 bool zero3, zero2, zero1, zero;
6719 count3 = (N32 - N31) /[cl] STEP3;
6721 count2 = (N22 - N21) /[cl] STEP2;
6723 count1 = (N12 - N11) /[cl] STEP1;
6724 zero = zero3 || zero2 || zero1;
6725 count = count1 * count2 * count3;
6726 if (__builtin_expect(zero, false)) goto zero_iter_bb;
6728 After all, we expect the zero=false, and thus we expect to have to
6729 evaluate all of the comparison expressions, so short-circuiting
6730 oughtn't be a win. Since the condition isn't protecting a
6731 denominator, we're not concerned about divide-by-zero, so we can
6732 fully evaluate count even if a numerator turned out to be wrong.
6734 It seems like putting this all together would create much better
6735 scheduling opportunities, and less pressure on the chip's branch
6739 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
6740 basic_block
&entry_bb
, tree
*counts
,
6741 basic_block
&zero_iter1_bb
, int &first_zero_iter1
,
6742 basic_block
&zero_iter2_bb
, int &first_zero_iter2
,
6743 basic_block
&l2_dom_bb
)
6745 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
6749 /* Collapsed loops need work for expansion into SSA form. */
6750 gcc_assert (!gimple_in_ssa_p (cfun
));
6752 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
6753 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
6755 gcc_assert (fd
->ordered
== 0);
6756 /* First two _looptemp_ clauses are for istart/iend, counts[0]
6757 isn't supposed to be handled, as the inner loop doesn't
6759 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6760 OMP_CLAUSE__LOOPTEMP_
);
6761 gcc_assert (innerc
);
6762 for (i
= 0; i
< fd
->collapse
; i
++)
6764 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6765 OMP_CLAUSE__LOOPTEMP_
);
6766 gcc_assert (innerc
);
6768 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
6770 counts
[0] = NULL_TREE
;
6775 for (i
= fd
->collapse
; i
< fd
->ordered
; i
++)
6777 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
6778 counts
[i
] = NULL_TREE
;
6779 t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
6780 fold_convert (itype
, fd
->loops
[i
].n1
),
6781 fold_convert (itype
, fd
->loops
[i
].n2
));
6782 if (t
&& integer_zerop (t
))
6784 for (i
= fd
->collapse
; i
< fd
->ordered
; i
++)
6785 counts
[i
] = build_int_cst (type
, 0);
6789 for (i
= 0; i
< (fd
->ordered
? fd
->ordered
: fd
->collapse
); i
++)
6791 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
6793 if (i
>= fd
->collapse
&& counts
[i
])
6795 if ((SSA_VAR_P (fd
->loop
.n2
) || i
>= fd
->collapse
)
6796 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
6797 fold_convert (itype
, fd
->loops
[i
].n1
),
6798 fold_convert (itype
, fd
->loops
[i
].n2
)))
6799 == NULL_TREE
|| !integer_onep (t
)))
6803 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
6804 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
6805 true, GSI_SAME_STMT
);
6806 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
6807 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
6808 true, GSI_SAME_STMT
);
6809 cond_stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
6810 NULL_TREE
, NULL_TREE
);
6811 gsi_insert_before (gsi
, cond_stmt
, GSI_SAME_STMT
);
6812 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6813 expand_omp_regimplify_p
, NULL
, NULL
)
6814 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6815 expand_omp_regimplify_p
, NULL
, NULL
))
6817 *gsi
= gsi_for_stmt (cond_stmt
);
6818 gimple_regimplify_operands (cond_stmt
, gsi
);
6820 e
= split_block (entry_bb
, cond_stmt
);
6821 basic_block
&zero_iter_bb
6822 = i
< fd
->collapse
? zero_iter1_bb
: zero_iter2_bb
;
6823 int &first_zero_iter
6824 = i
< fd
->collapse
? first_zero_iter1
: first_zero_iter2
;
6825 if (zero_iter_bb
== NULL
)
6827 gassign
*assign_stmt
;
6828 first_zero_iter
= i
;
6829 zero_iter_bb
= create_empty_bb (entry_bb
);
6830 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
6831 *gsi
= gsi_after_labels (zero_iter_bb
);
6832 if (i
< fd
->collapse
)
6833 assign_stmt
= gimple_build_assign (fd
->loop
.n2
,
6834 build_zero_cst (type
));
6837 counts
[i
] = create_tmp_reg (type
, ".count");
6839 = gimple_build_assign (counts
[i
], build_zero_cst (type
));
6841 gsi_insert_before (gsi
, assign_stmt
, GSI_SAME_STMT
);
6842 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
6845 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
6846 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6847 e
->flags
= EDGE_TRUE_VALUE
;
6848 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
6849 if (l2_dom_bb
== NULL
)
6850 l2_dom_bb
= entry_bb
;
6852 *gsi
= gsi_last_bb (entry_bb
);
6855 if (POINTER_TYPE_P (itype
))
6856 itype
= signed_type_for (itype
);
6857 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
6859 t
= fold_build2 (PLUS_EXPR
, itype
,
6860 fold_convert (itype
, fd
->loops
[i
].step
), t
);
6861 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
6862 fold_convert (itype
, fd
->loops
[i
].n2
));
6863 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
6864 fold_convert (itype
, fd
->loops
[i
].n1
));
6865 /* ?? We could probably use CEIL_DIV_EXPR instead of
6866 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
6867 generate the same code in the end because generically we
6868 don't know that the values involved must be negative for
6870 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
6871 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6872 fold_build1 (NEGATE_EXPR
, itype
, t
),
6873 fold_build1 (NEGATE_EXPR
, itype
,
6874 fold_convert (itype
,
6875 fd
->loops
[i
].step
)));
6877 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
6878 fold_convert (itype
, fd
->loops
[i
].step
));
6879 t
= fold_convert (type
, t
);
6880 if (TREE_CODE (t
) == INTEGER_CST
)
6884 if (i
< fd
->collapse
|| i
!= first_zero_iter2
)
6885 counts
[i
] = create_tmp_reg (type
, ".count");
6886 expand_omp_build_assign (gsi
, counts
[i
], t
);
6888 if (SSA_VAR_P (fd
->loop
.n2
) && i
< fd
->collapse
)
6893 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
6894 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
6900 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
6902 V3 = N31 + (T % count3) * STEP3;
6904 V2 = N21 + (T % count2) * STEP2;
6906 V1 = N11 + T * STEP1;
6907 if this loop doesn't have an inner loop construct combined with it.
6908 If it does have an inner loop construct combined with it and the
6909 iteration count isn't known constant, store values from counts array
6910 into its _looptemp_ temporaries instead. */
6913 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
6914 tree
*counts
, gimple
*inner_stmt
, tree startvar
)
6917 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6919 /* If fd->loop.n2 is constant, then no propagation of the counts
6920 is needed, they are constant. */
6921 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
6924 tree clauses
= gimple_code (inner_stmt
) != GIMPLE_OMP_FOR
6925 ? gimple_omp_taskreg_clauses (inner_stmt
)
6926 : gimple_omp_for_clauses (inner_stmt
);
6927 /* First two _looptemp_ clauses are for istart/iend, counts[0]
6928 isn't supposed to be handled, as the inner loop doesn't
6930 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6931 gcc_assert (innerc
);
6932 for (i
= 0; i
< fd
->collapse
; i
++)
6934 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6935 OMP_CLAUSE__LOOPTEMP_
);
6936 gcc_assert (innerc
);
6939 tree tem
= OMP_CLAUSE_DECL (innerc
);
6940 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
6941 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
6942 false, GSI_CONTINUE_LINKING
);
6943 gassign
*stmt
= gimple_build_assign (tem
, t
);
6944 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
6950 tree type
= TREE_TYPE (fd
->loop
.v
);
6951 tree tem
= create_tmp_reg (type
, ".tem");
6952 gassign
*stmt
= gimple_build_assign (tem
, startvar
);
6953 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
6955 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
6957 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
6959 if (POINTER_TYPE_P (vtype
))
6960 itype
= signed_type_for (vtype
);
6962 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
6965 t
= fold_convert (itype
, t
);
6966 t
= fold_build2 (MULT_EXPR
, itype
, t
,
6967 fold_convert (itype
, fd
->loops
[i
].step
));
6968 if (POINTER_TYPE_P (vtype
))
6969 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
6971 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
6972 t
= force_gimple_operand_gsi (gsi
, t
,
6973 DECL_P (fd
->loops
[i
].v
)
6974 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
6976 GSI_CONTINUE_LINKING
);
6977 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
6978 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
6981 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
6982 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
6983 false, GSI_CONTINUE_LINKING
);
6984 stmt
= gimple_build_assign (tem
, t
);
6985 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
6991 /* Helper function for expand_omp_for_*. Generate code like:
6994 if (V3 cond3 N32) goto BODY_BB; else goto L11;
6998 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7005 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
7006 basic_block body_bb
)
7008 basic_block last_bb
, bb
, collapse_bb
= NULL
;
7010 gimple_stmt_iterator gsi
;
7016 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
7018 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
7020 bb
= create_empty_bb (last_bb
);
7021 add_bb_to_loop (bb
, last_bb
->loop_father
);
7022 gsi
= gsi_start_bb (bb
);
7024 if (i
< fd
->collapse
- 1)
7026 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
7027 e
->probability
= REG_BR_PROB_BASE
/ 8;
7029 t
= fd
->loops
[i
+ 1].n1
;
7030 t
= force_gimple_operand_gsi (&gsi
, t
,
7031 DECL_P (fd
->loops
[i
+ 1].v
)
7032 && TREE_ADDRESSABLE (fd
->loops
[i
7035 GSI_CONTINUE_LINKING
);
7036 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
7037 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7042 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
7044 if (POINTER_TYPE_P (vtype
))
7045 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
7047 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
7048 t
= force_gimple_operand_gsi (&gsi
, t
,
7049 DECL_P (fd
->loops
[i
].v
)
7050 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
7051 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
7052 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
7053 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7057 t
= fd
->loops
[i
].n2
;
7058 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7059 false, GSI_CONTINUE_LINKING
);
7060 tree v
= fd
->loops
[i
].v
;
7061 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
7062 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
7063 false, GSI_CONTINUE_LINKING
);
7064 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
7065 stmt
= gimple_build_cond_empty (t
);
7066 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7067 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
7068 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7071 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
7079 /* Expand #pragma omp ordered depend(source). */
7082 expand_omp_ordered_source (gimple_stmt_iterator
*gsi
, struct omp_for_data
*fd
,
7083 tree
*counts
, location_t loc
)
7085 enum built_in_function source_ix
7086 = fd
->iter_type
== long_integer_type_node
7087 ? BUILT_IN_GOMP_DOACROSS_POST
: BUILT_IN_GOMP_DOACROSS_ULL_POST
;
7089 = gimple_build_call (builtin_decl_explicit (source_ix
), 1,
7090 build_fold_addr_expr (counts
[fd
->ordered
]));
7091 gimple_set_location (g
, loc
);
7092 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
7095 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7098 expand_omp_ordered_sink (gimple_stmt_iterator
*gsi
, struct omp_for_data
*fd
,
7099 tree
*counts
, tree c
, location_t loc
)
7101 auto_vec
<tree
, 10> args
;
7102 enum built_in_function sink_ix
7103 = fd
->iter_type
== long_integer_type_node
7104 ? BUILT_IN_GOMP_DOACROSS_WAIT
: BUILT_IN_GOMP_DOACROSS_ULL_WAIT
;
7105 tree t
, off
, coff
= NULL_TREE
, deps
= OMP_CLAUSE_DECL (c
), cond
= NULL_TREE
;
7107 gimple_stmt_iterator gsi2
= *gsi
;
7108 bool warned_step
= false;
7110 for (i
= 0; i
< fd
->ordered
; i
++)
7112 off
= TREE_PURPOSE (deps
);
7113 if (!integer_zerop (off
))
7115 gcc_assert (fd
->loops
[i
].cond_code
== LT_EXPR
7116 || fd
->loops
[i
].cond_code
== GT_EXPR
);
7117 bool forward
= fd
->loops
[i
].cond_code
== LT_EXPR
;
7118 if (forward
^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
7119 warning_at (loc
, 0, "%<depend(sink)%> clause waiting for "
7120 "lexically later iteration");
7123 deps
= TREE_CHAIN (deps
);
7125 /* If all offsets corresponding to the collapsed loops are zero,
7126 this depend clause can be ignored. FIXME: but there is still a
7127 flush needed. We need to emit one __sync_synchronize () for it
7128 though (perhaps conditionally)? Solve this together with the
7129 conservative dependence folding optimization.
7130 if (i >= fd->collapse)
7133 deps
= OMP_CLAUSE_DECL (c
);
7135 edge e1
= split_block (gsi_bb (gsi2
), gsi_stmt (gsi2
));
7136 edge e2
= split_block_after_labels (e1
->dest
);
7138 *gsi
= gsi_after_labels (e1
->dest
);
7139 for (i
= 0; i
< fd
->ordered
; i
++)
7141 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7142 if (POINTER_TYPE_P (itype
))
7145 deps
= TREE_CHAIN (deps
);
7146 off
= TREE_PURPOSE (deps
);
7147 tree s
= fold_convert_loc (loc
, itype
, fd
->loops
[i
].step
);
7149 if (integer_zerop (off
))
7150 t
= boolean_true_node
;
7154 tree co
= fold_convert_loc (loc
, itype
, off
);
7155 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7157 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
7158 co
= fold_build1_loc (loc
, NEGATE_EXPR
, itype
, co
);
7159 a
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
7160 TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].v
,
7163 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
7164 a
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7165 fd
->loops
[i
].v
, co
);
7167 a
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7168 fd
->loops
[i
].v
, co
);
7169 if (fd
->loops
[i
].cond_code
== LT_EXPR
)
7171 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
7172 t
= fold_build2_loc (loc
, GE_EXPR
, boolean_type_node
, a
,
7175 t
= fold_build2_loc (loc
, LT_EXPR
, boolean_type_node
, a
,
7178 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
7179 t
= fold_build2_loc (loc
, GT_EXPR
, boolean_type_node
, a
,
7182 t
= fold_build2_loc (loc
, LE_EXPR
, boolean_type_node
, a
,
7186 cond
= fold_build2_loc (loc
, BIT_AND_EXPR
, boolean_type_node
, cond
, t
);
7190 off
= fold_convert_loc (loc
, itype
, off
);
7192 if (fd
->loops
[i
].cond_code
== LT_EXPR
7193 ? !integer_onep (fd
->loops
[i
].step
)
7194 : !integer_minus_onep (fd
->loops
[i
].step
))
7196 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
7197 t
= fold_build2_loc (loc
, TRUNC_MOD_EXPR
, itype
, off
,
7198 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
7201 t
= fold_build2_loc (loc
, TRUNC_MOD_EXPR
, itype
, off
, s
);
7202 t
= fold_build2_loc (loc
, EQ_EXPR
, boolean_type_node
, t
,
7203 build_int_cst (itype
, 0));
7204 if (integer_zerop (t
) && !warned_step
)
7206 warning_at (loc
, 0, "%<depend(sink)%> refers to iteration never "
7207 "in the iteration space");
7210 cond
= fold_build2_loc (loc
, BIT_AND_EXPR
, boolean_type_node
,
7214 if (i
<= fd
->collapse
- 1 && fd
->collapse
> 1)
7220 t
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7221 fd
->loops
[i
].v
, fd
->loops
[i
].n1
);
7222 t
= fold_convert_loc (loc
, fd
->iter_type
, t
);
7224 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
7225 off
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, off
,
7226 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
7229 off
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, off
, s
);
7230 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
7231 off
= fold_build1_loc (loc
, NEGATE_EXPR
, itype
, off
);
7232 off
= fold_convert_loc (loc
, fd
->iter_type
, off
);
7233 if (i
<= fd
->collapse
- 1 && fd
->collapse
> 1)
7236 off
= fold_build2_loc (loc
, PLUS_EXPR
, fd
->iter_type
, coff
,
7238 if (i
< fd
->collapse
- 1)
7240 coff
= fold_build2_loc (loc
, MULT_EXPR
, fd
->iter_type
, off
,
7245 off
= unshare_expr (off
);
7246 t
= fold_build2_loc (loc
, PLUS_EXPR
, fd
->iter_type
, t
, off
);
7247 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
,
7248 true, GSI_SAME_STMT
);
7251 gimple
*g
= gimple_build_call_vec (builtin_decl_explicit (sink_ix
), args
);
7252 gimple_set_location (g
, loc
);
7253 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
7255 *gsi
= gsi_last_bb (e1
->src
);
7256 cond
= unshare_expr (cond
);
7257 cond
= force_gimple_operand_gsi (gsi
, cond
, true, NULL_TREE
, false,
7258 GSI_CONTINUE_LINKING
);
7259 gsi_insert_after (gsi
, gimple_build_cond_empty (cond
), GSI_NEW_STMT
);
7260 edge e3
= make_edge (e1
->src
, e2
->dest
, EDGE_FALSE_VALUE
);
7261 e3
->probability
= REG_BR_PROB_BASE
/ 8;
7262 e1
->probability
= REG_BR_PROB_BASE
- e3
->probability
;
7263 e1
->flags
= EDGE_TRUE_VALUE
;
7264 set_immediate_dominator (CDI_DOMINATORS
, e2
->dest
, e1
->src
);
7266 *gsi
= gsi_after_labels (e2
->dest
);
7269 /* Expand all #pragma omp ordered depend(source) and
7270 #pragma omp ordered depend(sink:...) constructs in the current
7271 #pragma omp for ordered(n) region. */
7274 expand_omp_ordered_source_sink (struct omp_region
*region
,
7275 struct omp_for_data
*fd
, tree
*counts
,
7276 basic_block cont_bb
)
7278 struct omp_region
*inner
;
7280 for (i
= fd
->collapse
- 1; i
< fd
->ordered
; i
++)
7281 if (i
== fd
->collapse
- 1 && fd
->collapse
> 1)
7282 counts
[i
] = NULL_TREE
;
7283 else if (i
>= fd
->collapse
&& !cont_bb
)
7284 counts
[i
] = build_zero_cst (fd
->iter_type
);
7285 else if (!POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
))
7286 && integer_onep (fd
->loops
[i
].step
))
7287 counts
[i
] = NULL_TREE
;
7289 counts
[i
] = create_tmp_var (fd
->iter_type
, ".orditer");
7291 = build_array_type_nelts (fd
->iter_type
, fd
->ordered
- fd
->collapse
+ 1);
7292 counts
[fd
->ordered
] = create_tmp_var (atype
, ".orditera");
7293 TREE_ADDRESSABLE (counts
[fd
->ordered
]) = 1;
7295 for (inner
= region
->inner
; inner
; inner
= inner
->next
)
7296 if (inner
->type
== GIMPLE_OMP_ORDERED
)
7298 gomp_ordered
*ord_stmt
= inner
->ord_stmt
;
7299 gimple_stmt_iterator gsi
= gsi_for_stmt (ord_stmt
);
7300 location_t loc
= gimple_location (ord_stmt
);
7302 for (c
= gimple_omp_ordered_clauses (ord_stmt
);
7303 c
; c
= OMP_CLAUSE_CHAIN (c
))
7304 if (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SOURCE
)
7307 expand_omp_ordered_source (&gsi
, fd
, counts
, loc
);
7308 for (c
= gimple_omp_ordered_clauses (ord_stmt
);
7309 c
; c
= OMP_CLAUSE_CHAIN (c
))
7310 if (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
)
7311 expand_omp_ordered_sink (&gsi
, fd
, counts
, c
, loc
);
7312 gsi_remove (&gsi
, true);
7316 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
7320 expand_omp_for_ordered_loops (struct omp_for_data
*fd
, tree
*counts
,
7321 basic_block cont_bb
, basic_block body_bb
,
7322 bool ordered_lastprivate
)
7324 if (fd
->ordered
== fd
->collapse
)
7329 gimple_stmt_iterator gsi
= gsi_after_labels (body_bb
);
7330 for (int i
= fd
->collapse
; i
< fd
->ordered
; i
++)
7332 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
7333 tree n1
= fold_convert (type
, fd
->loops
[i
].n1
);
7334 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, n1
);
7335 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
7336 size_int (i
- fd
->collapse
+ 1),
7337 NULL_TREE
, NULL_TREE
);
7338 expand_omp_build_assign (&gsi
, aref
, build_zero_cst (fd
->iter_type
));
7343 for (int i
= fd
->ordered
- 1; i
>= fd
->collapse
; i
--)
7345 tree t
, type
= TREE_TYPE (fd
->loops
[i
].v
);
7346 gimple_stmt_iterator gsi
= gsi_after_labels (body_bb
);
7347 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
,
7348 fold_convert (type
, fd
->loops
[i
].n1
));
7350 expand_omp_build_assign (&gsi
, counts
[i
],
7351 build_zero_cst (fd
->iter_type
));
7352 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
7353 size_int (i
- fd
->collapse
+ 1),
7354 NULL_TREE
, NULL_TREE
);
7355 expand_omp_build_assign (&gsi
, aref
, build_zero_cst (fd
->iter_type
));
7356 if (!gsi_end_p (gsi
))
7359 gsi
= gsi_last_bb (body_bb
);
7360 edge e1
= split_block (body_bb
, gsi_stmt (gsi
));
7361 basic_block new_body
= e1
->dest
;
7362 if (body_bb
== cont_bb
)
7365 basic_block new_header
;
7366 if (EDGE_COUNT (cont_bb
->preds
) > 0)
7368 gsi
= gsi_last_bb (cont_bb
);
7369 if (POINTER_TYPE_P (type
))
7370 t
= fold_build_pointer_plus (fd
->loops
[i
].v
,
7371 fold_convert (sizetype
,
7372 fd
->loops
[i
].step
));
7374 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loops
[i
].v
,
7375 fold_convert (type
, fd
->loops
[i
].step
));
7376 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7379 t
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, counts
[i
],
7380 build_int_cst (fd
->iter_type
, 1));
7381 expand_omp_build_assign (&gsi
, counts
[i
], t
);
7386 t
= fold_build2 (MINUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7387 fd
->loops
[i
].v
, fd
->loops
[i
].n1
);
7388 t
= fold_convert (fd
->iter_type
, t
);
7389 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7390 true, GSI_SAME_STMT
);
7392 aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
7393 size_int (i
- fd
->collapse
+ 1),
7394 NULL_TREE
, NULL_TREE
);
7395 expand_omp_build_assign (&gsi
, aref
, t
);
7397 e2
= split_block (cont_bb
, gsi_stmt (gsi
));
7398 new_header
= e2
->dest
;
7401 new_header
= cont_bb
;
7402 gsi
= gsi_after_labels (new_header
);
7403 tree v
= force_gimple_operand_gsi (&gsi
, fd
->loops
[i
].v
, true, NULL_TREE
,
7404 true, GSI_SAME_STMT
);
7406 = force_gimple_operand_gsi (&gsi
, fold_convert (type
, fd
->loops
[i
].n2
),
7407 true, NULL_TREE
, true, GSI_SAME_STMT
);
7408 t
= build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, n2
);
7409 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_NEW_STMT
);
7410 edge e3
= split_block (new_header
, gsi_stmt (gsi
));
7413 make_edge (body_bb
, new_header
, EDGE_FALLTHRU
);
7414 e3
->flags
= EDGE_FALSE_VALUE
;
7415 e3
->probability
= REG_BR_PROB_BASE
/ 8;
7416 e1
= make_edge (new_header
, new_body
, EDGE_TRUE_VALUE
);
7417 e1
->probability
= REG_BR_PROB_BASE
- e3
->probability
;
7419 set_immediate_dominator (CDI_DOMINATORS
, new_header
, body_bb
);
7420 set_immediate_dominator (CDI_DOMINATORS
, new_body
, new_header
);
7424 struct loop
*loop
= alloc_loop ();
7425 loop
->header
= new_header
;
7426 loop
->latch
= e2
->src
;
7427 add_loop (loop
, body_bb
->loop_father
);
7431 /* If there are any lastprivate clauses and it is possible some loops
7432 might have zero iterations, ensure all the decls are initialized,
7433 otherwise we could crash evaluating C++ class iterators with lastprivate
7435 bool need_inits
= false;
7436 for (int i
= fd
->collapse
; ordered_lastprivate
&& i
< fd
->ordered
; i
++)
7439 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
7440 gimple_stmt_iterator gsi
= gsi_after_labels (body_bb
);
7441 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
,
7442 fold_convert (type
, fd
->loops
[i
].n1
));
7446 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
7447 tree this_cond
= fold_build2 (fd
->loops
[i
].cond_code
,
7449 fold_convert (type
, fd
->loops
[i
].n1
),
7450 fold_convert (type
, fd
->loops
[i
].n2
));
7451 if (!integer_onep (this_cond
))
7459 /* A subroutine of expand_omp_for. Generate code for a parallel
7460 loop with any schedule. Given parameters:
7462 for (V = N1; V cond N2; V += STEP) BODY;
7464 where COND is "<" or ">", we generate pseudocode
7466 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
7467 if (more) goto L0; else goto L3;
7474 if (V cond iend) goto L1; else goto L2;
7476 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7479 If this is a combined omp parallel loop, instead of the call to
7480 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
7481 If this is gimple_omp_for_combined_p loop, then instead of assigning
7482 V and iend in L0 we assign the first two _looptemp_ clause decls of the
7483 inner GIMPLE_OMP_FOR and V += STEP; and
7484 if (V cond iend) goto L1; else goto L2; are removed.
7486 For collapsed loops, given parameters:
7488 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7489 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7490 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7493 we generate pseudocode
7495 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
7500 count3 = (adj + N32 - N31) / STEP3;
7501 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
7506 count2 = (adj + N22 - N21) / STEP2;
7507 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
7512 count1 = (adj + N12 - N11) / STEP1;
7513 count = count1 * count2 * count3;
7518 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
7519 if (more) goto L0; else goto L3;
7523 V3 = N31 + (T % count3) * STEP3;
7525 V2 = N21 + (T % count2) * STEP2;
7527 V1 = N11 + T * STEP1;
7532 if (V < iend) goto L10; else goto L2;
7535 if (V3 cond3 N32) goto L1; else goto L11;
7539 if (V2 cond2 N22) goto L1; else goto L12;
7545 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7551 expand_omp_for_generic (struct omp_region
*region
,
7552 struct omp_for_data
*fd
,
7553 enum built_in_function start_fn
,
7554 enum built_in_function next_fn
,
7557 tree type
, istart0
, iend0
, iend
;
7558 tree t
, vmain
, vback
, bias
= NULL_TREE
;
7559 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
7560 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
7561 gimple_stmt_iterator gsi
;
7562 gassign
*assign_stmt
;
7563 bool in_combined_parallel
= is_combined_parallel (region
);
7564 bool broken_loop
= region
->cont
== NULL
;
7566 tree
*counts
= NULL
;
7568 bool ordered_lastprivate
= false;
7570 gcc_assert (!broken_loop
|| !in_combined_parallel
);
7571 gcc_assert (fd
->iter_type
== long_integer_type_node
7572 || !in_combined_parallel
);
7574 entry_bb
= region
->entry
;
7575 cont_bb
= region
->cont
;
7577 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7578 gcc_assert (broken_loop
7579 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7580 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
7581 l1_bb
= single_succ (l0_bb
);
7584 l2_bb
= create_empty_bb (cont_bb
);
7585 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
7586 || (single_succ_edge (BRANCH_EDGE (cont_bb
)->dest
)->dest
7588 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7592 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7593 exit_bb
= region
->exit
;
7595 gsi
= gsi_last_bb (entry_bb
);
7597 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7599 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi
)),
7600 OMP_CLAUSE_LASTPRIVATE
))
7601 ordered_lastprivate
= false;
7602 if (fd
->collapse
> 1 || fd
->ordered
)
7604 int first_zero_iter1
= -1, first_zero_iter2
= -1;
7605 basic_block zero_iter1_bb
= NULL
, zero_iter2_bb
= NULL
, l2_dom_bb
= NULL
;
7607 counts
= XALLOCAVEC (tree
, fd
->ordered
? fd
->ordered
+ 1 : fd
->collapse
);
7608 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7609 zero_iter1_bb
, first_zero_iter1
,
7610 zero_iter2_bb
, first_zero_iter2
, l2_dom_bb
);
7614 /* Some counts[i] vars might be uninitialized if
7615 some loop has zero iterations. But the body shouldn't
7616 be executed in that case, so just avoid uninit warnings. */
7617 for (i
= first_zero_iter1
;
7618 i
< (fd
->ordered
? fd
->ordered
: fd
->collapse
); i
++)
7619 if (SSA_VAR_P (counts
[i
]))
7620 TREE_NO_WARNING (counts
[i
]) = 1;
7622 e
= split_block (entry_bb
, gsi_stmt (gsi
));
7624 make_edge (zero_iter1_bb
, entry_bb
, EDGE_FALLTHRU
);
7625 gsi
= gsi_last_bb (entry_bb
);
7626 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
7627 get_immediate_dominator (CDI_DOMINATORS
,
7632 /* Some counts[i] vars might be uninitialized if
7633 some loop has zero iterations. But the body shouldn't
7634 be executed in that case, so just avoid uninit warnings. */
7635 for (i
= first_zero_iter2
; i
< fd
->ordered
; i
++)
7636 if (SSA_VAR_P (counts
[i
]))
7637 TREE_NO_WARNING (counts
[i
]) = 1;
7639 make_edge (zero_iter2_bb
, entry_bb
, EDGE_FALLTHRU
);
7643 e
= split_block (entry_bb
, gsi_stmt (gsi
));
7645 make_edge (zero_iter2_bb
, entry_bb
, EDGE_FALLTHRU
);
7646 gsi
= gsi_last_bb (entry_bb
);
7647 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
7648 get_immediate_dominator
7649 (CDI_DOMINATORS
, zero_iter2_bb
));
7652 if (fd
->collapse
== 1)
7654 counts
[0] = fd
->loop
.n2
;
7655 fd
->loop
= fd
->loops
[0];
7659 type
= TREE_TYPE (fd
->loop
.v
);
7660 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
7661 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
7662 TREE_ADDRESSABLE (istart0
) = 1;
7663 TREE_ADDRESSABLE (iend0
) = 1;
7665 /* See if we need to bias by LLONG_MIN. */
7666 if (fd
->iter_type
== long_long_unsigned_type_node
7667 && TREE_CODE (type
) == INTEGER_TYPE
7668 && !TYPE_UNSIGNED (type
)
7669 && fd
->ordered
== 0)
7673 if (fd
->loop
.cond_code
== LT_EXPR
)
7676 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
7680 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
7683 if (TREE_CODE (n1
) != INTEGER_CST
7684 || TREE_CODE (n2
) != INTEGER_CST
7685 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
7686 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
7689 gimple_stmt_iterator gsif
= gsi
;
7692 tree arr
= NULL_TREE
;
7693 if (in_combined_parallel
)
7695 gcc_assert (fd
->ordered
== 0);
7696 /* In a combined parallel loop, emit a call to
7697 GOMP_loop_foo_next. */
7698 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
7699 build_fold_addr_expr (istart0
),
7700 build_fold_addr_expr (iend0
));
7704 tree t0
, t1
, t2
, t3
, t4
;
7705 /* If this is not a combined parallel loop, emit a call to
7706 GOMP_loop_foo_start in ENTRY_BB. */
7707 t4
= build_fold_addr_expr (iend0
);
7708 t3
= build_fold_addr_expr (istart0
);
7711 t0
= build_int_cst (unsigned_type_node
,
7712 fd
->ordered
- fd
->collapse
+ 1);
7713 arr
= create_tmp_var (build_array_type_nelts (fd
->iter_type
,
7715 - fd
->collapse
+ 1),
7717 DECL_NAMELESS (arr
) = 1;
7718 TREE_ADDRESSABLE (arr
) = 1;
7719 TREE_STATIC (arr
) = 1;
7720 vec
<constructor_elt
, va_gc
> *v
;
7721 vec_alloc (v
, fd
->ordered
- fd
->collapse
+ 1);
7724 for (idx
= 0; idx
< fd
->ordered
- fd
->collapse
+ 1; idx
++)
7727 if (idx
== 0 && fd
->collapse
> 1)
7730 c
= counts
[idx
+ fd
->collapse
- 1];
7731 tree purpose
= size_int (idx
);
7732 CONSTRUCTOR_APPEND_ELT (v
, purpose
, c
);
7733 if (TREE_CODE (c
) != INTEGER_CST
)
7734 TREE_STATIC (arr
) = 0;
7737 DECL_INITIAL (arr
) = build_constructor (TREE_TYPE (arr
), v
);
7738 if (!TREE_STATIC (arr
))
7739 force_gimple_operand_gsi (&gsi
, build1 (DECL_EXPR
,
7740 void_type_node
, arr
),
7741 true, NULL_TREE
, true, GSI_SAME_STMT
);
7742 t1
= build_fold_addr_expr (arr
);
7747 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
7750 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7753 = find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7754 OMP_CLAUSE__LOOPTEMP_
);
7755 gcc_assert (innerc
);
7756 t0
= OMP_CLAUSE_DECL (innerc
);
7757 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7758 OMP_CLAUSE__LOOPTEMP_
);
7759 gcc_assert (innerc
);
7760 t1
= OMP_CLAUSE_DECL (innerc
);
7762 if (POINTER_TYPE_P (TREE_TYPE (t0
))
7763 && TYPE_PRECISION (TREE_TYPE (t0
))
7764 != TYPE_PRECISION (fd
->iter_type
))
7766 /* Avoid casting pointers to integer of a different size. */
7767 tree itype
= signed_type_for (type
);
7768 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
7769 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
7773 t1
= fold_convert (fd
->iter_type
, t1
);
7774 t0
= fold_convert (fd
->iter_type
, t0
);
7778 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
7779 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
7782 if (fd
->iter_type
== long_integer_type_node
|| fd
->ordered
)
7786 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
7787 t
= omp_adjust_chunk_size (t
, fd
->simd_schedule
);
7789 t
= build_call_expr (builtin_decl_explicit (start_fn
),
7790 5, t0
, t1
, t
, t3
, t4
);
7792 t
= build_call_expr (builtin_decl_explicit (start_fn
),
7793 6, t0
, t1
, t2
, t
, t3
, t4
);
7795 else if (fd
->ordered
)
7796 t
= build_call_expr (builtin_decl_explicit (start_fn
),
7799 t
= build_call_expr (builtin_decl_explicit (start_fn
),
7800 5, t0
, t1
, t2
, t3
, t4
);
7808 /* The GOMP_loop_ull_*start functions have additional boolean
7809 argument, true for < loops and false for > loops.
7810 In Fortran, the C bool type can be different from
7811 boolean_type_node. */
7812 bfn_decl
= builtin_decl_explicit (start_fn
);
7813 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
7814 t5
= build_int_cst (c_bool_type
,
7815 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
7818 tree bfn_decl
= builtin_decl_explicit (start_fn
);
7819 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
7820 t
= omp_adjust_chunk_size (t
, fd
->simd_schedule
);
7821 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
7824 t
= build_call_expr (builtin_decl_explicit (start_fn
),
7825 6, t5
, t0
, t1
, t2
, t3
, t4
);
7828 if (TREE_TYPE (t
) != boolean_type_node
)
7829 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
7830 t
, build_int_cst (TREE_TYPE (t
), 0));
7831 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7832 true, GSI_SAME_STMT
);
7833 if (arr
&& !TREE_STATIC (arr
))
7835 tree clobber
= build_constructor (TREE_TYPE (arr
), NULL
);
7836 TREE_THIS_VOLATILE (clobber
) = 1;
7837 gsi_insert_before (&gsi
, gimple_build_assign (arr
, clobber
),
7840 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
7842 /* Remove the GIMPLE_OMP_FOR statement. */
7843 gsi_remove (&gsi
, true);
7845 if (gsi_end_p (gsif
))
7846 gsif
= gsi_after_labels (gsi_bb (gsif
));
7849 /* Iteration setup for sequential loop goes in L0_BB. */
7850 tree startvar
= fd
->loop
.v
;
7851 tree endvar
= NULL_TREE
;
7853 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7855 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
7856 && gimple_omp_for_kind (inner_stmt
)
7857 == GF_OMP_FOR_KIND_SIMD
);
7858 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
7859 OMP_CLAUSE__LOOPTEMP_
);
7860 gcc_assert (innerc
);
7861 startvar
= OMP_CLAUSE_DECL (innerc
);
7862 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7863 OMP_CLAUSE__LOOPTEMP_
);
7864 gcc_assert (innerc
);
7865 endvar
= OMP_CLAUSE_DECL (innerc
);
7868 gsi
= gsi_start_bb (l0_bb
);
7870 if (fd
->ordered
&& fd
->collapse
== 1)
7871 t
= fold_build2 (MULT_EXPR
, fd
->iter_type
, t
,
7872 fold_convert (fd
->iter_type
, fd
->loop
.step
));
7874 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
7875 if (fd
->ordered
&& fd
->collapse
== 1)
7877 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
7878 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (startvar
),
7879 fd
->loop
.n1
, fold_convert (sizetype
, t
));
7882 t
= fold_convert (TREE_TYPE (startvar
), t
);
7883 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (startvar
),
7889 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
7890 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
7891 t
= fold_convert (TREE_TYPE (startvar
), t
);
7893 t
= force_gimple_operand_gsi (&gsi
, t
,
7895 && TREE_ADDRESSABLE (startvar
),
7896 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
7897 assign_stmt
= gimple_build_assign (startvar
, t
);
7898 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7901 if (fd
->ordered
&& fd
->collapse
== 1)
7902 t
= fold_build2 (MULT_EXPR
, fd
->iter_type
, t
,
7903 fold_convert (fd
->iter_type
, fd
->loop
.step
));
7905 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
7906 if (fd
->ordered
&& fd
->collapse
== 1)
7908 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
7909 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (startvar
),
7910 fd
->loop
.n1
, fold_convert (sizetype
, t
));
7913 t
= fold_convert (TREE_TYPE (startvar
), t
);
7914 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (startvar
),
7920 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
7921 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
7922 t
= fold_convert (TREE_TYPE (startvar
), t
);
7924 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7925 false, GSI_CONTINUE_LINKING
);
7928 assign_stmt
= gimple_build_assign (endvar
, iend
);
7929 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7930 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
7931 assign_stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
7933 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, iend
);
7934 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7936 /* Handle linear clause adjustments. */
7937 tree itercnt
= NULL_TREE
;
7938 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_FOR
)
7939 for (tree c
= gimple_omp_for_clauses (fd
->for_stmt
);
7940 c
; c
= OMP_CLAUSE_CHAIN (c
))
7941 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
7942 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
7944 tree d
= OMP_CLAUSE_DECL (c
);
7945 bool is_ref
= is_reference (d
);
7946 tree t
= d
, a
, dest
;
7948 t
= build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c
), t
);
7949 tree type
= TREE_TYPE (t
);
7950 if (POINTER_TYPE_P (type
))
7952 dest
= unshare_expr (t
);
7953 tree v
= create_tmp_var (TREE_TYPE (t
), NULL
);
7954 expand_omp_build_assign (&gsif
, v
, t
);
7955 if (itercnt
== NULL_TREE
)
7958 tree n1
= fd
->loop
.n1
;
7959 if (POINTER_TYPE_P (TREE_TYPE (itercnt
)))
7962 = fold_convert (signed_type_for (TREE_TYPE (itercnt
)),
7964 n1
= fold_convert (TREE_TYPE (itercnt
), n1
);
7966 itercnt
= fold_build2 (MINUS_EXPR
, TREE_TYPE (itercnt
),
7968 itercnt
= fold_build2 (EXACT_DIV_EXPR
, TREE_TYPE (itercnt
),
7969 itercnt
, fd
->loop
.step
);
7970 itercnt
= force_gimple_operand_gsi (&gsi
, itercnt
, true,
7972 GSI_CONTINUE_LINKING
);
7974 a
= fold_build2 (MULT_EXPR
, type
,
7975 fold_convert (type
, itercnt
),
7976 fold_convert (type
, OMP_CLAUSE_LINEAR_STEP (c
)));
7977 t
= fold_build2 (type
== TREE_TYPE (t
) ? PLUS_EXPR
7978 : POINTER_PLUS_EXPR
, TREE_TYPE (t
), v
, a
);
7979 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7980 false, GSI_CONTINUE_LINKING
);
7981 assign_stmt
= gimple_build_assign (dest
, t
);
7982 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7984 if (fd
->collapse
> 1)
7985 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
7989 /* Until now, counts array contained number of iterations or
7990 variable containing it for ith loop. From now on, we need
7991 those counts only for collapsed loops, and only for the 2nd
7992 till the last collapsed one. Move those one element earlier,
7993 we'll use counts[fd->collapse - 1] for the first source/sink
7994 iteration counter and so on and counts[fd->ordered]
7995 as the array holding the current counter values for
7997 if (fd
->collapse
> 1)
7998 memmove (counts
, counts
+ 1, (fd
->collapse
- 1) * sizeof (counts
[0]));
8002 for (i
= fd
->collapse
; i
< fd
->ordered
; i
++)
8004 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
8006 = fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
8007 fold_convert (type
, fd
->loops
[i
].n1
),
8008 fold_convert (type
, fd
->loops
[i
].n2
));
8009 if (!integer_onep (this_cond
))
8012 if (i
< fd
->ordered
)
8015 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
);
8016 add_bb_to_loop (cont_bb
, l1_bb
->loop_father
);
8017 gimple_stmt_iterator gsi
= gsi_after_labels (cont_bb
);
8018 gimple
*g
= gimple_build_omp_continue (fd
->loop
.v
, fd
->loop
.v
);
8019 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
8020 make_edge (cont_bb
, l3_bb
, EDGE_FALLTHRU
);
8021 make_edge (cont_bb
, l1_bb
, 0);
8022 l2_bb
= create_empty_bb (cont_bb
);
8023 broken_loop
= false;
8026 expand_omp_ordered_source_sink (region
, fd
, counts
, cont_bb
);
8027 cont_bb
= expand_omp_for_ordered_loops (fd
, counts
, cont_bb
, l1_bb
,
8028 ordered_lastprivate
);
8029 if (counts
[fd
->collapse
- 1])
8031 gcc_assert (fd
->collapse
== 1);
8032 gsi
= gsi_last_bb (l0_bb
);
8033 expand_omp_build_assign (&gsi
, counts
[fd
->collapse
- 1],
8035 gsi
= gsi_last_bb (cont_bb
);
8036 t
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, counts
[fd
->collapse
- 1],
8037 build_int_cst (fd
->iter_type
, 1));
8038 expand_omp_build_assign (&gsi
, counts
[fd
->collapse
- 1], t
);
8039 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
8040 size_zero_node
, NULL_TREE
, NULL_TREE
);
8041 expand_omp_build_assign (&gsi
, aref
, counts
[fd
->collapse
- 1]);
8042 t
= counts
[fd
->collapse
- 1];
8044 else if (fd
->collapse
> 1)
8048 t
= fold_build2 (MINUS_EXPR
, TREE_TYPE (fd
->loops
[0].v
),
8049 fd
->loops
[0].v
, fd
->loops
[0].n1
);
8050 t
= fold_convert (fd
->iter_type
, t
);
8052 gsi
= gsi_last_bb (l0_bb
);
8053 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
8054 size_zero_node
, NULL_TREE
, NULL_TREE
);
8055 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8056 false, GSI_CONTINUE_LINKING
);
8057 expand_omp_build_assign (&gsi
, aref
, t
, true);
8062 /* Code to control the increment and predicate for the sequential
8063 loop goes in the CONT_BB. */
8064 gsi
= gsi_last_bb (cont_bb
);
8065 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
8066 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
8067 vmain
= gimple_omp_continue_control_use (cont_stmt
);
8068 vback
= gimple_omp_continue_control_def (cont_stmt
);
8070 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
8072 if (POINTER_TYPE_P (type
))
8073 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
8075 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
8076 t
= force_gimple_operand_gsi (&gsi
, t
,
8078 && TREE_ADDRESSABLE (vback
),
8079 NULL_TREE
, true, GSI_SAME_STMT
);
8080 assign_stmt
= gimple_build_assign (vback
, t
);
8081 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
8083 if (fd
->ordered
&& counts
[fd
->collapse
- 1] == NULL_TREE
)
8085 if (fd
->collapse
> 1)
8089 t
= fold_build2 (MINUS_EXPR
, TREE_TYPE (fd
->loops
[0].v
),
8090 fd
->loops
[0].v
, fd
->loops
[0].n1
);
8091 t
= fold_convert (fd
->iter_type
, t
);
8093 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
,
8094 counts
[fd
->ordered
], size_zero_node
,
8095 NULL_TREE
, NULL_TREE
);
8096 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8097 true, GSI_SAME_STMT
);
8098 expand_omp_build_assign (&gsi
, aref
, t
);
8101 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
8102 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
8104 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
8105 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
8108 /* Remove GIMPLE_OMP_CONTINUE. */
8109 gsi_remove (&gsi
, true);
8111 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
8112 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
8114 /* Emit code to get the next parallel iteration in L2_BB. */
8115 gsi
= gsi_start_bb (l2_bb
);
8117 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
8118 build_fold_addr_expr (istart0
),
8119 build_fold_addr_expr (iend0
));
8120 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8121 false, GSI_CONTINUE_LINKING
);
8122 if (TREE_TYPE (t
) != boolean_type_node
)
8123 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
8124 t
, build_int_cst (TREE_TYPE (t
), 0));
8125 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
8126 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
8129 /* Add the loop cleanup function. */
8130 gsi
= gsi_last_bb (exit_bb
);
8131 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
8132 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
8133 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
8134 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
8136 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
8137 gcall
*call_stmt
= gimple_build_call (t
, 0);
8138 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
8139 gimple_call_set_lhs (call_stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
8140 gsi_insert_after (&gsi
, call_stmt
, GSI_SAME_STMT
);
8143 tree arr
= counts
[fd
->ordered
];
8144 tree clobber
= build_constructor (TREE_TYPE (arr
), NULL
);
8145 TREE_THIS_VOLATILE (clobber
) = 1;
8146 gsi_insert_after (&gsi
, gimple_build_assign (arr
, clobber
),
8149 gsi_remove (&gsi
, true);
8151 /* Connect the new blocks. */
8152 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
8153 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
8159 e
= find_edge (cont_bb
, l3_bb
);
8160 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
8162 phis
= phi_nodes (l3_bb
);
8163 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
8165 gimple
*phi
= gsi_stmt (gsi
);
8166 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
8167 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
8171 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
8172 e
= find_edge (cont_bb
, l1_bb
);
8175 e
= BRANCH_EDGE (cont_bb
);
8176 gcc_assert (single_succ (e
->dest
) == l1_bb
);
8178 if (gimple_omp_for_combined_p (fd
->for_stmt
))
8183 else if (fd
->collapse
> 1)
8186 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
8189 e
->flags
= EDGE_TRUE_VALUE
;
8192 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
8193 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
8197 e
= find_edge (cont_bb
, l2_bb
);
8198 e
->flags
= EDGE_FALLTHRU
;
8200 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
8202 if (gimple_in_ssa_p (cfun
))
8204 /* Add phis to the outer loop that connect to the phis in the inner,
8205 original loop, and move the loop entry value of the inner phi to
8206 the loop entry value of the outer phi. */
8208 for (psi
= gsi_start_phis (l3_bb
); !gsi_end_p (psi
); gsi_next (&psi
))
8210 source_location locus
;
8212 gphi
*exit_phi
= psi
.phi ();
8214 edge l2_to_l3
= find_edge (l2_bb
, l3_bb
);
8215 tree exit_res
= PHI_ARG_DEF_FROM_EDGE (exit_phi
, l2_to_l3
);
8217 basic_block latch
= BRANCH_EDGE (cont_bb
)->dest
;
8218 edge latch_to_l1
= find_edge (latch
, l1_bb
);
8220 = find_phi_with_arg_on_edge (exit_res
, latch_to_l1
);
8222 tree t
= gimple_phi_result (exit_phi
);
8223 tree new_res
= copy_ssa_name (t
, NULL
);
8224 nphi
= create_phi_node (new_res
, l0_bb
);
8226 edge l0_to_l1
= find_edge (l0_bb
, l1_bb
);
8227 t
= PHI_ARG_DEF_FROM_EDGE (inner_phi
, l0_to_l1
);
8228 locus
= gimple_phi_arg_location_from_edge (inner_phi
, l0_to_l1
);
8229 edge entry_to_l0
= find_edge (entry_bb
, l0_bb
);
8230 add_phi_arg (nphi
, t
, entry_to_l0
, locus
);
8232 edge l2_to_l0
= find_edge (l2_bb
, l0_bb
);
8233 add_phi_arg (nphi
, exit_res
, l2_to_l0
, UNKNOWN_LOCATION
);
8235 add_phi_arg (inner_phi
, new_res
, l0_to_l1
, UNKNOWN_LOCATION
);
8239 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
8240 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
8241 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
8242 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
8243 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
8244 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
8245 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
8246 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
8248 /* We enter expand_omp_for_generic with a loop. This original loop may
8249 have its own loop struct, or it may be part of an outer loop struct
8250 (which may be the fake loop). */
8251 struct loop
*outer_loop
= entry_bb
->loop_father
;
8252 bool orig_loop_has_loop_struct
= l1_bb
->loop_father
!= outer_loop
;
8254 add_bb_to_loop (l2_bb
, outer_loop
);
8256 /* We've added a new loop around the original loop. Allocate the
8257 corresponding loop struct. */
8258 struct loop
*new_loop
= alloc_loop ();
8259 new_loop
->header
= l0_bb
;
8260 new_loop
->latch
= l2_bb
;
8261 add_loop (new_loop
, outer_loop
);
8263 /* Allocate a loop structure for the original loop unless we already
8265 if (!orig_loop_has_loop_struct
8266 && !gimple_omp_for_combined_p (fd
->for_stmt
))
8268 struct loop
*orig_loop
= alloc_loop ();
8269 orig_loop
->header
= l1_bb
;
8270 /* The loop may have multiple latches. */
8271 add_loop (orig_loop
, new_loop
);
8277 /* A subroutine of expand_omp_for. Generate code for a parallel
8278 loop with static schedule and no specified chunk size. Given
8281 for (V = N1; V cond N2; V += STEP) BODY;
8283 where COND is "<" or ">", we generate pseudocode
8285 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
8290 if ((__typeof (V)) -1 > 0 && cond is >)
8291 n = -(adj + N2 - N1) / -STEP;
8293 n = (adj + N2 - N1) / STEP;
8296 if (threadid < tt) goto L3; else goto L4;
8301 s0 = q * threadid + tt;
8304 if (s0 >= e0) goto L2; else goto L0;
8310 if (V cond e) goto L1;
8315 expand_omp_for_static_nochunk (struct omp_region
*region
,
8316 struct omp_for_data
*fd
,
8319 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
8320 tree type
, itype
, vmain
, vback
;
8321 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
8322 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
8324 gimple_stmt_iterator gsi
;
8326 bool broken_loop
= region
->cont
== NULL
;
8327 tree
*counts
= NULL
;
8330 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
8331 != GF_OMP_FOR_KIND_OACC_LOOP
)
8334 itype
= type
= TREE_TYPE (fd
->loop
.v
);
8335 if (POINTER_TYPE_P (type
))
8336 itype
= signed_type_for (type
);
8338 entry_bb
= region
->entry
;
8339 cont_bb
= region
->cont
;
8340 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
8341 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
8342 gcc_assert (broken_loop
8343 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
8344 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
8345 body_bb
= single_succ (seq_start_bb
);
8348 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
8349 || single_succ (BRANCH_EDGE (cont_bb
)->dest
) == body_bb
);
8350 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
8352 exit_bb
= region
->exit
;
8354 /* Iteration space partitioning goes in ENTRY_BB. */
8355 gsi
= gsi_last_bb (entry_bb
);
8356 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
8358 if (fd
->collapse
> 1)
8360 int first_zero_iter
= -1, dummy
= -1;
8361 basic_block l2_dom_bb
= NULL
, dummy_bb
= NULL
;
8363 counts
= XALLOCAVEC (tree
, fd
->collapse
);
8364 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
8365 fin_bb
, first_zero_iter
,
8366 dummy_bb
, dummy
, l2_dom_bb
);
8369 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
8370 t
= integer_one_node
;
8372 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
8373 fold_convert (type
, fd
->loop
.n1
),
8374 fold_convert (type
, fd
->loop
.n2
));
8375 if (fd
->collapse
== 1
8376 && TYPE_UNSIGNED (type
)
8377 && (t
== NULL_TREE
|| !integer_onep (t
)))
8379 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
8380 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
8381 true, GSI_SAME_STMT
);
8382 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
8383 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
8384 true, GSI_SAME_STMT
);
8385 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
8386 NULL_TREE
, NULL_TREE
);
8387 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
8388 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
8389 expand_omp_regimplify_p
, NULL
, NULL
)
8390 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
8391 expand_omp_regimplify_p
, NULL
, NULL
))
8393 gsi
= gsi_for_stmt (cond_stmt
);
8394 gimple_regimplify_operands (cond_stmt
, &gsi
);
8396 ep
= split_block (entry_bb
, cond_stmt
);
8397 ep
->flags
= EDGE_TRUE_VALUE
;
8398 entry_bb
= ep
->dest
;
8399 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
8400 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
8401 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
8402 if (gimple_in_ssa_p (cfun
))
8404 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
8405 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
8406 !gsi_end_p (gpi
); gsi_next (&gpi
))
8408 gphi
*phi
= gpi
.phi ();
8409 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
8410 ep
, UNKNOWN_LOCATION
);
8413 gsi
= gsi_last_bb (entry_bb
);
8416 switch (gimple_omp_for_kind (fd
->for_stmt
))
8418 case GF_OMP_FOR_KIND_FOR
:
8419 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
8420 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
8422 case GF_OMP_FOR_KIND_DISTRIBUTE
:
8423 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
8424 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
8426 case GF_OMP_FOR_KIND_OACC_LOOP
:
8427 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
8428 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
8433 nthreads
= build_call_expr (nthreads
, 0);
8434 nthreads
= fold_convert (itype
, nthreads
);
8435 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
8436 true, GSI_SAME_STMT
);
8437 threadid
= build_call_expr (threadid
, 0);
8438 threadid
= fold_convert (itype
, threadid
);
8439 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
8440 true, GSI_SAME_STMT
);
8444 step
= fd
->loop
.step
;
8445 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
8447 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
8448 OMP_CLAUSE__LOOPTEMP_
);
8449 gcc_assert (innerc
);
8450 n1
= OMP_CLAUSE_DECL (innerc
);
8451 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
8452 OMP_CLAUSE__LOOPTEMP_
);
8453 gcc_assert (innerc
);
8454 n2
= OMP_CLAUSE_DECL (innerc
);
8456 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
8457 true, NULL_TREE
, true, GSI_SAME_STMT
);
8458 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
8459 true, NULL_TREE
, true, GSI_SAME_STMT
);
8460 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
8461 true, NULL_TREE
, true, GSI_SAME_STMT
);
8463 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
8464 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
8465 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
8466 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
8467 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
8468 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
8469 fold_build1 (NEGATE_EXPR
, itype
, t
),
8470 fold_build1 (NEGATE_EXPR
, itype
, step
));
8472 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
8473 t
= fold_convert (itype
, t
);
8474 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8476 q
= create_tmp_reg (itype
, "q");
8477 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
8478 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
8479 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
8481 tt
= create_tmp_reg (itype
, "tt");
8482 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
8483 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
8484 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
8486 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
8487 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
8488 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
8490 second_bb
= split_block (entry_bb
, cond_stmt
)->dest
;
8491 gsi
= gsi_last_bb (second_bb
);
8492 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
8494 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
8496 gassign
*assign_stmt
8497 = gimple_build_assign (q
, PLUS_EXPR
, q
, build_int_cst (itype
, 1));
8498 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
8500 third_bb
= split_block (second_bb
, assign_stmt
)->dest
;
8501 gsi
= gsi_last_bb (third_bb
);
8502 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
8504 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
8505 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
8506 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8508 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
8509 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8511 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
8512 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
8514 /* Remove the GIMPLE_OMP_FOR statement. */
8515 gsi_remove (&gsi
, true);
8517 /* Setup code for sequential iteration goes in SEQ_START_BB. */
8518 gsi
= gsi_start_bb (seq_start_bb
);
8520 tree startvar
= fd
->loop
.v
;
8521 tree endvar
= NULL_TREE
;
8523 if (gimple_omp_for_combined_p (fd
->for_stmt
))
8525 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
8526 ? gimple_omp_parallel_clauses (inner_stmt
)
8527 : gimple_omp_for_clauses (inner_stmt
);
8528 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
8529 gcc_assert (innerc
);
8530 startvar
= OMP_CLAUSE_DECL (innerc
);
8531 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
8532 OMP_CLAUSE__LOOPTEMP_
);
8533 gcc_assert (innerc
);
8534 endvar
= OMP_CLAUSE_DECL (innerc
);
8536 t
= fold_convert (itype
, s0
);
8537 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
8538 if (POINTER_TYPE_P (type
))
8539 t
= fold_build_pointer_plus (n1
, t
);
8541 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
8542 t
= fold_convert (TREE_TYPE (startvar
), t
);
8543 t
= force_gimple_operand_gsi (&gsi
, t
,
8545 && TREE_ADDRESSABLE (startvar
),
8546 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
8547 assign_stmt
= gimple_build_assign (startvar
, t
);
8548 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8550 t
= fold_convert (itype
, e0
);
8551 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
8552 if (POINTER_TYPE_P (type
))
8553 t
= fold_build_pointer_plus (n1
, t
);
8555 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
8556 t
= fold_convert (TREE_TYPE (startvar
), t
);
8557 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8558 false, GSI_CONTINUE_LINKING
);
8561 assign_stmt
= gimple_build_assign (endvar
, e
);
8562 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8563 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
8564 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
8566 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
8567 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8569 /* Handle linear clause adjustments. */
8570 tree itercnt
= NULL_TREE
;
8571 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_FOR
)
8572 for (tree c
= gimple_omp_for_clauses (fd
->for_stmt
);
8573 c
; c
= OMP_CLAUSE_CHAIN (c
))
8574 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
8575 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
8577 tree d
= OMP_CLAUSE_DECL (c
);
8578 bool is_ref
= is_reference (d
);
8579 tree t
= d
, a
, dest
;
8581 t
= build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c
), t
);
8582 if (itercnt
== NULL_TREE
)
8584 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
8586 itercnt
= fold_build2 (MINUS_EXPR
, itype
,
8587 fold_convert (itype
, n1
),
8588 fold_convert (itype
, fd
->loop
.n1
));
8589 itercnt
= fold_build2 (EXACT_DIV_EXPR
, itype
, itercnt
, step
);
8590 itercnt
= fold_build2 (PLUS_EXPR
, itype
, itercnt
, s0
);
8591 itercnt
= force_gimple_operand_gsi (&gsi
, itercnt
, true,
8593 GSI_CONTINUE_LINKING
);
8598 tree type
= TREE_TYPE (t
);
8599 if (POINTER_TYPE_P (type
))
8601 a
= fold_build2 (MULT_EXPR
, type
,
8602 fold_convert (type
, itercnt
),
8603 fold_convert (type
, OMP_CLAUSE_LINEAR_STEP (c
)));
8604 dest
= unshare_expr (t
);
8605 t
= fold_build2 (type
== TREE_TYPE (t
) ? PLUS_EXPR
8606 : POINTER_PLUS_EXPR
, TREE_TYPE (t
), t
, a
);
8607 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8608 false, GSI_CONTINUE_LINKING
);
8609 assign_stmt
= gimple_build_assign (dest
, t
);
8610 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8612 if (fd
->collapse
> 1)
8613 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
8617 /* The code controlling the sequential loop replaces the
8618 GIMPLE_OMP_CONTINUE. */
8619 gsi
= gsi_last_bb (cont_bb
);
8620 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
8621 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
8622 vmain
= gimple_omp_continue_control_use (cont_stmt
);
8623 vback
= gimple_omp_continue_control_def (cont_stmt
);
8625 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
8627 if (POINTER_TYPE_P (type
))
8628 t
= fold_build_pointer_plus (vmain
, step
);
8630 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
8631 t
= force_gimple_operand_gsi (&gsi
, t
,
8633 && TREE_ADDRESSABLE (vback
),
8634 NULL_TREE
, true, GSI_SAME_STMT
);
8635 assign_stmt
= gimple_build_assign (vback
, t
);
8636 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
8638 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
8639 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
8641 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
8644 /* Remove the GIMPLE_OMP_CONTINUE statement. */
8645 gsi_remove (&gsi
, true);
8647 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
8648 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
8651 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
8652 gsi
= gsi_last_bb (exit_bb
);
8653 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
8655 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
8656 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
8657 gcc_checking_assert (t
== NULL_TREE
);
8659 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
8661 gsi_remove (&gsi
, true);
8663 /* Connect all the blocks. */
8664 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
8665 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
8666 ep
= find_edge (entry_bb
, second_bb
);
8667 ep
->flags
= EDGE_TRUE_VALUE
;
8668 ep
->probability
= REG_BR_PROB_BASE
/ 4;
8669 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
8670 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
8674 ep
= find_edge (cont_bb
, body_bb
);
8677 ep
= BRANCH_EDGE (cont_bb
);
8678 gcc_assert (single_succ (ep
->dest
) == body_bb
);
8680 if (gimple_omp_for_combined_p (fd
->for_stmt
))
8685 else if (fd
->collapse
> 1)
8688 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
8691 ep
->flags
= EDGE_TRUE_VALUE
;
8692 find_edge (cont_bb
, fin_bb
)->flags
8693 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
8696 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
8697 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
8698 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
8700 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
8701 recompute_dominator (CDI_DOMINATORS
, body_bb
));
8702 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
8703 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
8705 struct loop
*loop
= body_bb
->loop_father
;
8706 if (loop
!= entry_bb
->loop_father
)
8708 gcc_assert (loop
->header
== body_bb
);
8709 gcc_assert (broken_loop
8710 || loop
->latch
== region
->cont
8711 || single_pred (loop
->latch
) == region
->cont
);
8715 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
8717 loop
= alloc_loop ();
8718 loop
->header
= body_bb
;
8719 if (collapse_bb
== NULL
)
8720 loop
->latch
= cont_bb
;
8721 add_loop (loop
, body_bb
->loop_father
);
8725 /* Return phi in E->DEST with ARG on edge E. */
8728 find_phi_with_arg_on_edge (tree arg
, edge e
)
8730 basic_block bb
= e
->dest
;
8732 for (gphi_iterator gpi
= gsi_start_phis (bb
);
8736 gphi
*phi
= gpi
.phi ();
8737 if (PHI_ARG_DEF_FROM_EDGE (phi
, e
) == arg
)
8744 /* A subroutine of expand_omp_for. Generate code for a parallel
8745 loop with static schedule and a specified chunk size. Given
8748 for (V = N1; V cond N2; V += STEP) BODY;
8750 where COND is "<" or ">", we generate pseudocode
8752 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
8757 if ((__typeof (V)) -1 > 0 && cond is >)
8758 n = -(adj + N2 - N1) / -STEP;
8760 n = (adj + N2 - N1) / STEP;
8762 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
8763 here so that V is defined
8764 if the loop is not entered
8766 s0 = (trip * nthreads + threadid) * CHUNK;
8767 e0 = min(s0 + CHUNK, n);
8768 if (s0 < n) goto L1; else goto L4;
8775 if (V cond e) goto L2; else goto L3;
8783 expand_omp_for_static_chunk (struct omp_region
*region
,
8784 struct omp_for_data
*fd
, gimple
*inner_stmt
)
8786 tree n
, s0
, e0
, e
, t
;
8787 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
8788 tree type
, itype
, vmain
, vback
, vextra
;
8789 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
8790 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
8791 gimple_stmt_iterator gsi
;
8793 bool broken_loop
= region
->cont
== NULL
;
8794 tree
*counts
= NULL
;
8797 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
8798 != GF_OMP_FOR_KIND_OACC_LOOP
)
8801 itype
= type
= TREE_TYPE (fd
->loop
.v
);
8802 if (POINTER_TYPE_P (type
))
8803 itype
= signed_type_for (type
);
8805 entry_bb
= region
->entry
;
8806 se
= split_block (entry_bb
, last_stmt (entry_bb
));
8808 iter_part_bb
= se
->dest
;
8809 cont_bb
= region
->cont
;
8810 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
8811 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
8812 gcc_assert (broken_loop
8813 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
8814 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
8815 body_bb
= single_succ (seq_start_bb
);
8818 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
8819 || single_succ (BRANCH_EDGE (cont_bb
)->dest
) == body_bb
);
8820 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
8821 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
8823 exit_bb
= region
->exit
;
8825 /* Trip and adjustment setup goes in ENTRY_BB. */
8826 gsi
= gsi_last_bb (entry_bb
);
8827 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
8829 if (fd
->collapse
> 1)
8831 int first_zero_iter
= -1, dummy
= -1;
8832 basic_block l2_dom_bb
= NULL
, dummy_bb
= NULL
;
8834 counts
= XALLOCAVEC (tree
, fd
->collapse
);
8835 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
8836 fin_bb
, first_zero_iter
,
8837 dummy_bb
, dummy
, l2_dom_bb
);
8840 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
8841 t
= integer_one_node
;
8843 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
8844 fold_convert (type
, fd
->loop
.n1
),
8845 fold_convert (type
, fd
->loop
.n2
));
8846 if (fd
->collapse
== 1
8847 && TYPE_UNSIGNED (type
)
8848 && (t
== NULL_TREE
|| !integer_onep (t
)))
8850 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
8851 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
8852 true, GSI_SAME_STMT
);
8853 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
8854 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
8855 true, GSI_SAME_STMT
);
8856 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
8857 NULL_TREE
, NULL_TREE
);
8858 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
8859 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
8860 expand_omp_regimplify_p
, NULL
, NULL
)
8861 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
8862 expand_omp_regimplify_p
, NULL
, NULL
))
8864 gsi
= gsi_for_stmt (cond_stmt
);
8865 gimple_regimplify_operands (cond_stmt
, &gsi
);
8867 se
= split_block (entry_bb
, cond_stmt
);
8868 se
->flags
= EDGE_TRUE_VALUE
;
8869 entry_bb
= se
->dest
;
8870 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
8871 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
8872 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
8873 if (gimple_in_ssa_p (cfun
))
8875 int dest_idx
= find_edge (iter_part_bb
, fin_bb
)->dest_idx
;
8876 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
8877 !gsi_end_p (gpi
); gsi_next (&gpi
))
8879 gphi
*phi
= gpi
.phi ();
8880 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
8881 se
, UNKNOWN_LOCATION
);
8884 gsi
= gsi_last_bb (entry_bb
);
8887 switch (gimple_omp_for_kind (fd
->for_stmt
))
8889 case GF_OMP_FOR_KIND_FOR
:
8890 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
8891 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
8893 case GF_OMP_FOR_KIND_DISTRIBUTE
:
8894 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
8895 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
8897 case GF_OMP_FOR_KIND_OACC_LOOP
:
8898 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
8899 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
8904 nthreads
= build_call_expr (nthreads
, 0);
8905 nthreads
= fold_convert (itype
, nthreads
);
8906 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
8907 true, GSI_SAME_STMT
);
8908 threadid
= build_call_expr (threadid
, 0);
8909 threadid
= fold_convert (itype
, threadid
);
8910 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
8911 true, GSI_SAME_STMT
);
8915 step
= fd
->loop
.step
;
8916 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
8918 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
8919 OMP_CLAUSE__LOOPTEMP_
);
8920 gcc_assert (innerc
);
8921 n1
= OMP_CLAUSE_DECL (innerc
);
8922 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
8923 OMP_CLAUSE__LOOPTEMP_
);
8924 gcc_assert (innerc
);
8925 n2
= OMP_CLAUSE_DECL (innerc
);
8927 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
8928 true, NULL_TREE
, true, GSI_SAME_STMT
);
8929 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
8930 true, NULL_TREE
, true, GSI_SAME_STMT
);
8931 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
8932 true, NULL_TREE
, true, GSI_SAME_STMT
);
8933 tree chunk_size
= fold_convert (itype
, fd
->chunk_size
);
8934 chunk_size
= omp_adjust_chunk_size (chunk_size
, fd
->simd_schedule
);
8936 = force_gimple_operand_gsi (&gsi
, chunk_size
, true, NULL_TREE
, true,
8939 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
8940 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
8941 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
8942 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
8943 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
8944 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
8945 fold_build1 (NEGATE_EXPR
, itype
, t
),
8946 fold_build1 (NEGATE_EXPR
, itype
, step
));
8948 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
8949 t
= fold_convert (itype
, t
);
8950 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8951 true, GSI_SAME_STMT
);
8953 trip_var
= create_tmp_reg (itype
, ".trip");
8954 if (gimple_in_ssa_p (cfun
))
8956 trip_init
= make_ssa_name (trip_var
);
8957 trip_main
= make_ssa_name (trip_var
);
8958 trip_back
= make_ssa_name (trip_var
);
8962 trip_init
= trip_var
;
8963 trip_main
= trip_var
;
8964 trip_back
= trip_var
;
8967 gassign
*assign_stmt
8968 = gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
8969 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
8971 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, chunk_size
);
8972 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
8973 if (POINTER_TYPE_P (type
))
8974 t
= fold_build_pointer_plus (n1
, t
);
8976 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
8977 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8978 true, GSI_SAME_STMT
);
8980 /* Remove the GIMPLE_OMP_FOR. */
8981 gsi_remove (&gsi
, true);
8983 gimple_stmt_iterator gsif
= gsi
;
8985 /* Iteration space partitioning goes in ITER_PART_BB. */
8986 gsi
= gsi_last_bb (iter_part_bb
);
8988 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
8989 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
8990 t
= fold_build2 (MULT_EXPR
, itype
, t
, chunk_size
);
8991 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8992 false, GSI_CONTINUE_LINKING
);
8994 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, chunk_size
);
8995 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
8996 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8997 false, GSI_CONTINUE_LINKING
);
8999 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
9000 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
9002 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9003 gsi
= gsi_start_bb (seq_start_bb
);
9005 tree startvar
= fd
->loop
.v
;
9006 tree endvar
= NULL_TREE
;
9008 if (gimple_omp_for_combined_p (fd
->for_stmt
))
9010 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
9011 ? gimple_omp_parallel_clauses (inner_stmt
)
9012 : gimple_omp_for_clauses (inner_stmt
);
9013 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
9014 gcc_assert (innerc
);
9015 startvar
= OMP_CLAUSE_DECL (innerc
);
9016 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9017 OMP_CLAUSE__LOOPTEMP_
);
9018 gcc_assert (innerc
);
9019 endvar
= OMP_CLAUSE_DECL (innerc
);
9022 t
= fold_convert (itype
, s0
);
9023 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
9024 if (POINTER_TYPE_P (type
))
9025 t
= fold_build_pointer_plus (n1
, t
);
9027 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
9028 t
= fold_convert (TREE_TYPE (startvar
), t
);
9029 t
= force_gimple_operand_gsi (&gsi
, t
,
9031 && TREE_ADDRESSABLE (startvar
),
9032 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
9033 assign_stmt
= gimple_build_assign (startvar
, t
);
9034 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9036 t
= fold_convert (itype
, e0
);
9037 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
9038 if (POINTER_TYPE_P (type
))
9039 t
= fold_build_pointer_plus (n1
, t
);
9041 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
9042 t
= fold_convert (TREE_TYPE (startvar
), t
);
9043 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9044 false, GSI_CONTINUE_LINKING
);
9047 assign_stmt
= gimple_build_assign (endvar
, e
);
9048 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9049 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
9050 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
9052 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
9053 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9055 /* Handle linear clause adjustments. */
9056 tree itercnt
= NULL_TREE
, itercntbias
= NULL_TREE
;
9057 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_FOR
)
9058 for (tree c
= gimple_omp_for_clauses (fd
->for_stmt
);
9059 c
; c
= OMP_CLAUSE_CHAIN (c
))
9060 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
9061 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
9063 tree d
= OMP_CLAUSE_DECL (c
);
9064 bool is_ref
= is_reference (d
);
9065 tree t
= d
, a
, dest
;
9067 t
= build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c
), t
);
9068 tree type
= TREE_TYPE (t
);
9069 if (POINTER_TYPE_P (type
))
9071 dest
= unshare_expr (t
);
9072 tree v
= create_tmp_var (TREE_TYPE (t
), NULL
);
9073 expand_omp_build_assign (&gsif
, v
, t
);
9074 if (itercnt
== NULL_TREE
)
9076 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9079 = fold_build2 (MINUS_EXPR
, itype
, fold_convert (itype
, n1
),
9080 fold_convert (itype
, fd
->loop
.n1
));
9081 itercntbias
= fold_build2 (EXACT_DIV_EXPR
, itype
,
9084 = force_gimple_operand_gsi (&gsif
, itercntbias
, true,
9087 itercnt
= fold_build2 (PLUS_EXPR
, itype
, itercntbias
, s0
);
9088 itercnt
= force_gimple_operand_gsi (&gsi
, itercnt
, true,
9090 GSI_CONTINUE_LINKING
);
9095 a
= fold_build2 (MULT_EXPR
, type
,
9096 fold_convert (type
, itercnt
),
9097 fold_convert (type
, OMP_CLAUSE_LINEAR_STEP (c
)));
9098 t
= fold_build2 (type
== TREE_TYPE (t
) ? PLUS_EXPR
9099 : POINTER_PLUS_EXPR
, TREE_TYPE (t
), v
, a
);
9100 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9101 false, GSI_CONTINUE_LINKING
);
9102 assign_stmt
= gimple_build_assign (dest
, t
);
9103 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9105 if (fd
->collapse
> 1)
9106 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
9110 /* The code controlling the sequential loop goes in CONT_BB,
9111 replacing the GIMPLE_OMP_CONTINUE. */
9112 gsi
= gsi_last_bb (cont_bb
);
9113 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
9114 vmain
= gimple_omp_continue_control_use (cont_stmt
);
9115 vback
= gimple_omp_continue_control_def (cont_stmt
);
9117 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
9119 if (POINTER_TYPE_P (type
))
9120 t
= fold_build_pointer_plus (vmain
, step
);
9122 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
9123 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
9124 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9125 true, GSI_SAME_STMT
);
9126 assign_stmt
= gimple_build_assign (vback
, t
);
9127 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
9129 if (tree_int_cst_equal (fd
->chunk_size
, integer_one_node
))
9130 t
= build2 (EQ_EXPR
, boolean_type_node
,
9131 build_int_cst (itype
, 0),
9132 build_int_cst (itype
, 1));
9134 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
9135 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
9137 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
9140 /* Remove GIMPLE_OMP_CONTINUE. */
9141 gsi_remove (&gsi
, true);
9143 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
9144 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
9146 /* Trip update code goes into TRIP_UPDATE_BB. */
9147 gsi
= gsi_start_bb (trip_update_bb
);
9149 t
= build_int_cst (itype
, 1);
9150 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
9151 assign_stmt
= gimple_build_assign (trip_back
, t
);
9152 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9155 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9156 gsi
= gsi_last_bb (exit_bb
);
9157 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
9159 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
9160 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
9161 gcc_checking_assert (t
== NULL_TREE
);
9163 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
9165 gsi_remove (&gsi
, true);
9167 /* Connect the new blocks. */
9168 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
9169 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
9173 se
= find_edge (cont_bb
, body_bb
);
9176 se
= BRANCH_EDGE (cont_bb
);
9177 gcc_assert (single_succ (se
->dest
) == body_bb
);
9179 if (gimple_omp_for_combined_p (fd
->for_stmt
))
9184 else if (fd
->collapse
> 1)
9187 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
9190 se
->flags
= EDGE_TRUE_VALUE
;
9191 find_edge (cont_bb
, trip_update_bb
)->flags
9192 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
9194 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
9197 if (gimple_in_ssa_p (cfun
))
9205 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
9207 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9208 remove arguments of the phi nodes in fin_bb. We need to create
9209 appropriate phi nodes in iter_part_bb instead. */
9210 se
= find_edge (iter_part_bb
, fin_bb
);
9211 re
= single_succ_edge (trip_update_bb
);
9212 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
9213 ene
= single_succ_edge (entry_bb
);
9215 psi
= gsi_start_phis (fin_bb
);
9216 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
9217 gsi_next (&psi
), ++i
)
9220 source_location locus
;
9223 t
= gimple_phi_result (phi
);
9224 gcc_assert (t
== redirect_edge_var_map_result (vm
));
9226 if (!single_pred_p (fin_bb
))
9227 t
= copy_ssa_name (t
, phi
);
9229 nphi
= create_phi_node (t
, iter_part_bb
);
9231 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
9232 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
9234 /* A special case -- fd->loop.v is not yet computed in
9235 iter_part_bb, we need to use vextra instead. */
9236 if (t
== fd
->loop
.v
)
9238 add_phi_arg (nphi
, t
, ene
, locus
);
9239 locus
= redirect_edge_var_map_location (vm
);
9240 tree back_arg
= redirect_edge_var_map_def (vm
);
9241 add_phi_arg (nphi
, back_arg
, re
, locus
);
9242 edge ce
= find_edge (cont_bb
, body_bb
);
9245 ce
= BRANCH_EDGE (cont_bb
);
9246 gcc_assert (single_succ (ce
->dest
) == body_bb
);
9247 ce
= single_succ_edge (ce
->dest
);
9249 gphi
*inner_loop_phi
= find_phi_with_arg_on_edge (back_arg
, ce
);
9250 gcc_assert (inner_loop_phi
!= NULL
);
9251 add_phi_arg (inner_loop_phi
, gimple_phi_result (nphi
),
9252 find_edge (seq_start_bb
, body_bb
), locus
);
9254 if (!single_pred_p (fin_bb
))
9255 add_phi_arg (phi
, gimple_phi_result (nphi
), se
, locus
);
9257 gcc_assert (gsi_end_p (psi
) && (head
== NULL
|| i
== head
->length ()));
9258 redirect_edge_var_map_clear (re
);
9259 if (single_pred_p (fin_bb
))
9262 psi
= gsi_start_phis (fin_bb
);
9263 if (gsi_end_p (psi
))
9265 remove_phi_node (&psi
, false);
9268 /* Make phi node for trip. */
9269 phi
= create_phi_node (trip_main
, iter_part_bb
);
9270 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
9272 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
9277 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
9278 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
9279 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
9280 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
9281 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
9282 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
9283 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
9284 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
9285 recompute_dominator (CDI_DOMINATORS
, body_bb
));
9289 struct loop
*loop
= body_bb
->loop_father
;
9290 struct loop
*trip_loop
= alloc_loop ();
9291 trip_loop
->header
= iter_part_bb
;
9292 trip_loop
->latch
= trip_update_bb
;
9293 add_loop (trip_loop
, iter_part_bb
->loop_father
);
9295 if (loop
!= entry_bb
->loop_father
)
9297 gcc_assert (loop
->header
== body_bb
);
9298 gcc_assert (loop
->latch
== region
->cont
9299 || single_pred (loop
->latch
) == region
->cont
);
9300 trip_loop
->inner
= loop
;
9304 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
9306 loop
= alloc_loop ();
9307 loop
->header
= body_bb
;
9308 if (collapse_bb
== NULL
)
9309 loop
->latch
= cont_bb
;
9310 add_loop (loop
, trip_loop
);
9315 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
9317 for (V = N1; V cond N2; V += STEP) BODY;
9319 where COND is "<" or ">" or "!=", we generate pseudocode
9321 for (ind_var = low; ind_var < high; ind_var++)
9323 V = n1 + (ind_var * STEP)
9328 In the above pseudocode, low and high are function parameters of the
9329 child function. In the function below, we are inserting a temp.
9330 variable that will be making a call to two OMP functions that will not be
9331 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
9332 with _Cilk_for). These functions are replaced with low and high
9333 by the function that handles taskreg. */
9337 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
9339 bool broken_loop
= region
->cont
== NULL
;
9340 basic_block entry_bb
= region
->entry
;
9341 basic_block cont_bb
= region
->cont
;
9343 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
9344 gcc_assert (broken_loop
9345 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
9346 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
9347 basic_block l1_bb
, l2_bb
;
9351 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
9352 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
9353 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
9354 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
9358 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
9359 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
9360 l2_bb
= single_succ (l1_bb
);
9362 basic_block exit_bb
= region
->exit
;
9363 basic_block l2_dom_bb
= NULL
;
9365 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
9367 /* Below statements until the "tree high_val = ..." are pseudo statements
9368 used to pass information to be used by expand_omp_taskreg.
9369 low_val and high_val will be replaced by the __low and __high
9370 parameter from the child function.
9372 The call_exprs part is a place-holder, it is mainly used
9373 to distinctly identify to the top-level part that this is
9374 where we should put low and high (reasoning given in header
9378 = gimple_omp_parallel_child_fn (
9379 as_a
<gomp_parallel
*> (last_stmt (region
->outer
->entry
)));
9380 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
9381 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
9383 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
9385 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
9388 gcc_assert (low_val
&& high_val
);
9390 tree type
= TREE_TYPE (low_val
);
9391 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
9392 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
9394 /* Not needed in SSA form right now. */
9395 gcc_assert (!gimple_in_ssa_p (cfun
));
9396 if (l2_dom_bb
== NULL
)
9402 gimple
*stmt
= gimple_build_assign (ind_var
, n1
);
9404 /* Replace the GIMPLE_OMP_FOR statement. */
9405 gsi_replace (&gsi
, stmt
, true);
9409 /* Code to control the increment goes in the CONT_BB. */
9410 gsi
= gsi_last_bb (cont_bb
);
9411 stmt
= gsi_stmt (gsi
);
9412 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
9413 stmt
= gimple_build_assign (ind_var
, PLUS_EXPR
, ind_var
,
9414 build_one_cst (type
));
9416 /* Replace GIMPLE_OMP_CONTINUE. */
9417 gsi_replace (&gsi
, stmt
, true);
9420 /* Emit the condition in L1_BB. */
9421 gsi
= gsi_after_labels (l1_bb
);
9422 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
9423 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
9425 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
9426 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
9427 fd
->loop
.n1
, fold_convert (sizetype
, t
));
9429 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
9430 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
9431 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
9432 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
9434 /* The condition is always '<' since the runtime will fill in the low
9436 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
9437 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
9439 /* Remove GIMPLE_OMP_RETURN. */
9440 gsi
= gsi_last_bb (exit_bb
);
9441 gsi_remove (&gsi
, true);
9443 /* Connect the new blocks. */
9444 remove_edge (FALLTHRU_EDGE (entry_bb
));
9449 remove_edge (BRANCH_EDGE (entry_bb
));
9450 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
9452 e
= BRANCH_EDGE (l1_bb
);
9453 ne
= FALLTHRU_EDGE (l1_bb
);
9454 e
->flags
= EDGE_TRUE_VALUE
;
9458 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
9460 ne
= single_succ_edge (l1_bb
);
9461 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
9464 ne
->flags
= EDGE_FALSE_VALUE
;
9465 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
9466 ne
->probability
= REG_BR_PROB_BASE
/ 8;
9468 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
9469 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
9470 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
9474 struct loop
*loop
= alloc_loop ();
9475 loop
->header
= l1_bb
;
9476 loop
->latch
= cont_bb
;
9477 add_loop (loop
, l1_bb
->loop_father
);
9478 loop
->safelen
= INT_MAX
;
9481 /* Pick the correct library function based on the precision of the
9482 induction variable type. */
9483 tree lib_fun
= NULL_TREE
;
9484 if (TYPE_PRECISION (type
) == 32)
9485 lib_fun
= cilk_for_32_fndecl
;
9486 else if (TYPE_PRECISION (type
) == 64)
9487 lib_fun
= cilk_for_64_fndecl
;
9491 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
9493 /* WS_ARGS contains the library function flavor to call:
9494 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
9495 user-defined grain value. If the user does not define one, then zero
9496 is passed in by the parser. */
9497 vec_alloc (region
->ws_args
, 2);
9498 region
->ws_args
->quick_push (lib_fun
);
9499 region
->ws_args
->quick_push (fd
->chunk_size
);
9502 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
9503 loop. Given parameters:
9505 for (V = N1; V cond N2; V += STEP) BODY;
9507 where COND is "<" or ">", we generate pseudocode
9515 if (V cond N2) goto L0; else goto L2;
9518 For collapsed loops, given parameters:
9520 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
9521 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
9522 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
9525 we generate pseudocode
9531 count3 = (adj + N32 - N31) / STEP3;
9536 count2 = (adj + N22 - N21) / STEP2;
9541 count1 = (adj + N12 - N11) / STEP1;
9542 count = count1 * count2 * count3;
9552 V2 += (V3 cond3 N32) ? 0 : STEP2;
9553 V3 = (V3 cond3 N32) ? V3 : N31;
9554 V1 += (V2 cond2 N22) ? 0 : STEP1;
9555 V2 = (V2 cond2 N22) ? V2 : N21;
9557 if (V < count) goto L0; else goto L2;
9563 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
9566 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
9567 gimple_stmt_iterator gsi
;
9570 bool broken_loop
= region
->cont
== NULL
;
9572 tree
*counts
= NULL
;
9574 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
9575 OMP_CLAUSE_SAFELEN
);
9576 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
9577 OMP_CLAUSE__SIMDUID_
);
9580 type
= TREE_TYPE (fd
->loop
.v
);
9581 entry_bb
= region
->entry
;
9582 cont_bb
= region
->cont
;
9583 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
9584 gcc_assert (broken_loop
9585 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
9586 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
9589 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
9590 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
9591 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
9592 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
9596 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
9597 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
9598 l2_bb
= single_succ (l1_bb
);
9600 exit_bb
= region
->exit
;
9603 gsi
= gsi_last_bb (entry_bb
);
9605 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
9606 /* Not needed in SSA form right now. */
9607 gcc_assert (!gimple_in_ssa_p (cfun
));
9608 if (fd
->collapse
> 1)
9610 int first_zero_iter
= -1, dummy
= -1;
9611 basic_block zero_iter_bb
= l2_bb
, dummy_bb
= NULL
;
9613 counts
= XALLOCAVEC (tree
, fd
->collapse
);
9614 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
9615 zero_iter_bb
, first_zero_iter
,
9616 dummy_bb
, dummy
, l2_dom_bb
);
9618 if (l2_dom_bb
== NULL
)
9623 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9625 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
9626 OMP_CLAUSE__LOOPTEMP_
);
9627 gcc_assert (innerc
);
9628 n1
= OMP_CLAUSE_DECL (innerc
);
9629 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9630 OMP_CLAUSE__LOOPTEMP_
);
9631 gcc_assert (innerc
);
9632 n2
= OMP_CLAUSE_DECL (innerc
);
9633 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
9634 fold_convert (type
, n1
));
9635 if (fd
->collapse
> 1)
9638 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
9644 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
9645 fold_convert (type
, fd
->loop
.n1
));
9646 if (fd
->collapse
> 1)
9647 for (i
= 0; i
< fd
->collapse
; i
++)
9649 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
9650 if (POINTER_TYPE_P (itype
))
9651 itype
= signed_type_for (itype
);
9652 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
9653 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
9657 /* Remove the GIMPLE_OMP_FOR statement. */
9658 gsi_remove (&gsi
, true);
9662 /* Code to control the increment goes in the CONT_BB. */
9663 gsi
= gsi_last_bb (cont_bb
);
9664 stmt
= gsi_stmt (gsi
);
9665 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
9667 if (POINTER_TYPE_P (type
))
9668 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
9670 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
9671 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
9673 if (fd
->collapse
> 1)
9675 i
= fd
->collapse
- 1;
9676 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
9678 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
9679 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
9683 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
9685 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
9688 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
9690 for (i
= fd
->collapse
- 1; i
> 0; i
--)
9692 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
9693 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
9694 if (POINTER_TYPE_P (itype2
))
9695 itype2
= signed_type_for (itype2
);
9696 t
= build3 (COND_EXPR
, itype2
,
9697 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
9699 fold_convert (itype
, fd
->loops
[i
].n2
)),
9700 build_int_cst (itype2
, 0),
9701 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
9702 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
9703 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
9705 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
9706 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
9708 t
= build3 (COND_EXPR
, itype
,
9709 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
9711 fold_convert (itype
, fd
->loops
[i
].n2
)),
9713 fold_convert (itype
, fd
->loops
[i
].n1
));
9714 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
9718 /* Remove GIMPLE_OMP_CONTINUE. */
9719 gsi_remove (&gsi
, true);
9722 /* Emit the condition in L1_BB. */
9723 gsi
= gsi_start_bb (l1_bb
);
9725 t
= fold_convert (type
, n2
);
9726 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9727 false, GSI_CONTINUE_LINKING
);
9728 tree v
= fd
->loop
.v
;
9729 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
9730 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
9731 false, GSI_CONTINUE_LINKING
);
9732 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, v
, t
);
9733 cond_stmt
= gimple_build_cond_empty (t
);
9734 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
9735 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
9737 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
9740 gsi
= gsi_for_stmt (cond_stmt
);
9741 gimple_regimplify_operands (cond_stmt
, &gsi
);
9744 /* Remove GIMPLE_OMP_RETURN. */
9745 gsi
= gsi_last_bb (exit_bb
);
9746 gsi_remove (&gsi
, true);
9748 /* Connect the new blocks. */
9749 remove_edge (FALLTHRU_EDGE (entry_bb
));
9753 remove_edge (BRANCH_EDGE (entry_bb
));
9754 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
9756 e
= BRANCH_EDGE (l1_bb
);
9757 ne
= FALLTHRU_EDGE (l1_bb
);
9758 e
->flags
= EDGE_TRUE_VALUE
;
9762 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
9764 ne
= single_succ_edge (l1_bb
);
9765 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
9768 ne
->flags
= EDGE_FALSE_VALUE
;
9769 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
9770 ne
->probability
= REG_BR_PROB_BASE
/ 8;
9772 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
9773 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
9774 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
9778 struct loop
*loop
= alloc_loop ();
9779 loop
->header
= l1_bb
;
9780 loop
->latch
= cont_bb
;
9781 add_loop (loop
, l1_bb
->loop_father
);
9782 if (safelen
== NULL_TREE
)
9783 loop
->safelen
= INT_MAX
;
9786 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
9787 if (TREE_CODE (safelen
) != INTEGER_CST
)
9789 else if (!tree_fits_uhwi_p (safelen
)
9790 || tree_to_uhwi (safelen
) > INT_MAX
)
9791 loop
->safelen
= INT_MAX
;
9793 loop
->safelen
= tree_to_uhwi (safelen
);
9794 if (loop
->safelen
== 1)
9799 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
9800 cfun
->has_simduid_loops
= true;
9802 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
9804 if ((flag_tree_loop_vectorize
9805 || (!global_options_set
.x_flag_tree_loop_vectorize
9806 && !global_options_set
.x_flag_tree_vectorize
))
9807 && flag_tree_loop_optimize
9808 && loop
->safelen
> 1)
9810 loop
->force_vectorize
= true;
9811 cfun
->has_force_vectorize_loops
= true;
9815 cfun
->has_simduid_loops
= true;
9818 /* Taskloop construct is represented after gimplification with
9819 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
9820 in between them. This routine expands the outer GIMPLE_OMP_FOR,
9821 which should just compute all the needed loop temporaries
9822 for GIMPLE_OMP_TASK. */
9825 expand_omp_taskloop_for_outer (struct omp_region
*region
,
9826 struct omp_for_data
*fd
,
9829 tree type
, bias
= NULL_TREE
;
9830 basic_block entry_bb
, cont_bb
, exit_bb
;
9831 gimple_stmt_iterator gsi
;
9832 gassign
*assign_stmt
;
9833 tree
*counts
= NULL
;
9836 gcc_assert (inner_stmt
);
9837 gcc_assert (region
->cont
);
9838 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_TASK
9839 && gimple_omp_task_taskloop_p (inner_stmt
));
9840 type
= TREE_TYPE (fd
->loop
.v
);
9842 /* See if we need to bias by LLONG_MIN. */
9843 if (fd
->iter_type
== long_long_unsigned_type_node
9844 && TREE_CODE (type
) == INTEGER_TYPE
9845 && !TYPE_UNSIGNED (type
))
9849 if (fd
->loop
.cond_code
== LT_EXPR
)
9852 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
9856 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
9859 if (TREE_CODE (n1
) != INTEGER_CST
9860 || TREE_CODE (n2
) != INTEGER_CST
9861 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
9862 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
9865 entry_bb
= region
->entry
;
9866 cont_bb
= region
->cont
;
9867 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
9868 gcc_assert (BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
9869 exit_bb
= region
->exit
;
9871 gsi
= gsi_last_bb (entry_bb
);
9872 gimple
*for_stmt
= gsi_stmt (gsi
);
9873 gcc_assert (gimple_code (for_stmt
) == GIMPLE_OMP_FOR
);
9874 if (fd
->collapse
> 1)
9876 int first_zero_iter
= -1, dummy
= -1;
9877 basic_block zero_iter_bb
= NULL
, dummy_bb
= NULL
, l2_dom_bb
= NULL
;
9879 counts
= XALLOCAVEC (tree
, fd
->collapse
);
9880 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
9881 zero_iter_bb
, first_zero_iter
,
9882 dummy_bb
, dummy
, l2_dom_bb
);
9886 /* Some counts[i] vars might be uninitialized if
9887 some loop has zero iterations. But the body shouldn't
9888 be executed in that case, so just avoid uninit warnings. */
9889 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
9890 if (SSA_VAR_P (counts
[i
]))
9891 TREE_NO_WARNING (counts
[i
]) = 1;
9893 edge e
= split_block (entry_bb
, gsi_stmt (gsi
));
9895 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
9896 gsi
= gsi_last_bb (entry_bb
);
9897 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
9898 get_immediate_dominator (CDI_DOMINATORS
,
9906 if (POINTER_TYPE_P (TREE_TYPE (t0
))
9907 && TYPE_PRECISION (TREE_TYPE (t0
))
9908 != TYPE_PRECISION (fd
->iter_type
))
9910 /* Avoid casting pointers to integer of a different size. */
9911 tree itype
= signed_type_for (type
);
9912 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
9913 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
9917 t1
= fold_convert (fd
->iter_type
, t1
);
9918 t0
= fold_convert (fd
->iter_type
, t0
);
9922 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
9923 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
9926 tree innerc
= find_omp_clause (gimple_omp_task_clauses (inner_stmt
),
9927 OMP_CLAUSE__LOOPTEMP_
);
9928 gcc_assert (innerc
);
9929 tree startvar
= OMP_CLAUSE_DECL (innerc
);
9930 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
), OMP_CLAUSE__LOOPTEMP_
);
9931 gcc_assert (innerc
);
9932 tree endvar
= OMP_CLAUSE_DECL (innerc
);
9933 if (fd
->collapse
> 1 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
9935 gcc_assert (innerc
);
9936 for (i
= 1; i
< fd
->collapse
; i
++)
9938 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9939 OMP_CLAUSE__LOOPTEMP_
);
9940 gcc_assert (innerc
);
9942 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9943 OMP_CLAUSE__LOOPTEMP_
);
9946 /* If needed (inner taskloop has lastprivate clause), propagate
9947 down the total number of iterations. */
9948 tree t
= force_gimple_operand_gsi (&gsi
, fd
->loop
.n2
, false,
9950 GSI_CONTINUE_LINKING
);
9951 assign_stmt
= gimple_build_assign (OMP_CLAUSE_DECL (innerc
), t
);
9952 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9956 t0
= force_gimple_operand_gsi (&gsi
, t0
, false, NULL_TREE
, false,
9957 GSI_CONTINUE_LINKING
);
9958 assign_stmt
= gimple_build_assign (startvar
, t0
);
9959 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9961 t1
= force_gimple_operand_gsi (&gsi
, t1
, false, NULL_TREE
, false,
9962 GSI_CONTINUE_LINKING
);
9963 assign_stmt
= gimple_build_assign (endvar
, t1
);
9964 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9965 if (fd
->collapse
> 1)
9966 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
9968 /* Remove the GIMPLE_OMP_FOR statement. */
9969 gsi
= gsi_for_stmt (for_stmt
);
9970 gsi_remove (&gsi
, true);
9972 gsi
= gsi_last_bb (cont_bb
);
9973 gsi_remove (&gsi
, true);
9975 gsi
= gsi_last_bb (exit_bb
);
9976 gsi_remove (&gsi
, true);
9978 FALLTHRU_EDGE (entry_bb
)->probability
= REG_BR_PROB_BASE
;
9979 remove_edge (BRANCH_EDGE (entry_bb
));
9980 FALLTHRU_EDGE (cont_bb
)->probability
= REG_BR_PROB_BASE
;
9981 remove_edge (BRANCH_EDGE (cont_bb
));
9982 set_immediate_dominator (CDI_DOMINATORS
, exit_bb
, cont_bb
);
9983 set_immediate_dominator (CDI_DOMINATORS
, region
->entry
,
9984 recompute_dominator (CDI_DOMINATORS
, region
->entry
));
9987 /* Taskloop construct is represented after gimplification with
9988 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
9989 in between them. This routine expands the inner GIMPLE_OMP_FOR.
9990 GOMP_taskloop{,_ull} function arranges for each task to be given just
9991 a single range of iterations. */
9994 expand_omp_taskloop_for_inner (struct omp_region
*region
,
9995 struct omp_for_data
*fd
,
9998 tree e
, t
, type
, itype
, vmain
, vback
, bias
= NULL_TREE
;
9999 basic_block entry_bb
, exit_bb
, body_bb
, cont_bb
, collapse_bb
= NULL
;
10000 basic_block fin_bb
;
10001 gimple_stmt_iterator gsi
;
10003 bool broken_loop
= region
->cont
== NULL
;
10004 tree
*counts
= NULL
;
10007 itype
= type
= TREE_TYPE (fd
->loop
.v
);
10008 if (POINTER_TYPE_P (type
))
10009 itype
= signed_type_for (type
);
10011 /* See if we need to bias by LLONG_MIN. */
10012 if (fd
->iter_type
== long_long_unsigned_type_node
10013 && TREE_CODE (type
) == INTEGER_TYPE
10014 && !TYPE_UNSIGNED (type
))
10018 if (fd
->loop
.cond_code
== LT_EXPR
)
10021 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
10025 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
10028 if (TREE_CODE (n1
) != INTEGER_CST
10029 || TREE_CODE (n2
) != INTEGER_CST
10030 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
10031 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
10034 entry_bb
= region
->entry
;
10035 cont_bb
= region
->cont
;
10036 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
10037 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
10038 gcc_assert (broken_loop
10039 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
10040 body_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
10043 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
10044 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
10046 exit_bb
= region
->exit
;
10048 /* Iteration space partitioning goes in ENTRY_BB. */
10049 gsi
= gsi_last_bb (entry_bb
);
10050 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
10052 if (fd
->collapse
> 1)
10054 int first_zero_iter
= -1, dummy
= -1;
10055 basic_block l2_dom_bb
= NULL
, dummy_bb
= NULL
;
10057 counts
= XALLOCAVEC (tree
, fd
->collapse
);
10058 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
10059 fin_bb
, first_zero_iter
,
10060 dummy_bb
, dummy
, l2_dom_bb
);
10064 t
= integer_one_node
;
10066 step
= fd
->loop
.step
;
10067 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
10068 OMP_CLAUSE__LOOPTEMP_
);
10069 gcc_assert (innerc
);
10070 n1
= OMP_CLAUSE_DECL (innerc
);
10071 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
), OMP_CLAUSE__LOOPTEMP_
);
10072 gcc_assert (innerc
);
10073 n2
= OMP_CLAUSE_DECL (innerc
);
10076 n1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, n1
, bias
);
10077 n2
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, n2
, bias
);
10079 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
10080 true, NULL_TREE
, true, GSI_SAME_STMT
);
10081 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
10082 true, NULL_TREE
, true, GSI_SAME_STMT
);
10083 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
10084 true, NULL_TREE
, true, GSI_SAME_STMT
);
10086 tree startvar
= fd
->loop
.v
;
10087 tree endvar
= NULL_TREE
;
10089 if (gimple_omp_for_combined_p (fd
->for_stmt
))
10091 tree clauses
= gimple_omp_for_clauses (inner_stmt
);
10092 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
10093 gcc_assert (innerc
);
10094 startvar
= OMP_CLAUSE_DECL (innerc
);
10095 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
10096 OMP_CLAUSE__LOOPTEMP_
);
10097 gcc_assert (innerc
);
10098 endvar
= OMP_CLAUSE_DECL (innerc
);
10100 t
= fold_convert (TREE_TYPE (startvar
), n1
);
10101 t
= force_gimple_operand_gsi (&gsi
, t
,
10103 && TREE_ADDRESSABLE (startvar
),
10104 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
10105 gimple
*assign_stmt
= gimple_build_assign (startvar
, t
);
10106 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10108 t
= fold_convert (TREE_TYPE (startvar
), n2
);
10109 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
10110 false, GSI_CONTINUE_LINKING
);
10113 assign_stmt
= gimple_build_assign (endvar
, e
);
10114 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10115 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
10116 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
10118 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
10119 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10121 if (fd
->collapse
> 1)
10122 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
10126 /* The code controlling the sequential loop replaces the
10127 GIMPLE_OMP_CONTINUE. */
10128 gsi
= gsi_last_bb (cont_bb
);
10129 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
10130 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
10131 vmain
= gimple_omp_continue_control_use (cont_stmt
);
10132 vback
= gimple_omp_continue_control_def (cont_stmt
);
10134 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
10136 if (POINTER_TYPE_P (type
))
10137 t
= fold_build_pointer_plus (vmain
, step
);
10139 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
10140 t
= force_gimple_operand_gsi (&gsi
, t
,
10142 && TREE_ADDRESSABLE (vback
),
10143 NULL_TREE
, true, GSI_SAME_STMT
);
10144 assign_stmt
= gimple_build_assign (vback
, t
);
10145 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
10147 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
10148 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
10150 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
10153 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10154 gsi_remove (&gsi
, true);
10156 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
10157 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
10160 /* Remove the GIMPLE_OMP_FOR statement. */
10161 gsi
= gsi_for_stmt (fd
->for_stmt
);
10162 gsi_remove (&gsi
, true);
10164 /* Remove the GIMPLE_OMP_RETURN statement. */
10165 gsi
= gsi_last_bb (exit_bb
);
10166 gsi_remove (&gsi
, true);
10168 FALLTHRU_EDGE (entry_bb
)->probability
= REG_BR_PROB_BASE
;
10170 remove_edge (BRANCH_EDGE (entry_bb
));
10173 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb
));
10174 region
->outer
->cont
= NULL
;
10177 /* Connect all the blocks. */
10180 ep
= find_edge (cont_bb
, body_bb
);
10181 if (gimple_omp_for_combined_p (fd
->for_stmt
))
10186 else if (fd
->collapse
> 1)
10189 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
10192 ep
->flags
= EDGE_TRUE_VALUE
;
10193 find_edge (cont_bb
, fin_bb
)->flags
10194 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
10197 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
10198 recompute_dominator (CDI_DOMINATORS
, body_bb
));
10200 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
10201 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
10203 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
10205 struct loop
*loop
= alloc_loop ();
10206 loop
->header
= body_bb
;
10207 if (collapse_bb
== NULL
)
10208 loop
->latch
= cont_bb
;
10209 add_loop (loop
, body_bb
->loop_father
);
10213 /* Expand the OMP loop defined by REGION. */
10216 expand_omp_for (struct omp_region
*region
, gimple
*inner_stmt
)
10218 struct omp_for_data fd
;
10219 struct omp_for_data_loop
*loops
;
10222 = (struct omp_for_data_loop
*)
10223 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
10224 * sizeof (struct omp_for_data_loop
));
10225 extract_omp_for_data (as_a
<gomp_for
*> (last_stmt (region
->entry
)),
10227 region
->sched_kind
= fd
.sched_kind
;
10229 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
10230 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
10231 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
10234 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
10235 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
10236 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
10239 /* If there isn't a continue then this is a degerate case where
10240 the introduction of abnormal edges during lowering will prevent
10241 original loops from being detected. Fix that up. */
10242 loops_state_set (LOOPS_NEED_FIXUP
);
10244 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
10245 expand_omp_simd (region
, &fd
);
10246 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
10247 expand_cilk_for (region
, &fd
);
10248 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_TASKLOOP
)
10250 if (gimple_omp_for_combined_into_p (fd
.for_stmt
))
10251 expand_omp_taskloop_for_inner (region
, &fd
, inner_stmt
);
10253 expand_omp_taskloop_for_outer (region
, &fd
, inner_stmt
);
10255 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
10256 && !fd
.have_ordered
)
10258 if (fd
.chunk_size
== NULL
)
10259 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
10261 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
10265 int fn_index
, start_ix
, next_ix
;
10267 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
10268 == GF_OMP_FOR_KIND_FOR
);
10269 if (fd
.chunk_size
== NULL
10270 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
10271 fd
.chunk_size
= integer_zero_node
;
10272 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
10273 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
10274 ? 3 : fd
.sched_kind
;
10276 fn_index
+= fd
.have_ordered
* 4;
10278 start_ix
= ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START
) + fn_index
;
10280 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
10281 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
10282 if (fd
.iter_type
== long_long_unsigned_type_node
)
10284 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
10285 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
10286 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
10287 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
10289 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
10290 (enum built_in_function
) next_ix
, inner_stmt
);
10293 if (gimple_in_ssa_p (cfun
))
10294 update_ssa (TODO_update_ssa_only_virtuals
);
10298 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
10300 v = GOMP_sections_start (n);
10317 v = GOMP_sections_next ();
10322 If this is a combined parallel sections, replace the call to
10323 GOMP_sections_start with call to GOMP_sections_next. */
10326 expand_omp_sections (struct omp_region
*region
)
10328 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
10330 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
10331 gimple_stmt_iterator si
, switch_si
;
10332 gomp_sections
*sections_stmt
;
10334 gomp_continue
*cont
;
10337 struct omp_region
*inner
;
10339 bool exit_reachable
= region
->cont
!= NULL
;
10341 gcc_assert (region
->exit
!= NULL
);
10342 entry_bb
= region
->entry
;
10343 l0_bb
= single_succ (entry_bb
);
10344 l1_bb
= region
->cont
;
10345 l2_bb
= region
->exit
;
10346 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
10347 l2
= gimple_block_label (l2_bb
);
10350 /* This can happen if there are reductions. */
10351 len
= EDGE_COUNT (l0_bb
->succs
);
10352 gcc_assert (len
> 0);
10353 e
= EDGE_SUCC (l0_bb
, len
- 1);
10354 si
= gsi_last_bb (e
->dest
);
10357 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
10358 l2
= gimple_block_label (e
->dest
);
10360 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
10362 si
= gsi_last_bb (e
->dest
);
10364 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
10366 l2
= gimple_block_label (e
->dest
);
10371 if (exit_reachable
)
10372 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
10374 default_bb
= create_empty_bb (l0_bb
);
10376 /* We will build a switch() with enough cases for all the
10377 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
10378 and a default case to abort if something goes wrong. */
10379 len
= EDGE_COUNT (l0_bb
->succs
);
10381 /* Use vec::quick_push on label_vec throughout, since we know the size
10383 auto_vec
<tree
> label_vec (len
);
10385 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
10386 GIMPLE_OMP_SECTIONS statement. */
10387 si
= gsi_last_bb (entry_bb
);
10388 sections_stmt
= as_a
<gomp_sections
*> (gsi_stmt (si
));
10389 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
10390 vin
= gimple_omp_sections_control (sections_stmt
);
10391 if (!is_combined_parallel (region
))
10393 /* If we are not inside a combined parallel+sections region,
10394 call GOMP_sections_start. */
10395 t
= build_int_cst (unsigned_type_node
, len
- 1);
10396 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
10397 stmt
= gimple_build_call (u
, 1, t
);
10401 /* Otherwise, call GOMP_sections_next. */
10402 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
10403 stmt
= gimple_build_call (u
, 0);
10405 gimple_call_set_lhs (stmt
, vin
);
10406 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
10407 gsi_remove (&si
, true);
10409 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
10411 switch_si
= gsi_last_bb (l0_bb
);
10412 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
10413 if (exit_reachable
)
10415 cont
= as_a
<gomp_continue
*> (last_stmt (l1_bb
));
10416 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
10417 vmain
= gimple_omp_continue_control_use (cont
);
10418 vnext
= gimple_omp_continue_control_def (cont
);
10426 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
10427 label_vec
.quick_push (t
);
10430 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
10431 for (inner
= region
->inner
, casei
= 1;
10433 inner
= inner
->next
, i
++, casei
++)
10435 basic_block s_entry_bb
, s_exit_bb
;
10437 /* Skip optional reduction region. */
10438 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
10445 s_entry_bb
= inner
->entry
;
10446 s_exit_bb
= inner
->exit
;
10448 t
= gimple_block_label (s_entry_bb
);
10449 u
= build_int_cst (unsigned_type_node
, casei
);
10450 u
= build_case_label (u
, NULL
, t
);
10451 label_vec
.quick_push (u
);
10453 si
= gsi_last_bb (s_entry_bb
);
10454 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
10455 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
10456 gsi_remove (&si
, true);
10457 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
10459 if (s_exit_bb
== NULL
)
10462 si
= gsi_last_bb (s_exit_bb
);
10463 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
10464 gsi_remove (&si
, true);
10466 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
10469 /* Error handling code goes in DEFAULT_BB. */
10470 t
= gimple_block_label (default_bb
);
10471 u
= build_case_label (NULL
, NULL
, t
);
10472 make_edge (l0_bb
, default_bb
, 0);
10473 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
10475 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
10476 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
10477 gsi_remove (&switch_si
, true);
10479 si
= gsi_start_bb (default_bb
);
10480 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
10481 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
10483 if (exit_reachable
)
10487 /* Code to get the next section goes in L1_BB. */
10488 si
= gsi_last_bb (l1_bb
);
10489 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
10491 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
10492 stmt
= gimple_build_call (bfn_decl
, 0);
10493 gimple_call_set_lhs (stmt
, vnext
);
10494 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
10495 gsi_remove (&si
, true);
10497 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
10500 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
10501 si
= gsi_last_bb (l2_bb
);
10502 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
10503 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
10504 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
10505 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
10507 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
10508 stmt
= gimple_build_call (t
, 0);
10509 if (gimple_omp_return_lhs (gsi_stmt (si
)))
10510 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
10511 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
10512 gsi_remove (&si
, true);
10514 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
10518 /* Expand code for an OpenMP single directive. We've already expanded
10519 much of the code, here we simply place the GOMP_barrier call. */
10522 expand_omp_single (struct omp_region
*region
)
10524 basic_block entry_bb
, exit_bb
;
10525 gimple_stmt_iterator si
;
10527 entry_bb
= region
->entry
;
10528 exit_bb
= region
->exit
;
10530 si
= gsi_last_bb (entry_bb
);
10531 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
10532 gsi_remove (&si
, true);
10533 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
10535 si
= gsi_last_bb (exit_bb
);
10536 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
10538 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
10539 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
10541 gsi_remove (&si
, true);
10542 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
10546 /* Generic expansion for OpenMP synchronization directives: master,
10547 ordered and critical. All we need to do here is remove the entry
10548 and exit markers for REGION. */
10551 expand_omp_synch (struct omp_region
*region
)
10553 basic_block entry_bb
, exit_bb
;
10554 gimple_stmt_iterator si
;
10556 entry_bb
= region
->entry
;
10557 exit_bb
= region
->exit
;
10559 si
= gsi_last_bb (entry_bb
);
10560 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
10561 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
10562 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
10563 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
10564 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
10565 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
10566 gsi_remove (&si
, true);
10567 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
10571 si
= gsi_last_bb (exit_bb
);
10572 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
10573 gsi_remove (&si
, true);
10574 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
10578 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
10579 operation as a normal volatile load. */
10582 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
10583 tree loaded_val
, int index
)
10585 enum built_in_function tmpbase
;
10586 gimple_stmt_iterator gsi
;
10587 basic_block store_bb
;
10590 tree decl
, call
, type
, itype
;
10592 gsi
= gsi_last_bb (load_bb
);
10593 stmt
= gsi_stmt (gsi
);
10594 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
10595 loc
= gimple_location (stmt
);
10597 /* ??? If the target does not implement atomic_load_optab[mode], and mode
10598 is smaller than word size, then expand_atomic_load assumes that the load
10599 is atomic. We could avoid the builtin entirely in this case. */
10601 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
10602 decl
= builtin_decl_explicit (tmpbase
);
10603 if (decl
== NULL_TREE
)
10606 type
= TREE_TYPE (loaded_val
);
10607 itype
= TREE_TYPE (TREE_TYPE (decl
));
10609 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
10610 build_int_cst (NULL
,
10611 gimple_omp_atomic_seq_cst_p (stmt
)
10613 : MEMMODEL_RELAXED
));
10614 if (!useless_type_conversion_p (type
, itype
))
10615 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
10616 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
10618 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
10619 gsi_remove (&gsi
, true);
10621 store_bb
= single_succ (load_bb
);
10622 gsi
= gsi_last_bb (store_bb
);
10623 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
10624 gsi_remove (&gsi
, true);
10626 if (gimple_in_ssa_p (cfun
))
10627 update_ssa (TODO_update_ssa_no_phi
);
10632 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
10633 operation as a normal volatile store. */
10636 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
10637 tree loaded_val
, tree stored_val
, int index
)
10639 enum built_in_function tmpbase
;
10640 gimple_stmt_iterator gsi
;
10641 basic_block store_bb
= single_succ (load_bb
);
10644 tree decl
, call
, type
, itype
;
10645 machine_mode imode
;
10648 gsi
= gsi_last_bb (load_bb
);
10649 stmt
= gsi_stmt (gsi
);
10650 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
10652 /* If the load value is needed, then this isn't a store but an exchange. */
10653 exchange
= gimple_omp_atomic_need_value_p (stmt
);
10655 gsi
= gsi_last_bb (store_bb
);
10656 stmt
= gsi_stmt (gsi
);
10657 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
10658 loc
= gimple_location (stmt
);
10660 /* ??? If the target does not implement atomic_store_optab[mode], and mode
10661 is smaller than word size, then expand_atomic_store assumes that the store
10662 is atomic. We could avoid the builtin entirely in this case. */
10664 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
10665 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
10666 decl
= builtin_decl_explicit (tmpbase
);
10667 if (decl
== NULL_TREE
)
10670 type
= TREE_TYPE (stored_val
);
10672 /* Dig out the type of the function's second argument. */
10673 itype
= TREE_TYPE (decl
);
10674 itype
= TYPE_ARG_TYPES (itype
);
10675 itype
= TREE_CHAIN (itype
);
10676 itype
= TREE_VALUE (itype
);
10677 imode
= TYPE_MODE (itype
);
10679 if (exchange
&& !can_atomic_exchange_p (imode
, true))
10682 if (!useless_type_conversion_p (itype
, type
))
10683 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
10684 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
10685 build_int_cst (NULL
,
10686 gimple_omp_atomic_seq_cst_p (stmt
)
10688 : MEMMODEL_RELAXED
));
10691 if (!useless_type_conversion_p (type
, itype
))
10692 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
10693 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
10696 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
10697 gsi_remove (&gsi
, true);
10699 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
10700 gsi
= gsi_last_bb (load_bb
);
10701 gsi_remove (&gsi
, true);
10703 if (gimple_in_ssa_p (cfun
))
10704 update_ssa (TODO_update_ssa_no_phi
);
10709 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
10710 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
10711 size of the data type, and thus usable to find the index of the builtin
10712 decl. Returns false if the expression is not of the proper form. */
10715 expand_omp_atomic_fetch_op (basic_block load_bb
,
10716 tree addr
, tree loaded_val
,
10717 tree stored_val
, int index
)
10719 enum built_in_function oldbase
, newbase
, tmpbase
;
10720 tree decl
, itype
, call
;
10722 basic_block store_bb
= single_succ (load_bb
);
10723 gimple_stmt_iterator gsi
;
10726 enum tree_code code
;
10727 bool need_old
, need_new
;
10728 machine_mode imode
;
10731 /* We expect to find the following sequences:
10734 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
10737 val = tmp OP something; (or: something OP tmp)
10738 GIMPLE_OMP_STORE (val)
10740 ???FIXME: Allow a more flexible sequence.
10741 Perhaps use data flow to pick the statements.
10745 gsi
= gsi_after_labels (store_bb
);
10746 stmt
= gsi_stmt (gsi
);
10747 loc
= gimple_location (stmt
);
10748 if (!is_gimple_assign (stmt
))
10751 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
10753 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
10754 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
10755 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
10756 gcc_checking_assert (!need_old
|| !need_new
);
10758 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
10761 /* Check for one of the supported fetch-op operations. */
10762 code
= gimple_assign_rhs_code (stmt
);
10766 case POINTER_PLUS_EXPR
:
10767 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
10768 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
10771 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
10772 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
10775 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
10776 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
10779 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
10780 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
10783 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
10784 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
10790 /* Make sure the expression is of the proper form. */
10791 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
10792 rhs
= gimple_assign_rhs2 (stmt
);
10793 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
10794 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
10795 rhs
= gimple_assign_rhs1 (stmt
);
10799 tmpbase
= ((enum built_in_function
)
10800 ((need_new
? newbase
: oldbase
) + index
+ 1));
10801 decl
= builtin_decl_explicit (tmpbase
);
10802 if (decl
== NULL_TREE
)
10804 itype
= TREE_TYPE (TREE_TYPE (decl
));
10805 imode
= TYPE_MODE (itype
);
10807 /* We could test all of the various optabs involved, but the fact of the
10808 matter is that (with the exception of i486 vs i586 and xadd) all targets
10809 that support any atomic operaton optab also implements compare-and-swap.
10810 Let optabs.c take care of expanding any compare-and-swap loop. */
10811 if (!can_compare_and_swap_p (imode
, true))
10814 gsi
= gsi_last_bb (load_bb
);
10815 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
10817 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
10818 It only requires that the operation happen atomically. Thus we can
10819 use the RELAXED memory model. */
10820 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
10821 fold_convert_loc (loc
, itype
, rhs
),
10822 build_int_cst (NULL
,
10823 seq_cst
? MEMMODEL_SEQ_CST
10824 : MEMMODEL_RELAXED
));
10826 if (need_old
|| need_new
)
10828 lhs
= need_old
? loaded_val
: stored_val
;
10829 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
10830 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
10833 call
= fold_convert_loc (loc
, void_type_node
, call
);
10834 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
10835 gsi_remove (&gsi
, true);
10837 gsi
= gsi_last_bb (store_bb
);
10838 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
10839 gsi_remove (&gsi
, true);
10840 gsi
= gsi_last_bb (store_bb
);
10841 gsi_remove (&gsi
, true);
10843 if (gimple_in_ssa_p (cfun
))
10844 update_ssa (TODO_update_ssa_no_phi
);
10849 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
10853 newval = rhs; // with oldval replacing *addr in rhs
10854 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
10855 if (oldval != newval)
10858 INDEX is log2 of the size of the data type, and thus usable to find the
10859 index of the builtin decl. */
10862 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
10863 tree addr
, tree loaded_val
, tree stored_val
,
10866 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
10867 tree type
, itype
, cmpxchg
, iaddr
;
10868 gimple_stmt_iterator si
;
10869 basic_block loop_header
= single_succ (load_bb
);
10870 gimple
*phi
, *stmt
;
10872 enum built_in_function fncode
;
10874 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
10875 order to use the RELAXED memory model effectively. */
10876 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
10878 cmpxchg
= builtin_decl_explicit (fncode
);
10879 if (cmpxchg
== NULL_TREE
)
10881 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
10882 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
10884 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
10887 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
10888 si
= gsi_last_bb (load_bb
);
10889 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
10891 /* For floating-point values, we'll need to view-convert them to integers
10892 so that we can perform the atomic compare and swap. Simplify the
10893 following code by always setting up the "i"ntegral variables. */
10894 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
10898 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
10901 = force_gimple_operand_gsi (&si
,
10902 fold_convert (TREE_TYPE (iaddr
), addr
),
10903 false, NULL_TREE
, true, GSI_SAME_STMT
);
10904 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
10905 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
10906 loadedi
= create_tmp_var (itype
);
10907 if (gimple_in_ssa_p (cfun
))
10908 loadedi
= make_ssa_name (loadedi
);
10913 loadedi
= loaded_val
;
10916 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
10917 tree loaddecl
= builtin_decl_explicit (fncode
);
10920 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
10921 build_call_expr (loaddecl
, 2, iaddr
,
10922 build_int_cst (NULL_TREE
,
10923 MEMMODEL_RELAXED
)));
10925 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
10926 build_int_cst (TREE_TYPE (iaddr
), 0));
10929 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
10932 /* Move the value to the LOADEDI temporary. */
10933 if (gimple_in_ssa_p (cfun
))
10935 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
10936 phi
= create_phi_node (loadedi
, loop_header
);
10937 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
10941 gsi_insert_before (&si
,
10942 gimple_build_assign (loadedi
, initial
),
10944 if (loadedi
!= loaded_val
)
10946 gimple_stmt_iterator gsi2
;
10949 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
10950 gsi2
= gsi_start_bb (loop_header
);
10951 if (gimple_in_ssa_p (cfun
))
10954 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
10955 true, GSI_SAME_STMT
);
10956 stmt
= gimple_build_assign (loaded_val
, x
);
10957 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
10961 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
10962 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
10963 true, GSI_SAME_STMT
);
10966 gsi_remove (&si
, true);
10968 si
= gsi_last_bb (store_bb
);
10969 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
10972 storedi
= stored_val
;
10975 force_gimple_operand_gsi (&si
,
10976 build1 (VIEW_CONVERT_EXPR
, itype
,
10977 stored_val
), true, NULL_TREE
, true,
10980 /* Build the compare&swap statement. */
10981 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
10982 new_storedi
= force_gimple_operand_gsi (&si
,
10983 fold_convert (TREE_TYPE (loadedi
),
10986 true, GSI_SAME_STMT
);
10988 if (gimple_in_ssa_p (cfun
))
10989 old_vali
= loadedi
;
10992 old_vali
= create_tmp_var (TREE_TYPE (loadedi
));
10993 stmt
= gimple_build_assign (old_vali
, loadedi
);
10994 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
10996 stmt
= gimple_build_assign (loadedi
, new_storedi
);
10997 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
11000 /* Note that we always perform the comparison as an integer, even for
11001 floating point. This allows the atomic operation to properly
11002 succeed even with NaNs and -0.0. */
11003 stmt
= gimple_build_cond_empty
11004 (build2 (NE_EXPR
, boolean_type_node
,
11005 new_storedi
, old_vali
));
11006 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
11009 e
= single_succ_edge (store_bb
);
11010 e
->flags
&= ~EDGE_FALLTHRU
;
11011 e
->flags
|= EDGE_FALSE_VALUE
;
11013 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
11015 /* Copy the new value to loadedi (we already did that before the condition
11016 if we are not in SSA). */
11017 if (gimple_in_ssa_p (cfun
))
11019 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
11020 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
11023 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
11024 gsi_remove (&si
, true);
11026 struct loop
*loop
= alloc_loop ();
11027 loop
->header
= loop_header
;
11028 loop
->latch
= store_bb
;
11029 add_loop (loop
, loop_header
->loop_father
);
11031 if (gimple_in_ssa_p (cfun
))
11032 update_ssa (TODO_update_ssa_no_phi
);
11037 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11039 GOMP_atomic_start ();
11041 GOMP_atomic_end ();
11043 The result is not globally atomic, but works so long as all parallel
11044 references are within #pragma omp atomic directives. According to
11045 responses received from omp@openmp.org, appears to be within spec.
11046 Which makes sense, since that's how several other compilers handle
11047 this situation as well.
11048 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
11049 expanding. STORED_VAL is the operand of the matching
11050 GIMPLE_OMP_ATOMIC_STORE.
11053 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
11054 loaded_val = *addr;
11057 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
11058 *addr = stored_val;
11062 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
11063 tree addr
, tree loaded_val
, tree stored_val
)
11065 gimple_stmt_iterator si
;
11069 si
= gsi_last_bb (load_bb
);
11070 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
11072 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
11073 t
= build_call_expr (t
, 0);
11074 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
11076 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
11077 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
11078 gsi_remove (&si
, true);
11080 si
= gsi_last_bb (store_bb
);
11081 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
11083 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
11085 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
11087 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
11088 t
= build_call_expr (t
, 0);
11089 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
11090 gsi_remove (&si
, true);
11092 if (gimple_in_ssa_p (cfun
))
11093 update_ssa (TODO_update_ssa_no_phi
);
11097 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
11098 using expand_omp_atomic_fetch_op. If it failed, we try to
11099 call expand_omp_atomic_pipeline, and if it fails too, the
11100 ultimate fallback is wrapping the operation in a mutex
11101 (expand_omp_atomic_mutex). REGION is the atomic region built
11102 by build_omp_regions_1(). */
11105 expand_omp_atomic (struct omp_region
*region
)
11107 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
11108 gomp_atomic_load
*load
= as_a
<gomp_atomic_load
*> (last_stmt (load_bb
));
11109 gomp_atomic_store
*store
= as_a
<gomp_atomic_store
*> (last_stmt (store_bb
));
11110 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
11111 tree addr
= gimple_omp_atomic_load_rhs (load
);
11112 tree stored_val
= gimple_omp_atomic_store_val (store
);
11113 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
11114 HOST_WIDE_INT index
;
11116 /* Make sure the type is one of the supported sizes. */
11117 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
11118 index
= exact_log2 (index
);
11119 if (index
>= 0 && index
<= 4)
11121 unsigned int align
= TYPE_ALIGN_UNIT (type
);
11123 /* __sync builtins require strict data alignment. */
11124 if (exact_log2 (align
) >= index
)
11127 if (loaded_val
== stored_val
11128 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
11129 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
11130 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
11131 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
11134 /* Atomic store. */
11135 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
11136 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
11137 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
11138 && store_bb
== single_succ (load_bb
)
11139 && first_stmt (store_bb
) == store
11140 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
11141 stored_val
, index
))
11144 /* When possible, use specialized atomic update functions. */
11145 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
11146 && store_bb
== single_succ (load_bb
)
11147 && expand_omp_atomic_fetch_op (load_bb
, addr
,
11148 loaded_val
, stored_val
, index
))
11151 /* If we don't have specialized __sync builtins, try and implement
11152 as a compare and swap loop. */
11153 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
11154 loaded_val
, stored_val
, index
))
11159 /* The ultimate fallback is wrapping the operation in a mutex. */
11160 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
11164 /* Encode an oacc launc argument. This matches the GOMP_LAUNCH_PACK
11165 macro on gomp-constants.h. We do not check for overflow. */
11168 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
11172 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
11175 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
11176 device
, build_int_cst (unsigned_type_node
,
11177 GOMP_LAUNCH_DEVICE_SHIFT
));
11178 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
11183 /* Look for compute grid dimension clauses and convert to an attribute
11184 attached to FN. This permits the target-side code to (a) massage
11185 the dimensions, (b) emit that data and (c) optimize. Non-constant
11186 dimensions are pushed onto ARGS.
11188 The attribute value is a TREE_LIST. A set of dimensions is
11189 represented as a list of INTEGER_CST. Those that are runtime
11190 expres are represented as an INTEGER_CST of zero.
11192 TOOO. Normally the attribute will just contain a single such list. If
11193 however it contains a list of lists, this will represent the use of
11194 device_type. Each member of the outer list is an assoc list of
11195 dimensions, keyed by the device type. The first entry will be the
11196 default. Well, that's the plan. */
11198 #define OACC_FN_ATTRIB "oacc function"
11200 /* Replace any existing oacc fn attribute with updated dimensions. */
11203 replace_oacc_fn_attrib (tree fn
, tree dims
)
11205 tree ident
= get_identifier (OACC_FN_ATTRIB
);
11206 tree attribs
= DECL_ATTRIBUTES (fn
);
11208 /* If we happen to be present as the first attrib, drop it. */
11209 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
11210 attribs
= TREE_CHAIN (attribs
);
11211 DECL_ATTRIBUTES (fn
) = tree_cons (ident
, dims
, attribs
);
11214 /* Scan CLAUSES for launch dimensions and attach them to the oacc
11215 function attribute. Push any that are non-constant onto the ARGS
11216 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
11219 set_oacc_fn_attrib (tree fn
, tree clauses
, vec
<tree
> *args
)
11221 /* Must match GOMP_DIM ordering. */
11222 static const omp_clause_code ids
[]
11223 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
11224 OMP_CLAUSE_VECTOR_LENGTH
};
11226 tree dims
[GOMP_DIM_MAX
];
11227 tree attr
= NULL_TREE
;
11228 unsigned non_const
= 0;
11230 for (ix
= GOMP_DIM_MAX
; ix
--;)
11232 tree clause
= find_omp_clause (clauses
, ids
[ix
]);
11233 tree dim
= NULL_TREE
;
11236 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
11238 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
11240 dim
= integer_zero_node
;
11241 non_const
|= GOMP_DIM_MASK (ix
);
11243 attr
= tree_cons (NULL_TREE
, dim
, attr
);
11246 replace_oacc_fn_attrib (fn
, attr
);
11250 /* Push a dynamic argument set. */
11251 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
11252 NULL_TREE
, non_const
));
11253 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
11254 if (non_const
& GOMP_DIM_MASK (ix
))
11255 args
->safe_push (dims
[ix
]);
11259 /* Retrieve the oacc function attrib and return it. Non-oacc
11260 functions will return NULL. */
11263 get_oacc_fn_attrib (tree fn
)
11265 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
11268 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
11271 expand_omp_target (struct omp_region
*region
)
11273 basic_block entry_bb
, exit_bb
, new_bb
;
11274 struct function
*child_cfun
;
11275 tree child_fn
, block
, t
;
11276 gimple_stmt_iterator gsi
;
11277 gomp_target
*entry_stmt
;
11280 bool offloaded
, data_region
;
11282 entry_stmt
= as_a
<gomp_target
*> (last_stmt (region
->entry
));
11283 new_bb
= region
->entry
;
11285 offloaded
= is_gimple_omp_offloaded (entry_stmt
);
11286 switch (gimple_omp_target_kind (entry_stmt
))
11288 case GF_OMP_TARGET_KIND_REGION
:
11289 case GF_OMP_TARGET_KIND_UPDATE
:
11290 case GF_OMP_TARGET_KIND_ENTER_DATA
:
11291 case GF_OMP_TARGET_KIND_EXIT_DATA
:
11292 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
11293 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
11294 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
11295 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
11296 data_region
= false;
11298 case GF_OMP_TARGET_KIND_DATA
:
11299 case GF_OMP_TARGET_KIND_OACC_DATA
:
11300 data_region
= true;
11303 gcc_unreachable ();
11306 child_fn
= NULL_TREE
;
11310 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
11311 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
11314 /* Supported by expand_omp_taskreg, but not here. */
11315 if (child_cfun
!= NULL
)
11316 gcc_checking_assert (!child_cfun
->cfg
);
11317 gcc_checking_assert (!gimple_in_ssa_p (cfun
));
11319 entry_bb
= region
->entry
;
11320 exit_bb
= region
->exit
;
11324 unsigned srcidx
, dstidx
, num
;
11326 /* If the offloading region needs data sent from the parent
11327 function, then the very first statement (except possible
11328 tree profile counter updates) of the offloading body
11329 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
11330 &.OMP_DATA_O is passed as an argument to the child function,
11331 we need to replace it with the argument as seen by the child
11334 In most cases, this will end up being the identity assignment
11335 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
11336 a function call that has been inlined, the original PARM_DECL
11337 .OMP_DATA_I may have been converted into a different local
11338 variable. In which case, we need to keep the assignment. */
11339 tree data_arg
= gimple_omp_target_data_arg (entry_stmt
);
11342 basic_block entry_succ_bb
= single_succ (entry_bb
);
11343 gimple_stmt_iterator gsi
;
11345 gimple
*tgtcopy_stmt
= NULL
;
11346 tree sender
= TREE_VEC_ELT (data_arg
, 0);
11348 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
11350 gcc_assert (!gsi_end_p (gsi
));
11351 stmt
= gsi_stmt (gsi
);
11352 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
11355 if (gimple_num_ops (stmt
) == 2)
11357 tree arg
= gimple_assign_rhs1 (stmt
);
11359 /* We're ignoring the subcode because we're
11360 effectively doing a STRIP_NOPS. */
11362 if (TREE_CODE (arg
) == ADDR_EXPR
11363 && TREE_OPERAND (arg
, 0) == sender
)
11365 tgtcopy_stmt
= stmt
;
11371 gcc_assert (tgtcopy_stmt
!= NULL
);
11372 arg
= DECL_ARGUMENTS (child_fn
);
11374 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
11375 gsi_remove (&gsi
, true);
11378 /* Declare local variables needed in CHILD_CFUN. */
11379 block
= DECL_INITIAL (child_fn
);
11380 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
11381 /* The gimplifier could record temporaries in the offloading block
11382 rather than in containing function's local_decls chain,
11383 which would mean cgraph missed finalizing them. Do it now. */
11384 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
11385 if (TREE_CODE (t
) == VAR_DECL
11387 && !DECL_EXTERNAL (t
))
11388 varpool_node::finalize_decl (t
);
11389 DECL_SAVED_TREE (child_fn
) = NULL
;
11390 /* We'll create a CFG for child_fn, so no gimple body is needed. */
11391 gimple_set_body (child_fn
, NULL
);
11392 TREE_USED (block
) = 1;
11394 /* Reset DECL_CONTEXT on function arguments. */
11395 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
11396 DECL_CONTEXT (t
) = child_fn
;
11398 /* Split ENTRY_BB at GIMPLE_*,
11399 so that it can be moved to the child function. */
11400 gsi
= gsi_last_bb (entry_bb
);
11401 stmt
= gsi_stmt (gsi
);
11403 && gimple_code (stmt
) == gimple_code (entry_stmt
));
11404 e
= split_block (entry_bb
, stmt
);
11405 gsi_remove (&gsi
, true);
11406 entry_bb
= e
->dest
;
11407 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
11409 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
11412 gsi
= gsi_last_bb (exit_bb
);
11413 gcc_assert (!gsi_end_p (gsi
)
11414 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
11415 stmt
= gimple_build_return (NULL
);
11416 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
11417 gsi_remove (&gsi
, true);
11420 /* Move the offloading region into CHILD_CFUN. */
11422 block
= gimple_block (entry_stmt
);
11424 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
11426 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
11427 /* When the OMP expansion process cannot guarantee an up-to-date
11428 loop tree arrange for the child function to fixup loops. */
11429 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
11430 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
11432 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
11433 num
= vec_safe_length (child_cfun
->local_decls
);
11434 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
11436 t
= (*child_cfun
->local_decls
)[srcidx
];
11437 if (DECL_CONTEXT (t
) == cfun
->decl
)
11439 if (srcidx
!= dstidx
)
11440 (*child_cfun
->local_decls
)[dstidx
] = t
;
11444 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
11446 /* Inform the callgraph about the new function. */
11447 child_cfun
->curr_properties
= cfun
->curr_properties
;
11448 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
11449 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
11450 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
11451 node
->parallelized_function
= 1;
11452 cgraph_node::add_new_function (child_fn
, true);
11454 #ifdef ENABLE_OFFLOADING
11455 /* Add the new function to the offload table. */
11456 vec_safe_push (offload_funcs
, child_fn
);
11459 /* Fix the callgraph edges for child_cfun. Those for cfun will be
11460 fixed in a following pass. */
11461 push_cfun (child_cfun
);
11462 cgraph_edge::rebuild_edges ();
11464 #ifdef ENABLE_OFFLOADING
11465 /* Prevent IPA from removing child_fn as unreachable, since there are no
11466 refs from the parent function to child_fn in offload LTO mode. */
11467 cgraph_node::get (child_fn
)->mark_force_output ();
11470 /* Some EH regions might become dead, see PR34608. If
11471 pass_cleanup_cfg isn't the first pass to happen with the
11472 new child, these dead EH edges might cause problems.
11473 Clean them up now. */
11474 if (flag_exceptions
)
11477 bool changed
= false;
11479 FOR_EACH_BB_FN (bb
, cfun
)
11480 changed
|= gimple_purge_dead_eh_edges (bb
);
11482 cleanup_tree_cfg ();
11484 #ifdef ENABLE_CHECKING
11485 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
11486 verify_loop_structure ();
11491 /* Emit a library call to launch the offloading region, or do data
11493 tree t1
, t2
, t3
, t4
, device
, cond
, depend
, c
, clauses
;
11494 enum built_in_function start_ix
;
11495 location_t clause_loc
;
11496 unsigned int flags_i
= 0;
11498 switch (gimple_omp_target_kind (entry_stmt
))
11500 case GF_OMP_TARGET_KIND_REGION
:
11501 start_ix
= BUILT_IN_GOMP_TARGET
;
11503 case GF_OMP_TARGET_KIND_DATA
:
11504 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
11506 case GF_OMP_TARGET_KIND_UPDATE
:
11507 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
11509 case GF_OMP_TARGET_KIND_ENTER_DATA
:
11510 start_ix
= BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
;
11512 case GF_OMP_TARGET_KIND_EXIT_DATA
:
11513 start_ix
= BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
;
11514 flags_i
|= GOMP_TARGET_FLAG_EXIT_DATA
;
11516 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
11517 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
11518 start_ix
= BUILT_IN_GOACC_PARALLEL
;
11520 case GF_OMP_TARGET_KIND_OACC_DATA
:
11521 start_ix
= BUILT_IN_GOACC_DATA_START
;
11523 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
11524 start_ix
= BUILT_IN_GOACC_UPDATE
;
11526 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
11527 start_ix
= BUILT_IN_GOACC_ENTER_EXIT_DATA
;
11530 gcc_unreachable ();
11533 clauses
= gimple_omp_target_clauses (entry_stmt
);
11535 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
11536 library choose) and there is no conditional. */
11538 device
= build_int_cst (integer_type_node
, GOMP_DEVICE_ICV
);
11540 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
11542 cond
= OMP_CLAUSE_IF_EXPR (c
);
11544 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
11547 /* Even if we pass it to all library function calls, it is currently only
11548 defined/used for the OpenMP target ones. */
11549 gcc_checking_assert (start_ix
== BUILT_IN_GOMP_TARGET
11550 || start_ix
== BUILT_IN_GOMP_TARGET_DATA
11551 || start_ix
== BUILT_IN_GOMP_TARGET_UPDATE
11552 || start_ix
== BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
);
11554 device
= OMP_CLAUSE_DEVICE_ID (c
);
11555 clause_loc
= OMP_CLAUSE_LOCATION (c
);
11558 clause_loc
= gimple_location (entry_stmt
);
11560 c
= find_omp_clause (clauses
, OMP_CLAUSE_NOWAIT
);
11562 flags_i
|= GOMP_TARGET_FLAG_NOWAIT
;
11564 /* Ensure 'device' is of the correct type. */
11565 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
11567 /* If we found the clause 'if (cond)', build
11568 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
11571 cond
= gimple_boolify (cond
);
11573 basic_block cond_bb
, then_bb
, else_bb
;
11577 tmp_var
= create_tmp_var (TREE_TYPE (device
));
11579 e
= split_block_after_labels (new_bb
);
11582 gsi
= gsi_last_bb (new_bb
);
11584 e
= split_block (new_bb
, gsi_stmt (gsi
));
11590 then_bb
= create_empty_bb (cond_bb
);
11591 else_bb
= create_empty_bb (then_bb
);
11592 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
11593 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
11595 stmt
= gimple_build_cond_empty (cond
);
11596 gsi
= gsi_last_bb (cond_bb
);
11597 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
11599 gsi
= gsi_start_bb (then_bb
);
11600 stmt
= gimple_build_assign (tmp_var
, device
);
11601 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
11603 gsi
= gsi_start_bb (else_bb
);
11604 stmt
= gimple_build_assign (tmp_var
,
11605 build_int_cst (integer_type_node
,
11606 GOMP_DEVICE_HOST_FALLBACK
));
11607 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
11609 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
11610 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
11611 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
11612 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
11613 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
11614 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
11619 gsi
= gsi_last_bb (new_bb
);
11620 t
= gimple_omp_target_data_arg (entry_stmt
);
11623 t1
= size_zero_node
;
11624 t2
= build_zero_cst (ptr_type_node
);
11630 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
11631 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
11632 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
11633 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
11634 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
11638 bool tagging
= false;
11639 /* The maximum number used by any start_ix, without varargs. */
11640 auto_vec
<tree
, 11> args
;
11641 args
.quick_push (device
);
11643 args
.quick_push (build_fold_addr_expr (child_fn
));
11644 args
.quick_push (t1
);
11645 args
.quick_push (t2
);
11646 args
.quick_push (t3
);
11647 args
.quick_push (t4
);
11650 case BUILT_IN_GOACC_DATA_START
:
11651 case BUILT_IN_GOMP_TARGET_DATA
:
11653 case BUILT_IN_GOMP_TARGET
:
11654 case BUILT_IN_GOMP_TARGET_UPDATE
:
11655 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
:
11656 args
.quick_push (build_int_cst (unsigned_type_node
, flags_i
));
11657 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
11659 depend
= OMP_CLAUSE_DECL (c
);
11661 depend
= build_int_cst (ptr_type_node
, 0);
11662 args
.quick_push (depend
);
11664 case BUILT_IN_GOACC_PARALLEL
:
11666 set_oacc_fn_attrib (child_fn
, clauses
, &args
);
11670 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
11671 case BUILT_IN_GOACC_UPDATE
:
11673 tree t_async
= NULL_TREE
;
11675 /* If present, use the value specified by the respective
11676 clause, making sure that is of the correct type. */
11677 c
= find_omp_clause (clauses
, OMP_CLAUSE_ASYNC
);
11679 t_async
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
11681 OMP_CLAUSE_ASYNC_EXPR (c
));
11683 /* Default values for t_async. */
11684 t_async
= fold_convert_loc (gimple_location (entry_stmt
),
11686 build_int_cst (integer_type_node
,
11688 if (tagging
&& t_async
)
11690 unsigned HOST_WIDE_INT i_async
;
11692 if (TREE_CODE (t_async
) == INTEGER_CST
)
11694 /* See if we can pack the async arg in to the tag's
11696 i_async
= TREE_INT_CST_LOW (t_async
);
11698 if (i_async
< GOMP_LAUNCH_OP_MAX
)
11699 t_async
= NULL_TREE
;
11702 i_async
= GOMP_LAUNCH_OP_MAX
;
11703 args
.safe_push (oacc_launch_pack
11704 (GOMP_LAUNCH_ASYNC
, NULL_TREE
, i_async
));
11707 args
.safe_push (t_async
);
11709 /* Save the argument index, and ... */
11710 unsigned t_wait_idx
= args
.length ();
11711 unsigned num_waits
= 0;
11712 c
= find_omp_clause (clauses
, OMP_CLAUSE_WAIT
);
11714 /* ... push a placeholder. */
11715 args
.safe_push (integer_zero_node
);
11717 for (; c
; c
= OMP_CLAUSE_CHAIN (c
))
11718 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WAIT
)
11720 args
.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
11722 OMP_CLAUSE_WAIT_EXPR (c
)));
11726 if (!tagging
|| num_waits
)
11730 /* Now that we know the number, update the placeholder. */
11732 len
= oacc_launch_pack (GOMP_LAUNCH_WAIT
, NULL_TREE
, num_waits
);
11734 len
= build_int_cst (integer_type_node
, num_waits
);
11735 len
= fold_convert_loc (gimple_location (entry_stmt
),
11736 unsigned_type_node
, len
);
11737 args
[t_wait_idx
] = len
;
11742 gcc_unreachable ();
11745 /* Push terminal marker - zero. */
11746 args
.safe_push (oacc_launch_pack (0, NULL_TREE
, 0));
11748 g
= gimple_build_call_vec (builtin_decl_explicit (start_ix
), args
);
11749 gimple_set_location (g
, gimple_location (entry_stmt
));
11750 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
11753 g
= gsi_stmt (gsi
);
11754 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
11755 gsi_remove (&gsi
, true);
11757 if (data_region
&& region
->exit
)
11759 gsi
= gsi_last_bb (region
->exit
);
11760 g
= gsi_stmt (gsi
);
11761 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
11762 gsi_remove (&gsi
, true);
11767 /* Expand the parallel region tree rooted at REGION. Expansion
11768 proceeds in depth-first order. Innermost regions are expanded
11769 first. This way, parallel regions that require a new function to
11770 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
11771 internal dependencies in their body. */
11774 expand_omp (struct omp_region
*region
)
11778 location_t saved_location
;
11779 gimple
*inner_stmt
= NULL
;
11781 /* First, determine whether this is a combined parallel+workshare
11783 if (region
->type
== GIMPLE_OMP_PARALLEL
)
11784 determine_parallel_type (region
);
11786 if (region
->type
== GIMPLE_OMP_FOR
11787 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
11788 inner_stmt
= last_stmt (region
->inner
->entry
);
11791 expand_omp (region
->inner
);
11793 saved_location
= input_location
;
11794 if (gimple_has_location (last_stmt (region
->entry
)))
11795 input_location
= gimple_location (last_stmt (region
->entry
));
11797 switch (region
->type
)
11799 case GIMPLE_OMP_PARALLEL
:
11800 case GIMPLE_OMP_TASK
:
11801 expand_omp_taskreg (region
);
11804 case GIMPLE_OMP_FOR
:
11805 expand_omp_for (region
, inner_stmt
);
11808 case GIMPLE_OMP_SECTIONS
:
11809 expand_omp_sections (region
);
11812 case GIMPLE_OMP_SECTION
:
11813 /* Individual omp sections are handled together with their
11814 parent GIMPLE_OMP_SECTIONS region. */
11817 case GIMPLE_OMP_SINGLE
:
11818 expand_omp_single (region
);
11821 case GIMPLE_OMP_ORDERED
:
11823 gomp_ordered
*ord_stmt
11824 = as_a
<gomp_ordered
*> (last_stmt (region
->entry
));
11825 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt
),
11826 OMP_CLAUSE_DEPEND
))
11828 /* We'll expand these when expanding corresponding
11829 worksharing region with ordered(n) clause. */
11830 gcc_assert (region
->outer
11831 && region
->outer
->type
== GIMPLE_OMP_FOR
);
11832 region
->ord_stmt
= ord_stmt
;
11837 case GIMPLE_OMP_MASTER
:
11838 case GIMPLE_OMP_TASKGROUP
:
11839 case GIMPLE_OMP_CRITICAL
:
11840 case GIMPLE_OMP_TEAMS
:
11841 expand_omp_synch (region
);
11844 case GIMPLE_OMP_ATOMIC_LOAD
:
11845 expand_omp_atomic (region
);
11848 case GIMPLE_OMP_TARGET
:
11849 expand_omp_target (region
);
11853 gcc_unreachable ();
11856 input_location
= saved_location
;
11857 region
= region
->next
;
11862 /* Helper for build_omp_regions. Scan the dominator tree starting at
11863 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
11864 true, the function ends once a single tree is built (otherwise, whole
11865 forest of OMP constructs may be built). */
11868 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
11871 gimple_stmt_iterator gsi
;
11875 gsi
= gsi_last_bb (bb
);
11876 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
11878 struct omp_region
*region
;
11879 enum gimple_code code
;
11881 stmt
= gsi_stmt (gsi
);
11882 code
= gimple_code (stmt
);
11883 if (code
== GIMPLE_OMP_RETURN
)
11885 /* STMT is the return point out of region PARENT. Mark it
11886 as the exit point and make PARENT the immediately
11887 enclosing region. */
11888 gcc_assert (parent
);
11891 parent
= parent
->outer
;
11893 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
11895 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
11896 GIMPLE_OMP_RETURN, but matches with
11897 GIMPLE_OMP_ATOMIC_LOAD. */
11898 gcc_assert (parent
);
11899 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
11902 parent
= parent
->outer
;
11904 else if (code
== GIMPLE_OMP_CONTINUE
)
11906 gcc_assert (parent
);
11909 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
11911 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
11912 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
11916 region
= new_omp_region (bb
, code
, parent
);
11918 if (code
== GIMPLE_OMP_TARGET
)
11920 switch (gimple_omp_target_kind (stmt
))
11922 case GF_OMP_TARGET_KIND_REGION
:
11923 case GF_OMP_TARGET_KIND_DATA
:
11924 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
11925 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
11926 case GF_OMP_TARGET_KIND_OACC_DATA
:
11928 case GF_OMP_TARGET_KIND_UPDATE
:
11929 case GF_OMP_TARGET_KIND_ENTER_DATA
:
11930 case GF_OMP_TARGET_KIND_EXIT_DATA
:
11931 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
11932 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
11933 /* ..., other than for those stand-alone directives... */
11937 gcc_unreachable ();
11940 else if (code
== GIMPLE_OMP_ORDERED
11941 && find_omp_clause (gimple_omp_ordered_clauses
11942 (as_a
<gomp_ordered
*> (stmt
)),
11943 OMP_CLAUSE_DEPEND
))
11944 /* #pragma omp ordered depend is also just a stand-alone
11947 /* ..., this directive becomes the parent for a new region. */
11953 if (single_tree
&& !parent
)
11956 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
11958 son
= next_dom_son (CDI_DOMINATORS
, son
))
11959 build_omp_regions_1 (son
, parent
, single_tree
);
11962 /* Builds the tree of OMP regions rooted at ROOT, storing it to
11963 root_omp_region. */
11966 build_omp_regions_root (basic_block root
)
11968 gcc_assert (root_omp_region
== NULL
);
11969 build_omp_regions_1 (root
, NULL
, true);
11970 gcc_assert (root_omp_region
!= NULL
);
11973 /* Expands omp construct (and its subconstructs) starting in HEAD. */
11976 omp_expand_local (basic_block head
)
11978 build_omp_regions_root (head
);
11979 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
11981 fprintf (dump_file
, "\nOMP region tree\n\n");
11982 dump_omp_region (dump_file
, root_omp_region
, 0);
11983 fprintf (dump_file
, "\n");
11986 remove_exit_barriers (root_omp_region
);
11987 expand_omp (root_omp_region
);
11989 free_omp_regions ();
11992 /* Scan the CFG and build a tree of OMP regions. Return the root of
11993 the OMP region tree. */
11996 build_omp_regions (void)
11998 gcc_assert (root_omp_region
== NULL
);
11999 calculate_dominance_info (CDI_DOMINATORS
);
12000 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
12003 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
12005 static unsigned int
12006 execute_expand_omp (void)
12008 build_omp_regions ();
12010 if (!root_omp_region
)
12015 fprintf (dump_file
, "\nOMP region tree\n\n");
12016 dump_omp_region (dump_file
, root_omp_region
, 0);
12017 fprintf (dump_file
, "\n");
12020 remove_exit_barriers (root_omp_region
);
12022 expand_omp (root_omp_region
);
12024 #ifdef ENABLE_CHECKING
12025 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
12026 verify_loop_structure ();
12028 cleanup_tree_cfg ();
12030 free_omp_regions ();
12035 /* OMP expansion -- the default pass, run before creation of SSA form. */
12039 const pass_data pass_data_expand_omp
=
12041 GIMPLE_PASS
, /* type */
12042 "ompexp", /* name */
12043 OPTGROUP_NONE
, /* optinfo_flags */
12044 TV_NONE
, /* tv_id */
12045 PROP_gimple_any
, /* properties_required */
12046 PROP_gimple_eomp
, /* properties_provided */
12047 0, /* properties_destroyed */
12048 0, /* todo_flags_start */
12049 0, /* todo_flags_finish */
12052 class pass_expand_omp
: public gimple_opt_pass
12055 pass_expand_omp (gcc::context
*ctxt
)
12056 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
12059 /* opt_pass methods: */
12060 virtual unsigned int execute (function
*)
12062 bool gate
= ((flag_cilkplus
!= 0 || flag_openacc
!= 0 || flag_openmp
!= 0
12063 || flag_openmp_simd
!= 0)
12064 && !seen_error ());
12066 /* This pass always runs, to provide PROP_gimple_eomp.
12067 But often, there is nothing to do. */
12071 return execute_expand_omp ();
12074 }; // class pass_expand_omp
12076 } // anon namespace
12079 make_pass_expand_omp (gcc::context
*ctxt
)
12081 return new pass_expand_omp (ctxt
);
12086 const pass_data pass_data_expand_omp_ssa
=
12088 GIMPLE_PASS
, /* type */
12089 "ompexpssa", /* name */
12090 OPTGROUP_NONE
, /* optinfo_flags */
12091 TV_NONE
, /* tv_id */
12092 PROP_cfg
| PROP_ssa
, /* properties_required */
12093 PROP_gimple_eomp
, /* properties_provided */
12094 0, /* properties_destroyed */
12095 0, /* todo_flags_start */
12096 TODO_cleanup_cfg
| TODO_rebuild_alias
, /* todo_flags_finish */
12099 class pass_expand_omp_ssa
: public gimple_opt_pass
12102 pass_expand_omp_ssa (gcc::context
*ctxt
)
12103 : gimple_opt_pass (pass_data_expand_omp_ssa
, ctxt
)
12106 /* opt_pass methods: */
12107 virtual bool gate (function
*fun
)
12109 return !(fun
->curr_properties
& PROP_gimple_eomp
);
12111 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
12113 }; // class pass_expand_omp_ssa
12115 } // anon namespace
12118 make_pass_expand_omp_ssa (gcc::context
*ctxt
)
12120 return new pass_expand_omp_ssa (ctxt
);
12123 /* Routines to lower OMP directives into OMP-GIMPLE. */
12125 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
12126 convert it to gimple. */
12128 oacc_gimple_assign (tree dest
, tree_code op
, tree src
, gimple_seq
*seq
)
12132 if (TREE_CODE (TREE_TYPE (dest
)) != COMPLEX_TYPE
)
12134 stmt
= gimple_build_assign (dest
, op
, dest
, src
);
12135 gimple_seq_add_stmt (seq
, stmt
);
12139 tree t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12140 tree rdest
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
12141 gimplify_assign (t
, rdest
, seq
);
12144 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12145 tree idest
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
12146 gimplify_assign (t
, idest
, seq
);
12149 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
12150 tree rsrc
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
12151 gimplify_assign (t
, rsrc
, seq
);
12154 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
12155 tree isrc
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
12156 gimplify_assign (t
, isrc
, seq
);
12159 tree r
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12160 tree i
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12163 if (op
== PLUS_EXPR
)
12165 stmt
= gimple_build_assign (r
, op
, rdest
, rsrc
);
12166 gimple_seq_add_stmt (seq
, stmt
);
12168 stmt
= gimple_build_assign (i
, op
, idest
, isrc
);
12169 gimple_seq_add_stmt (seq
, stmt
);
12171 else if (op
== MULT_EXPR
)
12173 /* Let x = a + ib = dest, y = c + id = src.
12174 x * y = (ac - bd) + i(ad + bc) */
12175 tree ac
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12176 tree bd
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12177 tree ad
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12178 tree bc
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
12180 stmt
= gimple_build_assign (ac
, MULT_EXPR
, rdest
, rsrc
);
12181 gimple_seq_add_stmt (seq
, stmt
);
12183 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, isrc
);
12184 gimple_seq_add_stmt (seq
, stmt
);
12186 stmt
= gimple_build_assign (r
, MINUS_EXPR
, ac
, bd
);
12187 gimple_seq_add_stmt (seq
, stmt
);
12189 stmt
= gimple_build_assign (ad
, MULT_EXPR
, rdest
, isrc
);
12190 gimple_seq_add_stmt (seq
, stmt
);
12192 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, rsrc
);
12193 gimple_seq_add_stmt (seq
, stmt
);
12195 stmt
= gimple_build_assign (i
, PLUS_EXPR
, ad
, bc
);
12196 gimple_seq_add_stmt (seq
, stmt
);
12199 gcc_unreachable ();
12201 result
= build2 (COMPLEX_EXPR
, TREE_TYPE (dest
), r
, i
);
12202 gimplify_assign (dest
, result
, seq
);
12205 /* Helper function to initialize local data for the reduction arrays.
12206 The reduction arrays need to be placed inside the calling function
12207 for accelerators, or else the host won't be able to preform the final
12211 oacc_initialize_reduction_data (tree clauses
, tree nthreads
,
12212 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
12218 /* Find the innermost OpenACC parallel context. */
12219 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
12220 && (gimple_omp_target_kind (ctx
->stmt
)
12221 == GF_OMP_TARGET_KIND_OACC_PARALLEL
))
12225 gcc_checking_assert (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
12226 && (gimple_omp_target_kind (octx
->stmt
)
12227 == GF_OMP_TARGET_KIND_OACC_PARALLEL
));
12229 /* Extract the clauses. */
12230 oc
= gimple_omp_target_clauses (octx
->stmt
);
12232 /* Find the last outer clause. */
12233 for (; oc
&& OMP_CLAUSE_CHAIN (oc
); oc
= OMP_CLAUSE_CHAIN (oc
))
12236 /* Allocate arrays for each reduction variable. */
12237 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
12239 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
12242 tree var
= OMP_CLAUSE_DECL (c
);
12243 tree type
= get_base_type (var
);
12244 tree array
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
),
12248 /* Calculate size of the reduction array. */
12249 t
= create_tmp_var (TREE_TYPE (nthreads
));
12250 stmt
= gimple_build_assign (t
, MULT_EXPR
, nthreads
,
12251 fold_convert (TREE_TYPE (nthreads
),
12252 TYPE_SIZE_UNIT (type
)));
12253 gimple_seq_add_stmt (stmt_seqp
, stmt
);
12255 size
= create_tmp_var (sizetype
);
12256 gimplify_assign (size
, fold_build1 (NOP_EXPR
, sizetype
, t
), stmt_seqp
);
12258 /* Now allocate memory for it. */
12259 call
= unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA
));
12260 stmt
= gimple_build_call (call
, 1, size
);
12261 gimple_call_set_lhs (stmt
, array
);
12262 gimple_seq_add_stmt (stmt_seqp
, stmt
);
12264 /* Map this array into the accelerator. */
12266 /* Add the reduction array to the list of clauses. */
12268 t
= build_omp_clause (gimple_location (ctx
->stmt
), OMP_CLAUSE_MAP
);
12269 OMP_CLAUSE_SET_MAP_KIND (t
, GOMP_MAP_FORCE_FROM
);
12270 OMP_CLAUSE_DECL (t
) = x
;
12271 OMP_CLAUSE_CHAIN (t
) = NULL
;
12273 OMP_CLAUSE_CHAIN (oc
) = t
;
12275 gimple_omp_target_set_clauses (as_a
<gomp_target
*> (octx
->stmt
), t
);
12276 OMP_CLAUSE_SIZE (t
) = size
;
12281 /* Helper function to process the array of partial reductions. Nthreads
12282 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
12283 cannot be used here, because nthreads on the host may be different than
12284 on the accelerator. */
12287 oacc_finalize_reduction_data (tree clauses
, tree nthreads
,
12288 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
12290 tree c
, x
, var
, array
, loop_header
, loop_body
, loop_exit
, type
;
12293 /* Create for loop.
12295 let var = the original reduction variable
12296 let array = reduction variable array
12298 for (i = 0; i < nthreads; i++)
12302 loop_header
= create_artificial_label (UNKNOWN_LOCATION
);
12303 loop_body
= create_artificial_label (UNKNOWN_LOCATION
);
12304 loop_exit
= create_artificial_label (UNKNOWN_LOCATION
);
12306 /* Create and initialize an index variable. */
12307 tree ix
= create_tmp_var (sizetype
);
12308 gimplify_assign (ix
, fold_build1 (NOP_EXPR
, sizetype
, integer_zero_node
),
12311 /* Insert the loop header label here. */
12312 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_header
));
12314 /* Exit loop if ix >= nthreads. */
12315 x
= create_tmp_var (sizetype
);
12316 gimplify_assign (x
, fold_build1 (NOP_EXPR
, sizetype
, nthreads
), stmt_seqp
);
12317 stmt
= gimple_build_cond (GE_EXPR
, ix
, x
, loop_exit
, loop_body
);
12318 gimple_seq_add_stmt (stmt_seqp
, stmt
);
12320 /* Insert the loop body label here. */
12321 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_body
));
12323 /* Collapse each reduction array, one element at a time. */
12324 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
12326 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
12329 tree_code reduction_code
= OMP_CLAUSE_REDUCTION_CODE (c
);
12331 /* reduction(-:var) sums up the partial results, so it acts
12332 identically to reduction(+:var). */
12333 if (reduction_code
== MINUS_EXPR
)
12334 reduction_code
= PLUS_EXPR
;
12336 /* Set up reduction variable var. */
12337 var
= OMP_CLAUSE_DECL (c
);
12338 type
= get_base_type (var
);
12339 array
= lookup_oacc_reduction (oacc_get_reduction_array_id
12340 (OMP_CLAUSE_DECL (c
)), ctx
);
12342 /* Calculate the array offset. */
12343 tree offset
= create_tmp_var (sizetype
);
12344 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
), stmt_seqp
);
12345 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, ix
);
12346 gimple_seq_add_stmt (stmt_seqp
, stmt
);
12348 tree ptr
= create_tmp_var (TREE_TYPE (array
));
12349 stmt
= gimple_build_assign (ptr
, POINTER_PLUS_EXPR
, array
, offset
);
12350 gimple_seq_add_stmt (stmt_seqp
, stmt
);
12352 /* Extract array[ix] into mem. */
12353 tree mem
= create_tmp_var (type
);
12354 gimplify_assign (mem
, build_simple_mem_ref (ptr
), stmt_seqp
);
12356 /* Find the original reduction variable. */
12357 if (is_reference (var
))
12358 var
= build_simple_mem_ref (var
);
12360 tree t
= create_tmp_var (type
);
12362 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, t
, var
);
12363 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
12365 /* var = var op mem */
12366 switch (OMP_CLAUSE_REDUCTION_CODE (c
))
12368 case TRUTH_ANDIF_EXPR
:
12369 case TRUTH_ORIF_EXPR
:
12370 t
= fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c
), integer_type_node
,
12372 gimplify_and_add (t
, stmt_seqp
);
12375 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
12376 oacc_gimple_assign (t
, OMP_CLAUSE_REDUCTION_CODE (c
), mem
,
12380 t
= fold_build1 (NOP_EXPR
, TREE_TYPE (var
), t
);
12381 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, var
, t
);
12382 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
12385 /* Increment the induction variable. */
12386 tree one
= fold_build1 (NOP_EXPR
, sizetype
, integer_one_node
);
12387 stmt
= gimple_build_assign (ix
, PLUS_EXPR
, ix
, one
);
12388 gimple_seq_add_stmt (stmt_seqp
, stmt
);
12390 /* Go back to the top of the loop. */
12391 gimple_seq_add_stmt (stmt_seqp
, gimple_build_goto (loop_header
));
12393 /* Place the loop exit label here. */
12394 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_exit
));
12397 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
12398 scan that for reductions. */
12401 oacc_process_reduction_data (gimple_seq
*body
, gimple_seq
*in_stmt_seqp
,
12402 gimple_seq
*out_stmt_seqp
, omp_context
*ctx
)
12404 gimple_stmt_iterator gsi
;
12405 gimple_seq inner
= NULL
;
12407 /* A collapse clause may have inserted a new bind block. */
12408 gsi
= gsi_start (*body
);
12409 while (!gsi_end_p (gsi
))
12411 gimple
*stmt
= gsi_stmt (gsi
);
12412 if (gbind
*bind_stmt
= dyn_cast
<gbind
*> (stmt
))
12414 inner
= gimple_bind_body (bind_stmt
);
12416 gsi
= gsi_start (*body
);
12418 else if (dyn_cast
<gomp_for
*> (stmt
))
12424 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
12426 tree clauses
, nthreads
, t
, c
, acc_device
, acc_device_host
, call
,
12428 bool reduction_found
= false;
12430 gimple
*stmt
= gsi_stmt (gsi
);
12432 switch (gimple_code (stmt
))
12434 case GIMPLE_OMP_FOR
:
12435 clauses
= gimple_omp_for_clauses (stmt
);
12437 /* Search for a reduction clause. */
12438 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
12439 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
12441 reduction_found
= true;
12445 if (!reduction_found
)
12448 ctx
= maybe_lookup_ctx (stmt
);
12451 /* Extract the number of threads. */
12452 nthreads
= create_tmp_var (sizetype
);
12453 t
= oacc_max_threads (ctx
);
12454 gimplify_assign (nthreads
, t
, in_stmt_seqp
);
12456 /* Determine if this is kernel will be executed on the host. */
12457 call
= builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE
);
12458 acc_device
= create_tmp_var (integer_type_node
, ".acc_device_type");
12459 stmt
= gimple_build_call (call
, 0);
12460 gimple_call_set_lhs (stmt
, acc_device
);
12461 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
12463 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
12464 acc_device_host
= create_tmp_var (integer_type_node
,
12465 ".acc_device_host");
12466 gimplify_assign (acc_device_host
,
12467 build_int_cst (integer_type_node
,
12471 enter
= create_artificial_label (UNKNOWN_LOCATION
);
12472 exit
= create_artificial_label (UNKNOWN_LOCATION
);
12474 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
12476 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
12477 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
12478 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
12481 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
12483 oacc_initialize_reduction_data (clauses
, nthreads
, in_stmt_seqp
,
12485 oacc_finalize_reduction_data (clauses
, nthreads
, out_stmt_seqp
, ctx
);
12488 // Scan for other directives which support reduction here.
12494 /* If ctx is a worksharing context inside of a cancellable parallel
12495 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
12496 and conditional branch to parallel's cancel_label to handle
12497 cancellation in the implicit barrier. */
12500 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
12502 gimple
*omp_return
= gimple_seq_last_stmt (*body
);
12503 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
12504 if (gimple_omp_return_nowait_p (omp_return
))
12507 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
12508 && ctx
->outer
->cancellable
)
12510 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
12511 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
12512 tree lhs
= create_tmp_var (c_bool_type
);
12513 gimple_omp_return_set_lhs (omp_return
, lhs
);
12514 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
12515 gimple
*g
= gimple_build_cond (NE_EXPR
, lhs
,
12516 fold_convert (c_bool_type
,
12517 boolean_false_node
),
12518 ctx
->outer
->cancel_label
, fallthru_label
);
12519 gimple_seq_add_stmt (body
, g
);
12520 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
12524 /* Lower the OpenMP sections directive in the current statement in GSI_P.
12525 CTX is the enclosing OMP context for the current statement. */
12528 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
12530 tree block
, control
;
12531 gimple_stmt_iterator tgsi
;
12532 gomp_sections
*stmt
;
12534 gbind
*new_stmt
, *bind
;
12535 gimple_seq ilist
, dlist
, olist
, new_body
;
12537 stmt
= as_a
<gomp_sections
*> (gsi_stmt (*gsi_p
));
12539 push_gimplify_context ();
12543 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
12544 &ilist
, &dlist
, ctx
, NULL
);
12546 new_body
= gimple_omp_body (stmt
);
12547 gimple_omp_set_body (stmt
, NULL
);
12548 tgsi
= gsi_start (new_body
);
12549 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
12554 sec_start
= gsi_stmt (tgsi
);
12555 sctx
= maybe_lookup_ctx (sec_start
);
12558 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
12559 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
12560 GSI_CONTINUE_LINKING
);
12561 gimple_omp_set_body (sec_start
, NULL
);
12563 if (gsi_one_before_end_p (tgsi
))
12565 gimple_seq l
= NULL
;
12566 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
12568 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
12569 gimple_omp_section_set_last (sec_start
);
12572 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
12573 GSI_CONTINUE_LINKING
);
12576 block
= make_node (BLOCK
);
12577 bind
= gimple_build_bind (NULL
, new_body
, block
);
12580 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
12582 block
= make_node (BLOCK
);
12583 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
12584 gsi_replace (gsi_p
, new_stmt
, true);
12586 pop_gimplify_context (new_stmt
);
12587 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
12588 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
12589 if (BLOCK_VARS (block
))
12590 TREE_USED (block
) = 1;
12593 gimple_seq_add_seq (&new_body
, ilist
);
12594 gimple_seq_add_stmt (&new_body
, stmt
);
12595 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
12596 gimple_seq_add_stmt (&new_body
, bind
);
12598 control
= create_tmp_var (unsigned_type_node
, ".section");
12599 t
= gimple_build_omp_continue (control
, control
);
12600 gimple_omp_sections_set_control (stmt
, control
);
12601 gimple_seq_add_stmt (&new_body
, t
);
12603 gimple_seq_add_seq (&new_body
, olist
);
12604 if (ctx
->cancellable
)
12605 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
12606 gimple_seq_add_seq (&new_body
, dlist
);
12608 new_body
= maybe_catch_exception (new_body
);
12610 t
= gimple_build_omp_return
12611 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
12612 OMP_CLAUSE_NOWAIT
));
12613 gimple_seq_add_stmt (&new_body
, t
);
12614 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
12616 gimple_bind_set_body (new_stmt
, new_body
);
12620 /* A subroutine of lower_omp_single. Expand the simple form of
12621 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
12623 if (GOMP_single_start ())
12625 [ GOMP_barrier (); ] -> unless 'nowait' is present.
12627 FIXME. It may be better to delay expanding the logic of this until
12628 pass_expand_omp. The expanded logic may make the job more difficult
12629 to a synchronization analysis pass. */
12632 lower_omp_single_simple (gomp_single
*single_stmt
, gimple_seq
*pre_p
)
12634 location_t loc
= gimple_location (single_stmt
);
12635 tree tlabel
= create_artificial_label (loc
);
12636 tree flabel
= create_artificial_label (loc
);
12637 gimple
*call
, *cond
;
12640 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
12641 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)));
12642 call
= gimple_build_call (decl
, 0);
12643 gimple_call_set_lhs (call
, lhs
);
12644 gimple_seq_add_stmt (pre_p
, call
);
12646 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
12647 fold_convert_loc (loc
, TREE_TYPE (lhs
),
12648 boolean_true_node
),
12650 gimple_seq_add_stmt (pre_p
, cond
);
12651 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
12652 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
12653 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
12657 /* A subroutine of lower_omp_single. Expand the simple form of
12658 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
12660 #pragma omp single copyprivate (a, b, c)
12662 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
12665 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
12671 GOMP_single_copy_end (©out);
12682 FIXME. It may be better to delay expanding the logic of this until
12683 pass_expand_omp. The expanded logic may make the job more difficult
12684 to a synchronization analysis pass. */
12687 lower_omp_single_copy (gomp_single
*single_stmt
, gimple_seq
*pre_p
,
12690 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
12691 gimple_seq copyin_seq
;
12692 location_t loc
= gimple_location (single_stmt
);
12694 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
12696 ptr_type
= build_pointer_type (ctx
->record_type
);
12697 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
12699 l0
= create_artificial_label (loc
);
12700 l1
= create_artificial_label (loc
);
12701 l2
= create_artificial_label (loc
);
12703 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
12704 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
12705 t
= fold_convert_loc (loc
, ptr_type
, t
);
12706 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
12708 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
12709 build_int_cst (ptr_type
, 0));
12710 t
= build3 (COND_EXPR
, void_type_node
, t
,
12711 build_and_jump (&l0
), build_and_jump (&l1
));
12712 gimplify_and_add (t
, pre_p
);
12714 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
12716 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
12719 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
12722 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
12723 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
12724 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
12725 gimplify_and_add (t
, pre_p
);
12727 t
= build_and_jump (&l2
);
12728 gimplify_and_add (t
, pre_p
);
12730 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
12732 gimple_seq_add_seq (pre_p
, copyin_seq
);
12734 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
12738 /* Expand code for an OpenMP single directive. */
12741 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
12745 gomp_single
*single_stmt
= as_a
<gomp_single
*> (gsi_stmt (*gsi_p
));
12747 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
12749 push_gimplify_context ();
12751 block
= make_node (BLOCK
);
12752 bind
= gimple_build_bind (NULL
, NULL
, block
);
12753 gsi_replace (gsi_p
, bind
, true);
12756 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
12757 &bind_body
, &dlist
, ctx
, NULL
);
12758 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
12760 gimple_seq_add_stmt (&bind_body
, single_stmt
);
12762 if (ctx
->record_type
)
12763 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
12765 lower_omp_single_simple (single_stmt
, &bind_body
);
12767 gimple_omp_set_body (single_stmt
, NULL
);
12769 gimple_seq_add_seq (&bind_body
, dlist
);
12771 bind_body
= maybe_catch_exception (bind_body
);
12773 t
= gimple_build_omp_return
12774 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
12775 OMP_CLAUSE_NOWAIT
));
12776 gimple_seq_add_stmt (&bind_body_tail
, t
);
12777 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
12778 if (ctx
->record_type
)
12780 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
12781 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
12782 TREE_THIS_VOLATILE (clobber
) = 1;
12783 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
12784 clobber
), GSI_SAME_STMT
);
12786 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
12787 gimple_bind_set_body (bind
, bind_body
);
12789 pop_gimplify_context (bind
);
12791 gimple_bind_append_vars (bind
, ctx
->block_vars
);
12792 BLOCK_VARS (block
) = ctx
->block_vars
;
12793 if (BLOCK_VARS (block
))
12794 TREE_USED (block
) = 1;
12798 /* Expand code for an OpenMP master directive. */
12801 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
12803 tree block
, lab
= NULL
, x
, bfn_decl
;
12804 gimple
*stmt
= gsi_stmt (*gsi_p
);
12806 location_t loc
= gimple_location (stmt
);
12809 push_gimplify_context ();
12811 block
= make_node (BLOCK
);
12812 bind
= gimple_build_bind (NULL
, NULL
, block
);
12813 gsi_replace (gsi_p
, bind
, true);
12814 gimple_bind_add_stmt (bind
, stmt
);
12816 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
12817 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
12818 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
12819 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
12821 gimplify_and_add (x
, &tseq
);
12822 gimple_bind_add_seq (bind
, tseq
);
12824 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
12825 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
12826 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
12827 gimple_omp_set_body (stmt
, NULL
);
12829 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
12831 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
12833 pop_gimplify_context (bind
);
12835 gimple_bind_append_vars (bind
, ctx
->block_vars
);
12836 BLOCK_VARS (block
) = ctx
->block_vars
;
12840 /* Expand code for an OpenMP taskgroup directive. */
12843 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
12845 gimple
*stmt
= gsi_stmt (*gsi_p
);
12848 tree block
= make_node (BLOCK
);
12850 bind
= gimple_build_bind (NULL
, NULL
, block
);
12851 gsi_replace (gsi_p
, bind
, true);
12852 gimple_bind_add_stmt (bind
, stmt
);
12854 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
12856 gimple_bind_add_stmt (bind
, x
);
12858 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
12859 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
12860 gimple_omp_set_body (stmt
, NULL
);
12862 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
12864 gimple_bind_append_vars (bind
, ctx
->block_vars
);
12865 BLOCK_VARS (block
) = ctx
->block_vars
;
12869 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
12872 lower_omp_ordered_clauses (gimple_stmt_iterator
*gsi_p
, gomp_ordered
*ord_stmt
,
12875 struct omp_for_data fd
;
12876 if (!ctx
->outer
|| gimple_code (ctx
->outer
->stmt
) != GIMPLE_OMP_FOR
)
12879 unsigned int len
= gimple_omp_for_collapse (ctx
->outer
->stmt
);
12880 struct omp_for_data_loop
*loops
= XALLOCAVEC (struct omp_for_data_loop
, len
);
12881 extract_omp_for_data (as_a
<gomp_for
*> (ctx
->outer
->stmt
), &fd
, loops
);
12885 tree
*list_p
= gimple_omp_ordered_clauses_ptr (ord_stmt
);
12886 tree c
= gimple_omp_ordered_clauses (ord_stmt
);
12887 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
12888 && OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
)
12890 /* Merge depend clauses from multiple adjacent
12891 #pragma omp ordered depend(sink:...) constructs
12892 into one #pragma omp ordered depend(sink:...), so that
12893 we can optimize them together. */
12894 gimple_stmt_iterator gsi
= *gsi_p
;
12896 while (!gsi_end_p (gsi
))
12898 gimple
*stmt
= gsi_stmt (gsi
);
12899 if (is_gimple_debug (stmt
)
12900 || gimple_code (stmt
) == GIMPLE_NOP
)
12905 if (gimple_code (stmt
) != GIMPLE_OMP_ORDERED
)
12907 gomp_ordered
*ord_stmt2
= as_a
<gomp_ordered
*> (stmt
);
12908 c
= gimple_omp_ordered_clauses (ord_stmt2
);
12910 || OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_DEPEND
12911 || OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_SINK
)
12914 list_p
= &OMP_CLAUSE_CHAIN (*list_p
);
12916 gsi_remove (&gsi
, true);
12920 /* Canonicalize sink dependence clauses into one folded clause if
12923 The basic algorithm is to create a sink vector whose first
12924 element is the GCD of all the first elements, and whose remaining
12925 elements are the minimum of the subsequent columns.
12927 We ignore dependence vectors whose first element is zero because
12928 such dependencies are known to be executed by the same thread.
12930 We take into account the direction of the loop, so a minimum
12931 becomes a maximum if the loop is iterating forwards. We also
12932 ignore sink clauses where the loop direction is unknown, or where
12933 the offsets are clearly invalid because they are not a multiple
12934 of the loop increment.
12938 #pragma omp for ordered(2)
12939 for (i=0; i < N; ++i)
12940 for (j=0; j < M; ++j)
12942 #pragma omp ordered \
12943 depend(sink:i-8,j-2) \
12944 depend(sink:i,j-1) \ // Completely ignored because i+0.
12945 depend(sink:i-4,j-3) \
12946 depend(sink:i-6,j-4)
12947 #pragma omp ordered depend(source)
12952 depend(sink:-gcd(8,4,6),-min(2,3,4))
12957 /* FIXME: Computing GCD's where the first element is zero is
12958 non-trivial in the presence of collapsed loops. Do this later. */
12959 if (fd
.collapse
> 1)
12962 wide_int
*folded_deps
= XALLOCAVEC (wide_int
, 2 * len
- 1);
12963 memset (folded_deps
, 0, sizeof (*folded_deps
) * (2 * len
- 1));
12964 tree folded_dep
= NULL_TREE
;
12965 /* TRUE if the first dimension's offset is negative. */
12966 bool neg_offset_p
= false;
12968 list_p
= gimple_omp_ordered_clauses_ptr (ord_stmt
);
12970 while ((c
= *list_p
) != NULL
)
12972 bool remove
= false;
12974 gcc_assert (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
);
12975 if (OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_SINK
)
12976 goto next_ordered_clause
;
12979 for (vec
= OMP_CLAUSE_DECL (c
), i
= 0;
12980 vec
&& TREE_CODE (vec
) == TREE_LIST
;
12981 vec
= TREE_CHAIN (vec
), ++i
)
12983 gcc_assert (i
< len
);
12985 /* extract_omp_for_data has canonicalized the condition. */
12986 gcc_assert (fd
.loops
[i
].cond_code
== LT_EXPR
12987 || fd
.loops
[i
].cond_code
== GT_EXPR
);
12988 bool forward
= fd
.loops
[i
].cond_code
== LT_EXPR
;
12989 bool maybe_lexically_later
= true;
12991 /* While the committee makes up its mind, bail if we have any
12992 non-constant steps. */
12993 if (TREE_CODE (fd
.loops
[i
].step
) != INTEGER_CST
)
12994 goto lower_omp_ordered_ret
;
12996 tree itype
= TREE_TYPE (TREE_VALUE (vec
));
12997 if (POINTER_TYPE_P (itype
))
12999 wide_int offset
= wide_int::from (TREE_PURPOSE (vec
),
13000 TYPE_PRECISION (itype
),
13001 TYPE_SIGN (itype
));
13003 /* Ignore invalid offsets that are not multiples of the step. */
13004 if (!wi::multiple_of_p
13005 (wi::abs (offset
), wi::abs ((wide_int
) fd
.loops
[i
].step
),
13008 warning_at (OMP_CLAUSE_LOCATION (c
), 0,
13009 "ignoring sink clause with offset that is not "
13010 "a multiple of the loop step");
13012 goto next_ordered_clause
;
13015 /* Calculate the first dimension. The first dimension of
13016 the folded dependency vector is the GCD of the first
13017 elements, while ignoring any first elements whose offset
13021 /* Ignore dependence vectors whose first dimension is 0. */
13025 goto next_ordered_clause
;
13029 if (!TYPE_UNSIGNED (itype
) && (forward
^ wi::neg_p (offset
)))
13031 error_at (OMP_CLAUSE_LOCATION (c
),
13032 "first offset must be in opposite direction "
13033 "of loop iterations");
13034 goto lower_omp_ordered_ret
;
13038 neg_offset_p
= forward
;
13039 /* Initialize the first time around. */
13040 if (folded_dep
== NULL_TREE
)
13043 folded_deps
[0] = offset
;
13046 folded_deps
[0] = wi::gcd (folded_deps
[0],
13050 /* Calculate minimum for the remaining dimensions. */
13053 folded_deps
[len
+ i
- 1] = offset
;
13054 if (folded_dep
== c
)
13055 folded_deps
[i
] = offset
;
13056 else if (maybe_lexically_later
13057 && !wi::eq_p (folded_deps
[i
], offset
))
13059 if (forward
^ wi::gts_p (folded_deps
[i
], offset
))
13063 for (j
= 1; j
<= i
; j
++)
13064 folded_deps
[j
] = folded_deps
[len
+ j
- 1];
13067 maybe_lexically_later
= false;
13071 gcc_assert (i
== len
);
13075 next_ordered_clause
:
13077 *list_p
= OMP_CLAUSE_CHAIN (c
);
13079 list_p
= &OMP_CLAUSE_CHAIN (c
);
13085 folded_deps
[0] = -folded_deps
[0];
13087 tree itype
= TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep
)));
13088 if (POINTER_TYPE_P (itype
))
13091 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep
))
13092 = wide_int_to_tree (itype
, folded_deps
[0]);
13093 OMP_CLAUSE_CHAIN (folded_dep
) = gimple_omp_ordered_clauses (ord_stmt
);
13094 *gimple_omp_ordered_clauses_ptr (ord_stmt
) = folded_dep
;
13097 lower_omp_ordered_ret
:
13099 /* Ordered without clauses is #pragma omp threads, while we want
13100 a nop instead if we remove all clauses. */
13101 if (gimple_omp_ordered_clauses (ord_stmt
) == NULL_TREE
)
13102 gsi_replace (gsi_p
, gimple_build_nop (), true);
13106 /* Expand code for an OpenMP ordered directive. */
13109 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
13112 gimple
*stmt
= gsi_stmt (*gsi_p
);
13113 gomp_ordered
*ord_stmt
= as_a
<gomp_ordered
*> (stmt
);
13117 = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt
), OMP_CLAUSE_SIMD
);
13119 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt
),
13120 OMP_CLAUSE_DEPEND
))
13122 /* FIXME: This is needs to be moved to the expansion to verify various
13123 conditions only testable on cfg with dominators computed, and also
13124 all the depend clauses to be merged still might need to be available
13125 for the runtime checks. */
13127 lower_omp_ordered_clauses (gsi_p
, ord_stmt
, ctx
);
13131 push_gimplify_context ();
13133 block
= make_node (BLOCK
);
13134 bind
= gimple_build_bind (NULL
, NULL
, block
);
13135 gsi_replace (gsi_p
, bind
, true);
13136 gimple_bind_add_stmt (bind
, stmt
);
13140 x
= gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START
, 0);
13141 cfun
->has_simduid_loops
= true;
13144 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
13146 gimple_bind_add_stmt (bind
, x
);
13148 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
13149 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
13150 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
13151 gimple_omp_set_body (stmt
, NULL
);
13154 x
= gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END
, 0);
13156 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
),
13158 gimple_bind_add_stmt (bind
, x
);
13160 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
13162 pop_gimplify_context (bind
);
13164 gimple_bind_append_vars (bind
, ctx
->block_vars
);
13165 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
13169 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
13170 substitution of a couple of function calls. But in the NAMED case,
13171 requires that languages coordinate a symbol name. It is therefore
13172 best put here in common code. */
13174 static GTY(()) hash_map
<tree
, tree
> *critical_name_mutexes
;
13177 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
13180 tree name
, lock
, unlock
;
13181 gomp_critical
*stmt
= as_a
<gomp_critical
*> (gsi_stmt (*gsi_p
));
13183 location_t loc
= gimple_location (stmt
);
13186 name
= gimple_omp_critical_name (stmt
);
13191 if (!critical_name_mutexes
)
13192 critical_name_mutexes
= hash_map
<tree
, tree
>::create_ggc (10);
13194 tree
*n
= critical_name_mutexes
->get (name
);
13199 decl
= create_tmp_var_raw (ptr_type_node
);
13201 new_str
= ACONCAT ((".gomp_critical_user_",
13202 IDENTIFIER_POINTER (name
), NULL
));
13203 DECL_NAME (decl
) = get_identifier (new_str
);
13204 TREE_PUBLIC (decl
) = 1;
13205 TREE_STATIC (decl
) = 1;
13206 DECL_COMMON (decl
) = 1;
13207 DECL_ARTIFICIAL (decl
) = 1;
13208 DECL_IGNORED_P (decl
) = 1;
13210 varpool_node::finalize_decl (decl
);
13212 critical_name_mutexes
->put (name
, decl
);
13217 /* If '#pragma omp critical' is inside offloaded region or
13218 inside function marked as offloadable, the symbol must be
13219 marked as offloadable too. */
13221 if (cgraph_node::get (current_function_decl
)->offloadable
)
13222 varpool_node::get_create (decl
)->offloadable
= 1;
13224 for (octx
= ctx
->outer
; octx
; octx
= octx
->outer
)
13225 if (is_gimple_omp_offloaded (octx
->stmt
))
13227 varpool_node::get_create (decl
)->offloadable
= 1;
13231 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
13232 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
13234 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
13235 unlock
= build_call_expr_loc (loc
, unlock
, 1,
13236 build_fold_addr_expr_loc (loc
, decl
));
13240 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
13241 lock
= build_call_expr_loc (loc
, lock
, 0);
13243 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
13244 unlock
= build_call_expr_loc (loc
, unlock
, 0);
13247 push_gimplify_context ();
13249 block
= make_node (BLOCK
);
13250 bind
= gimple_build_bind (NULL
, NULL
, block
);
13251 gsi_replace (gsi_p
, bind
, true);
13252 gimple_bind_add_stmt (bind
, stmt
);
13254 tbody
= gimple_bind_body (bind
);
13255 gimplify_and_add (lock
, &tbody
);
13256 gimple_bind_set_body (bind
, tbody
);
13258 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
13259 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
13260 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
13261 gimple_omp_set_body (stmt
, NULL
);
13263 tbody
= gimple_bind_body (bind
);
13264 gimplify_and_add (unlock
, &tbody
);
13265 gimple_bind_set_body (bind
, tbody
);
13267 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
13269 pop_gimplify_context (bind
);
13270 gimple_bind_append_vars (bind
, ctx
->block_vars
);
13271 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
13275 /* A subroutine of lower_omp_for. Generate code to emit the predicate
13276 for a lastprivate clause. Given a loop control predicate of (V
13277 cond N2), we gate the clause on (!(V cond N2)). The lowered form
13278 is appended to *DLIST, iterator initialization is appended to
13282 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
13283 gimple_seq
*dlist
, struct omp_context
*ctx
)
13285 tree clauses
, cond
, vinit
;
13286 enum tree_code cond_code
;
13289 cond_code
= fd
->loop
.cond_code
;
13290 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
13292 /* When possible, use a strict equality expression. This can let VRP
13293 type optimizations deduce the value and remove a copy. */
13294 if (tree_fits_shwi_p (fd
->loop
.step
))
13296 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
13297 if (step
== 1 || step
== -1)
13298 cond_code
= EQ_EXPR
;
13301 tree n2
= fd
->loop
.n2
;
13302 if (fd
->collapse
> 1
13303 && TREE_CODE (n2
) != INTEGER_CST
13304 && gimple_omp_for_combined_into_p (fd
->for_stmt
))
13306 struct omp_context
*task_ctx
= NULL
;
13307 if (gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_FOR
)
13309 gomp_for
*gfor
= as_a
<gomp_for
*> (ctx
->outer
->stmt
);
13310 if (gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_FOR
)
13312 struct omp_for_data outer_fd
;
13313 extract_omp_for_data (gfor
, &outer_fd
, NULL
);
13314 n2
= fold_convert (TREE_TYPE (n2
), outer_fd
.loop
.n2
);
13316 else if (gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_TASKLOOP
)
13317 task_ctx
= ctx
->outer
->outer
;
13319 else if (is_task_ctx (ctx
->outer
))
13320 task_ctx
= ctx
->outer
;
13325 = find_omp_clause (gimple_omp_task_clauses (task_ctx
->stmt
),
13326 OMP_CLAUSE__LOOPTEMP_
);
13327 gcc_assert (innerc
);
13328 for (i
= 0; i
< fd
->collapse
; i
++)
13330 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
13331 OMP_CLAUSE__LOOPTEMP_
);
13332 gcc_assert (innerc
);
13334 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
13335 OMP_CLAUSE__LOOPTEMP_
);
13337 n2
= fold_convert (TREE_TYPE (n2
),
13338 lookup_decl (OMP_CLAUSE_DECL (innerc
),
13342 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, n2
);
13344 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
13346 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
13347 if (!gimple_seq_empty_p (stmts
))
13349 gimple_seq_add_seq (&stmts
, *dlist
);
13352 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
13353 vinit
= fd
->loop
.n1
;
13354 if (cond_code
== EQ_EXPR
13355 && tree_fits_shwi_p (fd
->loop
.n2
)
13356 && ! integer_zerop (fd
->loop
.n2
))
13357 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
13359 vinit
= unshare_expr (vinit
);
13361 /* Initialize the iterator variable, so that threads that don't execute
13362 any iterations don't execute the lastprivate clauses by accident. */
13363 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
13368 /* Lower code for an OMP loop directive. */
13371 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
13373 tree
*rhs_p
, block
;
13374 struct omp_for_data fd
, *fdp
= NULL
;
13375 gomp_for
*stmt
= as_a
<gomp_for
*> (gsi_stmt (*gsi_p
));
13377 gimple_seq omp_for_body
, body
, dlist
;
13380 push_gimplify_context ();
13382 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
13384 block
= make_node (BLOCK
);
13385 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
13386 /* Replace at gsi right away, so that 'stmt' is no member
13387 of a sequence anymore as we're going to add to a different
13389 gsi_replace (gsi_p
, new_stmt
, true);
13391 /* Move declaration of temporaries in the loop body before we make
13393 omp_for_body
= gimple_omp_body (stmt
);
13394 if (!gimple_seq_empty_p (omp_for_body
)
13395 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
13398 = as_a
<gbind
*> (gimple_seq_first_stmt (omp_for_body
));
13399 tree vars
= gimple_bind_vars (inner_bind
);
13400 gimple_bind_append_vars (new_stmt
, vars
);
13401 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
13402 keep them on the inner_bind and it's block. */
13403 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
13404 if (gimple_bind_block (inner_bind
))
13405 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
13408 if (gimple_omp_for_combined_into_p (stmt
))
13410 extract_omp_for_data (stmt
, &fd
, NULL
);
13413 /* We need two temporaries with fd.loop.v type (istart/iend)
13414 and then (fd.collapse - 1) temporaries with the same
13415 type for count2 ... countN-1 vars if not constant. */
13417 tree type
= fd
.iter_type
;
13418 if (fd
.collapse
> 1
13419 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
13420 count
+= fd
.collapse
- 1;
13422 = (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
13423 || gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_TASKLOOP
);
13424 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
13425 tree clauses
= *pc
;
13428 = find_omp_clause (gimple_omp_taskreg_clauses (ctx
->outer
->stmt
),
13429 OMP_CLAUSE__LOOPTEMP_
);
13430 for (i
= 0; i
< count
; i
++)
13435 gcc_assert (outerc
);
13436 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
13437 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
13438 OMP_CLAUSE__LOOPTEMP_
);
13442 temp
= create_tmp_var (type
);
13443 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
13445 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
13446 OMP_CLAUSE_DECL (*pc
) = temp
;
13447 pc
= &OMP_CLAUSE_CHAIN (*pc
);
13452 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
13455 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
13457 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
13459 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
13461 /* Lower the header expressions. At this point, we can assume that
13462 the header is of the form:
13464 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
13466 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
13467 using the .omp_data_s mapping, if needed. */
13468 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
13470 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
13471 if (!is_gimple_min_invariant (*rhs_p
))
13472 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
13474 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
13475 if (!is_gimple_min_invariant (*rhs_p
))
13476 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
13478 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
13479 if (!is_gimple_min_invariant (*rhs_p
))
13480 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
13483 /* Once lowered, extract the bounds and clauses. */
13484 extract_omp_for_data (stmt
, &fd
, NULL
);
13486 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
13488 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
13489 for (tree c
= gimple_omp_for_clauses (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
13490 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
13491 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
13493 OMP_CLAUSE_DECL (c
) = lookup_decl (OMP_CLAUSE_DECL (c
), ctx
);
13494 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c
)))
13495 OMP_CLAUSE_LINEAR_STEP (c
)
13496 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c
),
13500 gimple_seq_add_stmt (&body
, stmt
);
13501 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
13503 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
13506 /* After the loop, add exit clauses. */
13507 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
13509 if (ctx
->cancellable
)
13510 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
13512 gimple_seq_add_seq (&body
, dlist
);
13514 body
= maybe_catch_exception (body
);
13516 /* Region exit marker goes at the end of the loop body. */
13517 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
13518 maybe_add_implicit_barrier_cancel (ctx
, &body
);
13519 pop_gimplify_context (new_stmt
);
13521 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
13522 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
13523 if (BLOCK_VARS (block
))
13524 TREE_USED (block
) = 1;
13526 gimple_bind_set_body (new_stmt
, body
);
13527 gimple_omp_set_body (stmt
, NULL
);
13528 gimple_omp_for_set_pre_body (stmt
, NULL
);
13531 /* Callback for walk_stmts. Check if the current statement only contains
13532 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
13535 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
13536 bool *handled_ops_p
,
13537 struct walk_stmt_info
*wi
)
13539 int *info
= (int *) wi
->info
;
13540 gimple
*stmt
= gsi_stmt (*gsi_p
);
13542 *handled_ops_p
= true;
13543 switch (gimple_code (stmt
))
13547 case GIMPLE_OMP_FOR
:
13548 case GIMPLE_OMP_SECTIONS
:
13549 *info
= *info
== 0 ? 1 : -1;
13558 struct omp_taskcopy_context
13560 /* This field must be at the beginning, as we do "inheritance": Some
13561 callback functions for tree-inline.c (e.g., omp_copy_decl)
13562 receive a copy_body_data pointer that is up-casted to an
13563 omp_context pointer. */
13569 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
13571 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
13573 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
13574 return create_tmp_var (TREE_TYPE (var
));
13580 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
13582 tree name
, new_fields
= NULL
, type
, f
;
13584 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
13585 name
= DECL_NAME (TYPE_NAME (orig_type
));
13586 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
13587 TYPE_DECL
, name
, type
);
13588 TYPE_NAME (type
) = name
;
13590 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
13592 tree new_f
= copy_node (f
);
13593 DECL_CONTEXT (new_f
) = type
;
13594 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
13595 TREE_CHAIN (new_f
) = new_fields
;
13596 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
13597 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
13598 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
13600 new_fields
= new_f
;
13601 tcctx
->cb
.decl_map
->put (f
, new_f
);
13603 TYPE_FIELDS (type
) = nreverse (new_fields
);
13604 layout_type (type
);
13608 /* Create task copyfn. */
13611 create_task_copyfn (gomp_task
*task_stmt
, omp_context
*ctx
)
13613 struct function
*child_cfun
;
13614 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
13615 tree record_type
, srecord_type
, bind
, list
;
13616 bool record_needs_remap
= false, srecord_needs_remap
= false;
13618 struct omp_taskcopy_context tcctx
;
13619 location_t loc
= gimple_location (task_stmt
);
13621 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
13622 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
13623 gcc_assert (child_cfun
->cfg
== NULL
);
13624 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
13626 /* Reset DECL_CONTEXT on function arguments. */
13627 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
13628 DECL_CONTEXT (t
) = child_fn
;
13630 /* Populate the function. */
13631 push_gimplify_context ();
13632 push_cfun (child_cfun
);
13634 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
13635 TREE_SIDE_EFFECTS (bind
) = 1;
13637 DECL_SAVED_TREE (child_fn
) = bind
;
13638 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
13640 /* Remap src and dst argument types if needed. */
13641 record_type
= ctx
->record_type
;
13642 srecord_type
= ctx
->srecord_type
;
13643 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
13644 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
13646 record_needs_remap
= true;
13649 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
13650 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
13652 srecord_needs_remap
= true;
13656 if (record_needs_remap
|| srecord_needs_remap
)
13658 memset (&tcctx
, '\0', sizeof (tcctx
));
13659 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
13660 tcctx
.cb
.dst_fn
= child_fn
;
13661 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
13662 gcc_checking_assert (tcctx
.cb
.src_node
);
13663 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
13664 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
13665 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
13666 tcctx
.cb
.eh_lp_nr
= 0;
13667 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
13668 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
13671 if (record_needs_remap
)
13672 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
13673 if (srecord_needs_remap
)
13674 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
13677 tcctx
.cb
.decl_map
= NULL
;
13679 arg
= DECL_ARGUMENTS (child_fn
);
13680 TREE_TYPE (arg
) = build_pointer_type (record_type
);
13681 sarg
= DECL_CHAIN (arg
);
13682 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
13684 /* First pass: initialize temporaries used in record_type and srecord_type
13685 sizes and field offsets. */
13686 if (tcctx
.cb
.decl_map
)
13687 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
13688 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
13692 decl
= OMP_CLAUSE_DECL (c
);
13693 p
= tcctx
.cb
.decl_map
->get (decl
);
13696 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
13697 sf
= (tree
) n
->value
;
13698 sf
= *tcctx
.cb
.decl_map
->get (sf
);
13699 src
= build_simple_mem_ref_loc (loc
, sarg
);
13700 src
= omp_build_component_ref (src
, sf
);
13701 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
13702 append_to_statement_list (t
, &list
);
13705 /* Second pass: copy shared var pointers and copy construct non-VLA
13706 firstprivate vars. */
13707 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
13708 switch (OMP_CLAUSE_CODE (c
))
13710 splay_tree_key key
;
13711 case OMP_CLAUSE_SHARED
:
13712 decl
= OMP_CLAUSE_DECL (c
);
13713 key
= (splay_tree_key
) decl
;
13714 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
13715 key
= (splay_tree_key
) &DECL_UID (decl
);
13716 n
= splay_tree_lookup (ctx
->field_map
, key
);
13719 f
= (tree
) n
->value
;
13720 if (tcctx
.cb
.decl_map
)
13721 f
= *tcctx
.cb
.decl_map
->get (f
);
13722 n
= splay_tree_lookup (ctx
->sfield_map
, key
);
13723 sf
= (tree
) n
->value
;
13724 if (tcctx
.cb
.decl_map
)
13725 sf
= *tcctx
.cb
.decl_map
->get (sf
);
13726 src
= build_simple_mem_ref_loc (loc
, sarg
);
13727 src
= omp_build_component_ref (src
, sf
);
13728 dst
= build_simple_mem_ref_loc (loc
, arg
);
13729 dst
= omp_build_component_ref (dst
, f
);
13730 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
13731 append_to_statement_list (t
, &list
);
13733 case OMP_CLAUSE_FIRSTPRIVATE
:
13734 decl
= OMP_CLAUSE_DECL (c
);
13735 if (is_variable_sized (decl
))
13737 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
13740 f
= (tree
) n
->value
;
13741 if (tcctx
.cb
.decl_map
)
13742 f
= *tcctx
.cb
.decl_map
->get (f
);
13743 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
13746 sf
= (tree
) n
->value
;
13747 if (tcctx
.cb
.decl_map
)
13748 sf
= *tcctx
.cb
.decl_map
->get (sf
);
13749 src
= build_simple_mem_ref_loc (loc
, sarg
);
13750 src
= omp_build_component_ref (src
, sf
);
13751 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
13752 src
= build_simple_mem_ref_loc (loc
, src
);
13756 dst
= build_simple_mem_ref_loc (loc
, arg
);
13757 dst
= omp_build_component_ref (dst
, f
);
13758 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
13759 append_to_statement_list (t
, &list
);
13761 case OMP_CLAUSE_PRIVATE
:
13762 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
13764 decl
= OMP_CLAUSE_DECL (c
);
13765 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
13766 f
= (tree
) n
->value
;
13767 if (tcctx
.cb
.decl_map
)
13768 f
= *tcctx
.cb
.decl_map
->get (f
);
13769 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
13772 sf
= (tree
) n
->value
;
13773 if (tcctx
.cb
.decl_map
)
13774 sf
= *tcctx
.cb
.decl_map
->get (sf
);
13775 src
= build_simple_mem_ref_loc (loc
, sarg
);
13776 src
= omp_build_component_ref (src
, sf
);
13777 if (use_pointer_for_field (decl
, NULL
))
13778 src
= build_simple_mem_ref_loc (loc
, src
);
13782 dst
= build_simple_mem_ref_loc (loc
, arg
);
13783 dst
= omp_build_component_ref (dst
, f
);
13784 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
13785 append_to_statement_list (t
, &list
);
13791 /* Last pass: handle VLA firstprivates. */
13792 if (tcctx
.cb
.decl_map
)
13793 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
13794 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
13798 decl
= OMP_CLAUSE_DECL (c
);
13799 if (!is_variable_sized (decl
))
13801 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
13804 f
= (tree
) n
->value
;
13805 f
= *tcctx
.cb
.decl_map
->get (f
);
13806 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
13807 ind
= DECL_VALUE_EXPR (decl
);
13808 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
13809 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
13810 n
= splay_tree_lookup (ctx
->sfield_map
,
13811 (splay_tree_key
) TREE_OPERAND (ind
, 0));
13812 sf
= (tree
) n
->value
;
13813 sf
= *tcctx
.cb
.decl_map
->get (sf
);
13814 src
= build_simple_mem_ref_loc (loc
, sarg
);
13815 src
= omp_build_component_ref (src
, sf
);
13816 src
= build_simple_mem_ref_loc (loc
, src
);
13817 dst
= build_simple_mem_ref_loc (loc
, arg
);
13818 dst
= omp_build_component_ref (dst
, f
);
13819 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
13820 append_to_statement_list (t
, &list
);
13821 n
= splay_tree_lookup (ctx
->field_map
,
13822 (splay_tree_key
) TREE_OPERAND (ind
, 0));
13823 df
= (tree
) n
->value
;
13824 df
= *tcctx
.cb
.decl_map
->get (df
);
13825 ptr
= build_simple_mem_ref_loc (loc
, arg
);
13826 ptr
= omp_build_component_ref (ptr
, df
);
13827 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
13828 build_fold_addr_expr_loc (loc
, dst
));
13829 append_to_statement_list (t
, &list
);
13832 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
13833 append_to_statement_list (t
, &list
);
13835 if (tcctx
.cb
.decl_map
)
13836 delete tcctx
.cb
.decl_map
;
13837 pop_gimplify_context (NULL
);
13838 BIND_EXPR_BODY (bind
) = list
;
13843 lower_depend_clauses (tree
*pclauses
, gimple_seq
*iseq
, gimple_seq
*oseq
)
13847 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
13849 clauses
= find_omp_clause (*pclauses
, OMP_CLAUSE_DEPEND
);
13850 gcc_assert (clauses
);
13851 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
13852 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
13853 switch (OMP_CLAUSE_DEPEND_KIND (c
))
13855 case OMP_CLAUSE_DEPEND_IN
:
13858 case OMP_CLAUSE_DEPEND_OUT
:
13859 case OMP_CLAUSE_DEPEND_INOUT
:
13862 case OMP_CLAUSE_DEPEND_SOURCE
:
13863 case OMP_CLAUSE_DEPEND_SINK
:
13866 gcc_unreachable ();
13868 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
13869 tree array
= create_tmp_var (type
);
13870 TREE_ADDRESSABLE (array
) = 1;
13871 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
13873 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
13874 gimple_seq_add_stmt (iseq
, g
);
13875 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
13877 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
13878 gimple_seq_add_stmt (iseq
, g
);
13879 for (i
= 0; i
< 2; i
++)
13881 if ((i
? n_in
: n_out
) == 0)
13883 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
13884 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
13885 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
13887 tree t
= OMP_CLAUSE_DECL (c
);
13888 t
= fold_convert (ptr_type_node
, t
);
13889 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
13890 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
13891 NULL_TREE
, NULL_TREE
);
13892 g
= gimple_build_assign (r
, t
);
13893 gimple_seq_add_stmt (iseq
, g
);
13896 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
13897 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
13898 OMP_CLAUSE_CHAIN (c
) = *pclauses
;
13900 tree clobber
= build_constructor (type
, NULL
);
13901 TREE_THIS_VOLATILE (clobber
) = 1;
13902 g
= gimple_build_assign (array
, clobber
);
13903 gimple_seq_add_stmt (oseq
, g
);
13906 /* Lower the OpenMP parallel or task directive in the current statement
13907 in GSI_P. CTX holds context information for the directive. */
13910 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
13914 gimple
*stmt
= gsi_stmt (*gsi_p
);
13915 gbind
*par_bind
, *bind
, *dep_bind
= NULL
;
13916 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
13917 location_t loc
= gimple_location (stmt
);
13919 clauses
= gimple_omp_taskreg_clauses (stmt
);
13921 = as_a
<gbind
*> (gimple_seq_first_stmt (gimple_omp_body (stmt
)));
13922 par_body
= gimple_bind_body (par_bind
);
13923 child_fn
= ctx
->cb
.dst_fn
;
13924 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
13925 && !gimple_omp_parallel_combined_p (stmt
))
13927 struct walk_stmt_info wi
;
13930 memset (&wi
, 0, sizeof (wi
));
13932 wi
.val_only
= true;
13933 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
13935 gimple_omp_parallel_set_combined_p (stmt
, true);
13937 gimple_seq dep_ilist
= NULL
;
13938 gimple_seq dep_olist
= NULL
;
13939 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
13940 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
13942 push_gimplify_context ();
13943 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
13944 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt
),
13945 &dep_ilist
, &dep_olist
);
13948 if (ctx
->srecord_type
)
13949 create_task_copyfn (as_a
<gomp_task
*> (stmt
), ctx
);
13951 push_gimplify_context ();
13956 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
13957 lower_omp (&par_body
, ctx
);
13958 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
13959 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
13961 /* Declare all the variables created by mapping and the variables
13962 declared in the scope of the parallel body. */
13963 record_vars_into (ctx
->block_vars
, child_fn
);
13964 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
13966 if (ctx
->record_type
)
13969 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
13970 : ctx
->record_type
, ".omp_data_o");
13971 DECL_NAMELESS (ctx
->sender_decl
) = 1;
13972 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
13973 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
13978 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
13979 lower_send_shared_vars (&ilist
, &olist
, ctx
);
13981 if (ctx
->record_type
)
13983 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
13984 TREE_THIS_VOLATILE (clobber
) = 1;
13985 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
13989 /* Once all the expansions are done, sequence all the different
13990 fragments inside gimple_omp_body. */
13994 if (ctx
->record_type
)
13996 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
13997 /* fixup_child_record_type might have changed receiver_decl's type. */
13998 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
13999 gimple_seq_add_stmt (&new_body
,
14000 gimple_build_assign (ctx
->receiver_decl
, t
));
14003 gimple_seq_add_seq (&new_body
, par_ilist
);
14004 gimple_seq_add_seq (&new_body
, par_body
);
14005 gimple_seq_add_seq (&new_body
, par_rlist
);
14006 if (ctx
->cancellable
)
14007 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
14008 gimple_seq_add_seq (&new_body
, par_olist
);
14009 new_body
= maybe_catch_exception (new_body
);
14010 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
)
14011 gimple_seq_add_stmt (&new_body
,
14012 gimple_build_omp_continue (integer_zero_node
,
14013 integer_zero_node
));
14014 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
14015 gimple_omp_set_body (stmt
, new_body
);
14017 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
14018 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
14019 gimple_bind_add_seq (bind
, ilist
);
14020 gimple_bind_add_stmt (bind
, stmt
);
14021 gimple_bind_add_seq (bind
, olist
);
14023 pop_gimplify_context (NULL
);
14027 gimple_bind_add_seq (dep_bind
, dep_ilist
);
14028 gimple_bind_add_stmt (dep_bind
, bind
);
14029 gimple_bind_add_seq (dep_bind
, dep_olist
);
14030 pop_gimplify_context (dep_bind
);
14034 /* Lower the GIMPLE_OMP_TARGET in the current statement
14035 in GSI_P. CTX holds context information for the directive. */
14038 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
14041 tree child_fn
, t
, c
;
14042 gomp_target
*stmt
= as_a
<gomp_target
*> (gsi_stmt (*gsi_p
));
14043 gbind
*tgt_bind
, *bind
, *dep_bind
= NULL
;
14044 gimple_seq tgt_body
, olist
, ilist
, orlist
, irlist
, new_body
;
14045 location_t loc
= gimple_location (stmt
);
14046 bool offloaded
, data_region
;
14047 unsigned int map_cnt
= 0;
14048 bool has_depend
= false;
14050 offloaded
= is_gimple_omp_offloaded (stmt
);
14051 switch (gimple_omp_target_kind (stmt
))
14053 case GF_OMP_TARGET_KIND_REGION
:
14054 case GF_OMP_TARGET_KIND_UPDATE
:
14055 case GF_OMP_TARGET_KIND_ENTER_DATA
:
14056 case GF_OMP_TARGET_KIND_EXIT_DATA
:
14057 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
14058 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
14059 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
14060 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
14061 data_region
= false;
14063 case GF_OMP_TARGET_KIND_DATA
:
14064 case GF_OMP_TARGET_KIND_OACC_DATA
:
14065 data_region
= true;
14068 gcc_unreachable ();
14071 clauses
= gimple_omp_target_clauses (stmt
);
14073 gimple_seq dep_ilist
= NULL
;
14074 gimple_seq dep_olist
= NULL
;
14075 if (find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
14077 push_gimplify_context ();
14078 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
14079 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt
),
14080 &dep_ilist
, &dep_olist
);
14088 tgt_bind
= gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt
));
14089 tgt_body
= gimple_bind_body (tgt_bind
);
14091 else if (data_region
)
14092 tgt_body
= gimple_omp_body (stmt
);
14093 child_fn
= ctx
->cb
.dst_fn
;
14095 push_gimplify_context ();
14100 && is_gimple_omp_oacc (stmt
))
14101 oacc_process_reduction_data (&tgt_body
, &irlist
, &orlist
, ctx
);
14103 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
14104 switch (OMP_CLAUSE_CODE (c
))
14110 case OMP_CLAUSE_MAP
:
14111 #ifdef ENABLE_CHECKING
14112 /* First check what we're prepared to handle in the following. */
14113 switch (OMP_CLAUSE_MAP_KIND (c
))
14115 case GOMP_MAP_ALLOC
:
14117 case GOMP_MAP_FROM
:
14118 case GOMP_MAP_TOFROM
:
14119 case GOMP_MAP_POINTER
:
14120 case GOMP_MAP_TO_PSET
:
14121 case GOMP_MAP_FORCE_DEALLOC
:
14122 case GOMP_MAP_RELEASE
:
14123 case GOMP_MAP_ALWAYS_TO
:
14124 case GOMP_MAP_ALWAYS_FROM
:
14125 case GOMP_MAP_ALWAYS_TOFROM
:
14126 case GOMP_MAP_FIRSTPRIVATE_POINTER
:
14127 case GOMP_MAP_STRUCT
:
14129 case GOMP_MAP_FORCE_ALLOC
:
14130 case GOMP_MAP_FORCE_TO
:
14131 case GOMP_MAP_FORCE_FROM
:
14132 case GOMP_MAP_FORCE_TOFROM
:
14133 case GOMP_MAP_FORCE_PRESENT
:
14134 case GOMP_MAP_FORCE_DEVICEPTR
:
14135 gcc_assert (is_gimple_omp_oacc (stmt
));
14138 gcc_unreachable ();
14142 case OMP_CLAUSE_TO
:
14143 case OMP_CLAUSE_FROM
:
14144 var
= OMP_CLAUSE_DECL (c
);
14147 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
14148 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
14149 && (OMP_CLAUSE_MAP_KIND (c
)
14150 != GOMP_MAP_FIRSTPRIVATE_POINTER
)))
14155 if (DECL_SIZE (var
)
14156 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
14158 tree var2
= DECL_VALUE_EXPR (var
);
14159 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
14160 var2
= TREE_OPERAND (var2
, 0);
14161 gcc_assert (DECL_P (var2
));
14166 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
)
14168 if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
14170 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
))
14171 && varpool_node::get_create (var
)->offloadable
)
14174 tree type
= build_pointer_type (TREE_TYPE (var
));
14175 tree new_var
= lookup_decl (var
, ctx
);
14176 x
= create_tmp_var_raw (type
, get_name (new_var
));
14177 gimple_add_tmp_var (x
);
14178 x
= build_simple_mem_ref (x
);
14179 SET_DECL_VALUE_EXPR (new_var
, x
);
14180 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
14185 if (offloaded
&& OMP_CLAUSE_MAP_PRIVATE (c
))
14191 if (!maybe_lookup_field (var
, ctx
))
14196 x
= build_receiver_ref (var
, true, ctx
);
14197 tree new_var
= lookup_decl (var
, ctx
);
14199 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
14200 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
14201 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
14202 x
= build_simple_mem_ref (x
);
14203 SET_DECL_VALUE_EXPR (new_var
, x
);
14204 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
14209 case OMP_CLAUSE_FIRSTPRIVATE
:
14211 var
= OMP_CLAUSE_DECL (c
);
14212 if (!is_reference (var
)
14213 && !is_gimple_reg_type (TREE_TYPE (var
)))
14215 tree new_var
= lookup_decl (var
, ctx
);
14216 if (is_variable_sized (var
))
14218 tree pvar
= DECL_VALUE_EXPR (var
);
14219 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
14220 pvar
= TREE_OPERAND (pvar
, 0);
14221 gcc_assert (DECL_P (pvar
));
14222 tree new_pvar
= lookup_decl (pvar
, ctx
);
14223 x
= build_fold_indirect_ref (new_pvar
);
14224 TREE_THIS_NOTRAP (x
) = 1;
14227 x
= build_receiver_ref (var
, true, ctx
);
14228 SET_DECL_VALUE_EXPR (new_var
, x
);
14229 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
14233 case OMP_CLAUSE_PRIVATE
:
14234 var
= OMP_CLAUSE_DECL (c
);
14235 if (is_variable_sized (var
))
14237 tree new_var
= lookup_decl (var
, ctx
);
14238 tree pvar
= DECL_VALUE_EXPR (var
);
14239 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
14240 pvar
= TREE_OPERAND (pvar
, 0);
14241 gcc_assert (DECL_P (pvar
));
14242 tree new_pvar
= lookup_decl (pvar
, ctx
);
14243 x
= build_fold_indirect_ref (new_pvar
);
14244 TREE_THIS_NOTRAP (x
) = 1;
14245 SET_DECL_VALUE_EXPR (new_var
, x
);
14246 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
14250 case OMP_CLAUSE_USE_DEVICE_PTR
:
14251 case OMP_CLAUSE_IS_DEVICE_PTR
:
14252 var
= OMP_CLAUSE_DECL (c
);
14254 if (is_variable_sized (var
))
14256 tree new_var
= lookup_decl (var
, ctx
);
14257 tree pvar
= DECL_VALUE_EXPR (var
);
14258 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
14259 pvar
= TREE_OPERAND (pvar
, 0);
14260 gcc_assert (DECL_P (pvar
));
14261 tree new_pvar
= lookup_decl (pvar
, ctx
);
14262 x
= build_fold_indirect_ref (new_pvar
);
14263 TREE_THIS_NOTRAP (x
) = 1;
14264 SET_DECL_VALUE_EXPR (new_var
, x
);
14265 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
14267 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
14269 tree new_var
= lookup_decl (var
, ctx
);
14270 tree type
= build_pointer_type (TREE_TYPE (var
));
14271 x
= create_tmp_var_raw (type
, get_name (new_var
));
14272 gimple_add_tmp_var (x
);
14273 x
= build_simple_mem_ref (x
);
14274 SET_DECL_VALUE_EXPR (new_var
, x
);
14275 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
14282 target_nesting_level
++;
14283 lower_omp (&tgt_body
, ctx
);
14284 target_nesting_level
--;
14286 else if (data_region
)
14287 lower_omp (&tgt_body
, ctx
);
14291 /* Declare all the variables created by mapping and the variables
14292 declared in the scope of the target body. */
14293 record_vars_into (ctx
->block_vars
, child_fn
);
14294 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
14299 if (ctx
->record_type
)
14302 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
14303 DECL_NAMELESS (ctx
->sender_decl
) = 1;
14304 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
14305 t
= make_tree_vec (3);
14306 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
14307 TREE_VEC_ELT (t
, 1)
14308 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
14309 ".omp_data_sizes");
14310 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
14311 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
14312 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
14313 tree tkind_type
= short_unsigned_type_node
;
14314 int talign_shift
= 8;
14315 TREE_VEC_ELT (t
, 2)
14316 = create_tmp_var (build_array_type_nelts (tkind_type
, map_cnt
),
14317 ".omp_data_kinds");
14318 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
14319 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
14320 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
14321 gimple_omp_target_set_data_arg (stmt
, t
);
14323 vec
<constructor_elt
, va_gc
> *vsize
;
14324 vec
<constructor_elt
, va_gc
> *vkind
;
14325 vec_alloc (vsize
, map_cnt
);
14326 vec_alloc (vkind
, map_cnt
);
14327 unsigned int map_idx
= 0;
14329 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
14330 switch (OMP_CLAUSE_CODE (c
))
14332 tree ovar
, nc
, s
, purpose
, var
, x
, type
;
14333 unsigned int talign
;
14337 case OMP_CLAUSE_MAP
:
14338 case OMP_CLAUSE_TO
:
14339 case OMP_CLAUSE_FROM
:
14341 ovar
= OMP_CLAUSE_DECL (c
);
14342 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
14343 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
)
14345 if (!DECL_P (ovar
))
14347 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
14348 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
14350 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
14351 == get_base_address (ovar
));
14352 nc
= OMP_CLAUSE_CHAIN (c
);
14353 ovar
= OMP_CLAUSE_DECL (nc
);
14357 tree x
= build_sender_ref (ovar
, ctx
);
14359 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
14360 gimplify_assign (x
, v
, &ilist
);
14366 if (DECL_SIZE (ovar
)
14367 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
14369 tree ovar2
= DECL_VALUE_EXPR (ovar
);
14370 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
14371 ovar2
= TREE_OPERAND (ovar2
, 0);
14372 gcc_assert (DECL_P (ovar2
));
14375 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
14376 && OMP_CLAUSE_MAP_PRIVATE (c
))
14378 if (!maybe_lookup_field ((splay_tree_key
) &DECL_UID (ovar
),
14382 else if (!maybe_lookup_field (ovar
, ctx
))
14386 talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
14387 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
14388 talign
= DECL_ALIGN_UNIT (ovar
);
14391 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
14392 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
14393 && OMP_CLAUSE_MAP_PRIVATE (c
))
14394 x
= build_sender_ref ((splay_tree_key
) &DECL_UID (ovar
),
14397 x
= build_sender_ref (ovar
, ctx
);
14398 if (maybe_lookup_oacc_reduction (var
, ctx
))
14400 gcc_checking_assert (offloaded
14401 && is_gimple_omp_oacc (stmt
));
14402 gimplify_assign (x
, var
, &ilist
);
14404 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
14405 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
14406 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
14407 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
14409 gcc_assert (offloaded
);
14411 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)));
14412 mark_addressable (avar
);
14413 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
14414 talign
= DECL_ALIGN_UNIT (avar
);
14415 avar
= build_fold_addr_expr (avar
);
14416 gimplify_assign (x
, avar
, &ilist
);
14418 else if (is_gimple_reg (var
))
14420 gcc_assert (offloaded
);
14421 tree avar
= create_tmp_var (TREE_TYPE (var
));
14422 mark_addressable (avar
);
14423 enum gomp_map_kind map_kind
= OMP_CLAUSE_MAP_KIND (c
);
14424 if (GOMP_MAP_COPY_TO_P (map_kind
)
14425 || map_kind
== GOMP_MAP_POINTER
14426 || map_kind
== GOMP_MAP_TO_PSET
14427 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
14428 gimplify_assign (avar
, var
, &ilist
);
14429 avar
= build_fold_addr_expr (avar
);
14430 gimplify_assign (x
, avar
, &ilist
);
14431 if ((GOMP_MAP_COPY_FROM_P (map_kind
)
14432 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
14433 && !TYPE_READONLY (TREE_TYPE (var
)))
14435 x
= unshare_expr (x
);
14436 x
= build_simple_mem_ref (x
);
14437 gimplify_assign (var
, x
, &olist
);
14442 var
= build_fold_addr_expr (var
);
14443 gimplify_assign (x
, var
, &ilist
);
14446 s
= OMP_CLAUSE_SIZE (c
);
14447 if (s
== NULL_TREE
)
14448 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
14449 s
= fold_convert (size_type_node
, s
);
14450 purpose
= size_int (map_idx
++);
14451 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
14452 if (TREE_CODE (s
) != INTEGER_CST
)
14453 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
14455 unsigned HOST_WIDE_INT tkind
, tkind_zero
;
14456 switch (OMP_CLAUSE_CODE (c
))
14458 case OMP_CLAUSE_MAP
:
14459 tkind
= OMP_CLAUSE_MAP_KIND (c
);
14460 tkind_zero
= tkind
;
14461 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c
))
14464 case GOMP_MAP_ALLOC
:
14466 case GOMP_MAP_FROM
:
14467 case GOMP_MAP_TOFROM
:
14468 case GOMP_MAP_ALWAYS_TO
:
14469 case GOMP_MAP_ALWAYS_FROM
:
14470 case GOMP_MAP_ALWAYS_TOFROM
:
14471 case GOMP_MAP_RELEASE
:
14472 tkind_zero
= GOMP_MAP_ZERO_LEN_ARRAY_SECTION
;
14474 case GOMP_MAP_DELETE
:
14475 tkind_zero
= GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION
;
14479 if (tkind_zero
!= tkind
)
14481 if (integer_zerop (s
))
14482 tkind
= tkind_zero
;
14483 else if (integer_nonzerop (s
))
14484 tkind_zero
= tkind
;
14487 case OMP_CLAUSE_TO
:
14488 tkind
= GOMP_MAP_TO
;
14489 tkind_zero
= tkind
;
14491 case OMP_CLAUSE_FROM
:
14492 tkind
= GOMP_MAP_FROM
;
14493 tkind_zero
= tkind
;
14496 gcc_unreachable ();
14498 gcc_checking_assert (tkind
14499 < (HOST_WIDE_INT_C (1U) << talign_shift
));
14500 gcc_checking_assert (tkind_zero
14501 < (HOST_WIDE_INT_C (1U) << talign_shift
));
14502 talign
= ceil_log2 (talign
);
14503 tkind
|= talign
<< talign_shift
;
14504 tkind_zero
|= talign
<< talign_shift
;
14505 gcc_checking_assert (tkind
14506 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
14507 gcc_checking_assert (tkind_zero
14508 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
14509 if (tkind
== tkind_zero
)
14510 x
= build_int_cstu (tkind_type
, tkind
);
14513 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 0;
14514 x
= build3 (COND_EXPR
, tkind_type
,
14515 fold_build2 (EQ_EXPR
, boolean_type_node
,
14516 unshare_expr (s
), size_zero_node
),
14517 build_int_cstu (tkind_type
, tkind_zero
),
14518 build_int_cstu (tkind_type
, tkind
));
14520 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
, x
);
14525 case OMP_CLAUSE_FIRSTPRIVATE
:
14526 ovar
= OMP_CLAUSE_DECL (c
);
14527 if (is_reference (ovar
))
14528 talign
= TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar
)));
14530 talign
= DECL_ALIGN_UNIT (ovar
);
14531 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
14532 x
= build_sender_ref (ovar
, ctx
);
14533 tkind
= GOMP_MAP_FIRSTPRIVATE
;
14534 type
= TREE_TYPE (ovar
);
14535 if (is_reference (ovar
))
14536 type
= TREE_TYPE (type
);
14537 bool use_firstprivate_int
, force_addr
;
14538 use_firstprivate_int
= false;
14539 force_addr
= false;
14540 if ((INTEGRAL_TYPE_P (type
)
14541 && TYPE_PRECISION (type
) <= POINTER_SIZE
)
14542 || TREE_CODE (type
) == POINTER_TYPE
)
14543 use_firstprivate_int
= true;
14546 if (is_reference (var
))
14547 use_firstprivate_int
= false;
14548 else if (is_gimple_reg (var
))
14550 if (DECL_HAS_VALUE_EXPR_P (var
))
14552 tree v
= get_base_address (var
);
14553 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
14555 use_firstprivate_int
= false;
14559 switch (TREE_CODE (v
))
14563 use_firstprivate_int
= false;
14572 use_firstprivate_int
= false;
14574 if (use_firstprivate_int
)
14576 tkind
= GOMP_MAP_FIRSTPRIVATE_INT
;
14578 if (is_reference (var
))
14579 t
= build_simple_mem_ref (var
);
14580 if (TREE_CODE (type
) != POINTER_TYPE
)
14581 t
= fold_convert (pointer_sized_int_node
, t
);
14582 t
= fold_convert (TREE_TYPE (x
), t
);
14583 gimplify_assign (x
, t
, &ilist
);
14585 else if (is_reference (var
))
14586 gimplify_assign (x
, var
, &ilist
);
14587 else if (!force_addr
&& is_gimple_reg (var
))
14589 tree avar
= create_tmp_var (TREE_TYPE (var
));
14590 mark_addressable (avar
);
14591 gimplify_assign (avar
, var
, &ilist
);
14592 avar
= build_fold_addr_expr (avar
);
14593 gimplify_assign (x
, avar
, &ilist
);
14597 var
= build_fold_addr_expr (var
);
14598 gimplify_assign (x
, var
, &ilist
);
14600 if (tkind
== GOMP_MAP_FIRSTPRIVATE_INT
)
14602 else if (is_reference (var
))
14603 s
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar
)));
14605 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
14606 s
= fold_convert (size_type_node
, s
);
14607 purpose
= size_int (map_idx
++);
14608 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
14609 if (TREE_CODE (s
) != INTEGER_CST
)
14610 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
14612 gcc_checking_assert (tkind
14613 < (HOST_WIDE_INT_C (1U) << talign_shift
));
14614 talign
= ceil_log2 (talign
);
14615 tkind
|= talign
<< talign_shift
;
14616 gcc_checking_assert (tkind
14617 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
14618 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
14619 build_int_cstu (tkind_type
, tkind
));
14622 case OMP_CLAUSE_USE_DEVICE_PTR
:
14623 case OMP_CLAUSE_IS_DEVICE_PTR
:
14624 ovar
= OMP_CLAUSE_DECL (c
);
14625 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
14626 x
= build_sender_ref (ovar
, ctx
);
14627 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_USE_DEVICE_PTR
)
14628 tkind
= GOMP_MAP_USE_DEVICE_PTR
;
14630 tkind
= GOMP_MAP_FIRSTPRIVATE_INT
;
14631 type
= TREE_TYPE (ovar
);
14632 if (TREE_CODE (type
) == ARRAY_TYPE
)
14633 var
= build_fold_addr_expr (var
);
14636 if (is_reference (ovar
))
14638 type
= TREE_TYPE (type
);
14639 if (TREE_CODE (type
) != ARRAY_TYPE
)
14640 var
= build_simple_mem_ref (var
);
14641 var
= fold_convert (TREE_TYPE (x
), var
);
14644 gimplify_assign (x
, var
, &ilist
);
14646 purpose
= size_int (map_idx
++);
14647 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
14648 gcc_checking_assert (tkind
14649 < (HOST_WIDE_INT_C (1U) << talign_shift
));
14650 gcc_checking_assert (tkind
14651 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
14652 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
14653 build_int_cstu (tkind_type
, tkind
));
14657 gcc_assert (map_idx
== map_cnt
);
14659 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
14660 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
14661 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
14662 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
14663 for (int i
= 1; i
<= 2; i
++)
14664 if (!TREE_STATIC (TREE_VEC_ELT (t
, i
)))
14666 gimple_seq initlist
= NULL
;
14667 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
14668 TREE_VEC_ELT (t
, i
)),
14669 &initlist
, true, NULL_TREE
);
14670 gimple_seq_add_seq (&ilist
, initlist
);
14672 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, i
)),
14674 TREE_THIS_VOLATILE (clobber
) = 1;
14675 gimple_seq_add_stmt (&olist
,
14676 gimple_build_assign (TREE_VEC_ELT (t
, i
),
14680 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
14681 TREE_THIS_VOLATILE (clobber
) = 1;
14682 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
14686 /* Once all the expansions are done, sequence all the different
14687 fragments inside gimple_omp_body. */
14692 && ctx
->record_type
)
14694 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
14695 /* fixup_child_record_type might have changed receiver_decl's type. */
14696 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
14697 gimple_seq_add_stmt (&new_body
,
14698 gimple_build_assign (ctx
->receiver_decl
, t
));
14701 if (offloaded
|| data_region
)
14703 tree prev
= NULL_TREE
;
14704 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
14705 switch (OMP_CLAUSE_CODE (c
))
14710 case OMP_CLAUSE_FIRSTPRIVATE
:
14711 var
= OMP_CLAUSE_DECL (c
);
14712 if (is_reference (var
)
14713 || is_gimple_reg_type (TREE_TYPE (var
)))
14715 tree new_var
= lookup_decl (var
, ctx
);
14717 type
= TREE_TYPE (var
);
14718 if (is_reference (var
))
14719 type
= TREE_TYPE (type
);
14720 bool use_firstprivate_int
;
14721 use_firstprivate_int
= false;
14722 if ((INTEGRAL_TYPE_P (type
)
14723 && TYPE_PRECISION (type
) <= POINTER_SIZE
)
14724 || TREE_CODE (type
) == POINTER_TYPE
)
14725 use_firstprivate_int
= true;
14728 tree v
= lookup_decl_in_outer_ctx (var
, ctx
);
14729 if (is_reference (v
))
14730 use_firstprivate_int
= false;
14731 else if (is_gimple_reg (v
))
14733 if (DECL_HAS_VALUE_EXPR_P (v
))
14735 v
= get_base_address (v
);
14736 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
14737 use_firstprivate_int
= false;
14739 switch (TREE_CODE (v
))
14743 use_firstprivate_int
= false;
14751 use_firstprivate_int
= false;
14753 if (use_firstprivate_int
)
14755 x
= build_receiver_ref (var
, false, ctx
);
14756 if (TREE_CODE (type
) != POINTER_TYPE
)
14757 x
= fold_convert (pointer_sized_int_node
, x
);
14758 x
= fold_convert (type
, x
);
14759 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
,
14761 if (is_reference (var
))
14763 tree v
= create_tmp_var_raw (type
, get_name (var
));
14764 gimple_add_tmp_var (v
);
14765 TREE_ADDRESSABLE (v
) = 1;
14766 gimple_seq_add_stmt (&new_body
,
14767 gimple_build_assign (v
, x
));
14768 x
= build_fold_addr_expr (v
);
14770 gimple_seq_add_stmt (&new_body
,
14771 gimple_build_assign (new_var
, x
));
14775 x
= build_receiver_ref (var
, !is_reference (var
), ctx
);
14776 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
,
14778 gimple_seq_add_stmt (&new_body
,
14779 gimple_build_assign (new_var
, x
));
14782 else if (is_variable_sized (var
))
14784 tree pvar
= DECL_VALUE_EXPR (var
);
14785 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
14786 pvar
= TREE_OPERAND (pvar
, 0);
14787 gcc_assert (DECL_P (pvar
));
14788 tree new_var
= lookup_decl (pvar
, ctx
);
14789 x
= build_receiver_ref (var
, false, ctx
);
14790 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
14791 gimple_seq_add_stmt (&new_body
,
14792 gimple_build_assign (new_var
, x
));
14795 case OMP_CLAUSE_PRIVATE
:
14796 var
= OMP_CLAUSE_DECL (c
);
14797 if (is_reference (var
))
14799 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
14800 tree new_var
= lookup_decl (var
, ctx
);
14801 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
14802 if (TREE_CONSTANT (x
))
14804 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
14806 gimple_add_tmp_var (x
);
14807 TREE_ADDRESSABLE (x
) = 1;
14808 x
= build_fold_addr_expr_loc (clause_loc
, x
);
14813 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
14814 tree rtype
= TREE_TYPE (TREE_TYPE (new_var
));
14815 tree al
= size_int (TYPE_ALIGN (rtype
));
14816 x
= build_call_expr_loc (clause_loc
, atmp
, 2, x
, al
);
14819 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
14820 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
14821 gimple_seq_add_stmt (&new_body
,
14822 gimple_build_assign (new_var
, x
));
14825 case OMP_CLAUSE_USE_DEVICE_PTR
:
14826 case OMP_CLAUSE_IS_DEVICE_PTR
:
14827 var
= OMP_CLAUSE_DECL (c
);
14828 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_USE_DEVICE_PTR
)
14829 x
= build_sender_ref (var
, ctx
);
14831 x
= build_receiver_ref (var
, false, ctx
);
14832 if (is_variable_sized (var
))
14834 tree pvar
= DECL_VALUE_EXPR (var
);
14835 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
14836 pvar
= TREE_OPERAND (pvar
, 0);
14837 gcc_assert (DECL_P (pvar
));
14838 tree new_var
= lookup_decl (pvar
, ctx
);
14839 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
14840 gimple_seq_add_stmt (&new_body
,
14841 gimple_build_assign (new_var
, x
));
14843 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
14845 tree new_var
= lookup_decl (var
, ctx
);
14846 new_var
= DECL_VALUE_EXPR (new_var
);
14847 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
14848 new_var
= TREE_OPERAND (new_var
, 0);
14849 gcc_assert (DECL_P (new_var
));
14850 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
14851 gimple_seq_add_stmt (&new_body
,
14852 gimple_build_assign (new_var
, x
));
14856 tree type
= TREE_TYPE (var
);
14857 tree new_var
= lookup_decl (var
, ctx
);
14858 if (is_reference (var
))
14860 type
= TREE_TYPE (type
);
14861 if (TREE_CODE (type
) != ARRAY_TYPE
)
14863 tree v
= create_tmp_var_raw (type
, get_name (var
));
14864 gimple_add_tmp_var (v
);
14865 TREE_ADDRESSABLE (v
) = 1;
14866 x
= fold_convert (type
, x
);
14867 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
,
14869 gimple_seq_add_stmt (&new_body
,
14870 gimple_build_assign (v
, x
));
14871 x
= build_fold_addr_expr (v
);
14874 x
= fold_convert (TREE_TYPE (new_var
), x
);
14875 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
14876 gimple_seq_add_stmt (&new_body
,
14877 gimple_build_assign (new_var
, x
));
14881 /* Handle GOMP_MAP_FIRSTPRIVATE_POINTER in second pass,
14882 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
14883 are already handled. */
14884 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
14885 switch (OMP_CLAUSE_CODE (c
))
14890 case OMP_CLAUSE_MAP
:
14891 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
)
14893 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
14894 HOST_WIDE_INT offset
= 0;
14896 var
= OMP_CLAUSE_DECL (c
);
14898 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
14899 && is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
14901 && varpool_node::get_create (var
)->offloadable
)
14903 if (TREE_CODE (var
) == INDIRECT_REF
14904 && TREE_CODE (TREE_OPERAND (var
, 0)) == COMPONENT_REF
)
14905 var
= TREE_OPERAND (var
, 0);
14906 if (TREE_CODE (var
) == COMPONENT_REF
)
14908 var
= get_addr_base_and_unit_offset (var
, &offset
);
14909 gcc_assert (var
!= NULL_TREE
&& DECL_P (var
));
14911 else if (DECL_SIZE (var
)
14912 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
14914 tree var2
= DECL_VALUE_EXPR (var
);
14915 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
14916 var2
= TREE_OPERAND (var2
, 0);
14917 gcc_assert (DECL_P (var2
));
14920 tree new_var
= lookup_decl (var
, ctx
), x
;
14921 tree type
= TREE_TYPE (new_var
);
14923 if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == INDIRECT_REF
14924 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c
), 0))
14927 type
= TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c
), 0));
14929 new_var
= build2 (MEM_REF
, type
,
14930 build_fold_addr_expr (new_var
),
14931 build_int_cst (build_pointer_type (type
),
14934 else if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == COMPONENT_REF
)
14936 type
= TREE_TYPE (OMP_CLAUSE_DECL (c
));
14937 is_ref
= TREE_CODE (type
) == REFERENCE_TYPE
;
14938 new_var
= build2 (MEM_REF
, type
,
14939 build_fold_addr_expr (new_var
),
14940 build_int_cst (build_pointer_type (type
),
14944 is_ref
= is_reference (var
);
14945 bool ref_to_array
= false;
14948 type
= TREE_TYPE (type
);
14949 if (TREE_CODE (type
) == ARRAY_TYPE
)
14951 type
= build_pointer_type (type
);
14952 ref_to_array
= true;
14955 else if (TREE_CODE (type
) == ARRAY_TYPE
)
14957 tree decl2
= DECL_VALUE_EXPR (new_var
);
14958 gcc_assert (TREE_CODE (decl2
) == MEM_REF
);
14959 decl2
= TREE_OPERAND (decl2
, 0);
14960 gcc_assert (DECL_P (decl2
));
14962 type
= TREE_TYPE (new_var
);
14964 x
= build_receiver_ref (OMP_CLAUSE_DECL (prev
), false, ctx
);
14965 x
= fold_convert_loc (clause_loc
, type
, x
);
14966 if (!integer_zerop (OMP_CLAUSE_SIZE (c
)))
14968 tree bias
= OMP_CLAUSE_SIZE (c
);
14970 bias
= lookup_decl (bias
, ctx
);
14971 bias
= fold_convert_loc (clause_loc
, sizetype
, bias
);
14972 bias
= fold_build1_loc (clause_loc
, NEGATE_EXPR
, sizetype
,
14974 x
= fold_build2_loc (clause_loc
, POINTER_PLUS_EXPR
,
14975 TREE_TYPE (x
), x
, bias
);
14978 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
14979 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
14980 if (is_ref
&& !ref_to_array
)
14982 tree t
= create_tmp_var_raw (type
, get_name (var
));
14983 gimple_add_tmp_var (t
);
14984 TREE_ADDRESSABLE (t
) = 1;
14985 gimple_seq_add_stmt (&new_body
,
14986 gimple_build_assign (t
, x
));
14987 x
= build_fold_addr_expr_loc (clause_loc
, t
);
14989 gimple_seq_add_stmt (&new_body
,
14990 gimple_build_assign (new_var
, x
));
14993 else if (OMP_CLAUSE_CHAIN (c
)
14994 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c
))
14996 && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c
))
14997 == GOMP_MAP_FIRSTPRIVATE_POINTER
)
15000 case OMP_CLAUSE_PRIVATE
:
15001 var
= OMP_CLAUSE_DECL (c
);
15002 if (is_variable_sized (var
))
15004 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
15005 tree new_var
= lookup_decl (var
, ctx
);
15006 tree pvar
= DECL_VALUE_EXPR (var
);
15007 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
15008 pvar
= TREE_OPERAND (pvar
, 0);
15009 gcc_assert (DECL_P (pvar
));
15010 tree new_pvar
= lookup_decl (pvar
, ctx
);
15011 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
15012 tree al
= size_int (DECL_ALIGN (var
));
15013 tree x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
15014 x
= build_call_expr_loc (clause_loc
, atmp
, 2, x
, al
);
15015 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_pvar
), x
);
15016 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
15017 gimple_seq_add_stmt (&new_body
,
15018 gimple_build_assign (new_pvar
, x
));
15022 gimple_seq_add_seq (&new_body
, tgt_body
);
15024 new_body
= maybe_catch_exception (new_body
);
15026 else if (data_region
)
15027 new_body
= tgt_body
;
15028 if (offloaded
|| data_region
)
15030 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
15031 gimple_omp_set_body (stmt
, new_body
);
15034 bind
= gimple_build_bind (NULL
, NULL
,
15035 tgt_bind
? gimple_bind_block (tgt_bind
)
15037 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
15038 gimple_bind_add_seq (bind
, irlist
);
15039 gimple_bind_add_seq (bind
, ilist
);
15040 gimple_bind_add_stmt (bind
, stmt
);
15041 gimple_bind_add_seq (bind
, olist
);
15042 gimple_bind_add_seq (bind
, orlist
);
15044 pop_gimplify_context (NULL
);
15048 gimple_bind_add_seq (dep_bind
, dep_ilist
);
15049 gimple_bind_add_stmt (dep_bind
, bind
);
15050 gimple_bind_add_seq (dep_bind
, dep_olist
);
15051 pop_gimplify_context (dep_bind
);
15055 /* Expand code for an OpenMP teams directive. */
15058 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
15060 gomp_teams
*teams_stmt
= as_a
<gomp_teams
*> (gsi_stmt (*gsi_p
));
15061 push_gimplify_context ();
15063 tree block
= make_node (BLOCK
);
15064 gbind
*bind
= gimple_build_bind (NULL
, NULL
, block
);
15065 gsi_replace (gsi_p
, bind
, true);
15066 gimple_seq bind_body
= NULL
;
15067 gimple_seq dlist
= NULL
;
15068 gimple_seq olist
= NULL
;
15070 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
15071 OMP_CLAUSE_NUM_TEAMS
);
15072 if (num_teams
== NULL_TREE
)
15073 num_teams
= build_int_cst (unsigned_type_node
, 0);
15076 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
15077 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
15078 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
15080 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
15081 OMP_CLAUSE_THREAD_LIMIT
);
15082 if (thread_limit
== NULL_TREE
)
15083 thread_limit
= build_int_cst (unsigned_type_node
, 0);
15086 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
15087 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
15088 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
15092 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
15093 &bind_body
, &dlist
, ctx
, NULL
);
15094 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
15095 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
15096 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
15098 location_t loc
= gimple_location (teams_stmt
);
15099 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
15100 gimple
*call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
15101 gimple_set_location (call
, loc
);
15102 gimple_seq_add_stmt (&bind_body
, call
);
15104 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
15105 gimple_omp_set_body (teams_stmt
, NULL
);
15106 gimple_seq_add_seq (&bind_body
, olist
);
15107 gimple_seq_add_seq (&bind_body
, dlist
);
15108 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
15109 gimple_bind_set_body (bind
, bind_body
);
15111 pop_gimplify_context (bind
);
15113 gimple_bind_append_vars (bind
, ctx
->block_vars
);
15114 BLOCK_VARS (block
) = ctx
->block_vars
;
15115 if (BLOCK_VARS (block
))
15116 TREE_USED (block
) = 1;
15120 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
15121 regimplified. If DATA is non-NULL, lower_omp_1 is outside
15122 of OMP context, but with task_shared_vars set. */
15125 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
15130 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
15131 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
15134 if (task_shared_vars
15136 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
15139 /* If a global variable has been privatized, TREE_CONSTANT on
15140 ADDR_EXPR might be wrong. */
15141 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
15142 recompute_tree_invariant_for_addr_expr (t
);
15144 *walk_subtrees
= !IS_TYPE_OR_DECL_P (t
);
15148 /* Data to be communicated between lower_omp_regimplify_operands and
15149 lower_omp_regimplify_operands_p. */
15151 struct lower_omp_regimplify_operands_data
15157 /* Helper function for lower_omp_regimplify_operands. Find
15158 omp_member_access_dummy_var vars and adjust temporarily their
15159 DECL_VALUE_EXPRs if needed. */
15162 lower_omp_regimplify_operands_p (tree
*tp
, int *walk_subtrees
,
15165 tree t
= omp_member_access_dummy_var (*tp
);
15168 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
15169 lower_omp_regimplify_operands_data
*ldata
15170 = (lower_omp_regimplify_operands_data
*) wi
->info
;
15171 tree o
= maybe_lookup_decl (t
, ldata
->ctx
);
15174 ldata
->decls
->safe_push (DECL_VALUE_EXPR (*tp
));
15175 ldata
->decls
->safe_push (*tp
);
15176 tree v
= unshare_and_remap (DECL_VALUE_EXPR (*tp
), t
, o
);
15177 SET_DECL_VALUE_EXPR (*tp
, v
);
15180 *walk_subtrees
= !IS_TYPE_OR_DECL_P (*tp
);
15184 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
15185 of omp_member_access_dummy_var vars during regimplification. */
15188 lower_omp_regimplify_operands (omp_context
*ctx
, gimple
*stmt
,
15189 gimple_stmt_iterator
*gsi_p
)
15191 auto_vec
<tree
, 10> decls
;
15194 struct walk_stmt_info wi
;
15195 memset (&wi
, '\0', sizeof (wi
));
15196 struct lower_omp_regimplify_operands_data data
;
15198 data
.decls
= &decls
;
15200 walk_gimple_op (stmt
, lower_omp_regimplify_operands_p
, &wi
);
15202 gimple_regimplify_operands (stmt
, gsi_p
);
15203 while (!decls
.is_empty ())
15205 tree t
= decls
.pop ();
15206 tree v
= decls
.pop ();
15207 SET_DECL_VALUE_EXPR (t
, v
);
15212 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
15214 gimple
*stmt
= gsi_stmt (*gsi_p
);
15215 struct walk_stmt_info wi
;
15218 if (gimple_has_location (stmt
))
15219 input_location
= gimple_location (stmt
);
15221 if (task_shared_vars
)
15222 memset (&wi
, '\0', sizeof (wi
));
15224 /* If we have issued syntax errors, avoid doing any heavy lifting.
15225 Just replace the OMP directives with a NOP to avoid
15226 confusing RTL expansion. */
15227 if (seen_error () && is_gimple_omp (stmt
))
15229 gsi_replace (gsi_p
, gimple_build_nop (), true);
15233 switch (gimple_code (stmt
))
15237 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
15238 if ((ctx
|| task_shared_vars
)
15239 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
15240 lower_omp_regimplify_p
,
15241 ctx
? NULL
: &wi
, NULL
)
15242 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
15243 lower_omp_regimplify_p
,
15244 ctx
? NULL
: &wi
, NULL
)))
15245 lower_omp_regimplify_operands (ctx
, cond_stmt
, gsi_p
);
15249 lower_omp (gimple_catch_handler_ptr (as_a
<gcatch
*> (stmt
)), ctx
);
15251 case GIMPLE_EH_FILTER
:
15252 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
15255 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
15256 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
15258 case GIMPLE_TRANSACTION
:
15259 lower_omp (gimple_transaction_body_ptr (
15260 as_a
<gtransaction
*> (stmt
)),
15264 lower_omp (gimple_bind_body_ptr (as_a
<gbind
*> (stmt
)), ctx
);
15266 case GIMPLE_OMP_PARALLEL
:
15267 case GIMPLE_OMP_TASK
:
15268 ctx
= maybe_lookup_ctx (stmt
);
15270 if (ctx
->cancellable
)
15271 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
15272 lower_omp_taskreg (gsi_p
, ctx
);
15274 case GIMPLE_OMP_FOR
:
15275 ctx
= maybe_lookup_ctx (stmt
);
15277 if (ctx
->cancellable
)
15278 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
15279 lower_omp_for (gsi_p
, ctx
);
15281 case GIMPLE_OMP_SECTIONS
:
15282 ctx
= maybe_lookup_ctx (stmt
);
15284 if (ctx
->cancellable
)
15285 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
15286 lower_omp_sections (gsi_p
, ctx
);
15288 case GIMPLE_OMP_SINGLE
:
15289 ctx
= maybe_lookup_ctx (stmt
);
15291 lower_omp_single (gsi_p
, ctx
);
15293 case GIMPLE_OMP_MASTER
:
15294 ctx
= maybe_lookup_ctx (stmt
);
15296 lower_omp_master (gsi_p
, ctx
);
15298 case GIMPLE_OMP_TASKGROUP
:
15299 ctx
= maybe_lookup_ctx (stmt
);
15301 lower_omp_taskgroup (gsi_p
, ctx
);
15303 case GIMPLE_OMP_ORDERED
:
15304 ctx
= maybe_lookup_ctx (stmt
);
15306 lower_omp_ordered (gsi_p
, ctx
);
15308 case GIMPLE_OMP_CRITICAL
:
15309 ctx
= maybe_lookup_ctx (stmt
);
15311 lower_omp_critical (gsi_p
, ctx
);
15313 case GIMPLE_OMP_ATOMIC_LOAD
:
15314 if ((ctx
|| task_shared_vars
)
15315 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
15316 as_a
<gomp_atomic_load
*> (stmt
)),
15317 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
15318 lower_omp_regimplify_operands (ctx
, stmt
, gsi_p
);
15320 case GIMPLE_OMP_TARGET
:
15321 ctx
= maybe_lookup_ctx (stmt
);
15323 lower_omp_target (gsi_p
, ctx
);
15325 case GIMPLE_OMP_TEAMS
:
15326 ctx
= maybe_lookup_ctx (stmt
);
15328 lower_omp_teams (gsi_p
, ctx
);
15332 call_stmt
= as_a
<gcall
*> (stmt
);
15333 fndecl
= gimple_call_fndecl (call_stmt
);
15335 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
15336 switch (DECL_FUNCTION_CODE (fndecl
))
15338 case BUILT_IN_GOMP_BARRIER
:
15342 case BUILT_IN_GOMP_CANCEL
:
15343 case BUILT_IN_GOMP_CANCELLATION_POINT
:
15346 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
15347 cctx
= cctx
->outer
;
15348 gcc_assert (gimple_call_lhs (call_stmt
) == NULL_TREE
);
15349 if (!cctx
->cancellable
)
15351 if (DECL_FUNCTION_CODE (fndecl
)
15352 == BUILT_IN_GOMP_CANCELLATION_POINT
)
15354 stmt
= gimple_build_nop ();
15355 gsi_replace (gsi_p
, stmt
, false);
15359 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
15361 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
15362 gimple_call_set_fndecl (call_stmt
, fndecl
);
15363 gimple_call_set_fntype (call_stmt
, TREE_TYPE (fndecl
));
15366 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)));
15367 gimple_call_set_lhs (call_stmt
, lhs
);
15368 tree fallthru_label
;
15369 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
15371 g
= gimple_build_label (fallthru_label
);
15372 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
15373 g
= gimple_build_cond (NE_EXPR
, lhs
,
15374 fold_convert (TREE_TYPE (lhs
),
15375 boolean_false_node
),
15376 cctx
->cancel_label
, fallthru_label
);
15377 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
15384 if ((ctx
|| task_shared_vars
)
15385 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
15388 /* Just remove clobbers, this should happen only if we have
15389 "privatized" local addressable variables in SIMD regions,
15390 the clobber isn't needed in that case and gimplifying address
15391 of the ARRAY_REF into a pointer and creating MEM_REF based
15392 clobber would create worse code than we get with the clobber
15394 if (gimple_clobber_p (stmt
))
15396 gsi_replace (gsi_p
, gimple_build_nop (), true);
15399 lower_omp_regimplify_operands (ctx
, stmt
, gsi_p
);
15406 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
15408 location_t saved_location
= input_location
;
15409 gimple_stmt_iterator gsi
;
15410 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
15411 lower_omp_1 (&gsi
, ctx
);
15412 /* During gimplification, we haven't folded statments inside offloading
15413 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
15414 if (target_nesting_level
|| taskreg_nesting_level
)
15415 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
15417 input_location
= saved_location
;
15420 /* Main entry point. */
15422 static unsigned int
15423 execute_lower_omp (void)
15429 /* This pass always runs, to provide PROP_gimple_lomp.
15430 But often, there is nothing to do. */
15431 if (flag_cilkplus
== 0 && flag_openacc
== 0 && flag_openmp
== 0
15432 && flag_openmp_simd
== 0)
15435 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
15436 delete_omp_context
);
15438 body
= gimple_body (current_function_decl
);
15439 scan_omp (&body
, NULL
);
15440 gcc_assert (taskreg_nesting_level
== 0);
15441 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
15442 finish_taskreg_scan (ctx
);
15443 taskreg_contexts
.release ();
15445 if (all_contexts
->root
)
15447 if (task_shared_vars
)
15448 push_gimplify_context ();
15449 lower_omp (&body
, NULL
);
15450 if (task_shared_vars
)
15451 pop_gimplify_context (NULL
);
15456 splay_tree_delete (all_contexts
);
15457 all_contexts
= NULL
;
15459 BITMAP_FREE (task_shared_vars
);
15465 const pass_data pass_data_lower_omp
=
15467 GIMPLE_PASS
, /* type */
15468 "omplower", /* name */
15469 OPTGROUP_NONE
, /* optinfo_flags */
15470 TV_NONE
, /* tv_id */
15471 PROP_gimple_any
, /* properties_required */
15472 PROP_gimple_lomp
, /* properties_provided */
15473 0, /* properties_destroyed */
15474 0, /* todo_flags_start */
15475 0, /* todo_flags_finish */
15478 class pass_lower_omp
: public gimple_opt_pass
15481 pass_lower_omp (gcc::context
*ctxt
)
15482 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
15485 /* opt_pass methods: */
15486 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
15488 }; // class pass_lower_omp
15490 } // anon namespace
15493 make_pass_lower_omp (gcc::context
*ctxt
)
15495 return new pass_lower_omp (ctxt
);
15498 /* The following is a utility to diagnose structured block violations.
15499 It is not part of the "omplower" pass, as that's invoked too late. It
15500 should be invoked by the respective front ends after gimplification. */
15502 static splay_tree all_labels
;
15504 /* Check for mismatched contexts and generate an error if needed. Return
15505 true if an error is detected. */
15508 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
15509 gimple
*branch_ctx
, gimple
*label_ctx
)
15511 gcc_checking_assert (!branch_ctx
|| is_gimple_omp (branch_ctx
));
15512 gcc_checking_assert (!label_ctx
|| is_gimple_omp (label_ctx
));
15514 if (label_ctx
== branch_ctx
)
15517 const char* kind
= NULL
;
15522 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
15523 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
15525 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
15526 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
15527 kind
= "Cilk Plus";
15531 if ((branch_ctx
&& is_gimple_omp_oacc (branch_ctx
))
15532 || (label_ctx
&& is_gimple_omp_oacc (label_ctx
)))
15534 gcc_checking_assert (kind
== NULL
);
15540 gcc_checking_assert (flag_openmp
);
15545 Previously we kept track of the label's entire context in diagnose_sb_[12]
15546 so we could traverse it and issue a correct "exit" or "enter" error
15547 message upon a structured block violation.
15549 We built the context by building a list with tree_cons'ing, but there is
15550 no easy counterpart in gimple tuples. It seems like far too much work
15551 for issuing exit/enter error messages. If someone really misses the
15552 distinct error message... patches welcome.
15556 /* Try to avoid confusing the user by producing and error message
15557 with correct "exit" or "enter" verbiage. We prefer "exit"
15558 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
15559 if (branch_ctx
== NULL
)
15565 if (TREE_VALUE (label_ctx
) == branch_ctx
)
15570 label_ctx
= TREE_CHAIN (label_ctx
);
15575 error ("invalid exit from %s structured block", kind
);
15577 error ("invalid entry to %s structured block", kind
);
15580 /* If it's obvious we have an invalid entry, be specific about the error. */
15581 if (branch_ctx
== NULL
)
15582 error ("invalid entry to %s structured block", kind
);
15585 /* Otherwise, be vague and lazy, but efficient. */
15586 error ("invalid branch to/from %s structured block", kind
);
15589 gsi_replace (gsi_p
, gimple_build_nop (), false);
15593 /* Pass 1: Create a minimal tree of structured blocks, and record
15594 where each label is found. */
15597 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
15598 struct walk_stmt_info
*wi
)
15600 gimple
*context
= (gimple
*) wi
->info
;
15601 gimple
*inner_context
;
15602 gimple
*stmt
= gsi_stmt (*gsi_p
);
15604 *handled_ops_p
= true;
15606 switch (gimple_code (stmt
))
15610 case GIMPLE_OMP_PARALLEL
:
15611 case GIMPLE_OMP_TASK
:
15612 case GIMPLE_OMP_SECTIONS
:
15613 case GIMPLE_OMP_SINGLE
:
15614 case GIMPLE_OMP_SECTION
:
15615 case GIMPLE_OMP_MASTER
:
15616 case GIMPLE_OMP_ORDERED
:
15617 case GIMPLE_OMP_CRITICAL
:
15618 case GIMPLE_OMP_TARGET
:
15619 case GIMPLE_OMP_TEAMS
:
15620 case GIMPLE_OMP_TASKGROUP
:
15621 /* The minimal context here is just the current OMP construct. */
15622 inner_context
= stmt
;
15623 wi
->info
= inner_context
;
15624 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
15625 wi
->info
= context
;
15628 case GIMPLE_OMP_FOR
:
15629 inner_context
= stmt
;
15630 wi
->info
= inner_context
;
15631 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15633 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
15634 diagnose_sb_1
, NULL
, wi
);
15635 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
15636 wi
->info
= context
;
15640 splay_tree_insert (all_labels
,
15641 (splay_tree_key
) gimple_label_label (
15642 as_a
<glabel
*> (stmt
)),
15643 (splay_tree_value
) context
);
15653 /* Pass 2: Check each branch and see if its context differs from that of
15654 the destination label's context. */
15657 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
15658 struct walk_stmt_info
*wi
)
15660 gimple
*context
= (gimple
*) wi
->info
;
15662 gimple
*stmt
= gsi_stmt (*gsi_p
);
15664 *handled_ops_p
= true;
15666 switch (gimple_code (stmt
))
15670 case GIMPLE_OMP_PARALLEL
:
15671 case GIMPLE_OMP_TASK
:
15672 case GIMPLE_OMP_SECTIONS
:
15673 case GIMPLE_OMP_SINGLE
:
15674 case GIMPLE_OMP_SECTION
:
15675 case GIMPLE_OMP_MASTER
:
15676 case GIMPLE_OMP_ORDERED
:
15677 case GIMPLE_OMP_CRITICAL
:
15678 case GIMPLE_OMP_TARGET
:
15679 case GIMPLE_OMP_TEAMS
:
15680 case GIMPLE_OMP_TASKGROUP
:
15682 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
15683 wi
->info
= context
;
15686 case GIMPLE_OMP_FOR
:
15688 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15690 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
15691 diagnose_sb_2
, NULL
, wi
);
15692 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
15693 wi
->info
= context
;
15698 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
15699 tree lab
= gimple_cond_true_label (cond_stmt
);
15702 n
= splay_tree_lookup (all_labels
,
15703 (splay_tree_key
) lab
);
15704 diagnose_sb_0 (gsi_p
, context
,
15705 n
? (gimple
*) n
->value
: NULL
);
15707 lab
= gimple_cond_false_label (cond_stmt
);
15710 n
= splay_tree_lookup (all_labels
,
15711 (splay_tree_key
) lab
);
15712 diagnose_sb_0 (gsi_p
, context
,
15713 n
? (gimple
*) n
->value
: NULL
);
15720 tree lab
= gimple_goto_dest (stmt
);
15721 if (TREE_CODE (lab
) != LABEL_DECL
)
15724 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
15725 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
*) n
->value
: NULL
);
15729 case GIMPLE_SWITCH
:
15731 gswitch
*switch_stmt
= as_a
<gswitch
*> (stmt
);
15733 for (i
= 0; i
< gimple_switch_num_labels (switch_stmt
); ++i
)
15735 tree lab
= CASE_LABEL (gimple_switch_label (switch_stmt
, i
));
15736 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
15737 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
*) n
->value
))
15743 case GIMPLE_RETURN
:
15744 diagnose_sb_0 (gsi_p
, context
, NULL
);
15754 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
15757 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
15760 gimple
*last
= last_stmt (bb
);
15761 enum gimple_code code
= gimple_code (last
);
15762 struct omp_region
*cur_region
= *region
;
15763 bool fallthru
= false;
15767 case GIMPLE_OMP_PARALLEL
:
15768 case GIMPLE_OMP_TASK
:
15769 case GIMPLE_OMP_FOR
:
15770 case GIMPLE_OMP_SINGLE
:
15771 case GIMPLE_OMP_TEAMS
:
15772 case GIMPLE_OMP_MASTER
:
15773 case GIMPLE_OMP_TASKGROUP
:
15774 case GIMPLE_OMP_CRITICAL
:
15775 case GIMPLE_OMP_SECTION
:
15776 cur_region
= new_omp_region (bb
, code
, cur_region
);
15780 case GIMPLE_OMP_ORDERED
:
15781 cur_region
= new_omp_region (bb
, code
, cur_region
);
15783 if (find_omp_clause (gimple_omp_ordered_clauses
15784 (as_a
<gomp_ordered
*> (last
)),
15785 OMP_CLAUSE_DEPEND
))
15786 cur_region
= cur_region
->outer
;
15789 case GIMPLE_OMP_TARGET
:
15790 cur_region
= new_omp_region (bb
, code
, cur_region
);
15792 switch (gimple_omp_target_kind (last
))
15794 case GF_OMP_TARGET_KIND_REGION
:
15795 case GF_OMP_TARGET_KIND_DATA
:
15796 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
15797 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
15798 case GF_OMP_TARGET_KIND_OACC_DATA
:
15800 case GF_OMP_TARGET_KIND_UPDATE
:
15801 case GF_OMP_TARGET_KIND_ENTER_DATA
:
15802 case GF_OMP_TARGET_KIND_EXIT_DATA
:
15803 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
15804 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
15805 cur_region
= cur_region
->outer
;
15808 gcc_unreachable ();
15812 case GIMPLE_OMP_SECTIONS
:
15813 cur_region
= new_omp_region (bb
, code
, cur_region
);
15817 case GIMPLE_OMP_SECTIONS_SWITCH
:
15821 case GIMPLE_OMP_ATOMIC_LOAD
:
15822 case GIMPLE_OMP_ATOMIC_STORE
:
15826 case GIMPLE_OMP_RETURN
:
15827 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
15828 somewhere other than the next block. This will be
15830 cur_region
->exit
= bb
;
15831 if (cur_region
->type
== GIMPLE_OMP_TASK
)
15832 /* Add an edge corresponding to not scheduling the task
15834 make_edge (cur_region
->entry
, bb
, EDGE_ABNORMAL
);
15835 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
15836 cur_region
= cur_region
->outer
;
15839 case GIMPLE_OMP_CONTINUE
:
15840 cur_region
->cont
= bb
;
15841 switch (cur_region
->type
)
15843 case GIMPLE_OMP_FOR
:
15844 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
15845 succs edges as abnormal to prevent splitting
15847 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
15848 /* Make the loopback edge. */
15849 make_edge (bb
, single_succ (cur_region
->entry
),
15852 /* Create an edge from GIMPLE_OMP_FOR to exit, which
15853 corresponds to the case that the body of the loop
15854 is not executed at all. */
15855 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
15856 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
15860 case GIMPLE_OMP_SECTIONS
:
15861 /* Wire up the edges into and out of the nested sections. */
15863 basic_block switch_bb
= single_succ (cur_region
->entry
);
15865 struct omp_region
*i
;
15866 for (i
= cur_region
->inner
; i
; i
= i
->next
)
15868 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
15869 make_edge (switch_bb
, i
->entry
, 0);
15870 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
15873 /* Make the loopback edge to the block with
15874 GIMPLE_OMP_SECTIONS_SWITCH. */
15875 make_edge (bb
, switch_bb
, 0);
15877 /* Make the edge from the switch to exit. */
15878 make_edge (switch_bb
, bb
->next_bb
, 0);
15883 case GIMPLE_OMP_TASK
:
15888 gcc_unreachable ();
15893 gcc_unreachable ();
15896 if (*region
!= cur_region
)
15898 *region
= cur_region
;
15900 *region_idx
= cur_region
->entry
->index
;
15908 static unsigned int
15909 diagnose_omp_structured_block_errors (void)
15911 struct walk_stmt_info wi
;
15912 gimple_seq body
= gimple_body (current_function_decl
);
15914 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
15916 memset (&wi
, 0, sizeof (wi
));
15917 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
15919 memset (&wi
, 0, sizeof (wi
));
15920 wi
.want_locations
= true;
15921 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
15923 gimple_set_body (current_function_decl
, body
);
15925 splay_tree_delete (all_labels
);
15933 const pass_data pass_data_diagnose_omp_blocks
=
15935 GIMPLE_PASS
, /* type */
15936 "*diagnose_omp_blocks", /* name */
15937 OPTGROUP_NONE
, /* optinfo_flags */
15938 TV_NONE
, /* tv_id */
15939 PROP_gimple_any
, /* properties_required */
15940 0, /* properties_provided */
15941 0, /* properties_destroyed */
15942 0, /* todo_flags_start */
15943 0, /* todo_flags_finish */
15946 class pass_diagnose_omp_blocks
: public gimple_opt_pass
15949 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
15950 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
15953 /* opt_pass methods: */
15954 virtual bool gate (function
*)
15956 return flag_cilkplus
|| flag_openacc
|| flag_openmp
;
15958 virtual unsigned int execute (function
*)
15960 return diagnose_omp_structured_block_errors ();
15963 }; // class pass_diagnose_omp_blocks
15965 } // anon namespace
15968 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
15970 return new pass_diagnose_omp_blocks (ctxt
);
15973 /* SIMD clone supporting code. */
15975 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
15976 of arguments to reserve space for. */
15978 static struct cgraph_simd_clone
*
15979 simd_clone_struct_alloc (int nargs
)
15981 struct cgraph_simd_clone
*clone_info
;
15982 size_t len
= (sizeof (struct cgraph_simd_clone
)
15983 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
15984 clone_info
= (struct cgraph_simd_clone
*)
15985 ggc_internal_cleared_alloc (len
);
15989 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
15992 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
15993 struct cgraph_simd_clone
*from
)
15995 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
15996 + ((from
->nargs
- from
->inbranch
)
15997 * sizeof (struct cgraph_simd_clone_arg
))));
16000 /* Return vector of parameter types of function FNDECL. This uses
16001 TYPE_ARG_TYPES if available, otherwise falls back to types of
16002 DECL_ARGUMENTS types. */
16005 simd_clone_vector_of_formal_parm_types (tree fndecl
)
16007 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
16008 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
16009 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
16012 FOR_EACH_VEC_ELT (args
, i
, arg
)
16013 args
[i
] = TREE_TYPE (args
[i
]);
16017 /* Given a simd function in NODE, extract the simd specific
16018 information from the OMP clauses passed in CLAUSES, and return
16019 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
16020 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
16021 otherwise set to FALSE. */
16023 static struct cgraph_simd_clone
*
16024 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
16025 bool *inbranch_specified
)
16027 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
16030 *inbranch_specified
= false;
16032 n
= args
.length ();
16033 if (n
> 0 && args
.last () == void_type_node
)
16036 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
16037 be cloned have a distinctive artificial label in addition to "omp
16041 && lookup_attribute ("cilk simd function",
16042 DECL_ATTRIBUTES (node
->decl
)));
16044 /* Allocate one more than needed just in case this is an in-branch
16045 clone which will require a mask argument. */
16046 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
16047 clone_info
->nargs
= n
;
16048 clone_info
->cilk_elemental
= cilk_clone
;
16055 clauses
= TREE_VALUE (clauses
);
16056 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
16059 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
16061 switch (OMP_CLAUSE_CODE (t
))
16063 case OMP_CLAUSE_INBRANCH
:
16064 clone_info
->inbranch
= 1;
16065 *inbranch_specified
= true;
16067 case OMP_CLAUSE_NOTINBRANCH
:
16068 clone_info
->inbranch
= 0;
16069 *inbranch_specified
= true;
16071 case OMP_CLAUSE_SIMDLEN
:
16072 clone_info
->simdlen
16073 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
16075 case OMP_CLAUSE_LINEAR
:
16077 tree decl
= OMP_CLAUSE_DECL (t
);
16078 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
16079 int argno
= TREE_INT_CST_LOW (decl
);
16080 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
16082 clone_info
->args
[argno
].arg_type
16083 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
16084 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
16085 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
16086 && clone_info
->args
[argno
].linear_step
< n
);
16090 if (POINTER_TYPE_P (args
[argno
]))
16091 step
= fold_convert (ssizetype
, step
);
16092 if (!tree_fits_shwi_p (step
))
16094 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
16095 "ignoring large linear step");
16099 else if (integer_zerop (step
))
16101 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
16102 "ignoring zero linear step");
16108 enum cgraph_simd_clone_arg_type arg_type
;
16109 if (TREE_CODE (args
[argno
]) == REFERENCE_TYPE
)
16110 switch (OMP_CLAUSE_LINEAR_KIND (t
))
16112 case OMP_CLAUSE_LINEAR_REF
:
16114 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP
;
16116 case OMP_CLAUSE_LINEAR_UVAL
:
16118 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
;
16120 case OMP_CLAUSE_LINEAR_VAL
:
16121 case OMP_CLAUSE_LINEAR_DEFAULT
:
16123 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP
;
16126 gcc_unreachable ();
16129 arg_type
= SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
16130 clone_info
->args
[argno
].arg_type
= arg_type
;
16131 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
16136 case OMP_CLAUSE_UNIFORM
:
16138 tree decl
= OMP_CLAUSE_DECL (t
);
16139 int argno
= tree_to_uhwi (decl
);
16140 clone_info
->args
[argno
].arg_type
16141 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
16144 case OMP_CLAUSE_ALIGNED
:
16146 tree decl
= OMP_CLAUSE_DECL (t
);
16147 int argno
= tree_to_uhwi (decl
);
16148 clone_info
->args
[argno
].alignment
16149 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
16160 /* Given a SIMD clone in NODE, calculate the characteristic data
16161 type and return the coresponding type. The characteristic data
16162 type is computed as described in the Intel Vector ABI. */
16165 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
16166 struct cgraph_simd_clone
*clone_info
)
16168 tree type
= integer_type_node
;
16169 tree fndecl
= node
->decl
;
16171 /* a) For non-void function, the characteristic data type is the
16173 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
16174 type
= TREE_TYPE (TREE_TYPE (fndecl
));
16176 /* b) If the function has any non-uniform, non-linear parameters,
16177 then the characteristic data type is the type of the first
16181 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
16182 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
16183 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
16191 /* c) If the characteristic data type determined by a) or b) above
16192 is struct, union, or class type which is pass-by-value (except
16193 for the type that maps to the built-in complex data type), the
16194 characteristic data type is int. */
16195 if (RECORD_OR_UNION_TYPE_P (type
)
16196 && !aggregate_value_p (type
, NULL
)
16197 && TREE_CODE (type
) != COMPLEX_TYPE
)
16198 return integer_type_node
;
16200 /* d) If none of the above three classes is applicable, the
16201 characteristic data type is int. */
16205 /* e) For Intel Xeon Phi native and offload compilation, if the
16206 resulting characteristic data type is 8-bit or 16-bit integer
16207 data type, the characteristic data type is int. */
16208 /* Well, we don't handle Xeon Phi yet. */
16212 simd_clone_mangle (struct cgraph_node
*node
,
16213 struct cgraph_simd_clone
*clone_info
)
16215 char vecsize_mangle
= clone_info
->vecsize_mangle
;
16216 char mask
= clone_info
->inbranch
? 'M' : 'N';
16217 unsigned int simdlen
= clone_info
->simdlen
;
16221 gcc_assert (vecsize_mangle
&& simdlen
);
16223 pp_string (&pp
, "_ZGV");
16224 pp_character (&pp
, vecsize_mangle
);
16225 pp_character (&pp
, mask
);
16226 pp_decimal_int (&pp
, simdlen
);
16228 for (n
= 0; n
< clone_info
->nargs
; ++n
)
16230 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
16232 switch (arg
.arg_type
)
16234 case SIMD_CLONE_ARG_TYPE_UNIFORM
:
16235 pp_character (&pp
, 'u');
16237 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
:
16238 pp_character (&pp
, 'l');
16239 goto mangle_linear
;
16240 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP
:
16241 pp_character (&pp
, 'R');
16242 goto mangle_linear
;
16243 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP
:
16244 pp_character (&pp
, 'L');
16245 goto mangle_linear
;
16246 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
:
16247 pp_character (&pp
, 'U');
16248 goto mangle_linear
;
16250 gcc_assert (arg
.linear_step
!= 0);
16251 if (arg
.linear_step
> 1)
16252 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
16253 else if (arg
.linear_step
< 0)
16255 pp_character (&pp
, 'n');
16256 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
16260 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
:
16261 pp_character (&pp
, 's');
16262 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
16265 pp_character (&pp
, 'v');
16269 pp_character (&pp
, 'a');
16270 pp_decimal_int (&pp
, arg
.alignment
);
16274 pp_underscore (&pp
);
16275 const char *str
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
));
16278 pp_string (&pp
, str
);
16279 str
= pp_formatted_text (&pp
);
16281 /* If there already is a SIMD clone with the same mangled name, don't
16282 add another one. This can happen e.g. for
16283 #pragma omp declare simd
16284 #pragma omp declare simd simdlen(8)
16285 int foo (int, int);
16286 if the simdlen is assumed to be 8 for the first one, etc. */
16287 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
16288 clone
= clone
->simdclone
->next_clone
)
16289 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
16293 return get_identifier (str
);
16296 /* Create a simd clone of OLD_NODE and return it. */
16298 static struct cgraph_node
*
16299 simd_clone_create (struct cgraph_node
*old_node
)
16301 struct cgraph_node
*new_node
;
16302 if (old_node
->definition
)
16304 if (!old_node
->has_gimple_body_p ())
16306 old_node
->get_body ();
16307 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
16313 tree old_decl
= old_node
->decl
;
16314 tree new_decl
= copy_node (old_node
->decl
);
16315 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
16316 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
16317 SET_DECL_RTL (new_decl
, NULL
);
16318 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
16319 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
16320 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
16321 symtab
->call_cgraph_insertion_hooks (new_node
);
16323 if (new_node
== NULL
)
16326 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
16328 /* The function cgraph_function_versioning () will force the new
16329 symbol local. Undo this, and inherit external visability from
16331 new_node
->local
.local
= old_node
->local
.local
;
16332 new_node
->externally_visible
= old_node
->externally_visible
;
16337 /* Adjust the return type of the given function to its appropriate
16338 vector counterpart. Returns a simd array to be used throughout the
16339 function as a return value. */
16342 simd_clone_adjust_return_type (struct cgraph_node
*node
)
16344 tree fndecl
= node
->decl
;
16345 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
16346 unsigned int veclen
;
16349 /* Adjust the function return type. */
16350 if (orig_rettype
== void_type_node
)
16352 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
16353 t
= TREE_TYPE (TREE_TYPE (fndecl
));
16354 if (INTEGRAL_TYPE_P (t
) || POINTER_TYPE_P (t
))
16355 veclen
= node
->simdclone
->vecsize_int
;
16357 veclen
= node
->simdclone
->vecsize_float
;
16358 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (t
));
16359 if (veclen
> node
->simdclone
->simdlen
)
16360 veclen
= node
->simdclone
->simdlen
;
16361 if (POINTER_TYPE_P (t
))
16362 t
= pointer_sized_int_node
;
16363 if (veclen
== node
->simdclone
->simdlen
)
16364 t
= build_vector_type (t
, node
->simdclone
->simdlen
);
16367 t
= build_vector_type (t
, veclen
);
16368 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
16370 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
16371 if (!node
->definition
)
16374 t
= DECL_RESULT (fndecl
);
16375 /* Adjust the DECL_RESULT. */
16376 gcc_assert (TREE_TYPE (t
) != void_type_node
);
16377 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
16380 tree atype
= build_array_type_nelts (orig_rettype
,
16381 node
->simdclone
->simdlen
);
16382 if (veclen
!= node
->simdclone
->simdlen
)
16383 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
16385 /* Set up a SIMD array to use as the return value. */
16386 tree retval
= create_tmp_var_raw (atype
, "retval");
16387 gimple_add_tmp_var (retval
);
16391 /* Each vector argument has a corresponding array to be used locally
16392 as part of the eventual loop. Create such temporary array and
16395 PREFIX is the prefix to be used for the temporary.
16397 TYPE is the inner element type.
16399 SIMDLEN is the number of elements. */
16402 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
16404 tree atype
= build_array_type_nelts (type
, simdlen
);
16405 tree avar
= create_tmp_var_raw (atype
, prefix
);
16406 gimple_add_tmp_var (avar
);
16410 /* Modify the function argument types to their corresponding vector
16411 counterparts if appropriate. Also, create one array for each simd
16412 argument to be used locally when using the function arguments as
16415 NODE is the function whose arguments are to be adjusted.
16417 Returns an adjustment vector that will be filled describing how the
16418 argument types will be adjusted. */
16420 static ipa_parm_adjustment_vec
16421 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
16424 ipa_parm_adjustment_vec adjustments
;
16426 if (node
->definition
)
16427 args
= ipa_get_vector_of_formal_parms (node
->decl
);
16429 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
16430 adjustments
.create (args
.length ());
16431 unsigned i
, j
, veclen
;
16432 struct ipa_parm_adjustment adj
;
16433 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
16435 memset (&adj
, 0, sizeof (adj
));
16436 tree parm
= args
[i
];
16437 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
16438 adj
.base_index
= i
;
16441 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
16442 node
->simdclone
->args
[i
].orig_type
= parm_type
;
16444 switch (node
->simdclone
->args
[i
].arg_type
)
16447 /* No adjustment necessary for scalar arguments. */
16448 adj
.op
= IPA_PARM_OP_COPY
;
16450 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
:
16451 if (node
->definition
)
16452 node
->simdclone
->args
[i
].simd_array
16453 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
16454 TREE_TYPE (parm_type
),
16455 node
->simdclone
->simdlen
);
16456 adj
.op
= IPA_PARM_OP_COPY
;
16458 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP
:
16459 case SIMD_CLONE_ARG_TYPE_VECTOR
:
16460 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
16461 veclen
= node
->simdclone
->vecsize_int
;
16463 veclen
= node
->simdclone
->vecsize_float
;
16464 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
16465 if (veclen
> node
->simdclone
->simdlen
)
16466 veclen
= node
->simdclone
->simdlen
;
16467 adj
.arg_prefix
= "simd";
16468 if (POINTER_TYPE_P (parm_type
))
16469 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
16471 adj
.type
= build_vector_type (parm_type
, veclen
);
16472 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
16473 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
16475 adjustments
.safe_push (adj
);
16478 memset (&adj
, 0, sizeof (adj
));
16479 adj
.op
= IPA_PARM_OP_NEW
;
16480 adj
.arg_prefix
= "simd";
16481 adj
.base_index
= i
;
16482 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
16486 if (node
->definition
)
16487 node
->simdclone
->args
[i
].simd_array
16488 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
16489 parm_type
, node
->simdclone
->simdlen
);
16491 adjustments
.safe_push (adj
);
16494 if (node
->simdclone
->inbranch
)
16497 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
16500 memset (&adj
, 0, sizeof (adj
));
16501 adj
.op
= IPA_PARM_OP_NEW
;
16502 adj
.arg_prefix
= "mask";
16504 adj
.base_index
= i
;
16505 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
16506 veclen
= node
->simdclone
->vecsize_int
;
16508 veclen
= node
->simdclone
->vecsize_float
;
16509 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
16510 if (veclen
> node
->simdclone
->simdlen
)
16511 veclen
= node
->simdclone
->simdlen
;
16512 if (POINTER_TYPE_P (base_type
))
16513 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
16515 adj
.type
= build_vector_type (base_type
, veclen
);
16516 adjustments
.safe_push (adj
);
16518 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
16519 adjustments
.safe_push (adj
);
16521 /* We have previously allocated one extra entry for the mask. Use
16523 struct cgraph_simd_clone
*sc
= node
->simdclone
;
16525 if (node
->definition
)
16527 sc
->args
[i
].orig_arg
16528 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
16529 sc
->args
[i
].simd_array
16530 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
16532 sc
->args
[i
].orig_type
= base_type
;
16533 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
16536 if (node
->definition
)
16537 ipa_modify_formal_parameters (node
->decl
, adjustments
);
16540 tree new_arg_types
= NULL_TREE
, new_reversed
;
16541 bool last_parm_void
= false;
16542 if (args
.length () > 0 && args
.last () == void_type_node
)
16543 last_parm_void
= true;
16545 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
16546 j
= adjustments
.length ();
16547 for (i
= 0; i
< j
; i
++)
16549 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
16551 if (adj
->op
== IPA_PARM_OP_COPY
)
16552 ptype
= args
[adj
->base_index
];
16555 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
16557 new_reversed
= nreverse (new_arg_types
);
16558 if (last_parm_void
)
16561 TREE_CHAIN (new_arg_types
) = void_list_node
;
16563 new_reversed
= void_list_node
;
16566 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
16567 TYPE_ARG_TYPES (new_type
) = new_reversed
;
16568 TREE_TYPE (node
->decl
) = new_type
;
16570 adjustments
.release ();
16573 return adjustments
;
16576 /* Initialize and copy the function arguments in NODE to their
16577 corresponding local simd arrays. Returns a fresh gimple_seq with
16578 the instruction sequence generated. */
16581 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
16582 ipa_parm_adjustment_vec adjustments
)
16584 gimple_seq seq
= NULL
;
16585 unsigned i
= 0, j
= 0, k
;
16587 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
16589 arg
= DECL_CHAIN (arg
), i
++, j
++)
16591 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
16592 || POINTER_TYPE_P (TREE_TYPE (arg
)))
16595 node
->simdclone
->args
[i
].vector_arg
= arg
;
16597 tree array
= node
->simdclone
->args
[i
].simd_array
;
16598 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
16600 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
16601 tree ptr
= build_fold_addr_expr (array
);
16602 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
16603 build_int_cst (ptype
, 0));
16604 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
16605 gimplify_and_add (t
, &seq
);
16609 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
16610 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
16611 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
16613 tree ptr
= build_fold_addr_expr (array
);
16617 arg
= DECL_CHAIN (arg
);
16621 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
16622 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
16623 build_int_cst (ptype
, k
* elemsize
));
16624 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
16625 gimplify_and_add (t
, &seq
);
16632 /* Callback info for ipa_simd_modify_stmt_ops below. */
16634 struct modify_stmt_info
{
16635 ipa_parm_adjustment_vec adjustments
;
16637 /* True if the parent statement was modified by
16638 ipa_simd_modify_stmt_ops. */
16642 /* Callback for walk_gimple_op.
16644 Adjust operands from a given statement as specified in the
16645 adjustments vector in the callback data. */
16648 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
16650 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
16651 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
16652 tree
*orig_tp
= tp
;
16653 if (TREE_CODE (*tp
) == ADDR_EXPR
)
16654 tp
= &TREE_OPERAND (*tp
, 0);
16655 struct ipa_parm_adjustment
*cand
= NULL
;
16656 if (TREE_CODE (*tp
) == PARM_DECL
)
16657 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
16661 *walk_subtrees
= 0;
16664 tree repl
= NULL_TREE
;
16666 repl
= unshare_expr (cand
->new_decl
);
16671 *walk_subtrees
= 0;
16672 bool modified
= info
->modified
;
16673 info
->modified
= false;
16674 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
16675 if (!info
->modified
)
16677 info
->modified
= modified
;
16680 info
->modified
= modified
;
16689 repl
= build_fold_addr_expr (repl
);
16691 if (is_gimple_debug (info
->stmt
))
16693 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
16694 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
16695 DECL_ARTIFICIAL (vexpr
) = 1;
16696 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
16697 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
16702 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
)), repl
);
16703 repl
= gimple_assign_lhs (stmt
);
16705 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
16706 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
16709 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
16711 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
16717 info
->modified
= true;
16721 /* Traverse the function body and perform all modifications as
16722 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
16723 modified such that the replacement/reduction value will now be an
16724 offset into the corresponding simd_array.
16726 This function will replace all function argument uses with their
16727 corresponding simd array elements, and ajust the return values
16731 ipa_simd_modify_function_body (struct cgraph_node
*node
,
16732 ipa_parm_adjustment_vec adjustments
,
16733 tree retval_array
, tree iter
)
16736 unsigned int i
, j
, l
;
16738 /* Re-use the adjustments array, but this time use it to replace
16739 every function argument use to an offset into the corresponding
16741 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
16743 if (!node
->simdclone
->args
[i
].vector_arg
)
16746 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
16747 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
16748 adjustments
[j
].new_decl
16749 = build4 (ARRAY_REF
,
16751 node
->simdclone
->args
[i
].simd_array
,
16753 NULL_TREE
, NULL_TREE
);
16754 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
16755 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
16756 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
16759 l
= adjustments
.length ();
16760 for (i
= 1; i
< num_ssa_names
; i
++)
16762 tree name
= ssa_name (i
);
16764 && SSA_NAME_VAR (name
)
16765 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
16767 for (j
= 0; j
< l
; j
++)
16768 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
16769 && adjustments
[j
].new_decl
)
16772 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
16775 = copy_var_decl (adjustments
[j
].base
,
16776 DECL_NAME (adjustments
[j
].base
),
16777 TREE_TYPE (adjustments
[j
].base
));
16778 adjustments
[j
].new_ssa_base
= base_var
;
16781 base_var
= adjustments
[j
].new_ssa_base
;
16782 if (SSA_NAME_IS_DEFAULT_DEF (name
))
16784 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
16785 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
16786 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
16787 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
16788 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
16789 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
16790 gimple
*stmt
= gimple_build_assign (name
, new_decl
);
16791 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
16794 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
16799 struct modify_stmt_info info
;
16800 info
.adjustments
= adjustments
;
16802 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
16804 gimple_stmt_iterator gsi
;
16806 gsi
= gsi_start_bb (bb
);
16807 while (!gsi_end_p (gsi
))
16809 gimple
*stmt
= gsi_stmt (gsi
);
16811 struct walk_stmt_info wi
;
16813 memset (&wi
, 0, sizeof (wi
));
16814 info
.modified
= false;
16816 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
16818 if (greturn
*return_stmt
= dyn_cast
<greturn
*> (stmt
))
16820 tree retval
= gimple_return_retval (return_stmt
);
16823 gsi_remove (&gsi
, true);
16827 /* Replace `return foo' with `retval_array[iter] = foo'. */
16828 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
16829 retval_array
, iter
, NULL
, NULL
);
16830 stmt
= gimple_build_assign (ref
, retval
);
16831 gsi_replace (&gsi
, stmt
, true);
16832 info
.modified
= true;
16837 update_stmt (stmt
);
16838 if (maybe_clean_eh_stmt (stmt
))
16839 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
16846 /* Adjust the argument types in NODE to their appropriate vector
16850 simd_clone_adjust (struct cgraph_node
*node
)
16852 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
16854 targetm
.simd_clone
.adjust (node
);
16856 tree retval
= simd_clone_adjust_return_type (node
);
16857 ipa_parm_adjustment_vec adjustments
16858 = simd_clone_adjust_argument_types (node
);
16860 push_gimplify_context ();
16862 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
16864 /* Adjust all uses of vector arguments accordingly. Adjust all
16865 return values accordingly. */
16866 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
16867 tree iter1
= make_ssa_name (iter
);
16868 tree iter2
= make_ssa_name (iter
);
16869 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
16871 /* Initialize the iteration variable. */
16872 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
16873 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
16874 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
16875 /* Insert the SIMD array and iv initialization at function
16877 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
16879 pop_gimplify_context (NULL
);
16881 /* Create a new BB right before the original exit BB, to hold the
16882 iteration increment and the condition/branch. */
16883 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
16884 basic_block incr_bb
= create_empty_bb (orig_exit
);
16885 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
16886 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
16887 flag. Set it now to be a FALLTHRU_EDGE. */
16888 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
16889 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
16890 for (unsigned i
= 0;
16891 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
16893 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
16894 redirect_edge_succ (e
, incr_bb
);
16896 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
16897 e
->probability
= REG_BR_PROB_BASE
;
16898 gsi
= gsi_last_bb (incr_bb
);
16899 gimple
*g
= gimple_build_assign (iter2
, PLUS_EXPR
, iter1
,
16900 build_int_cst (unsigned_type_node
, 1));
16901 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
16903 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
16904 struct loop
*loop
= alloc_loop ();
16905 cfun
->has_force_vectorize_loops
= true;
16906 loop
->safelen
= node
->simdclone
->simdlen
;
16907 loop
->force_vectorize
= true;
16908 loop
->header
= body_bb
;
16910 /* Branch around the body if the mask applies. */
16911 if (node
->simdclone
->inbranch
)
16913 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
16915 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
16916 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)));
16917 tree aref
= build4 (ARRAY_REF
,
16918 TREE_TYPE (TREE_TYPE (mask_array
)),
16921 g
= gimple_build_assign (mask
, aref
);
16922 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
16923 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
16924 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
16926 aref
= build1 (VIEW_CONVERT_EXPR
,
16927 build_nonstandard_integer_type (bitsize
, 0), mask
);
16928 mask
= make_ssa_name (TREE_TYPE (aref
));
16929 g
= gimple_build_assign (mask
, aref
);
16930 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
16933 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
16935 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
16936 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
16937 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
16940 /* Generate the condition. */
16941 g
= gimple_build_cond (LT_EXPR
,
16943 build_int_cst (unsigned_type_node
,
16944 node
->simdclone
->simdlen
),
16946 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
16947 e
= split_block (incr_bb
, gsi_stmt (gsi
));
16948 basic_block latch_bb
= e
->dest
;
16949 basic_block new_exit_bb
;
16950 new_exit_bb
= split_block_after_labels (latch_bb
)->dest
;
16951 loop
->latch
= latch_bb
;
16953 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
16955 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
16956 /* The successor of incr_bb is already pointing to latch_bb; just
16958 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
16959 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
16961 gphi
*phi
= create_phi_node (iter1
, body_bb
);
16962 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
16963 edge latch_edge
= single_succ_edge (latch_bb
);
16964 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
16966 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
16968 /* Generate the new return. */
16969 gsi
= gsi_last_bb (new_exit_bb
);
16971 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
16972 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
16973 retval
= TREE_OPERAND (retval
, 0);
16976 retval
= build1 (VIEW_CONVERT_EXPR
,
16977 TREE_TYPE (TREE_TYPE (node
->decl
)),
16979 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
16980 false, GSI_CONTINUE_LINKING
);
16982 g
= gimple_build_return (retval
);
16983 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
16985 /* Handle aligned clauses by replacing default defs of the aligned
16986 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
16987 lhs. Handle linear by adding PHIs. */
16988 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
16989 if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
16990 && (TREE_ADDRESSABLE (node
->simdclone
->args
[i
].orig_arg
)
16991 || !is_gimple_reg_type
16992 (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
16994 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
16995 if (is_gimple_reg_type (TREE_TYPE (orig_arg
)))
16996 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
16999 iter1
= create_tmp_var_raw (TREE_TYPE (orig_arg
));
17000 gimple_add_tmp_var (iter1
);
17002 gsi
= gsi_after_labels (entry_bb
);
17003 g
= gimple_build_assign (iter1
, orig_arg
);
17004 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
17005 gsi
= gsi_after_labels (body_bb
);
17006 g
= gimple_build_assign (orig_arg
, iter1
);
17007 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
17009 else if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
17010 && DECL_BY_REFERENCE (node
->simdclone
->args
[i
].orig_arg
)
17011 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
17013 && TREE_ADDRESSABLE
17014 (TREE_TYPE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
17016 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
17017 tree def
= ssa_default_def (cfun
, orig_arg
);
17018 if (def
&& !has_zero_uses (def
))
17020 iter1
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg
)));
17021 gimple_add_tmp_var (iter1
);
17022 gsi
= gsi_after_labels (entry_bb
);
17023 g
= gimple_build_assign (iter1
, build_simple_mem_ref (def
));
17024 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
17025 gsi
= gsi_after_labels (body_bb
);
17026 g
= gimple_build_assign (build_simple_mem_ref (def
), iter1
);
17027 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
17030 else if (node
->simdclone
->args
[i
].alignment
17031 && node
->simdclone
->args
[i
].arg_type
17032 == SIMD_CLONE_ARG_TYPE_UNIFORM
17033 && (node
->simdclone
->args
[i
].alignment
17034 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
17035 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
17038 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
17039 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
17040 tree def
= ssa_default_def (cfun
, orig_arg
);
17041 if (def
&& !has_zero_uses (def
))
17043 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
17044 gimple_seq seq
= NULL
;
17045 bool need_cvt
= false;
17047 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
17049 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
17052 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
);
17053 gimple_call_set_lhs (g
, t
);
17054 gimple_seq_add_stmt_without_update (&seq
, g
);
17057 t
= make_ssa_name (orig_arg
);
17058 g
= gimple_build_assign (t
, NOP_EXPR
, gimple_call_lhs (g
));
17059 gimple_seq_add_stmt_without_update (&seq
, g
);
17061 gsi_insert_seq_on_edge_immediate
17062 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
17064 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
17065 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
17067 node
->create_edge (cgraph_node::get_create (fn
),
17068 call
, entry_bb
->count
, freq
);
17070 imm_use_iterator iter
;
17071 use_operand_p use_p
;
17073 tree repl
= gimple_get_lhs (g
);
17074 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
17075 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
17078 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
17079 SET_USE (use_p
, repl
);
17082 else if ((node
->simdclone
->args
[i
].arg_type
17083 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
17084 || (node
->simdclone
->args
[i
].arg_type
17085 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP
))
17087 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
17088 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
17089 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
17090 tree def
= NULL_TREE
;
17091 if (TREE_ADDRESSABLE (orig_arg
))
17093 def
= make_ssa_name (TREE_TYPE (orig_arg
));
17094 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
17095 iter2
= make_ssa_name (TREE_TYPE (orig_arg
));
17096 gsi
= gsi_after_labels (entry_bb
);
17097 g
= gimple_build_assign (def
, orig_arg
);
17098 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
17102 def
= ssa_default_def (cfun
, orig_arg
);
17103 if (!def
|| has_zero_uses (def
))
17107 iter1
= make_ssa_name (orig_arg
);
17108 iter2
= make_ssa_name (orig_arg
);
17113 phi
= create_phi_node (iter1
, body_bb
);
17114 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
17115 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
17116 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
17117 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
17118 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
17119 ? TREE_TYPE (orig_arg
) : sizetype
;
17121 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
17122 g
= gimple_build_assign (iter2
, code
, iter1
, addcst
);
17123 gsi
= gsi_last_bb (incr_bb
);
17124 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
17126 imm_use_iterator iter
;
17127 use_operand_p use_p
;
17129 if (TREE_ADDRESSABLE (orig_arg
))
17131 gsi
= gsi_after_labels (body_bb
);
17132 g
= gimple_build_assign (orig_arg
, iter1
);
17133 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
17136 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
17137 if (use_stmt
== phi
)
17140 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
17141 SET_USE (use_p
, iter1
);
17144 else if (node
->simdclone
->args
[i
].arg_type
17145 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
)
17147 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
17148 tree def
= ssa_default_def (cfun
, orig_arg
);
17149 gcc_assert (!TREE_ADDRESSABLE (orig_arg
)
17150 && TREE_CODE (TREE_TYPE (orig_arg
)) == REFERENCE_TYPE
);
17151 if (def
&& !has_zero_uses (def
))
17153 tree rtype
= TREE_TYPE (TREE_TYPE (orig_arg
));
17154 iter1
= make_ssa_name (orig_arg
);
17155 iter2
= make_ssa_name (orig_arg
);
17156 tree iter3
= make_ssa_name (rtype
);
17157 tree iter4
= make_ssa_name (rtype
);
17158 tree iter5
= make_ssa_name (rtype
);
17159 gsi
= gsi_after_labels (entry_bb
);
17161 = gimple_build_assign (iter3
, build_simple_mem_ref (def
));
17162 gsi_insert_before (&gsi
, load
, GSI_NEW_STMT
);
17164 tree array
= node
->simdclone
->args
[i
].simd_array
;
17165 TREE_ADDRESSABLE (array
) = 1;
17166 tree ptr
= build_fold_addr_expr (array
);
17167 phi
= create_phi_node (iter1
, body_bb
);
17168 add_phi_arg (phi
, ptr
, preheader_edge
, UNKNOWN_LOCATION
);
17169 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
17170 g
= gimple_build_assign (iter2
, POINTER_PLUS_EXPR
, iter1
,
17171 TYPE_SIZE_UNIT (TREE_TYPE (iter3
)));
17172 gsi
= gsi_last_bb (incr_bb
);
17173 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
17175 phi
= create_phi_node (iter4
, body_bb
);
17176 add_phi_arg (phi
, iter3
, preheader_edge
, UNKNOWN_LOCATION
);
17177 add_phi_arg (phi
, iter5
, latch_edge
, UNKNOWN_LOCATION
);
17178 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (iter3
))
17179 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
17180 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (iter3
))
17181 ? TREE_TYPE (iter3
) : sizetype
;
17183 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
17184 g
= gimple_build_assign (iter5
, code
, iter4
, addcst
);
17185 gsi
= gsi_last_bb (incr_bb
);
17186 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
17188 g
= gimple_build_assign (build_simple_mem_ref (iter1
), iter4
);
17189 gsi
= gsi_after_labels (body_bb
);
17190 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
17192 imm_use_iterator iter
;
17193 use_operand_p use_p
;
17195 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
17196 if (use_stmt
== load
)
17199 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
17200 SET_USE (use_p
, iter1
);
17202 if (!TYPE_READONLY (rtype
))
17204 tree v
= make_ssa_name (rtype
);
17205 tree aref
= build4 (ARRAY_REF
, rtype
, array
,
17206 size_zero_node
, NULL_TREE
,
17208 gsi
= gsi_after_labels (new_exit_bb
);
17209 g
= gimple_build_assign (v
, aref
);
17210 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
17211 g
= gimple_build_assign (build_simple_mem_ref (def
), v
);
17212 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
17217 calculate_dominance_info (CDI_DOMINATORS
);
17218 add_loop (loop
, loop
->header
->loop_father
);
17219 update_ssa (TODO_update_ssa
);
17224 /* If the function in NODE is tagged as an elemental SIMD function,
17225 create the appropriate SIMD clones. */
17228 expand_simd_clones (struct cgraph_node
*node
)
17230 tree attr
= lookup_attribute ("omp declare simd",
17231 DECL_ATTRIBUTES (node
->decl
));
17232 if (attr
== NULL_TREE
17233 || node
->global
.inlined_to
17234 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
17238 #pragma omp declare simd
17240 in C, there we don't know the argument types at all. */
17241 if (!node
->definition
17242 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
17247 /* Start with parsing the "omp declare simd" attribute(s). */
17248 bool inbranch_clause_specified
;
17249 struct cgraph_simd_clone
*clone_info
17250 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
17251 &inbranch_clause_specified
);
17252 if (clone_info
== NULL
)
17255 int orig_simdlen
= clone_info
->simdlen
;
17256 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
17257 /* The target can return 0 (no simd clones should be created),
17258 1 (just one ISA of simd clones should be created) or higher
17259 count of ISA variants. In that case, clone_info is initialized
17260 for the first ISA variant. */
17262 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
17267 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
17268 also create one inbranch and one !inbranch clone of it. */
17269 for (int i
= 0; i
< count
* 2; i
++)
17271 struct cgraph_simd_clone
*clone
= clone_info
;
17272 if (inbranch_clause_specified
&& (i
& 1) != 0)
17277 clone
= simd_clone_struct_alloc (clone_info
->nargs
17279 simd_clone_struct_copy (clone
, clone_info
);
17280 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
17281 and simd_clone_adjust_argument_types did to the first
17283 clone
->nargs
-= clone_info
->inbranch
;
17284 clone
->simdlen
= orig_simdlen
;
17285 /* And call the target hook again to get the right ISA. */
17286 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
17290 clone
->inbranch
= 1;
17293 /* simd_clone_mangle might fail if such a clone has been created
17295 tree id
= simd_clone_mangle (node
, clone
);
17296 if (id
== NULL_TREE
)
17299 /* Only when we are sure we want to create the clone actually
17300 clone the function (or definitions) or create another
17301 extern FUNCTION_DECL (for prototypes without definitions). */
17302 struct cgraph_node
*n
= simd_clone_create (node
);
17306 n
->simdclone
= clone
;
17307 clone
->origin
= node
;
17308 clone
->next_clone
= NULL
;
17309 if (node
->simd_clones
== NULL
)
17311 clone
->prev_clone
= n
;
17312 node
->simd_clones
= n
;
17316 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
17317 clone
->prev_clone
->simdclone
->next_clone
= n
;
17318 node
->simd_clones
->simdclone
->prev_clone
= n
;
17320 symtab
->change_decl_assembler_name (n
->decl
, id
);
17321 /* And finally adjust the return type, parameters and for
17322 definitions also function body. */
17323 if (node
->definition
)
17324 simd_clone_adjust (n
);
17327 simd_clone_adjust_return_type (n
);
17328 simd_clone_adjust_argument_types (n
);
17332 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
17335 /* Entry point for IPA simd clone creation pass. */
17337 static unsigned int
17338 ipa_omp_simd_clone (void)
17340 struct cgraph_node
*node
;
17341 FOR_EACH_FUNCTION (node
)
17342 expand_simd_clones (node
);
17348 const pass_data pass_data_omp_simd_clone
=
17350 SIMPLE_IPA_PASS
, /* type */
17351 "simdclone", /* name */
17352 OPTGROUP_NONE
, /* optinfo_flags */
17353 TV_NONE
, /* tv_id */
17354 ( PROP_ssa
| PROP_cfg
), /* properties_required */
17355 0, /* properties_provided */
17356 0, /* properties_destroyed */
17357 0, /* todo_flags_start */
17358 0, /* todo_flags_finish */
17361 class pass_omp_simd_clone
: public simple_ipa_opt_pass
17364 pass_omp_simd_clone(gcc::context
*ctxt
)
17365 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
17368 /* opt_pass methods: */
17369 virtual bool gate (function
*);
17370 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
17374 pass_omp_simd_clone::gate (function
*)
17376 return ((flag_openmp
|| flag_openmp_simd
17378 || (in_lto_p
&& !flag_wpa
))
17379 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
17382 } // anon namespace
17384 simple_ipa_opt_pass
*
17385 make_pass_omp_simd_clone (gcc::context
*ctxt
)
17387 return new pass_omp_simd_clone (ctxt
);
17390 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
17391 adds their addresses and sizes to constructor-vector V_CTOR. */
17393 add_decls_addresses_to_decl_constructor (vec
<tree
, va_gc
> *v_decls
,
17394 vec
<constructor_elt
, va_gc
> *v_ctor
)
17396 unsigned len
= vec_safe_length (v_decls
);
17397 for (unsigned i
= 0; i
< len
; i
++)
17399 tree it
= (*v_decls
)[i
];
17400 bool is_function
= TREE_CODE (it
) != VAR_DECL
;
17402 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, build_fold_addr_expr (it
));
17404 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
,
17405 fold_convert (const_ptr_type_node
,
17406 DECL_SIZE_UNIT (it
)));
17410 /* Create new symbols containing (address, size) pairs for global variables,
17411 marked with "omp declare target" attribute, as well as addresses for the
17412 functions, which are outlined offloading regions. */
17414 omp_finish_file (void)
17416 unsigned num_funcs
= vec_safe_length (offload_funcs
);
17417 unsigned num_vars
= vec_safe_length (offload_vars
);
17419 if (num_funcs
== 0 && num_vars
== 0)
17422 if (targetm_common
.have_named_sections
)
17424 vec
<constructor_elt
, va_gc
> *v_f
, *v_v
;
17425 vec_alloc (v_f
, num_funcs
);
17426 vec_alloc (v_v
, num_vars
* 2);
17428 add_decls_addresses_to_decl_constructor (offload_funcs
, v_f
);
17429 add_decls_addresses_to_decl_constructor (offload_vars
, v_v
);
17431 tree vars_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
17433 tree funcs_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
17435 TYPE_ALIGN (vars_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
17436 TYPE_ALIGN (funcs_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
17437 tree ctor_v
= build_constructor (vars_decl_type
, v_v
);
17438 tree ctor_f
= build_constructor (funcs_decl_type
, v_f
);
17439 TREE_CONSTANT (ctor_v
) = TREE_CONSTANT (ctor_f
) = 1;
17440 TREE_STATIC (ctor_v
) = TREE_STATIC (ctor_f
) = 1;
17441 tree funcs_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
17442 get_identifier (".offload_func_table"),
17444 tree vars_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
17445 get_identifier (".offload_var_table"),
17447 TREE_STATIC (funcs_decl
) = TREE_STATIC (vars_decl
) = 1;
17448 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
17449 otherwise a joint table in a binary will contain padding between
17450 tables from multiple object files. */
17451 DECL_USER_ALIGN (funcs_decl
) = DECL_USER_ALIGN (vars_decl
) = 1;
17452 DECL_ALIGN (funcs_decl
) = TYPE_ALIGN (funcs_decl_type
);
17453 DECL_ALIGN (vars_decl
) = TYPE_ALIGN (vars_decl_type
);
17454 DECL_INITIAL (funcs_decl
) = ctor_f
;
17455 DECL_INITIAL (vars_decl
) = ctor_v
;
17456 set_decl_section_name (funcs_decl
, OFFLOAD_FUNC_TABLE_SECTION_NAME
);
17457 set_decl_section_name (vars_decl
, OFFLOAD_VAR_TABLE_SECTION_NAME
);
17459 varpool_node::finalize_decl (vars_decl
);
17460 varpool_node::finalize_decl (funcs_decl
);
17464 for (unsigned i
= 0; i
< num_funcs
; i
++)
17466 tree it
= (*offload_funcs
)[i
];
17467 targetm
.record_offload_symbol (it
);
17469 for (unsigned i
= 0; i
< num_vars
; i
++)
17471 tree it
= (*offload_vars
)[i
];
17472 targetm
.record_offload_symbol (it
);
17477 /* Validate and update the dimensions for offloaded FN. ATTRS is the
17478 raw attribute. DIMS is an array of dimensions, which is returned.
17479 Returns the function level dimensionality -- the level at which an
17480 offload routine wishes to partition a loop. */
17483 oacc_validate_dims (tree fn
, tree attrs
, int *dims
)
17485 tree purpose
[GOMP_DIM_MAX
];
17487 tree pos
= TREE_VALUE (attrs
);
17490 /* Make sure the attribute creator attached the dimension
17494 for (ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
17496 purpose
[ix
] = TREE_PURPOSE (pos
);
17500 if (integer_zerop (purpose
[ix
]))
17502 else if (fn_level
< 0)
17506 tree val
= TREE_VALUE (pos
);
17507 dims
[ix
] = val
? TREE_INT_CST_LOW (val
) : -1;
17508 pos
= TREE_CHAIN (pos
);
17511 bool changed
= targetm
.goacc
.validate_dims (fn
, dims
, fn_level
);
17513 /* Default anything left to 1. */
17514 for (ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
17523 /* Replace the attribute with new values. */
17525 for (ix
= GOMP_DIM_MAX
; ix
--;)
17526 pos
= tree_cons (purpose
[ix
],
17527 build_int_cst (integer_type_node
, dims
[ix
]),
17529 replace_oacc_fn_attrib (fn
, pos
);
17535 /* Main entry point for oacc transformations which run on the device
17536 compiler after LTO, so we know what the target device is at this
17537 point (including the host fallback). */
17539 static unsigned int
17540 execute_oacc_device_lower ()
17542 tree attrs
= get_oacc_fn_attrib (current_function_decl
);
17543 int dims
[GOMP_DIM_MAX
];
17546 /* Not an offloaded function. */
17549 oacc_validate_dims (current_function_decl
, attrs
, dims
);
17554 /* Default launch dimension validator. Force everything to 1. A
17555 backend that wants to provide larger dimensions must override this
17559 default_goacc_validate_dims (tree
ARG_UNUSED (decl
), int *dims
,
17560 int ARG_UNUSED (fn_level
))
17562 bool changed
= false;
17564 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
17578 const pass_data pass_data_oacc_device_lower
=
17580 GIMPLE_PASS
, /* type */
17581 "oaccdevlow", /* name */
17582 OPTGROUP_NONE
, /* optinfo_flags */
17583 TV_NONE
, /* tv_id */
17584 PROP_cfg
, /* properties_required */
17585 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
17586 0, /* properties_destroyed */
17587 0, /* todo_flags_start */
17588 TODO_update_ssa
| TODO_cleanup_cfg
, /* todo_flags_finish */
17591 class pass_oacc_device_lower
: public gimple_opt_pass
17594 pass_oacc_device_lower (gcc::context
*ctxt
)
17595 : gimple_opt_pass (pass_data_oacc_device_lower
, ctxt
)
17598 /* opt_pass methods: */
17599 virtual unsigned int execute (function
*)
17601 bool gate
= (flag_openacc
!= 0 && !seen_error ());
17606 return execute_oacc_device_lower ();
17609 }; // class pass_oacc_transform
17611 } // anon namespace
17614 make_pass_oacc_device_lower (gcc::context
*ctxt
)
17616 return new pass_oacc_device_lower (ctxt
);
17619 #include "gt-omp-low.h"