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"
86 /* Lowering of OMP parallel and workshare constructs proceeds in two
87 phases. The first phase scans the function looking for OMP statements
88 and then for variables that must be replaced to satisfy data sharing
89 clauses. The second phase expands code for the constructs, as well as
90 re-gimplifying things when variables have been replaced with complex
93 Final code generation is done by pass_expand_omp. The flowgraph is
94 scanned for regions which are then moved to a new
95 function, to be invoked by the thread library, or offloaded. */
97 /* OMP region information. Every parallel and workshare
98 directive is enclosed between two markers, the OMP_* directive
99 and a corresponding OMP_RETURN statement. */
103 /* The enclosing region. */
104 struct omp_region
*outer
;
106 /* First child region. */
107 struct omp_region
*inner
;
109 /* Next peer region. */
110 struct omp_region
*next
;
112 /* Block containing the omp directive as its last stmt. */
115 /* Block containing the OMP_RETURN as its last stmt. */
118 /* Block containing the OMP_CONTINUE as its last stmt. */
121 /* If this is a combined parallel+workshare region, this is a list
122 of additional arguments needed by the combined parallel+workshare
124 vec
<tree
, va_gc
> *ws_args
;
126 /* The code for the omp directive of this region. */
127 enum gimple_code type
;
129 /* Schedule kind, only used for OMP_FOR type regions. */
130 enum omp_clause_schedule_kind sched_kind
;
132 /* True if this is a combined parallel+workshare region. */
133 bool is_combined_parallel
;
136 /* Levels of parallelism as defined by OpenACC. Increasing numbers
137 correspond to deeper loop nesting levels. */
139 #define MASK_WORKER 2
140 #define MASK_VECTOR 4
142 /* Context structure. Used to store information about each parallel
143 directive in the code. */
147 /* This field must be at the beginning, as we do "inheritance": Some
148 callback functions for tree-inline.c (e.g., omp_copy_decl)
149 receive a copy_body_data pointer that is up-casted to an
150 omp_context pointer. */
153 /* The tree of contexts corresponding to the encountered constructs. */
154 struct omp_context
*outer
;
157 /* Map variables to fields in a structure that allows communication
158 between sending and receiving threads. */
159 splay_tree field_map
;
164 /* These are used just by task contexts, if task firstprivate fn is
165 needed. srecord_type is used to communicate from the thread
166 that encountered the task construct to task firstprivate fn,
167 record_type is allocated by GOMP_task, initialized by task firstprivate
168 fn and passed to the task body fn. */
169 splay_tree sfield_map
;
172 /* A chain of variables to add to the top-level block surrounding the
173 construct. In the case of a parallel, this is in the child function. */
176 /* A map of reduction pointer variables. For accelerators, each
177 reduction variable is replaced with an array. Each thread, in turn,
178 is assigned to a slot on that array. */
179 splay_tree reduction_map
;
181 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
182 barriers should jump to during omplower pass. */
185 /* What to do with variables with implicitly determined sharing
187 enum omp_clause_default_kind default_kind
;
189 /* Nesting depth of this context. Used to beautify error messages re
190 invalid gotos. The outermost ctx is depth 1, with depth 0 being
191 reserved for the main body of the function. */
194 /* True if this parallel directive is nested within another. */
197 /* True if this construct can be cancelled. */
200 /* For OpenACC loops, a mask of gang, worker and vector used at
201 levels below this one. */
203 /* For OpenACC loops, a mask of gang, worker and vector used at
204 this level and above. For parallel and kernels clauses, a mask
205 indicating which of num_gangs/num_workers/num_vectors was used. */
209 /* A structure holding the elements of:
210 for (V = N1; V cond N2; V += STEP) [...] */
212 struct omp_for_data_loop
214 tree v
, n1
, n2
, step
;
215 enum tree_code cond_code
;
218 /* A structure describing the main elements of a parallel loop. */
222 struct omp_for_data_loop loop
;
227 bool have_nowait
, have_ordered
;
228 enum omp_clause_schedule_kind sched_kind
;
229 struct omp_for_data_loop
*loops
;
233 static splay_tree all_contexts
;
234 static int taskreg_nesting_level
;
235 static int target_nesting_level
;
236 static struct omp_region
*root_omp_region
;
237 static bitmap task_shared_vars
;
238 static vec
<omp_context
*> taskreg_contexts
;
240 static void scan_omp (gimple_seq
*, omp_context
*);
241 static tree
scan_omp_1_op (tree
*, int *, void *);
243 #define WALK_SUBSTMTS \
247 case GIMPLE_EH_FILTER: \
248 case GIMPLE_TRANSACTION: \
249 /* The sub-statements for these should be walked. */ \
250 *handled_ops_p = false; \
253 /* Helper function to get the name of the array containing the partial
254 reductions for OpenACC reductions. */
256 oacc_get_reduction_array_id (tree node
)
258 const char *id
= IDENTIFIER_POINTER (DECL_NAME (node
));
259 int len
= strlen ("OACC") + strlen (id
);
260 char *temp_name
= XALLOCAVEC (char, len
+ 1);
261 snprintf (temp_name
, len
+ 1, "OACC%s", id
);
262 return IDENTIFIER_POINTER (get_identifier (temp_name
));
265 /* Determine the number of threads OpenACC threads used to determine the
266 size of the array of partial reductions. Currently, this is num_gangs
267 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
268 because it is independed of the device used. */
271 oacc_max_threads (omp_context
*ctx
)
273 tree nthreads
, vector_length
, gangs
, clauses
;
275 gangs
= fold_convert (sizetype
, integer_one_node
);
276 vector_length
= gangs
;
278 /* The reduction clause may be nested inside a loop directive.
279 Scan for the innermost vector_length clause. */
280 for (omp_context
*oc
= ctx
; oc
; oc
= oc
->outer
)
282 if (gimple_code (oc
->stmt
) != GIMPLE_OMP_TARGET
283 || (gimple_omp_target_kind (oc
->stmt
)
284 != GF_OMP_TARGET_KIND_OACC_PARALLEL
))
287 clauses
= gimple_omp_target_clauses (oc
->stmt
);
289 vector_length
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
291 vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length
),
293 OMP_CLAUSE_VECTOR_LENGTH_EXPR
296 vector_length
= fold_convert (sizetype
, integer_one_node
);
298 gangs
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
300 gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (gangs
), sizetype
,
301 OMP_CLAUSE_NUM_GANGS_EXPR (gangs
));
303 gangs
= fold_convert (sizetype
, integer_one_node
);
308 nthreads
= fold_build2 (MULT_EXPR
, sizetype
, gangs
, vector_length
);
313 /* Holds offload tables with decls. */
314 vec
<tree
, va_gc
> *offload_funcs
, *offload_vars
;
316 /* Convenience function for calling scan_omp_1_op on tree operands. */
319 scan_omp_op (tree
*tp
, omp_context
*ctx
)
321 struct walk_stmt_info wi
;
323 memset (&wi
, 0, sizeof (wi
));
325 wi
.want_locations
= true;
327 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
330 static void lower_omp (gimple_seq
*, omp_context
*);
331 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
332 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
334 /* Find an OMP clause of type KIND within CLAUSES. */
337 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
339 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
340 if (OMP_CLAUSE_CODE (clauses
) == kind
)
346 /* Return true if CTX is for an omp parallel. */
349 is_parallel_ctx (omp_context
*ctx
)
351 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
355 /* Return true if CTX is for an omp task. */
358 is_task_ctx (omp_context
*ctx
)
360 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
364 /* Return true if CTX is for an omp parallel or omp task. */
367 is_taskreg_ctx (omp_context
*ctx
)
369 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
370 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
374 /* Return true if REGION is a combined parallel+workshare region. */
377 is_combined_parallel (struct omp_region
*region
)
379 return region
->is_combined_parallel
;
383 /* Extract the header elements of parallel loop FOR_STMT and store
387 extract_omp_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
388 struct omp_for_data_loop
*loops
)
390 tree t
, var
, *collapse_iter
, *collapse_count
;
391 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
392 struct omp_for_data_loop
*loop
;
394 struct omp_for_data_loop dummy_loop
;
395 location_t loc
= gimple_location (for_stmt
);
396 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
397 bool distribute
= gimple_omp_for_kind (for_stmt
)
398 == GF_OMP_FOR_KIND_DISTRIBUTE
;
400 fd
->for_stmt
= for_stmt
;
402 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
403 if (fd
->collapse
> 1)
406 fd
->loops
= &fd
->loop
;
408 fd
->have_nowait
= distribute
|| simd
;
409 fd
->have_ordered
= false;
410 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
411 fd
->chunk_size
= NULL_TREE
;
412 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
413 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
414 collapse_iter
= NULL
;
415 collapse_count
= NULL
;
417 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
418 switch (OMP_CLAUSE_CODE (t
))
420 case OMP_CLAUSE_NOWAIT
:
421 fd
->have_nowait
= true;
423 case OMP_CLAUSE_ORDERED
:
424 fd
->have_ordered
= true;
426 case OMP_CLAUSE_SCHEDULE
:
427 gcc_assert (!distribute
);
428 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
429 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
431 case OMP_CLAUSE_DIST_SCHEDULE
:
432 gcc_assert (distribute
);
433 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
435 case OMP_CLAUSE_COLLAPSE
:
436 if (fd
->collapse
> 1)
438 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
439 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
446 /* FIXME: for now map schedule(auto) to schedule(static).
447 There should be analysis to determine whether all iterations
448 are approximately the same amount of work (then schedule(static)
449 is best) or if it varies (then schedule(dynamic,N) is better). */
450 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
452 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
453 gcc_assert (fd
->chunk_size
== NULL
);
455 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
456 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
457 gcc_assert (fd
->chunk_size
== NULL
);
458 else if (fd
->chunk_size
== NULL
)
460 /* We only need to compute a default chunk size for ordered
461 static loops and dynamic loops. */
462 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
464 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
465 ? integer_zero_node
: integer_one_node
;
468 for (i
= 0; i
< fd
->collapse
; i
++)
470 if (fd
->collapse
== 1)
472 else if (loops
!= NULL
)
477 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
478 gcc_assert (SSA_VAR_P (loop
->v
));
479 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
480 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
481 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
482 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
484 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
485 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
486 switch (loop
->cond_code
)
492 gcc_assert (gimple_omp_for_kind (for_stmt
)
493 == GF_OMP_FOR_KIND_CILKSIMD
494 || (gimple_omp_for_kind (for_stmt
)
495 == GF_OMP_FOR_KIND_CILKFOR
));
498 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
499 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
501 loop
->n2
= fold_build2_loc (loc
,
502 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
503 build_int_cst (TREE_TYPE (loop
->n2
), 1));
504 loop
->cond_code
= LT_EXPR
;
507 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
508 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
510 loop
->n2
= fold_build2_loc (loc
,
511 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
512 build_int_cst (TREE_TYPE (loop
->n2
), 1));
513 loop
->cond_code
= GT_EXPR
;
519 t
= gimple_omp_for_incr (for_stmt
, i
);
520 gcc_assert (TREE_OPERAND (t
, 0) == var
);
521 switch (TREE_CODE (t
))
524 loop
->step
= TREE_OPERAND (t
, 1);
526 case POINTER_PLUS_EXPR
:
527 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
530 loop
->step
= TREE_OPERAND (t
, 1);
531 loop
->step
= fold_build1_loc (loc
,
532 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
540 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
541 && !fd
->have_ordered
))
543 if (fd
->collapse
== 1)
544 iter_type
= TREE_TYPE (loop
->v
);
546 || TYPE_PRECISION (iter_type
)
547 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
549 = build_nonstandard_integer_type
550 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
552 else if (iter_type
!= long_long_unsigned_type_node
)
554 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
555 iter_type
= long_long_unsigned_type_node
;
556 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
557 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
558 >= TYPE_PRECISION (iter_type
))
562 if (loop
->cond_code
== LT_EXPR
)
563 n
= fold_build2_loc (loc
,
564 PLUS_EXPR
, TREE_TYPE (loop
->v
),
565 loop
->n2
, loop
->step
);
568 if (TREE_CODE (n
) != INTEGER_CST
569 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
570 iter_type
= long_long_unsigned_type_node
;
572 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
573 > TYPE_PRECISION (iter_type
))
577 if (loop
->cond_code
== LT_EXPR
)
580 n2
= fold_build2_loc (loc
,
581 PLUS_EXPR
, TREE_TYPE (loop
->v
),
582 loop
->n2
, loop
->step
);
586 n1
= fold_build2_loc (loc
,
587 MINUS_EXPR
, TREE_TYPE (loop
->v
),
588 loop
->n2
, loop
->step
);
591 if (TREE_CODE (n1
) != INTEGER_CST
592 || TREE_CODE (n2
) != INTEGER_CST
593 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
594 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
595 iter_type
= long_long_unsigned_type_node
;
599 if (collapse_count
&& *collapse_count
== NULL
)
601 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
602 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
603 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
604 if (t
&& integer_zerop (t
))
605 count
= build_zero_cst (long_long_unsigned_type_node
);
606 else if ((i
== 0 || count
!= NULL_TREE
)
607 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
608 && TREE_CONSTANT (loop
->n1
)
609 && TREE_CONSTANT (loop
->n2
)
610 && TREE_CODE (loop
->step
) == INTEGER_CST
)
612 tree itype
= TREE_TYPE (loop
->v
);
614 if (POINTER_TYPE_P (itype
))
615 itype
= signed_type_for (itype
);
616 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
617 t
= fold_build2_loc (loc
,
619 fold_convert_loc (loc
, itype
, loop
->step
), t
);
620 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
621 fold_convert_loc (loc
, itype
, loop
->n2
));
622 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
623 fold_convert_loc (loc
, itype
, loop
->n1
));
624 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
625 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
626 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
627 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
628 fold_convert_loc (loc
, itype
,
631 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
632 fold_convert_loc (loc
, itype
, loop
->step
));
633 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
634 if (count
!= NULL_TREE
)
635 count
= fold_build2_loc (loc
,
636 MULT_EXPR
, long_long_unsigned_type_node
,
640 if (TREE_CODE (count
) != INTEGER_CST
)
643 else if (count
&& !integer_zerop (count
))
650 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
651 || fd
->have_ordered
))
653 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
654 iter_type
= long_long_unsigned_type_node
;
656 iter_type
= long_integer_type_node
;
658 else if (collapse_iter
&& *collapse_iter
!= NULL
)
659 iter_type
= TREE_TYPE (*collapse_iter
);
660 fd
->iter_type
= iter_type
;
661 if (collapse_iter
&& *collapse_iter
== NULL
)
662 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
663 if (collapse_count
&& *collapse_count
== NULL
)
666 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
668 *collapse_count
= create_tmp_var (iter_type
, ".count");
671 if (fd
->collapse
> 1)
673 fd
->loop
.v
= *collapse_iter
;
674 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
675 fd
->loop
.n2
= *collapse_count
;
676 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
677 fd
->loop
.cond_code
= LT_EXPR
;
680 /* For OpenACC loops, force a chunk size of one, as this avoids the default
681 scheduling where several subsequent iterations are being executed by the
683 if (gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
685 gcc_assert (fd
->chunk_size
== NULL_TREE
);
686 fd
->chunk_size
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
691 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
692 is the immediate dominator of PAR_ENTRY_BB, return true if there
693 are no data dependencies that would prevent expanding the parallel
694 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
696 When expanding a combined parallel+workshare region, the call to
697 the child function may need additional arguments in the case of
698 GIMPLE_OMP_FOR regions. In some cases, these arguments are
699 computed out of variables passed in from the parent to the child
700 via 'struct .omp_data_s'. For instance:
702 #pragma omp parallel for schedule (guided, i * 4)
707 # BLOCK 2 (PAR_ENTRY_BB)
709 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
711 # BLOCK 3 (WS_ENTRY_BB)
712 .omp_data_i = &.omp_data_o;
713 D.1667 = .omp_data_i->i;
715 #pragma omp for schedule (guided, D.1598)
717 When we outline the parallel region, the call to the child function
718 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
719 that value is computed *after* the call site. So, in principle we
720 cannot do the transformation.
722 To see whether the code in WS_ENTRY_BB blocks the combined
723 parallel+workshare call, we collect all the variables used in the
724 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
725 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
728 FIXME. If we had the SSA form built at this point, we could merely
729 hoist the code in block 3 into block 2 and be done with it. But at
730 this point we don't have dataflow information and though we could
731 hack something up here, it is really not worth the aggravation. */
734 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
736 struct omp_for_data fd
;
737 gimple ws_stmt
= last_stmt (ws_entry_bb
);
739 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
742 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
744 extract_omp_for_data (as_a
<gomp_for
*> (ws_stmt
), &fd
, NULL
);
746 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
748 if (fd
.iter_type
!= long_integer_type_node
)
751 /* FIXME. We give up too easily here. If any of these arguments
752 are not constants, they will likely involve variables that have
753 been mapped into fields of .omp_data_s for sharing with the child
754 function. With appropriate data flow, it would be possible to
756 if (!is_gimple_min_invariant (fd
.loop
.n1
)
757 || !is_gimple_min_invariant (fd
.loop
.n2
)
758 || !is_gimple_min_invariant (fd
.loop
.step
)
759 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
766 /* Collect additional arguments needed to emit a combined
767 parallel+workshare call. WS_STMT is the workshare directive being
770 static vec
<tree
, va_gc
> *
771 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
774 location_t loc
= gimple_location (ws_stmt
);
775 vec
<tree
, va_gc
> *ws_args
;
777 if (gomp_for
*for_stmt
= dyn_cast
<gomp_for
*> (ws_stmt
))
779 struct omp_for_data fd
;
782 extract_omp_for_data (for_stmt
, &fd
, NULL
);
786 if (gimple_omp_for_combined_into_p (for_stmt
))
789 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
790 OMP_CLAUSE__LOOPTEMP_
);
792 n1
= OMP_CLAUSE_DECL (innerc
);
793 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
794 OMP_CLAUSE__LOOPTEMP_
);
796 n2
= OMP_CLAUSE_DECL (innerc
);
799 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
801 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
802 ws_args
->quick_push (t
);
804 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
805 ws_args
->quick_push (t
);
807 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
808 ws_args
->quick_push (t
);
812 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
813 ws_args
->quick_push (t
);
818 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
820 /* Number of sections is equal to the number of edges from the
821 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
822 the exit of the sections region. */
823 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
824 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
825 vec_alloc (ws_args
, 1);
826 ws_args
->quick_push (t
);
834 /* Discover whether REGION is a combined parallel+workshare region. */
837 determine_parallel_type (struct omp_region
*region
)
839 basic_block par_entry_bb
, par_exit_bb
;
840 basic_block ws_entry_bb
, ws_exit_bb
;
842 if (region
== NULL
|| region
->inner
== NULL
843 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
844 || region
->inner
->cont
== NULL
)
847 /* We only support parallel+for and parallel+sections. */
848 if (region
->type
!= GIMPLE_OMP_PARALLEL
849 || (region
->inner
->type
!= GIMPLE_OMP_FOR
850 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
853 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
854 WS_EXIT_BB -> PAR_EXIT_BB. */
855 par_entry_bb
= region
->entry
;
856 par_exit_bb
= region
->exit
;
857 ws_entry_bb
= region
->inner
->entry
;
858 ws_exit_bb
= region
->inner
->exit
;
860 if (single_succ (par_entry_bb
) == ws_entry_bb
861 && single_succ (ws_exit_bb
) == par_exit_bb
862 && workshare_safe_to_combine_p (ws_entry_bb
)
863 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
864 || (last_and_only_stmt (ws_entry_bb
)
865 && last_and_only_stmt (par_exit_bb
))))
867 gimple par_stmt
= last_stmt (par_entry_bb
);
868 gimple ws_stmt
= last_stmt (ws_entry_bb
);
870 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
872 /* If this is a combined parallel loop, we need to determine
873 whether or not to use the combined library calls. There
874 are two cases where we do not apply the transformation:
875 static loops and any kind of ordered loop. In the first
876 case, we already open code the loop so there is no need
877 to do anything else. In the latter case, the combined
878 parallel loop call would still need extra synchronization
879 to implement ordered semantics, so there would not be any
880 gain in using the combined call. */
881 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
882 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
884 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
885 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
887 region
->is_combined_parallel
= false;
888 region
->inner
->is_combined_parallel
= false;
893 region
->is_combined_parallel
= true;
894 region
->inner
->is_combined_parallel
= true;
895 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
900 /* Return true if EXPR is variable sized. */
903 is_variable_sized (const_tree expr
)
905 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
908 /* Return true if DECL is a reference type. */
911 is_reference (tree decl
)
913 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
916 /* Return the type of a decl. If the decl is reference type,
917 return its base type. */
919 get_base_type (tree decl
)
921 tree type
= TREE_TYPE (decl
);
922 if (is_reference (decl
))
923 type
= TREE_TYPE (type
);
927 /* Lookup variables. The "maybe" form
928 allows for the variable form to not have been entered, otherwise we
929 assert that the variable must have been entered. */
932 lookup_decl (tree var
, omp_context
*ctx
)
934 tree
*n
= ctx
->cb
.decl_map
->get (var
);
939 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
941 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
942 return n
? *n
: NULL_TREE
;
946 lookup_field (tree var
, omp_context
*ctx
)
949 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
950 return (tree
) n
->value
;
954 lookup_sfield (tree var
, omp_context
*ctx
)
957 n
= splay_tree_lookup (ctx
->sfield_map
958 ? ctx
->sfield_map
: ctx
->field_map
,
959 (splay_tree_key
) var
);
960 return (tree
) n
->value
;
964 maybe_lookup_field (tree var
, omp_context
*ctx
)
967 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
968 return n
? (tree
) n
->value
: NULL_TREE
;
972 lookup_oacc_reduction (const char *id
, omp_context
*ctx
)
975 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) id
);
976 return (tree
) n
->value
;
980 maybe_lookup_oacc_reduction (tree var
, omp_context
*ctx
)
982 splay_tree_node n
= NULL
;
983 if (ctx
->reduction_map
)
984 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) var
);
985 return n
? (tree
) n
->value
: NULL_TREE
;
988 /* Return true if DECL should be copied by pointer. SHARED_CTX is
989 the parallel context if DECL is to be shared. */
992 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
994 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
997 /* We can only use copy-in/copy-out semantics for shared variables
998 when we know the value is not accessible from an outer scope. */
1001 gcc_assert (!is_gimple_omp_oacc (shared_ctx
->stmt
));
1003 /* ??? Trivially accessible from anywhere. But why would we even
1004 be passing an address in this case? Should we simply assert
1005 this to be false, or should we have a cleanup pass that removes
1006 these from the list of mappings? */
1007 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
1010 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1011 without analyzing the expression whether or not its location
1012 is accessible to anyone else. In the case of nested parallel
1013 regions it certainly may be. */
1014 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
1017 /* Do not use copy-in/copy-out for variables that have their
1019 if (TREE_ADDRESSABLE (decl
))
1022 /* lower_send_shared_vars only uses copy-in, but not copy-out
1024 if (TREE_READONLY (decl
)
1025 || ((TREE_CODE (decl
) == RESULT_DECL
1026 || TREE_CODE (decl
) == PARM_DECL
)
1027 && DECL_BY_REFERENCE (decl
)))
1030 /* Disallow copy-in/out in nested parallel if
1031 decl is shared in outer parallel, otherwise
1032 each thread could store the shared variable
1033 in its own copy-in location, making the
1034 variable no longer really shared. */
1035 if (shared_ctx
->is_nested
)
1039 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
1040 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
1047 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
1048 c
; c
= OMP_CLAUSE_CHAIN (c
))
1049 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1050 && OMP_CLAUSE_DECL (c
) == decl
)
1054 goto maybe_mark_addressable_and_ret
;
1058 /* For tasks avoid using copy-in/out. As tasks can be
1059 deferred or executed in different thread, when GOMP_task
1060 returns, the task hasn't necessarily terminated. */
1061 if (is_task_ctx (shared_ctx
))
1064 maybe_mark_addressable_and_ret
:
1065 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
1066 if (is_gimple_reg (outer
))
1068 /* Taking address of OUTER in lower_send_shared_vars
1069 might need regimplification of everything that uses the
1071 if (!task_shared_vars
)
1072 task_shared_vars
= BITMAP_ALLOC (NULL
);
1073 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
1074 TREE_ADDRESSABLE (outer
) = 1;
1083 /* Construct a new automatic decl similar to VAR. */
1086 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
1088 tree copy
= copy_var_decl (var
, name
, type
);
1090 DECL_CONTEXT (copy
) = current_function_decl
;
1091 DECL_CHAIN (copy
) = ctx
->block_vars
;
1092 ctx
->block_vars
= copy
;
1098 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
1100 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
1103 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1106 omp_build_component_ref (tree obj
, tree field
)
1108 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
1109 if (TREE_THIS_VOLATILE (field
))
1110 TREE_THIS_VOLATILE (ret
) |= 1;
1111 if (TREE_READONLY (field
))
1112 TREE_READONLY (ret
) |= 1;
1116 /* Build tree nodes to access the field for VAR on the receiver side. */
1119 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1121 tree x
, field
= lookup_field (var
, ctx
);
1123 /* If the receiver record type was remapped in the child function,
1124 remap the field into the new record type. */
1125 x
= maybe_lookup_field (field
, ctx
);
1129 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1130 TREE_THIS_NOTRAP (x
) = 1;
1131 x
= omp_build_component_ref (x
, field
);
1133 x
= build_simple_mem_ref (x
);
1138 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1139 of a parallel, this is a component reference; for workshare constructs
1140 this is some variable. */
1143 build_outer_var_ref (tree var
, omp_context
*ctx
)
1147 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1149 else if (is_variable_sized (var
))
1151 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1152 x
= build_outer_var_ref (x
, ctx
);
1153 x
= build_simple_mem_ref (x
);
1155 else if (is_taskreg_ctx (ctx
))
1157 bool by_ref
= use_pointer_for_field (var
, NULL
);
1158 x
= build_receiver_ref (var
, by_ref
, ctx
);
1160 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1161 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1163 /* #pragma omp simd isn't a worksharing construct, and can reference even
1164 private vars in its linear etc. clauses. */
1166 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1167 x
= lookup_decl (var
, ctx
->outer
);
1168 else if (ctx
->outer
)
1169 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1173 else if (ctx
->outer
)
1174 x
= lookup_decl (var
, ctx
->outer
);
1175 else if (is_reference (var
))
1176 /* This can happen with orphaned constructs. If var is reference, it is
1177 possible it is shared and as such valid. */
1182 if (is_reference (var
))
1183 x
= build_simple_mem_ref (x
);
1188 /* Build tree nodes to access the field for VAR on the sender side. */
1191 build_sender_ref (tree var
, omp_context
*ctx
)
1193 tree field
= lookup_sfield (var
, ctx
);
1194 return omp_build_component_ref (ctx
->sender_decl
, field
);
1197 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1200 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1202 tree field
, type
, sfield
= NULL_TREE
;
1204 gcc_assert ((mask
& 1) == 0
1205 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1206 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1207 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1208 gcc_assert ((mask
& 3) == 3
1209 || !is_gimple_omp_oacc (ctx
->stmt
));
1211 type
= TREE_TYPE (var
);
1214 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1215 type
= build_pointer_type (build_pointer_type (type
));
1218 type
= build_pointer_type (type
);
1219 else if ((mask
& 3) == 1 && is_reference (var
))
1220 type
= TREE_TYPE (type
);
1222 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1223 FIELD_DECL
, DECL_NAME (var
), type
);
1225 /* Remember what variable this field was created for. This does have a
1226 side effect of making dwarf2out ignore this member, so for helpful
1227 debugging we clear it later in delete_omp_context. */
1228 DECL_ABSTRACT_ORIGIN (field
) = var
;
1229 if (type
== TREE_TYPE (var
))
1231 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1232 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1233 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1236 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1238 if ((mask
& 3) == 3)
1240 insert_field_into_struct (ctx
->record_type
, field
);
1241 if (ctx
->srecord_type
)
1243 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1244 FIELD_DECL
, DECL_NAME (var
), type
);
1245 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1246 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1247 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1248 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1249 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1254 if (ctx
->srecord_type
== NULL_TREE
)
1258 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1259 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1260 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1262 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1263 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1264 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1265 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1266 splay_tree_insert (ctx
->sfield_map
,
1267 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1268 (splay_tree_value
) sfield
);
1272 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1273 : ctx
->srecord_type
, field
);
1277 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1278 (splay_tree_value
) field
);
1279 if ((mask
& 2) && ctx
->sfield_map
)
1280 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1281 (splay_tree_value
) sfield
);
1285 install_var_local (tree var
, omp_context
*ctx
)
1287 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1288 insert_decl_map (&ctx
->cb
, var
, new_var
);
1292 /* Adjust the replacement for DECL in CTX for the new context. This means
1293 copying the DECL_VALUE_EXPR, and fixing up the type. */
1296 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1298 tree new_decl
, size
;
1300 new_decl
= lookup_decl (decl
, ctx
);
1302 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1304 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1305 && DECL_HAS_VALUE_EXPR_P (decl
))
1307 tree ve
= DECL_VALUE_EXPR (decl
);
1308 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1309 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1310 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1313 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1315 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1316 if (size
== error_mark_node
)
1317 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1318 DECL_SIZE (new_decl
) = size
;
1320 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1321 if (size
== error_mark_node
)
1322 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1323 DECL_SIZE_UNIT (new_decl
) = size
;
1327 /* The callback for remap_decl. Search all containing contexts for a
1328 mapping of the variable; this avoids having to duplicate the splay
1329 tree ahead of time. We know a mapping doesn't already exist in the
1330 given context. Create new mappings to implement default semantics. */
1333 omp_copy_decl (tree var
, copy_body_data
*cb
)
1335 omp_context
*ctx
= (omp_context
*) cb
;
1338 if (TREE_CODE (var
) == LABEL_DECL
)
1340 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1341 DECL_CONTEXT (new_var
) = current_function_decl
;
1342 insert_decl_map (&ctx
->cb
, var
, new_var
);
1346 while (!is_taskreg_ctx (ctx
))
1351 new_var
= maybe_lookup_decl (var
, ctx
);
1356 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1359 return error_mark_node
;
1363 /* Debugging dumps for parallel regions. */
1364 void dump_omp_region (FILE *, struct omp_region
*, int);
1365 void debug_omp_region (struct omp_region
*);
1366 void debug_all_omp_regions (void);
1368 /* Dump the parallel region tree rooted at REGION. */
1371 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1373 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1374 gimple_code_name
[region
->type
]);
1377 dump_omp_region (file
, region
->inner
, indent
+ 4);
1381 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1382 region
->cont
->index
);
1386 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1387 region
->exit
->index
);
1389 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1392 dump_omp_region (file
, region
->next
, indent
);
1396 debug_omp_region (struct omp_region
*region
)
1398 dump_omp_region (stderr
, region
, 0);
1402 debug_all_omp_regions (void)
1404 dump_omp_region (stderr
, root_omp_region
, 0);
1408 /* Create a new parallel region starting at STMT inside region PARENT. */
1410 static struct omp_region
*
1411 new_omp_region (basic_block bb
, enum gimple_code type
,
1412 struct omp_region
*parent
)
1414 struct omp_region
*region
= XCNEW (struct omp_region
);
1416 region
->outer
= parent
;
1418 region
->type
= type
;
1422 /* This is a nested region. Add it to the list of inner
1423 regions in PARENT. */
1424 region
->next
= parent
->inner
;
1425 parent
->inner
= region
;
1429 /* This is a toplevel region. Add it to the list of toplevel
1430 regions in ROOT_OMP_REGION. */
1431 region
->next
= root_omp_region
;
1432 root_omp_region
= region
;
1438 /* Release the memory associated with the region tree rooted at REGION. */
1441 free_omp_region_1 (struct omp_region
*region
)
1443 struct omp_region
*i
, *n
;
1445 for (i
= region
->inner
; i
; i
= n
)
1448 free_omp_region_1 (i
);
1454 /* Release the memory for the entire omp region tree. */
1457 free_omp_regions (void)
1459 struct omp_region
*r
, *n
;
1460 for (r
= root_omp_region
; r
; r
= n
)
1463 free_omp_region_1 (r
);
1465 root_omp_region
= NULL
;
1469 /* Create a new context, with OUTER_CTX being the surrounding context. */
1471 static omp_context
*
1472 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1474 omp_context
*ctx
= XCNEW (omp_context
);
1476 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1477 (splay_tree_value
) ctx
);
1482 ctx
->outer
= outer_ctx
;
1483 ctx
->cb
= outer_ctx
->cb
;
1484 ctx
->cb
.block
= NULL
;
1485 ctx
->depth
= outer_ctx
->depth
+ 1;
1486 ctx
->reduction_map
= outer_ctx
->reduction_map
;
1490 ctx
->cb
.src_fn
= current_function_decl
;
1491 ctx
->cb
.dst_fn
= current_function_decl
;
1492 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1493 gcc_checking_assert (ctx
->cb
.src_node
);
1494 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1495 ctx
->cb
.src_cfun
= cfun
;
1496 ctx
->cb
.copy_decl
= omp_copy_decl
;
1497 ctx
->cb
.eh_lp_nr
= 0;
1498 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1502 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1507 static gimple_seq
maybe_catch_exception (gimple_seq
);
1509 /* Finalize task copyfn. */
1512 finalize_task_copyfn (gomp_task
*task_stmt
)
1514 struct function
*child_cfun
;
1516 gimple_seq seq
= NULL
, new_seq
;
1519 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1520 if (child_fn
== NULL_TREE
)
1523 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1524 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1526 push_cfun (child_cfun
);
1527 bind
= gimplify_body (child_fn
, false);
1528 gimple_seq_add_stmt (&seq
, bind
);
1529 new_seq
= maybe_catch_exception (seq
);
1532 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1534 gimple_seq_add_stmt (&seq
, bind
);
1536 gimple_set_body (child_fn
, seq
);
1539 /* Inform the callgraph about the new function. */
1540 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
1541 node
->parallelized_function
= 1;
1542 cgraph_node::add_new_function (child_fn
, false);
1545 /* Destroy a omp_context data structures. Called through the splay tree
1546 value delete callback. */
1549 delete_omp_context (splay_tree_value value
)
1551 omp_context
*ctx
= (omp_context
*) value
;
1553 delete ctx
->cb
.decl_map
;
1556 splay_tree_delete (ctx
->field_map
);
1557 if (ctx
->sfield_map
)
1558 splay_tree_delete (ctx
->sfield_map
);
1559 /* Reduction map is copied to nested contexts, so only delete it in the
1561 if (ctx
->reduction_map
1562 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
1563 && is_gimple_omp_offloaded (ctx
->stmt
)
1564 && is_gimple_omp_oacc (ctx
->stmt
))
1565 splay_tree_delete (ctx
->reduction_map
);
1567 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1568 it produces corrupt debug information. */
1569 if (ctx
->record_type
)
1572 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1573 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1575 if (ctx
->srecord_type
)
1578 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1579 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1582 if (is_task_ctx (ctx
))
1583 finalize_task_copyfn (as_a
<gomp_task
*> (ctx
->stmt
));
1588 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1592 fixup_child_record_type (omp_context
*ctx
)
1594 tree f
, type
= ctx
->record_type
;
1596 /* ??? It isn't sufficient to just call remap_type here, because
1597 variably_modified_type_p doesn't work the way we expect for
1598 record types. Testing each field for whether it needs remapping
1599 and creating a new record by hand works, however. */
1600 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1601 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1605 tree name
, new_fields
= NULL
;
1607 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1608 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1609 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1610 TYPE_DECL
, name
, type
);
1611 TYPE_NAME (type
) = name
;
1613 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1615 tree new_f
= copy_node (f
);
1616 DECL_CONTEXT (new_f
) = type
;
1617 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1618 DECL_CHAIN (new_f
) = new_fields
;
1619 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1620 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1622 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1626 /* Arrange to be able to look up the receiver field
1627 given the sender field. */
1628 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1629 (splay_tree_value
) new_f
);
1631 TYPE_FIELDS (type
) = nreverse (new_fields
);
1635 TREE_TYPE (ctx
->receiver_decl
)
1636 = build_qualified_type (build_reference_type (type
), TYPE_QUAL_RESTRICT
);
1639 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1640 specified by CLAUSES. */
1643 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1646 bool scan_array_reductions
= false;
1648 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1652 switch (OMP_CLAUSE_CODE (c
))
1654 case OMP_CLAUSE_PRIVATE
:
1655 decl
= OMP_CLAUSE_DECL (c
);
1656 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1658 else if (!is_variable_sized (decl
))
1659 install_var_local (decl
, ctx
);
1662 case OMP_CLAUSE_SHARED
:
1663 decl
= OMP_CLAUSE_DECL (c
);
1664 /* Ignore shared directives in teams construct. */
1665 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1667 /* Global variables don't need to be copied,
1668 the receiver side will use them directly. */
1669 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1670 if (is_global_var (odecl
))
1672 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1675 gcc_assert (is_taskreg_ctx (ctx
));
1676 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1677 || !is_variable_sized (decl
));
1678 /* Global variables don't need to be copied,
1679 the receiver side will use them directly. */
1680 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1682 by_ref
= use_pointer_for_field (decl
, ctx
);
1683 if (! TREE_READONLY (decl
)
1684 || TREE_ADDRESSABLE (decl
)
1686 || is_reference (decl
))
1688 install_var_field (decl
, by_ref
, 3, ctx
);
1689 install_var_local (decl
, ctx
);
1692 /* We don't need to copy const scalar vars back. */
1693 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1696 case OMP_CLAUSE_LASTPRIVATE
:
1697 /* Let the corresponding firstprivate clause create
1699 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1703 case OMP_CLAUSE_FIRSTPRIVATE
:
1704 if (is_gimple_omp_oacc (ctx
->stmt
))
1706 sorry ("clause not supported yet");
1710 case OMP_CLAUSE_REDUCTION
:
1711 case OMP_CLAUSE_LINEAR
:
1712 decl
= OMP_CLAUSE_DECL (c
);
1714 if (is_variable_sized (decl
))
1716 if (is_task_ctx (ctx
))
1717 install_var_field (decl
, false, 1, ctx
);
1720 else if (is_taskreg_ctx (ctx
))
1723 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1724 by_ref
= use_pointer_for_field (decl
, NULL
);
1726 if (is_task_ctx (ctx
)
1727 && (global
|| by_ref
|| is_reference (decl
)))
1729 install_var_field (decl
, false, 1, ctx
);
1731 install_var_field (decl
, by_ref
, 2, ctx
);
1734 install_var_field (decl
, by_ref
, 3, ctx
);
1736 install_var_local (decl
, ctx
);
1737 if (is_gimple_omp_oacc (ctx
->stmt
)
1738 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
1740 /* Create a decl for the reduction array. */
1741 tree var
= OMP_CLAUSE_DECL (c
);
1742 tree type
= get_base_type (var
);
1743 tree ptype
= build_pointer_type (type
);
1744 tree array
= create_tmp_var (ptype
,
1745 oacc_get_reduction_array_id (var
));
1746 omp_context
*c
= (ctx
->field_map
? ctx
: ctx
->outer
);
1747 install_var_field (array
, true, 3, c
);
1748 install_var_local (array
, c
);
1750 /* Insert it into the current context. */
1751 splay_tree_insert (ctx
->reduction_map
, (splay_tree_key
)
1752 oacc_get_reduction_array_id (var
),
1753 (splay_tree_value
) array
);
1754 splay_tree_insert (ctx
->reduction_map
,
1755 (splay_tree_key
) array
,
1756 (splay_tree_value
) array
);
1760 case OMP_CLAUSE__LOOPTEMP_
:
1761 gcc_assert (is_parallel_ctx (ctx
));
1762 decl
= OMP_CLAUSE_DECL (c
);
1763 install_var_field (decl
, false, 3, ctx
);
1764 install_var_local (decl
, ctx
);
1767 case OMP_CLAUSE_COPYPRIVATE
:
1768 case OMP_CLAUSE_COPYIN
:
1769 decl
= OMP_CLAUSE_DECL (c
);
1770 by_ref
= use_pointer_for_field (decl
, NULL
);
1771 install_var_field (decl
, by_ref
, 3, ctx
);
1774 case OMP_CLAUSE_DEFAULT
:
1775 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1778 case OMP_CLAUSE_FINAL
:
1780 case OMP_CLAUSE_NUM_THREADS
:
1781 case OMP_CLAUSE_NUM_TEAMS
:
1782 case OMP_CLAUSE_THREAD_LIMIT
:
1783 case OMP_CLAUSE_DEVICE
:
1784 case OMP_CLAUSE_SCHEDULE
:
1785 case OMP_CLAUSE_DIST_SCHEDULE
:
1786 case OMP_CLAUSE_DEPEND
:
1787 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1788 case OMP_CLAUSE_NUM_GANGS
:
1789 case OMP_CLAUSE_NUM_WORKERS
:
1790 case OMP_CLAUSE_VECTOR_LENGTH
:
1792 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1796 case OMP_CLAUSE_FROM
:
1797 case OMP_CLAUSE_MAP
:
1799 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1800 decl
= OMP_CLAUSE_DECL (c
);
1801 /* Global variables with "omp declare target" attribute
1802 don't need to be copied, the receiver side will use them
1804 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1806 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1807 && varpool_node::get_create (decl
)->offloadable
)
1809 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1810 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
)
1812 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1813 not offloaded; there is nothing to map for those. */
1814 if (!is_gimple_omp_offloaded (ctx
->stmt
)
1815 && !POINTER_TYPE_P (TREE_TYPE (decl
))
1816 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
1821 if (DECL_SIZE (decl
)
1822 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1824 tree decl2
= DECL_VALUE_EXPR (decl
);
1825 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1826 decl2
= TREE_OPERAND (decl2
, 0);
1827 gcc_assert (DECL_P (decl2
));
1828 install_var_field (decl2
, true, 3, ctx
);
1829 install_var_local (decl2
, ctx
);
1830 install_var_local (decl
, ctx
);
1834 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1835 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1836 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1837 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1838 install_var_field (decl
, true, 7, ctx
);
1840 install_var_field (decl
, true, 3, ctx
);
1841 if (is_gimple_omp_offloaded (ctx
->stmt
))
1842 install_var_local (decl
, ctx
);
1847 tree base
= get_base_address (decl
);
1848 tree nc
= OMP_CLAUSE_CHAIN (c
);
1851 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1852 && OMP_CLAUSE_DECL (nc
) == base
1853 && OMP_CLAUSE_MAP_KIND (nc
) == GOMP_MAP_POINTER
1854 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1856 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1857 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1863 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1864 decl
= OMP_CLAUSE_DECL (c
);
1866 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1867 (splay_tree_key
) decl
));
1869 = build_decl (OMP_CLAUSE_LOCATION (c
),
1870 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1871 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1872 insert_field_into_struct (ctx
->record_type
, field
);
1873 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1874 (splay_tree_value
) field
);
1879 case OMP_CLAUSE_NOWAIT
:
1880 case OMP_CLAUSE_ORDERED
:
1881 case OMP_CLAUSE_COLLAPSE
:
1882 case OMP_CLAUSE_UNTIED
:
1883 case OMP_CLAUSE_MERGEABLE
:
1884 case OMP_CLAUSE_PROC_BIND
:
1885 case OMP_CLAUSE_SAFELEN
:
1886 case OMP_CLAUSE_ASYNC
:
1887 case OMP_CLAUSE_WAIT
:
1888 case OMP_CLAUSE_GANG
:
1889 case OMP_CLAUSE_WORKER
:
1890 case OMP_CLAUSE_VECTOR
:
1893 case OMP_CLAUSE_ALIGNED
:
1894 decl
= OMP_CLAUSE_DECL (c
);
1895 if (is_global_var (decl
)
1896 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1897 install_var_local (decl
, ctx
);
1900 case OMP_CLAUSE_DEVICE_RESIDENT
:
1901 case OMP_CLAUSE_USE_DEVICE
:
1902 case OMP_CLAUSE__CACHE_
:
1903 case OMP_CLAUSE_INDEPENDENT
:
1904 case OMP_CLAUSE_AUTO
:
1905 case OMP_CLAUSE_SEQ
:
1906 sorry ("Clause not supported yet");
1914 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1916 switch (OMP_CLAUSE_CODE (c
))
1918 case OMP_CLAUSE_LASTPRIVATE
:
1919 /* Let the corresponding firstprivate clause create
1921 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1922 scan_array_reductions
= true;
1923 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1927 case OMP_CLAUSE_FIRSTPRIVATE
:
1928 if (is_gimple_omp_oacc (ctx
->stmt
))
1930 sorry ("clause not supported yet");
1934 case OMP_CLAUSE_PRIVATE
:
1935 case OMP_CLAUSE_REDUCTION
:
1936 case OMP_CLAUSE_LINEAR
:
1937 decl
= OMP_CLAUSE_DECL (c
);
1938 if (is_variable_sized (decl
))
1939 install_var_local (decl
, ctx
);
1940 fixup_remapped_decl (decl
, ctx
,
1941 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1942 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1943 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1944 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1945 scan_array_reductions
= true;
1946 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1947 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1948 scan_array_reductions
= true;
1951 case OMP_CLAUSE_SHARED
:
1952 /* Ignore shared directives in teams construct. */
1953 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1955 decl
= OMP_CLAUSE_DECL (c
);
1956 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1957 fixup_remapped_decl (decl
, ctx
, false);
1960 case OMP_CLAUSE_MAP
:
1961 if (!is_gimple_omp_offloaded (ctx
->stmt
))
1963 decl
= OMP_CLAUSE_DECL (c
);
1965 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1966 && varpool_node::get_create (decl
)->offloadable
)
1970 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1971 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1972 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1974 tree new_decl
= lookup_decl (decl
, ctx
);
1975 TREE_TYPE (new_decl
)
1976 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1978 else if (DECL_SIZE (decl
)
1979 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1981 tree decl2
= DECL_VALUE_EXPR (decl
);
1982 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1983 decl2
= TREE_OPERAND (decl2
, 0);
1984 gcc_assert (DECL_P (decl2
));
1985 fixup_remapped_decl (decl2
, ctx
, false);
1986 fixup_remapped_decl (decl
, ctx
, true);
1989 fixup_remapped_decl (decl
, ctx
, false);
1993 case OMP_CLAUSE_COPYPRIVATE
:
1994 case OMP_CLAUSE_COPYIN
:
1995 case OMP_CLAUSE_DEFAULT
:
1997 case OMP_CLAUSE_NUM_THREADS
:
1998 case OMP_CLAUSE_NUM_TEAMS
:
1999 case OMP_CLAUSE_THREAD_LIMIT
:
2000 case OMP_CLAUSE_DEVICE
:
2001 case OMP_CLAUSE_SCHEDULE
:
2002 case OMP_CLAUSE_DIST_SCHEDULE
:
2003 case OMP_CLAUSE_NOWAIT
:
2004 case OMP_CLAUSE_ORDERED
:
2005 case OMP_CLAUSE_COLLAPSE
:
2006 case OMP_CLAUSE_UNTIED
:
2007 case OMP_CLAUSE_FINAL
:
2008 case OMP_CLAUSE_MERGEABLE
:
2009 case OMP_CLAUSE_PROC_BIND
:
2010 case OMP_CLAUSE_SAFELEN
:
2011 case OMP_CLAUSE_ALIGNED
:
2012 case OMP_CLAUSE_DEPEND
:
2013 case OMP_CLAUSE__LOOPTEMP_
:
2015 case OMP_CLAUSE_FROM
:
2016 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2017 case OMP_CLAUSE_ASYNC
:
2018 case OMP_CLAUSE_WAIT
:
2019 case OMP_CLAUSE_NUM_GANGS
:
2020 case OMP_CLAUSE_NUM_WORKERS
:
2021 case OMP_CLAUSE_VECTOR_LENGTH
:
2022 case OMP_CLAUSE_GANG
:
2023 case OMP_CLAUSE_WORKER
:
2024 case OMP_CLAUSE_VECTOR
:
2027 case OMP_CLAUSE_DEVICE_RESIDENT
:
2028 case OMP_CLAUSE_USE_DEVICE
:
2029 case OMP_CLAUSE__CACHE_
:
2030 case OMP_CLAUSE_INDEPENDENT
:
2031 case OMP_CLAUSE_AUTO
:
2032 case OMP_CLAUSE_SEQ
:
2033 sorry ("Clause not supported yet");
2041 gcc_checking_assert (!scan_array_reductions
2042 || !is_gimple_omp_oacc (ctx
->stmt
));
2043 if (scan_array_reductions
)
2044 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2045 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
2046 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2048 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
2049 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
2051 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2052 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2053 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
2054 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2055 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2056 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
2059 /* Create a new name for omp child function. Returns an identifier. If
2060 IS_CILK_FOR is true then the suffix for the child function is
2064 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
2067 return clone_function_name (current_function_decl
, "_cilk_for_fn");
2068 return clone_function_name (current_function_decl
,
2069 task_copy
? "_omp_cpyfn" : "_omp_fn");
2072 /* Returns the type of the induction variable for the child function for
2073 _Cilk_for and the types for _high and _low variables based on TYPE. */
2076 cilk_for_check_loop_diff_type (tree type
)
2078 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
2080 if (TYPE_UNSIGNED (type
))
2081 return uint32_type_node
;
2083 return integer_type_node
;
2087 if (TYPE_UNSIGNED (type
))
2088 return uint64_type_node
;
2090 return long_long_integer_type_node
;
2094 /* Build a decl for the omp child function. It'll not contain a body
2095 yet, just the bare decl. */
2098 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
2100 tree decl
, type
, name
, t
;
2103 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2104 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2105 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
2106 tree cilk_var_type
= NULL_TREE
;
2108 name
= create_omp_child_function_name (task_copy
,
2109 cilk_for_count
!= NULL_TREE
);
2111 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2112 ptr_type_node
, NULL_TREE
);
2113 else if (cilk_for_count
)
2115 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
2116 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
2117 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2118 cilk_var_type
, cilk_var_type
, NULL_TREE
);
2121 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
2123 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
2125 gcc_checking_assert (!is_gimple_omp_oacc (ctx
->stmt
)
2128 ctx
->cb
.dst_fn
= decl
;
2130 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
2132 TREE_STATIC (decl
) = 1;
2133 TREE_USED (decl
) = 1;
2134 DECL_ARTIFICIAL (decl
) = 1;
2135 DECL_IGNORED_P (decl
) = 0;
2136 TREE_PUBLIC (decl
) = 0;
2137 DECL_UNINLINABLE (decl
) = 1;
2138 DECL_EXTERNAL (decl
) = 0;
2139 DECL_CONTEXT (decl
) = NULL_TREE
;
2140 DECL_INITIAL (decl
) = make_node (BLOCK
);
2141 if (cgraph_node::get (current_function_decl
)->offloadable
)
2142 cgraph_node::get_create (decl
)->offloadable
= 1;
2146 for (octx
= ctx
; octx
; octx
= octx
->outer
)
2147 if (is_gimple_omp_offloaded (octx
->stmt
))
2149 cgraph_node::get_create (decl
)->offloadable
= 1;
2150 #ifdef ENABLE_OFFLOADING
2151 g
->have_offload
= true;
2157 if (cgraph_node::get_create (decl
)->offloadable
2158 && !lookup_attribute ("omp declare target",
2159 DECL_ATTRIBUTES (current_function_decl
)))
2160 DECL_ATTRIBUTES (decl
)
2161 = tree_cons (get_identifier ("omp target entrypoint"),
2162 NULL_TREE
, DECL_ATTRIBUTES (decl
));
2164 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2165 RESULT_DECL
, NULL_TREE
, void_type_node
);
2166 DECL_ARTIFICIAL (t
) = 1;
2167 DECL_IGNORED_P (t
) = 1;
2168 DECL_CONTEXT (t
) = decl
;
2169 DECL_RESULT (decl
) = t
;
2171 /* _Cilk_for's child function requires two extra parameters called
2172 __low and __high that are set the by Cilk runtime when it calls this
2176 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2177 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
2178 DECL_ARTIFICIAL (t
) = 1;
2179 DECL_NAMELESS (t
) = 1;
2180 DECL_ARG_TYPE (t
) = ptr_type_node
;
2181 DECL_CONTEXT (t
) = current_function_decl
;
2183 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2184 DECL_ARGUMENTS (decl
) = t
;
2186 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2187 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
2188 DECL_ARTIFICIAL (t
) = 1;
2189 DECL_NAMELESS (t
) = 1;
2190 DECL_ARG_TYPE (t
) = ptr_type_node
;
2191 DECL_CONTEXT (t
) = current_function_decl
;
2193 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2194 DECL_ARGUMENTS (decl
) = t
;
2197 tree data_name
= get_identifier (".omp_data_i");
2198 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
2200 DECL_ARTIFICIAL (t
) = 1;
2201 DECL_NAMELESS (t
) = 1;
2202 DECL_ARG_TYPE (t
) = ptr_type_node
;
2203 DECL_CONTEXT (t
) = current_function_decl
;
2206 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2207 DECL_ARGUMENTS (decl
) = t
;
2209 ctx
->receiver_decl
= t
;
2212 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2213 PARM_DECL
, get_identifier (".omp_data_o"),
2215 DECL_ARTIFICIAL (t
) = 1;
2216 DECL_NAMELESS (t
) = 1;
2217 DECL_ARG_TYPE (t
) = ptr_type_node
;
2218 DECL_CONTEXT (t
) = current_function_decl
;
2220 TREE_ADDRESSABLE (t
) = 1;
2221 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2222 DECL_ARGUMENTS (decl
) = t
;
2225 /* Allocate memory for the function structure. The call to
2226 allocate_struct_function clobbers CFUN, so we need to restore
2228 push_struct_function (decl
);
2229 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2233 /* Callback for walk_gimple_seq. Check if combined parallel
2234 contains gimple_omp_for_combined_into_p OMP_FOR. */
2237 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2238 bool *handled_ops_p
,
2239 struct walk_stmt_info
*wi
)
2241 gimple stmt
= gsi_stmt (*gsi_p
);
2243 *handled_ops_p
= true;
2244 switch (gimple_code (stmt
))
2248 case GIMPLE_OMP_FOR
:
2249 if (gimple_omp_for_combined_into_p (stmt
)
2250 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
2253 return integer_zero_node
;
2262 /* Scan an OpenMP parallel directive. */
2265 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2269 gomp_parallel
*stmt
= as_a
<gomp_parallel
*> (gsi_stmt (*gsi
));
2271 /* Ignore parallel directives with empty bodies, unless there
2272 are copyin clauses. */
2274 && empty_body_p (gimple_omp_body (stmt
))
2275 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2276 OMP_CLAUSE_COPYIN
) == NULL
)
2278 gsi_replace (gsi
, gimple_build_nop (), false);
2282 if (gimple_omp_parallel_combined_p (stmt
))
2284 struct walk_stmt_info wi
;
2286 memset (&wi
, 0, sizeof (wi
));
2288 walk_gimple_seq (gimple_omp_body (stmt
),
2289 find_combined_for
, NULL
, &wi
);
2292 gomp_for
*for_stmt
= as_a
<gomp_for
*> ((gimple
) wi
.info
);
2293 struct omp_for_data fd
;
2294 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2295 /* We need two temporaries with fd.loop.v type (istart/iend)
2296 and then (fd.collapse - 1) temporaries with the same
2297 type for count2 ... countN-1 vars if not constant. */
2298 size_t count
= 2, i
;
2299 tree type
= fd
.iter_type
;
2301 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2302 count
+= fd
.collapse
- 1;
2303 for (i
= 0; i
< count
; i
++)
2305 tree temp
= create_tmp_var (type
);
2306 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2307 OMP_CLAUSE__LOOPTEMP_
);
2308 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2309 OMP_CLAUSE_DECL (c
) = temp
;
2310 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2311 gimple_omp_parallel_set_clauses (stmt
, c
);
2316 ctx
= new_omp_context (stmt
, outer_ctx
);
2317 taskreg_contexts
.safe_push (ctx
);
2318 if (taskreg_nesting_level
> 1)
2319 ctx
->is_nested
= true;
2320 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2321 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2322 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2323 name
= create_tmp_var_name (".omp_data_s");
2324 name
= build_decl (gimple_location (stmt
),
2325 TYPE_DECL
, name
, ctx
->record_type
);
2326 DECL_ARTIFICIAL (name
) = 1;
2327 DECL_NAMELESS (name
) = 1;
2328 TYPE_NAME (ctx
->record_type
) = name
;
2329 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2330 create_omp_child_function (ctx
, false);
2331 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2333 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2334 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2336 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2337 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2340 /* Scan an OpenMP task directive. */
2343 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2347 gomp_task
*stmt
= as_a
<gomp_task
*> (gsi_stmt (*gsi
));
2349 /* Ignore task directives with empty bodies. */
2351 && empty_body_p (gimple_omp_body (stmt
)))
2353 gsi_replace (gsi
, gimple_build_nop (), false);
2357 ctx
= new_omp_context (stmt
, outer_ctx
);
2358 taskreg_contexts
.safe_push (ctx
);
2359 if (taskreg_nesting_level
> 1)
2360 ctx
->is_nested
= true;
2361 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2362 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2363 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2364 name
= create_tmp_var_name (".omp_data_s");
2365 name
= build_decl (gimple_location (stmt
),
2366 TYPE_DECL
, name
, ctx
->record_type
);
2367 DECL_ARTIFICIAL (name
) = 1;
2368 DECL_NAMELESS (name
) = 1;
2369 TYPE_NAME (ctx
->record_type
) = name
;
2370 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2371 create_omp_child_function (ctx
, false);
2372 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2374 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2376 if (ctx
->srecord_type
)
2378 name
= create_tmp_var_name (".omp_data_a");
2379 name
= build_decl (gimple_location (stmt
),
2380 TYPE_DECL
, name
, ctx
->srecord_type
);
2381 DECL_ARTIFICIAL (name
) = 1;
2382 DECL_NAMELESS (name
) = 1;
2383 TYPE_NAME (ctx
->srecord_type
) = name
;
2384 TYPE_ARTIFICIAL (ctx
->srecord_type
) = 1;
2385 create_omp_child_function (ctx
, true);
2388 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2390 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2392 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2393 t
= build_int_cst (long_integer_type_node
, 0);
2394 gimple_omp_task_set_arg_size (stmt
, t
);
2395 t
= build_int_cst (long_integer_type_node
, 1);
2396 gimple_omp_task_set_arg_align (stmt
, t
);
2401 /* If any decls have been made addressable during scan_omp,
2402 adjust their fields if needed, and layout record types
2403 of parallel/task constructs. */
2406 finish_taskreg_scan (omp_context
*ctx
)
2408 if (ctx
->record_type
== NULL_TREE
)
2411 /* If any task_shared_vars were needed, verify all
2412 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2413 statements if use_pointer_for_field hasn't changed
2414 because of that. If it did, update field types now. */
2415 if (task_shared_vars
)
2419 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2420 c
; c
= OMP_CLAUSE_CHAIN (c
))
2421 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
2423 tree decl
= OMP_CLAUSE_DECL (c
);
2425 /* Global variables don't need to be copied,
2426 the receiver side will use them directly. */
2427 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2429 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2430 || !use_pointer_for_field (decl
, ctx
))
2432 tree field
= lookup_field (decl
, ctx
);
2433 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2434 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2436 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2437 TREE_THIS_VOLATILE (field
) = 0;
2438 DECL_USER_ALIGN (field
) = 0;
2439 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2440 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2441 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2442 if (ctx
->srecord_type
)
2444 tree sfield
= lookup_sfield (decl
, ctx
);
2445 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2446 TREE_THIS_VOLATILE (sfield
) = 0;
2447 DECL_USER_ALIGN (sfield
) = 0;
2448 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2449 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2450 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2455 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2457 layout_type (ctx
->record_type
);
2458 fixup_child_record_type (ctx
);
2462 location_t loc
= gimple_location (ctx
->stmt
);
2463 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2464 /* Move VLA fields to the end. */
2465 p
= &TYPE_FIELDS (ctx
->record_type
);
2467 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2468 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2471 *p
= TREE_CHAIN (*p
);
2472 TREE_CHAIN (*q
) = NULL_TREE
;
2473 q
= &TREE_CHAIN (*q
);
2476 p
= &DECL_CHAIN (*p
);
2478 layout_type (ctx
->record_type
);
2479 fixup_child_record_type (ctx
);
2480 if (ctx
->srecord_type
)
2481 layout_type (ctx
->srecord_type
);
2482 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2483 TYPE_SIZE_UNIT (ctx
->record_type
));
2484 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2485 t
= build_int_cst (long_integer_type_node
,
2486 TYPE_ALIGN_UNIT (ctx
->record_type
));
2487 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2492 static omp_context
*
2493 enclosing_target_ctx (omp_context
*ctx
)
2496 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
2498 gcc_assert (ctx
!= NULL
);
2503 oacc_loop_or_target_p (gimple stmt
)
2505 enum gimple_code outer_type
= gimple_code (stmt
);
2506 return ((outer_type
== GIMPLE_OMP_TARGET
2507 && ((gimple_omp_target_kind (stmt
)
2508 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2509 || (gimple_omp_target_kind (stmt
)
2510 == GF_OMP_TARGET_KIND_OACC_KERNELS
)))
2511 || (outer_type
== GIMPLE_OMP_FOR
2512 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
));
2515 /* Scan a GIMPLE_OMP_FOR. */
2518 scan_omp_for (gomp_for
*stmt
, omp_context
*outer_ctx
)
2520 enum gimple_code outer_type
= GIMPLE_ERROR_MARK
;
2523 tree clauses
= gimple_omp_for_clauses (stmt
);
2526 outer_type
= gimple_code (outer_ctx
->stmt
);
2528 ctx
= new_omp_context (stmt
, outer_ctx
);
2530 if (is_gimple_omp_oacc (stmt
))
2532 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2533 ctx
->gwv_this
= outer_ctx
->gwv_this
;
2534 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2537 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_GANG
)
2539 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WORKER
)
2541 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR
)
2545 ctx
->gwv_this
|= val
;
2548 /* Skip; not nested inside a region. */
2551 if (!oacc_loop_or_target_p (outer_ctx
->stmt
))
2553 /* Skip; not nested inside an OpenACC region. */
2556 if (outer_type
== GIMPLE_OMP_FOR
)
2557 outer_ctx
->gwv_below
|= val
;
2558 if (OMP_CLAUSE_OPERAND (c
, 0) != NULL_TREE
)
2560 omp_context
*enclosing
= enclosing_target_ctx (outer_ctx
);
2561 if (gimple_omp_target_kind (enclosing
->stmt
)
2562 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2563 error_at (gimple_location (stmt
),
2564 "no arguments allowed to gang, worker and vector clauses inside parallel");
2569 scan_sharing_clauses (clauses
, ctx
);
2571 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2572 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2574 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2575 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2576 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2577 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2579 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2581 if (is_gimple_omp_oacc (stmt
))
2583 if (ctx
->gwv_this
& ctx
->gwv_below
)
2584 error_at (gimple_location (stmt
),
2585 "gang, worker and vector may occur only once in a loop nest");
2586 else if (ctx
->gwv_below
!= 0
2587 && ctx
->gwv_this
> ctx
->gwv_below
)
2588 error_at (gimple_location (stmt
),
2589 "gang, worker and vector must occur in this order in a loop nest");
2590 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2591 outer_ctx
->gwv_below
|= ctx
->gwv_below
;
2595 /* Scan an OpenMP sections directive. */
2598 scan_omp_sections (gomp_sections
*stmt
, omp_context
*outer_ctx
)
2602 ctx
= new_omp_context (stmt
, outer_ctx
);
2603 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2604 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2607 /* Scan an OpenMP single directive. */
2610 scan_omp_single (gomp_single
*stmt
, omp_context
*outer_ctx
)
2615 ctx
= new_omp_context (stmt
, outer_ctx
);
2616 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2617 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2618 name
= create_tmp_var_name (".omp_copy_s");
2619 name
= build_decl (gimple_location (stmt
),
2620 TYPE_DECL
, name
, ctx
->record_type
);
2621 TYPE_NAME (ctx
->record_type
) = name
;
2623 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2624 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2626 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2627 ctx
->record_type
= NULL
;
2629 layout_type (ctx
->record_type
);
2632 /* Scan a GIMPLE_OMP_TARGET. */
2635 scan_omp_target (gomp_target
*stmt
, omp_context
*outer_ctx
)
2639 bool offloaded
= is_gimple_omp_offloaded (stmt
);
2640 tree clauses
= gimple_omp_target_clauses (stmt
);
2642 ctx
= new_omp_context (stmt
, outer_ctx
);
2643 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2644 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2645 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2646 name
= create_tmp_var_name (".omp_data_t");
2647 name
= build_decl (gimple_location (stmt
),
2648 TYPE_DECL
, name
, ctx
->record_type
);
2649 DECL_ARTIFICIAL (name
) = 1;
2650 DECL_NAMELESS (name
) = 1;
2651 TYPE_NAME (ctx
->record_type
) = name
;
2652 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2655 if (is_gimple_omp_oacc (stmt
))
2656 ctx
->reduction_map
= splay_tree_new (splay_tree_compare_pointers
,
2659 create_omp_child_function (ctx
, false);
2660 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2663 if (is_gimple_omp_oacc (stmt
))
2665 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2667 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_GANGS
)
2668 ctx
->gwv_this
|= MASK_GANG
;
2669 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_WORKERS
)
2670 ctx
->gwv_this
|= MASK_WORKER
;
2671 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR_LENGTH
)
2672 ctx
->gwv_this
|= MASK_VECTOR
;
2676 scan_sharing_clauses (clauses
, ctx
);
2677 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2679 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2680 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2683 TYPE_FIELDS (ctx
->record_type
)
2684 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2685 #ifdef ENABLE_CHECKING
2687 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2688 for (field
= TYPE_FIELDS (ctx
->record_type
);
2690 field
= DECL_CHAIN (field
))
2691 gcc_assert (DECL_ALIGN (field
) == align
);
2693 layout_type (ctx
->record_type
);
2695 fixup_child_record_type (ctx
);
2699 /* Scan an OpenMP teams directive. */
2702 scan_omp_teams (gomp_teams
*stmt
, omp_context
*outer_ctx
)
2704 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2705 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2706 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2709 /* Check nesting restrictions. */
2711 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2713 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2714 inside an OpenACC CTX. */
2715 if (!(is_gimple_omp (stmt
)
2716 && is_gimple_omp_oacc (stmt
)))
2718 for (omp_context
*ctx_
= ctx
; ctx_
!= NULL
; ctx_
= ctx_
->outer
)
2719 if (is_gimple_omp (ctx_
->stmt
)
2720 && is_gimple_omp_oacc (ctx_
->stmt
))
2722 error_at (gimple_location (stmt
),
2723 "non-OpenACC construct inside of OpenACC region");
2730 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2731 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2733 error_at (gimple_location (stmt
),
2734 "OpenMP constructs may not be nested inside simd region");
2737 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2739 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2740 || (gimple_omp_for_kind (stmt
)
2741 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2742 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2744 error_at (gimple_location (stmt
),
2745 "only distribute or parallel constructs are allowed to "
2746 "be closely nested inside teams construct");
2751 switch (gimple_code (stmt
))
2753 case GIMPLE_OMP_FOR
:
2754 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2756 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2758 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2760 error_at (gimple_location (stmt
),
2761 "distribute construct must be closely nested inside "
2769 if (is_gimple_call (stmt
)
2770 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2771 == BUILT_IN_GOMP_CANCEL
2772 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2773 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2775 const char *bad
= NULL
;
2776 const char *kind
= NULL
;
2779 error_at (gimple_location (stmt
), "orphaned %qs construct",
2780 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2781 == BUILT_IN_GOMP_CANCEL
2782 ? "#pragma omp cancel"
2783 : "#pragma omp cancellation point");
2786 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2787 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2791 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2792 bad
= "#pragma omp parallel";
2793 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2794 == BUILT_IN_GOMP_CANCEL
2795 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2796 ctx
->cancellable
= true;
2800 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2801 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2802 bad
= "#pragma omp for";
2803 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2804 == BUILT_IN_GOMP_CANCEL
2805 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2807 ctx
->cancellable
= true;
2808 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2810 warning_at (gimple_location (stmt
), 0,
2811 "%<#pragma omp cancel for%> inside "
2812 "%<nowait%> for construct");
2813 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2814 OMP_CLAUSE_ORDERED
))
2815 warning_at (gimple_location (stmt
), 0,
2816 "%<#pragma omp cancel for%> inside "
2817 "%<ordered%> for construct");
2822 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2823 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2824 bad
= "#pragma omp sections";
2825 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2826 == BUILT_IN_GOMP_CANCEL
2827 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2829 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2831 ctx
->cancellable
= true;
2832 if (find_omp_clause (gimple_omp_sections_clauses
2835 warning_at (gimple_location (stmt
), 0,
2836 "%<#pragma omp cancel sections%> inside "
2837 "%<nowait%> sections construct");
2841 gcc_assert (ctx
->outer
2842 && gimple_code (ctx
->outer
->stmt
)
2843 == GIMPLE_OMP_SECTIONS
);
2844 ctx
->outer
->cancellable
= true;
2845 if (find_omp_clause (gimple_omp_sections_clauses
2848 warning_at (gimple_location (stmt
), 0,
2849 "%<#pragma omp cancel sections%> inside "
2850 "%<nowait%> sections construct");
2856 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2857 bad
= "#pragma omp task";
2859 ctx
->cancellable
= true;
2863 error_at (gimple_location (stmt
), "invalid arguments");
2868 error_at (gimple_location (stmt
),
2869 "%<%s %s%> construct not closely nested inside of %qs",
2870 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2871 == BUILT_IN_GOMP_CANCEL
2872 ? "#pragma omp cancel"
2873 : "#pragma omp cancellation point", kind
, bad
);
2878 case GIMPLE_OMP_SECTIONS
:
2879 case GIMPLE_OMP_SINGLE
:
2880 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2881 switch (gimple_code (ctx
->stmt
))
2883 case GIMPLE_OMP_FOR
:
2884 case GIMPLE_OMP_SECTIONS
:
2885 case GIMPLE_OMP_SINGLE
:
2886 case GIMPLE_OMP_ORDERED
:
2887 case GIMPLE_OMP_MASTER
:
2888 case GIMPLE_OMP_TASK
:
2889 case GIMPLE_OMP_CRITICAL
:
2890 if (is_gimple_call (stmt
))
2892 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2893 != BUILT_IN_GOMP_BARRIER
)
2895 error_at (gimple_location (stmt
),
2896 "barrier region may not be closely nested inside "
2897 "of work-sharing, critical, ordered, master or "
2898 "explicit task region");
2901 error_at (gimple_location (stmt
),
2902 "work-sharing region may not be closely nested inside "
2903 "of work-sharing, critical, ordered, master or explicit "
2906 case GIMPLE_OMP_PARALLEL
:
2912 case GIMPLE_OMP_MASTER
:
2913 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2914 switch (gimple_code (ctx
->stmt
))
2916 case GIMPLE_OMP_FOR
:
2917 case GIMPLE_OMP_SECTIONS
:
2918 case GIMPLE_OMP_SINGLE
:
2919 case GIMPLE_OMP_TASK
:
2920 error_at (gimple_location (stmt
),
2921 "master region may not be closely nested inside "
2922 "of work-sharing or explicit task region");
2924 case GIMPLE_OMP_PARALLEL
:
2930 case GIMPLE_OMP_ORDERED
:
2931 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2932 switch (gimple_code (ctx
->stmt
))
2934 case GIMPLE_OMP_CRITICAL
:
2935 case GIMPLE_OMP_TASK
:
2936 error_at (gimple_location (stmt
),
2937 "ordered region may not be closely nested inside "
2938 "of critical or explicit task region");
2940 case GIMPLE_OMP_FOR
:
2941 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2942 OMP_CLAUSE_ORDERED
) == NULL
)
2944 error_at (gimple_location (stmt
),
2945 "ordered region must be closely nested inside "
2946 "a loop region with an ordered clause");
2950 case GIMPLE_OMP_PARALLEL
:
2951 error_at (gimple_location (stmt
),
2952 "ordered region must be closely nested inside "
2953 "a loop region with an ordered clause");
2959 case GIMPLE_OMP_CRITICAL
:
2962 = gimple_omp_critical_name (as_a
<gomp_critical
*> (stmt
));
2963 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2964 if (gomp_critical
*other_crit
2965 = dyn_cast
<gomp_critical
*> (ctx
->stmt
))
2966 if (this_stmt_name
== gimple_omp_critical_name (other_crit
))
2968 error_at (gimple_location (stmt
),
2969 "critical region may not be nested inside a critical "
2970 "region with the same name");
2975 case GIMPLE_OMP_TEAMS
:
2977 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2978 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2980 error_at (gimple_location (stmt
),
2981 "teams construct not closely nested inside of target "
2986 case GIMPLE_OMP_TARGET
:
2987 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2989 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
2991 if (is_gimple_omp (stmt
)
2992 && is_gimple_omp_oacc (stmt
)
2993 && is_gimple_omp (ctx
->stmt
))
2995 error_at (gimple_location (stmt
),
2996 "OpenACC construct inside of non-OpenACC region");
3002 const char *stmt_name
, *ctx_stmt_name
;
3003 switch (gimple_omp_target_kind (stmt
))
3005 case GF_OMP_TARGET_KIND_REGION
: stmt_name
= "target"; break;
3006 case GF_OMP_TARGET_KIND_DATA
: stmt_name
= "target data"; break;
3007 case GF_OMP_TARGET_KIND_UPDATE
: stmt_name
= "target update"; break;
3008 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: stmt_name
= "parallel"; break;
3009 case GF_OMP_TARGET_KIND_OACC_KERNELS
: stmt_name
= "kernels"; break;
3010 case GF_OMP_TARGET_KIND_OACC_DATA
: stmt_name
= "data"; break;
3011 case GF_OMP_TARGET_KIND_OACC_UPDATE
: stmt_name
= "update"; break;
3012 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
: stmt_name
= "enter/exit data"; break;
3013 default: gcc_unreachable ();
3015 switch (gimple_omp_target_kind (ctx
->stmt
))
3017 case GF_OMP_TARGET_KIND_REGION
: ctx_stmt_name
= "target"; break;
3018 case GF_OMP_TARGET_KIND_DATA
: ctx_stmt_name
= "target data"; break;
3019 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: ctx_stmt_name
= "parallel"; break;
3020 case GF_OMP_TARGET_KIND_OACC_KERNELS
: ctx_stmt_name
= "kernels"; break;
3021 case GF_OMP_TARGET_KIND_OACC_DATA
: ctx_stmt_name
= "data"; break;
3022 default: gcc_unreachable ();
3025 /* OpenACC/OpenMP mismatch? */
3026 if (is_gimple_omp_oacc (stmt
)
3027 != is_gimple_omp_oacc (ctx
->stmt
))
3029 error_at (gimple_location (stmt
),
3030 "%s %s construct inside of %s %s region",
3031 (is_gimple_omp_oacc (stmt
)
3032 ? "OpenACC" : "OpenMP"), stmt_name
,
3033 (is_gimple_omp_oacc (ctx
->stmt
)
3034 ? "OpenACC" : "OpenMP"), ctx_stmt_name
);
3037 if (is_gimple_omp_offloaded (ctx
->stmt
))
3039 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3040 if (is_gimple_omp_oacc (ctx
->stmt
))
3042 error_at (gimple_location (stmt
),
3043 "%s construct inside of %s region",
3044 stmt_name
, ctx_stmt_name
);
3049 gcc_checking_assert (!is_gimple_omp_oacc (stmt
));
3050 warning_at (gimple_location (stmt
), 0,
3051 "%s construct inside of %s region",
3052 stmt_name
, ctx_stmt_name
);
3064 /* Helper function scan_omp.
3066 Callback for walk_tree or operators in walk_gimple_stmt used to
3067 scan for OMP directives in TP. */
3070 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
3072 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
3073 omp_context
*ctx
= (omp_context
*) wi
->info
;
3076 switch (TREE_CODE (t
))
3083 *tp
= remap_decl (t
, &ctx
->cb
);
3087 if (ctx
&& TYPE_P (t
))
3088 *tp
= remap_type (t
, &ctx
->cb
);
3089 else if (!DECL_P (t
))
3094 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
3095 if (tem
!= TREE_TYPE (t
))
3097 if (TREE_CODE (t
) == INTEGER_CST
)
3098 *tp
= wide_int_to_tree (tem
, t
);
3100 TREE_TYPE (t
) = tem
;
3110 /* Return true if FNDECL is a setjmp or a longjmp. */
3113 setjmp_or_longjmp_p (const_tree fndecl
)
3115 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
3116 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
3117 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
3120 tree declname
= DECL_NAME (fndecl
);
3123 const char *name
= IDENTIFIER_POINTER (declname
);
3124 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
3128 /* Helper function for scan_omp.
3130 Callback for walk_gimple_stmt used to scan for OMP directives in
3131 the current statement in GSI. */
3134 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
3135 struct walk_stmt_info
*wi
)
3137 gimple stmt
= gsi_stmt (*gsi
);
3138 omp_context
*ctx
= (omp_context
*) wi
->info
;
3140 if (gimple_has_location (stmt
))
3141 input_location
= gimple_location (stmt
);
3143 /* Check the nesting restrictions. */
3144 bool remove
= false;
3145 if (is_gimple_omp (stmt
))
3146 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3147 else if (is_gimple_call (stmt
))
3149 tree fndecl
= gimple_call_fndecl (stmt
);
3152 if (setjmp_or_longjmp_p (fndecl
)
3154 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3155 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3158 error_at (gimple_location (stmt
),
3159 "setjmp/longjmp inside simd construct");
3161 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
3162 switch (DECL_FUNCTION_CODE (fndecl
))
3164 case BUILT_IN_GOMP_BARRIER
:
3165 case BUILT_IN_GOMP_CANCEL
:
3166 case BUILT_IN_GOMP_CANCELLATION_POINT
:
3167 case BUILT_IN_GOMP_TASKYIELD
:
3168 case BUILT_IN_GOMP_TASKWAIT
:
3169 case BUILT_IN_GOMP_TASKGROUP_START
:
3170 case BUILT_IN_GOMP_TASKGROUP_END
:
3171 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3180 stmt
= gimple_build_nop ();
3181 gsi_replace (gsi
, stmt
, false);
3184 *handled_ops_p
= true;
3186 switch (gimple_code (stmt
))
3188 case GIMPLE_OMP_PARALLEL
:
3189 taskreg_nesting_level
++;
3190 scan_omp_parallel (gsi
, ctx
);
3191 taskreg_nesting_level
--;
3194 case GIMPLE_OMP_TASK
:
3195 taskreg_nesting_level
++;
3196 scan_omp_task (gsi
, ctx
);
3197 taskreg_nesting_level
--;
3200 case GIMPLE_OMP_FOR
:
3201 scan_omp_for (as_a
<gomp_for
*> (stmt
), ctx
);
3204 case GIMPLE_OMP_SECTIONS
:
3205 scan_omp_sections (as_a
<gomp_sections
*> (stmt
), ctx
);
3208 case GIMPLE_OMP_SINGLE
:
3209 scan_omp_single (as_a
<gomp_single
*> (stmt
), ctx
);
3212 case GIMPLE_OMP_SECTION
:
3213 case GIMPLE_OMP_MASTER
:
3214 case GIMPLE_OMP_TASKGROUP
:
3215 case GIMPLE_OMP_ORDERED
:
3216 case GIMPLE_OMP_CRITICAL
:
3217 ctx
= new_omp_context (stmt
, ctx
);
3218 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3221 case GIMPLE_OMP_TARGET
:
3222 scan_omp_target (as_a
<gomp_target
*> (stmt
), ctx
);
3225 case GIMPLE_OMP_TEAMS
:
3226 scan_omp_teams (as_a
<gomp_teams
*> (stmt
), ctx
);
3233 *handled_ops_p
= false;
3235 for (var
= gimple_bind_vars (as_a
<gbind
*> (stmt
));
3237 var
= DECL_CHAIN (var
))
3238 insert_decl_map (&ctx
->cb
, var
, var
);
3242 *handled_ops_p
= false;
3250 /* Scan all the statements starting at the current statement. CTX
3251 contains context information about the OMP directives and
3252 clauses found during the scan. */
3255 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
3257 location_t saved_location
;
3258 struct walk_stmt_info wi
;
3260 memset (&wi
, 0, sizeof (wi
));
3262 wi
.want_locations
= true;
3264 saved_location
= input_location
;
3265 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
3266 input_location
= saved_location
;
3269 /* Re-gimplification and code generation routines. */
3271 /* Build a call to GOMP_barrier. */
3274 build_omp_barrier (tree lhs
)
3276 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
3277 : BUILT_IN_GOMP_BARRIER
);
3278 gcall
*g
= gimple_build_call (fndecl
, 0);
3280 gimple_call_set_lhs (g
, lhs
);
3284 /* If a context was created for STMT when it was scanned, return it. */
3286 static omp_context
*
3287 maybe_lookup_ctx (gimple stmt
)
3290 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
3291 return n
? (omp_context
*) n
->value
: NULL
;
3295 /* Find the mapping for DECL in CTX or the immediately enclosing
3296 context that has a mapping for DECL.
3298 If CTX is a nested parallel directive, we may have to use the decl
3299 mappings created in CTX's parent context. Suppose that we have the
3300 following parallel nesting (variable UIDs showed for clarity):
3303 #omp parallel shared(iD.1562) -> outer parallel
3304 iD.1562 = iD.1562 + 1;
3306 #omp parallel shared (iD.1562) -> inner parallel
3307 iD.1562 = iD.1562 - 1;
3309 Each parallel structure will create a distinct .omp_data_s structure
3310 for copying iD.1562 in/out of the directive:
3312 outer parallel .omp_data_s.1.i -> iD.1562
3313 inner parallel .omp_data_s.2.i -> iD.1562
3315 A shared variable mapping will produce a copy-out operation before
3316 the parallel directive and a copy-in operation after it. So, in
3317 this case we would have:
3320 .omp_data_o.1.i = iD.1562;
3321 #omp parallel shared(iD.1562) -> outer parallel
3322 .omp_data_i.1 = &.omp_data_o.1
3323 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3325 .omp_data_o.2.i = iD.1562; -> **
3326 #omp parallel shared(iD.1562) -> inner parallel
3327 .omp_data_i.2 = &.omp_data_o.2
3328 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3331 ** This is a problem. The symbol iD.1562 cannot be referenced
3332 inside the body of the outer parallel region. But since we are
3333 emitting this copy operation while expanding the inner parallel
3334 directive, we need to access the CTX structure of the outer
3335 parallel directive to get the correct mapping:
3337 .omp_data_o.2.i = .omp_data_i.1->i
3339 Since there may be other workshare or parallel directives enclosing
3340 the parallel directive, it may be necessary to walk up the context
3341 parent chain. This is not a problem in general because nested
3342 parallelism happens only rarely. */
3345 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3350 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3351 t
= maybe_lookup_decl (decl
, up
);
3353 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
3355 return t
? t
: decl
;
3359 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3360 in outer contexts. */
3363 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3368 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3369 t
= maybe_lookup_decl (decl
, up
);
3371 return t
? t
: decl
;
3375 /* Construct the initialization value for reduction CLAUSE. */
3378 omp_reduction_init (tree clause
, tree type
)
3380 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
3381 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
3388 case TRUTH_ORIF_EXPR
:
3389 case TRUTH_XOR_EXPR
:
3391 return build_zero_cst (type
);
3394 case TRUTH_AND_EXPR
:
3395 case TRUTH_ANDIF_EXPR
:
3397 return fold_convert_loc (loc
, type
, integer_one_node
);
3400 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3403 if (SCALAR_FLOAT_TYPE_P (type
))
3405 REAL_VALUE_TYPE max
, min
;
3406 if (HONOR_INFINITIES (type
))
3409 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3412 real_maxval (&min
, 1, TYPE_MODE (type
));
3413 return build_real (type
, min
);
3415 else if (POINTER_TYPE_P (type
))
3418 = wi::min_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
3419 return wide_int_to_tree (type
, min
);
3423 gcc_assert (INTEGRAL_TYPE_P (type
));
3424 return TYPE_MIN_VALUE (type
);
3428 if (SCALAR_FLOAT_TYPE_P (type
))
3430 REAL_VALUE_TYPE max
;
3431 if (HONOR_INFINITIES (type
))
3434 real_maxval (&max
, 0, TYPE_MODE (type
));
3435 return build_real (type
, max
);
3437 else if (POINTER_TYPE_P (type
))
3440 = wi::max_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
3441 return wide_int_to_tree (type
, max
);
3445 gcc_assert (INTEGRAL_TYPE_P (type
));
3446 return TYPE_MAX_VALUE (type
);
3454 /* Return alignment to be assumed for var in CLAUSE, which should be
3455 OMP_CLAUSE_ALIGNED. */
3458 omp_clause_aligned_alignment (tree clause
)
3460 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3461 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3463 /* Otherwise return implementation defined alignment. */
3464 unsigned int al
= 1;
3465 machine_mode mode
, vmode
;
3466 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3468 vs
= 1 << floor_log2 (vs
);
3469 static enum mode_class classes
[]
3470 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3471 for (int i
= 0; i
< 4; i
+= 2)
3472 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3474 mode
= GET_MODE_WIDER_MODE (mode
))
3476 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3477 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3480 && GET_MODE_SIZE (vmode
) < vs
3481 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3482 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3484 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3485 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3487 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3488 / GET_MODE_SIZE (mode
));
3489 if (TYPE_MODE (type
) != vmode
)
3491 if (TYPE_ALIGN_UNIT (type
) > al
)
3492 al
= TYPE_ALIGN_UNIT (type
);
3494 return build_int_cst (integer_type_node
, al
);
3497 /* Return maximum possible vectorization factor for the target. */
3504 || !flag_tree_loop_optimize
3505 || (!flag_tree_loop_vectorize
3506 && (global_options_set
.x_flag_tree_loop_vectorize
3507 || global_options_set
.x_flag_tree_vectorize
)))
3510 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3513 vs
= 1 << floor_log2 (vs
);
3516 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
3517 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
3518 return GET_MODE_NUNITS (vqimode
);
3522 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3526 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
3527 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
3531 max_vf
= omp_max_vf ();
3534 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3535 OMP_CLAUSE_SAFELEN
);
3536 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3538 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3540 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3544 idx
= create_tmp_var (unsigned_type_node
);
3545 lane
= create_tmp_var (unsigned_type_node
);
3551 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3552 tree avar
= create_tmp_var_raw (atype
);
3553 if (TREE_ADDRESSABLE (new_var
))
3554 TREE_ADDRESSABLE (avar
) = 1;
3555 DECL_ATTRIBUTES (avar
)
3556 = tree_cons (get_identifier ("omp simd array"), NULL
,
3557 DECL_ATTRIBUTES (avar
));
3558 gimple_add_tmp_var (avar
);
3559 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3560 NULL_TREE
, NULL_TREE
);
3561 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3562 NULL_TREE
, NULL_TREE
);
3563 if (DECL_P (new_var
))
3565 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3566 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3571 /* Helper function of lower_rec_input_clauses. For a reference
3572 in simd reduction, add an underlying variable it will reference. */
3575 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3577 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3578 if (TREE_CONSTANT (z
))
3580 const char *name
= NULL
;
3581 if (DECL_NAME (new_vard
))
3582 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3584 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3585 gimple_add_tmp_var (z
);
3586 TREE_ADDRESSABLE (z
) = 1;
3587 z
= build_fold_addr_expr_loc (loc
, z
);
3588 gimplify_assign (new_vard
, z
, ilist
);
3592 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3593 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3594 private variables. Initialization statements go in ILIST, while calls
3595 to destructors go in DLIST. */
3598 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3599 omp_context
*ctx
, struct omp_for_data
*fd
)
3601 tree c
, dtor
, copyin_seq
, x
, ptr
;
3602 bool copyin_by_ref
= false;
3603 bool lastprivate_firstprivate
= false;
3604 bool reduction_omp_orig_ref
= false;
3606 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3607 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3609 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3610 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3611 gimple_seq llist
[2] = { NULL
, NULL
};
3615 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3616 with data sharing clauses referencing variable sized vars. That
3617 is unnecessarily hard to support and very unlikely to result in
3618 vectorized code anyway. */
3620 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3621 switch (OMP_CLAUSE_CODE (c
))
3623 case OMP_CLAUSE_LINEAR
:
3624 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3627 case OMP_CLAUSE_REDUCTION
:
3628 case OMP_CLAUSE_PRIVATE
:
3629 case OMP_CLAUSE_FIRSTPRIVATE
:
3630 case OMP_CLAUSE_LASTPRIVATE
:
3631 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3638 /* Do all the fixed sized types in the first pass, and the variable sized
3639 types in the second pass. This makes sure that the scalar arguments to
3640 the variable sized types are processed before we use them in the
3641 variable sized operations. */
3642 for (pass
= 0; pass
< 2; ++pass
)
3644 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3646 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3649 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3653 case OMP_CLAUSE_PRIVATE
:
3654 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3657 case OMP_CLAUSE_SHARED
:
3658 /* Ignore shared directives in teams construct. */
3659 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3661 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3663 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3666 case OMP_CLAUSE_FIRSTPRIVATE
:
3667 case OMP_CLAUSE_COPYIN
:
3668 case OMP_CLAUSE_LINEAR
:
3670 case OMP_CLAUSE_REDUCTION
:
3671 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3672 reduction_omp_orig_ref
= true;
3674 case OMP_CLAUSE__LOOPTEMP_
:
3675 /* Handle _looptemp_ clauses only on parallel. */
3679 case OMP_CLAUSE_LASTPRIVATE
:
3680 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3682 lastprivate_firstprivate
= true;
3686 /* Even without corresponding firstprivate, if
3687 decl is Fortran allocatable, it needs outer var
3690 && lang_hooks
.decls
.omp_private_outer_ref
3691 (OMP_CLAUSE_DECL (c
)))
3692 lastprivate_firstprivate
= true;
3694 case OMP_CLAUSE_ALIGNED
:
3697 var
= OMP_CLAUSE_DECL (c
);
3698 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3699 && !is_global_var (var
))
3701 new_var
= maybe_lookup_decl (var
, ctx
);
3702 if (new_var
== NULL_TREE
)
3703 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3704 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3705 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3706 omp_clause_aligned_alignment (c
));
3707 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3708 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3709 gimplify_and_add (x
, ilist
);
3711 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3712 && is_global_var (var
))
3714 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3715 new_var
= lookup_decl (var
, ctx
);
3716 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3717 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3718 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3719 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3720 omp_clause_aligned_alignment (c
));
3721 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3722 x
= create_tmp_var (ptype
);
3723 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3724 gimplify_and_add (t
, ilist
);
3725 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3726 SET_DECL_VALUE_EXPR (new_var
, t
);
3727 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3734 new_var
= var
= OMP_CLAUSE_DECL (c
);
3735 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3736 new_var
= lookup_decl (var
, ctx
);
3738 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3743 else if (is_variable_sized (var
))
3745 /* For variable sized types, we need to allocate the
3746 actual storage here. Call alloca and store the
3747 result in the pointer decl that we created elsewhere. */
3751 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3756 ptr
= DECL_VALUE_EXPR (new_var
);
3757 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3758 ptr
= TREE_OPERAND (ptr
, 0);
3759 gcc_assert (DECL_P (ptr
));
3760 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3762 /* void *tmp = __builtin_alloca */
3763 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3764 stmt
= gimple_build_call (atmp
, 1, x
);
3765 tmp
= create_tmp_var_raw (ptr_type_node
);
3766 gimple_add_tmp_var (tmp
);
3767 gimple_call_set_lhs (stmt
, tmp
);
3769 gimple_seq_add_stmt (ilist
, stmt
);
3771 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3772 gimplify_assign (ptr
, x
, ilist
);
3775 else if (is_reference (var
))
3777 /* For references that are being privatized for Fortran,
3778 allocate new backing storage for the new pointer
3779 variable. This allows us to avoid changing all the
3780 code that expects a pointer to something that expects
3781 a direct variable. */
3785 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3786 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3788 x
= build_receiver_ref (var
, false, ctx
);
3789 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3791 else if (TREE_CONSTANT (x
))
3793 /* For reduction in SIMD loop, defer adding the
3794 initialization of the reference, because if we decide
3795 to use SIMD array for it, the initilization could cause
3797 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3801 const char *name
= NULL
;
3802 if (DECL_NAME (var
))
3803 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3805 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3807 gimple_add_tmp_var (x
);
3808 TREE_ADDRESSABLE (x
) = 1;
3809 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3814 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3815 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3820 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3821 gimplify_assign (new_var
, x
, ilist
);
3824 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3826 else if (c_kind
== OMP_CLAUSE_REDUCTION
3827 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3835 switch (OMP_CLAUSE_CODE (c
))
3837 case OMP_CLAUSE_SHARED
:
3838 /* Ignore shared directives in teams construct. */
3839 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3841 /* Shared global vars are just accessed directly. */
3842 if (is_global_var (new_var
))
3844 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3845 needs to be delayed until after fixup_child_record_type so
3846 that we get the correct type during the dereference. */
3847 by_ref
= use_pointer_for_field (var
, ctx
);
3848 x
= build_receiver_ref (var
, by_ref
, ctx
);
3849 SET_DECL_VALUE_EXPR (new_var
, x
);
3850 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3852 /* ??? If VAR is not passed by reference, and the variable
3853 hasn't been initialized yet, then we'll get a warning for
3854 the store into the omp_data_s structure. Ideally, we'd be
3855 able to notice this and not store anything at all, but
3856 we're generating code too early. Suppress the warning. */
3858 TREE_NO_WARNING (var
) = 1;
3861 case OMP_CLAUSE_LASTPRIVATE
:
3862 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3866 case OMP_CLAUSE_PRIVATE
:
3867 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3868 x
= build_outer_var_ref (var
, ctx
);
3869 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3871 if (is_task_ctx (ctx
))
3872 x
= build_receiver_ref (var
, false, ctx
);
3874 x
= build_outer_var_ref (var
, ctx
);
3880 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3883 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3884 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3885 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3886 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3887 idx
, lane
, ivar
, lvar
))
3890 x
= lang_hooks
.decls
.omp_clause_default_ctor
3891 (c
, unshare_expr (ivar
), x
);
3893 gimplify_and_add (x
, &llist
[0]);
3896 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3899 gimple_seq tseq
= NULL
;
3902 gimplify_stmt (&dtor
, &tseq
);
3903 gimple_seq_add_seq (&llist
[1], tseq
);
3910 gimplify_and_add (nx
, ilist
);
3914 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3917 gimple_seq tseq
= NULL
;
3920 gimplify_stmt (&dtor
, &tseq
);
3921 gimple_seq_add_seq (dlist
, tseq
);
3925 case OMP_CLAUSE_LINEAR
:
3926 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3927 goto do_firstprivate
;
3928 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3931 x
= build_outer_var_ref (var
, ctx
);
3934 case OMP_CLAUSE_FIRSTPRIVATE
:
3935 if (is_task_ctx (ctx
))
3937 if (is_reference (var
) || is_variable_sized (var
))
3939 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3941 || use_pointer_for_field (var
, NULL
))
3943 x
= build_receiver_ref (var
, false, ctx
);
3944 SET_DECL_VALUE_EXPR (new_var
, x
);
3945 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3950 x
= build_outer_var_ref (var
, ctx
);
3953 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3954 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3956 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3957 tree stept
= TREE_TYPE (t
);
3958 tree ct
= find_omp_clause (clauses
,
3959 OMP_CLAUSE__LOOPTEMP_
);
3961 tree l
= OMP_CLAUSE_DECL (ct
);
3962 tree n1
= fd
->loop
.n1
;
3963 tree step
= fd
->loop
.step
;
3964 tree itype
= TREE_TYPE (l
);
3965 if (POINTER_TYPE_P (itype
))
3966 itype
= signed_type_for (itype
);
3967 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3968 if (TYPE_UNSIGNED (itype
)
3969 && fd
->loop
.cond_code
== GT_EXPR
)
3970 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3971 fold_build1 (NEGATE_EXPR
, itype
, l
),
3972 fold_build1 (NEGATE_EXPR
,
3975 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3976 t
= fold_build2 (MULT_EXPR
, stept
,
3977 fold_convert (stept
, l
), t
);
3979 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3981 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3983 gimplify_and_add (x
, ilist
);
3987 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3988 x
= fold_build2 (POINTER_PLUS_EXPR
,
3989 TREE_TYPE (x
), x
, t
);
3991 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3994 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3995 || TREE_ADDRESSABLE (new_var
))
3996 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3997 idx
, lane
, ivar
, lvar
))
3999 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
4001 tree iv
= create_tmp_var (TREE_TYPE (new_var
));
4002 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
4003 gimplify_and_add (x
, ilist
);
4004 gimple_stmt_iterator gsi
4005 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4007 = gimple_build_assign (unshare_expr (lvar
), iv
);
4008 gsi_insert_before_without_update (&gsi
, g
,
4010 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
4011 enum tree_code code
= PLUS_EXPR
;
4012 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
4013 code
= POINTER_PLUS_EXPR
;
4014 g
= gimple_build_assign (iv
, code
, iv
, t
);
4015 gsi_insert_before_without_update (&gsi
, g
,
4019 x
= lang_hooks
.decls
.omp_clause_copy_ctor
4020 (c
, unshare_expr (ivar
), x
);
4021 gimplify_and_add (x
, &llist
[0]);
4022 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4025 gimple_seq tseq
= NULL
;
4028 gimplify_stmt (&dtor
, &tseq
);
4029 gimple_seq_add_seq (&llist
[1], tseq
);
4034 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
4035 gimplify_and_add (x
, ilist
);
4038 case OMP_CLAUSE__LOOPTEMP_
:
4039 gcc_assert (is_parallel_ctx (ctx
));
4040 x
= build_outer_var_ref (var
, ctx
);
4041 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
4042 gimplify_and_add (x
, ilist
);
4045 case OMP_CLAUSE_COPYIN
:
4046 by_ref
= use_pointer_for_field (var
, NULL
);
4047 x
= build_receiver_ref (var
, by_ref
, ctx
);
4048 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
4049 append_to_statement_list (x
, ©in_seq
);
4050 copyin_by_ref
|= by_ref
;
4053 case OMP_CLAUSE_REDUCTION
:
4054 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4056 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4058 x
= build_outer_var_ref (var
, ctx
);
4060 if (is_reference (var
)
4061 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4063 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4064 SET_DECL_VALUE_EXPR (placeholder
, x
);
4065 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4066 tree new_vard
= new_var
;
4067 if (is_reference (var
))
4069 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4070 new_vard
= TREE_OPERAND (new_var
, 0);
4071 gcc_assert (DECL_P (new_vard
));
4074 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4075 idx
, lane
, ivar
, lvar
))
4077 if (new_vard
== new_var
)
4079 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
4080 SET_DECL_VALUE_EXPR (new_var
, ivar
);
4084 SET_DECL_VALUE_EXPR (new_vard
,
4085 build_fold_addr_expr (ivar
));
4086 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4088 x
= lang_hooks
.decls
.omp_clause_default_ctor
4089 (c
, unshare_expr (ivar
),
4090 build_outer_var_ref (var
, ctx
));
4092 gimplify_and_add (x
, &llist
[0]);
4093 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4095 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4096 lower_omp (&tseq
, ctx
);
4097 gimple_seq_add_seq (&llist
[0], tseq
);
4099 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4100 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4101 lower_omp (&tseq
, ctx
);
4102 gimple_seq_add_seq (&llist
[1], tseq
);
4103 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4104 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4105 if (new_vard
== new_var
)
4106 SET_DECL_VALUE_EXPR (new_var
, lvar
);
4108 SET_DECL_VALUE_EXPR (new_vard
,
4109 build_fold_addr_expr (lvar
));
4110 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4115 gimplify_stmt (&dtor
, &tseq
);
4116 gimple_seq_add_seq (&llist
[1], tseq
);
4120 /* If this is a reference to constant size reduction var
4121 with placeholder, we haven't emitted the initializer
4122 for it because it is undesirable if SIMD arrays are used.
4123 But if they aren't used, we need to emit the deferred
4124 initialization now. */
4125 else if (is_reference (var
) && is_simd
)
4126 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4127 x
= lang_hooks
.decls
.omp_clause_default_ctor
4128 (c
, unshare_expr (new_var
),
4129 build_outer_var_ref (var
, ctx
));
4131 gimplify_and_add (x
, ilist
);
4132 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4134 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4135 lower_omp (&tseq
, ctx
);
4136 gimple_seq_add_seq (ilist
, tseq
);
4138 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4141 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4142 lower_omp (&tseq
, ctx
);
4143 gimple_seq_add_seq (dlist
, tseq
);
4144 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4146 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4151 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
4152 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
4153 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4155 /* reduction(-:var) sums up the partial results, so it
4156 acts identically to reduction(+:var). */
4157 if (code
== MINUS_EXPR
)
4160 tree new_vard
= new_var
;
4161 if (is_simd
&& is_reference (var
))
4163 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4164 new_vard
= TREE_OPERAND (new_var
, 0);
4165 gcc_assert (DECL_P (new_vard
));
4168 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4169 idx
, lane
, ivar
, lvar
))
4171 tree ref
= build_outer_var_ref (var
, ctx
);
4173 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
4175 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
4176 ref
= build_outer_var_ref (var
, ctx
);
4177 gimplify_assign (ref
, x
, &llist
[1]);
4179 if (new_vard
!= new_var
)
4181 SET_DECL_VALUE_EXPR (new_vard
,
4182 build_fold_addr_expr (lvar
));
4183 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4188 if (is_reference (var
) && is_simd
)
4189 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4190 gimplify_assign (new_var
, x
, ilist
);
4193 tree ref
= build_outer_var_ref (var
, ctx
);
4195 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4196 ref
= build_outer_var_ref (var
, ctx
);
4197 gimplify_assign (ref
, x
, dlist
);
4211 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
4212 /* Don't want uninit warnings on simduid, it is always uninitialized,
4213 but we use it not for the value, but for the DECL_UID only. */
4214 TREE_NO_WARNING (uid
) = 1;
4216 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
4217 gimple_call_set_lhs (g
, lane
);
4218 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4219 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
4220 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
4221 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
4222 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4223 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4224 g
= gimple_build_assign (lane
, INTEGER_CST
,
4225 build_int_cst (unsigned_type_node
, 0));
4226 gimple_seq_add_stmt (ilist
, g
);
4227 for (int i
= 0; i
< 2; i
++)
4230 tree vf
= create_tmp_var (unsigned_type_node
);
4231 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
4232 gimple_call_set_lhs (g
, vf
);
4233 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
4234 gimple_seq_add_stmt (seq
, g
);
4235 tree t
= build_int_cst (unsigned_type_node
, 0);
4236 g
= gimple_build_assign (idx
, INTEGER_CST
, t
);
4237 gimple_seq_add_stmt (seq
, g
);
4238 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
4239 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
4240 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
4241 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
4242 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
4243 gimple_seq_add_seq (seq
, llist
[i
]);
4244 t
= build_int_cst (unsigned_type_node
, 1);
4245 g
= gimple_build_assign (idx
, PLUS_EXPR
, idx
, t
);
4246 gimple_seq_add_stmt (seq
, g
);
4247 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
4248 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
4249 gimple_seq_add_stmt (seq
, g
);
4250 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
4254 /* The copyin sequence is not to be executed by the main thread, since
4255 that would result in self-copies. Perhaps not visible to scalars,
4256 but it certainly is to C++ operator=. */
4259 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
4261 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
4262 build_int_cst (TREE_TYPE (x
), 0));
4263 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
4264 gimplify_and_add (x
, ilist
);
4267 /* If any copyin variable is passed by reference, we must ensure the
4268 master thread doesn't modify it before it is copied over in all
4269 threads. Similarly for variables in both firstprivate and
4270 lastprivate clauses we need to ensure the lastprivate copying
4271 happens after firstprivate copying in all threads. And similarly
4272 for UDRs if initializer expression refers to omp_orig. */
4273 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
4275 /* Don't add any barrier for #pragma omp simd or
4276 #pragma omp distribute. */
4277 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
4278 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
4279 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
4282 /* If max_vf is non-zero, then we can use only a vectorization factor
4283 up to the max_vf we chose. So stick it into the safelen clause. */
4286 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
4287 OMP_CLAUSE_SAFELEN
);
4289 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
4290 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
4293 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
4294 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
4296 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4297 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4303 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4304 both parallel and workshare constructs. PREDICATE may be NULL if it's
4308 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
4311 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
4312 bool par_clauses
= false;
4313 tree simduid
= NULL
, lastlane
= NULL
;
4315 /* Early exit if there are no lastprivate or linear clauses. */
4316 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
4317 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
4318 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
4319 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
4321 if (clauses
== NULL
)
4323 /* If this was a workshare clause, see if it had been combined
4324 with its parallel. In that case, look for the clauses on the
4325 parallel statement itself. */
4326 if (is_parallel_ctx (ctx
))
4330 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4333 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4334 OMP_CLAUSE_LASTPRIVATE
);
4335 if (clauses
== NULL
)
4343 tree label_true
, arm1
, arm2
;
4345 label
= create_artificial_label (UNKNOWN_LOCATION
);
4346 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
4347 arm1
= TREE_OPERAND (predicate
, 0);
4348 arm2
= TREE_OPERAND (predicate
, 1);
4349 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4350 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4351 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
4353 gimple_seq_add_stmt (stmt_list
, stmt
);
4354 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
4357 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4358 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4360 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
4362 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
4365 for (c
= clauses
; c
;)
4368 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4370 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4371 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4372 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
4374 var
= OMP_CLAUSE_DECL (c
);
4375 new_var
= lookup_decl (var
, ctx
);
4377 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
4379 tree val
= DECL_VALUE_EXPR (new_var
);
4380 if (TREE_CODE (val
) == ARRAY_REF
4381 && VAR_P (TREE_OPERAND (val
, 0))
4382 && lookup_attribute ("omp simd array",
4383 DECL_ATTRIBUTES (TREE_OPERAND (val
,
4386 if (lastlane
== NULL
)
4388 lastlane
= create_tmp_var (unsigned_type_node
);
4390 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
4392 TREE_OPERAND (val
, 1));
4393 gimple_call_set_lhs (g
, lastlane
);
4394 gimple_seq_add_stmt (stmt_list
, g
);
4396 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
4397 TREE_OPERAND (val
, 0), lastlane
,
4398 NULL_TREE
, NULL_TREE
);
4402 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4403 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
4405 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
4406 gimple_seq_add_seq (stmt_list
,
4407 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
4408 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
4410 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4411 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
4413 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
4414 gimple_seq_add_seq (stmt_list
,
4415 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
4416 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
4419 x
= build_outer_var_ref (var
, ctx
);
4420 if (is_reference (var
))
4421 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4422 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
4423 gimplify_and_add (x
, stmt_list
);
4425 c
= OMP_CLAUSE_CHAIN (c
);
4426 if (c
== NULL
&& !par_clauses
)
4428 /* If this was a workshare clause, see if it had been combined
4429 with its parallel. In that case, continue looking for the
4430 clauses also on the parallel statement itself. */
4431 if (is_parallel_ctx (ctx
))
4435 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4438 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4439 OMP_CLAUSE_LASTPRIVATE
);
4445 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
4449 oacc_lower_reduction_var_helper (gimple_seq
*stmt_seqp
, omp_context
*ctx
,
4450 tree tid
, tree var
, tree new_var
)
4452 /* The atomic add at the end of the sum creates unnecessary
4453 write contention on accelerators. To work around this,
4454 create an array to store the partial reductions. Later, in
4455 lower_omp_for (for openacc), the values of array will be
4458 tree t
= NULL_TREE
, array
, x
;
4459 tree type
= get_base_type (var
);
4462 /* Now insert the partial reductions into the array. */
4464 /* Find the reduction array. */
4466 tree ptype
= build_pointer_type (type
);
4468 t
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
), ctx
);
4469 t
= build_receiver_ref (t
, false, ctx
->outer
);
4471 array
= create_tmp_var (ptype
);
4472 gimplify_assign (array
, t
, stmt_seqp
);
4474 tree ptr
= create_tmp_var (TREE_TYPE (array
));
4476 /* Find the reduction array. */
4478 /* testing a unary conversion. */
4479 tree offset
= create_tmp_var (sizetype
);
4480 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
),
4482 t
= create_tmp_var (sizetype
);
4483 gimplify_assign (t
, unshare_expr (fold_build1 (NOP_EXPR
, sizetype
, tid
)),
4485 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, t
);
4486 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4488 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4489 of adding sizeof(var) to the array? */
4490 ptr
= create_tmp_var (ptype
);
4491 stmt
= gimple_build_assign (unshare_expr (ptr
), POINTER_PLUS_EXPR
, array
,
4493 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4495 /* Move the local sum to gfc$sum[i]. */
4496 x
= unshare_expr (build_simple_mem_ref (ptr
));
4497 stmt
= gimplify_assign (x
, new_var
, stmt_seqp
);
4500 /* Generate code to implement the REDUCTION clauses. */
4503 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
4505 gimple_seq sub_seq
= NULL
;
4507 tree x
, c
, tid
= NULL_TREE
;
4510 /* SIMD reductions are handled in lower_rec_input_clauses. */
4511 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4512 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4515 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4516 update in that case, otherwise use a lock. */
4517 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
4518 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
4520 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4522 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4532 /* Initialize thread info for OpenACC. */
4533 if (is_gimple_omp_oacc (ctx
->stmt
))
4535 /* Get the current thread id. */
4536 tree call
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
4537 tid
= create_tmp_var (TREE_TYPE (TREE_TYPE (call
)));
4538 gimple stmt
= gimple_build_call (call
, 0);
4539 gimple_call_set_lhs (stmt
, tid
);
4540 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4543 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4545 tree var
, ref
, new_var
;
4546 enum tree_code code
;
4547 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4549 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
4552 var
= OMP_CLAUSE_DECL (c
);
4553 new_var
= lookup_decl (var
, ctx
);
4554 if (is_reference (var
))
4555 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4556 ref
= build_outer_var_ref (var
, ctx
);
4557 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4559 /* reduction(-:var) sums up the partial results, so it acts
4560 identically to reduction(+:var). */
4561 if (code
== MINUS_EXPR
)
4564 if (is_gimple_omp_oacc (ctx
->stmt
))
4566 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
));
4568 oacc_lower_reduction_var_helper (stmt_seqp
, ctx
, tid
, var
, new_var
);
4570 else if (count
== 1)
4572 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
4574 addr
= save_expr (addr
);
4575 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
4576 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
4577 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
4578 gimplify_and_add (x
, stmt_seqp
);
4581 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4583 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4585 if (is_reference (var
)
4586 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4588 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
4589 SET_DECL_VALUE_EXPR (placeholder
, ref
);
4590 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4591 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
4592 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
4593 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4594 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
4598 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4599 ref
= build_outer_var_ref (var
, ctx
);
4600 gimplify_assign (ref
, x
, &sub_seq
);
4604 if (is_gimple_omp_oacc (ctx
->stmt
))
4607 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4609 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4611 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4613 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4615 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4619 /* Generate code to implement the COPYPRIVATE clauses. */
4622 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4627 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4629 tree var
, new_var
, ref
, x
;
4631 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4633 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4636 var
= OMP_CLAUSE_DECL (c
);
4637 by_ref
= use_pointer_for_field (var
, NULL
);
4639 ref
= build_sender_ref (var
, ctx
);
4640 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4643 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4644 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4646 gimplify_assign (ref
, x
, slist
);
4648 ref
= build_receiver_ref (var
, false, ctx
);
4651 ref
= fold_convert_loc (clause_loc
,
4652 build_pointer_type (TREE_TYPE (new_var
)),
4654 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4656 if (is_reference (var
))
4658 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4659 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4660 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4662 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4663 gimplify_and_add (x
, rlist
);
4668 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4669 and REDUCTION from the sender (aka parent) side. */
4672 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4677 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4679 tree val
, ref
, x
, var
;
4680 bool by_ref
, do_in
= false, do_out
= false;
4681 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4683 switch (OMP_CLAUSE_CODE (c
))
4685 case OMP_CLAUSE_PRIVATE
:
4686 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4689 case OMP_CLAUSE_FIRSTPRIVATE
:
4690 case OMP_CLAUSE_COPYIN
:
4691 case OMP_CLAUSE_LASTPRIVATE
:
4692 case OMP_CLAUSE_REDUCTION
:
4693 case OMP_CLAUSE__LOOPTEMP_
:
4699 val
= OMP_CLAUSE_DECL (c
);
4700 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4702 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4703 && is_global_var (var
))
4705 if (is_variable_sized (val
))
4707 by_ref
= use_pointer_for_field (val
, NULL
);
4709 switch (OMP_CLAUSE_CODE (c
))
4711 case OMP_CLAUSE_PRIVATE
:
4712 case OMP_CLAUSE_FIRSTPRIVATE
:
4713 case OMP_CLAUSE_COPYIN
:
4714 case OMP_CLAUSE__LOOPTEMP_
:
4718 case OMP_CLAUSE_LASTPRIVATE
:
4719 if (by_ref
|| is_reference (val
))
4721 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4728 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4733 case OMP_CLAUSE_REDUCTION
:
4735 do_out
= !(by_ref
|| is_reference (val
));
4744 ref
= build_sender_ref (val
, ctx
);
4745 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4746 gimplify_assign (ref
, x
, ilist
);
4747 if (is_task_ctx (ctx
))
4748 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4753 ref
= build_sender_ref (val
, ctx
);
4754 gimplify_assign (var
, ref
, olist
);
4759 /* Generate code to implement SHARED from the sender (aka parent)
4760 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4761 list things that got automatically shared. */
4764 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4766 tree var
, ovar
, nvar
, f
, x
, record_type
;
4768 if (ctx
->record_type
== NULL
)
4771 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4772 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4774 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4775 nvar
= maybe_lookup_decl (ovar
, ctx
);
4776 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4779 /* If CTX is a nested parallel directive. Find the immediately
4780 enclosing parallel or workshare construct that contains a
4781 mapping for OVAR. */
4782 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4784 if (use_pointer_for_field (ovar
, ctx
))
4786 x
= build_sender_ref (ovar
, ctx
);
4787 var
= build_fold_addr_expr (var
);
4788 gimplify_assign (x
, var
, ilist
);
4792 x
= build_sender_ref (ovar
, ctx
);
4793 gimplify_assign (x
, var
, ilist
);
4795 if (!TREE_READONLY (var
)
4796 /* We don't need to receive a new reference to a result
4797 or parm decl. In fact we may not store to it as we will
4798 invalidate any pending RSO and generate wrong gimple
4800 && !((TREE_CODE (var
) == RESULT_DECL
4801 || TREE_CODE (var
) == PARM_DECL
)
4802 && DECL_BY_REFERENCE (var
)))
4804 x
= build_sender_ref (ovar
, ctx
);
4805 gimplify_assign (var
, x
, olist
);
4812 /* A convenience function to build an empty GIMPLE_COND with just the
4816 gimple_build_cond_empty (tree cond
)
4818 enum tree_code pred_code
;
4821 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4822 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4826 /* Build the function calls to GOMP_parallel_start etc to actually
4827 generate the parallel operation. REGION is the parallel region
4828 being expanded. BB is the block where to insert the code. WS_ARGS
4829 will be set if this is a call to a combined parallel+workshare
4830 construct, it contains the list of additional arguments needed by
4831 the workshare construct. */
4834 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4835 gomp_parallel
*entry_stmt
,
4836 vec
<tree
, va_gc
> *ws_args
)
4838 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4839 gimple_stmt_iterator gsi
;
4841 enum built_in_function start_ix
;
4843 location_t clause_loc
;
4844 vec
<tree
, va_gc
> *args
;
4846 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4848 /* Determine what flavor of GOMP_parallel we will be
4850 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4851 if (is_combined_parallel (region
))
4853 switch (region
->inner
->type
)
4855 case GIMPLE_OMP_FOR
:
4856 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4857 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4858 + (region
->inner
->sched_kind
4859 == OMP_CLAUSE_SCHEDULE_RUNTIME
4860 ? 3 : region
->inner
->sched_kind
));
4861 start_ix
= (enum built_in_function
)start_ix2
;
4863 case GIMPLE_OMP_SECTIONS
:
4864 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4871 /* By default, the value of NUM_THREADS is zero (selected at run time)
4872 and there is no conditional. */
4874 val
= build_int_cst (unsigned_type_node
, 0);
4875 flags
= build_int_cst (unsigned_type_node
, 0);
4877 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4879 cond
= OMP_CLAUSE_IF_EXPR (c
);
4881 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4884 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4885 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4888 clause_loc
= gimple_location (entry_stmt
);
4890 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4892 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4894 /* Ensure 'val' is of the correct type. */
4895 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4897 /* If we found the clause 'if (cond)', build either
4898 (cond != 0) or (cond ? val : 1u). */
4901 cond
= gimple_boolify (cond
);
4903 if (integer_zerop (val
))
4904 val
= fold_build2_loc (clause_loc
,
4905 EQ_EXPR
, unsigned_type_node
, cond
,
4906 build_int_cst (TREE_TYPE (cond
), 0));
4909 basic_block cond_bb
, then_bb
, else_bb
;
4910 edge e
, e_then
, e_else
;
4911 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4913 tmp_var
= create_tmp_var (TREE_TYPE (val
));
4914 if (gimple_in_ssa_p (cfun
))
4916 tmp_then
= make_ssa_name (tmp_var
);
4917 tmp_else
= make_ssa_name (tmp_var
);
4918 tmp_join
= make_ssa_name (tmp_var
);
4927 e
= split_block_after_labels (bb
);
4932 then_bb
= create_empty_bb (cond_bb
);
4933 else_bb
= create_empty_bb (then_bb
);
4934 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4935 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4937 stmt
= gimple_build_cond_empty (cond
);
4938 gsi
= gsi_start_bb (cond_bb
);
4939 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4941 gsi
= gsi_start_bb (then_bb
);
4942 stmt
= gimple_build_assign (tmp_then
, val
);
4943 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4945 gsi
= gsi_start_bb (else_bb
);
4946 stmt
= gimple_build_assign
4947 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4948 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4950 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4951 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4952 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4953 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4954 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4955 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4957 if (gimple_in_ssa_p (cfun
))
4959 gphi
*phi
= create_phi_node (tmp_join
, bb
);
4960 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4961 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4967 gsi
= gsi_start_bb (bb
);
4968 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4969 false, GSI_CONTINUE_LINKING
);
4972 gsi
= gsi_last_bb (bb
);
4973 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4975 t1
= null_pointer_node
;
4977 t1
= build_fold_addr_expr (t
);
4978 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4980 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4981 args
->quick_push (t2
);
4982 args
->quick_push (t1
);
4983 args
->quick_push (val
);
4985 args
->splice (*ws_args
);
4986 args
->quick_push (flags
);
4988 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4989 builtin_decl_explicit (start_ix
), args
);
4991 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4992 false, GSI_CONTINUE_LINKING
);
4995 /* Insert a function call whose name is FUNC_NAME with the information from
4996 ENTRY_STMT into the basic_block BB. */
4999 expand_cilk_for_call (basic_block bb
, gomp_parallel
*entry_stmt
,
5000 vec
<tree
, va_gc
> *ws_args
)
5003 gimple_stmt_iterator gsi
;
5004 vec
<tree
, va_gc
> *args
;
5006 gcc_assert (vec_safe_length (ws_args
) == 2);
5007 tree func_name
= (*ws_args
)[0];
5008 tree grain
= (*ws_args
)[1];
5010 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
5011 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
5012 gcc_assert (count
!= NULL_TREE
);
5013 count
= OMP_CLAUSE_OPERAND (count
, 0);
5015 gsi
= gsi_last_bb (bb
);
5016 t
= gimple_omp_parallel_data_arg (entry_stmt
);
5018 t1
= null_pointer_node
;
5020 t1
= build_fold_addr_expr (t
);
5021 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
5023 vec_alloc (args
, 4);
5024 args
->quick_push (t2
);
5025 args
->quick_push (t1
);
5026 args
->quick_push (count
);
5027 args
->quick_push (grain
);
5028 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
5030 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
5031 GSI_CONTINUE_LINKING
);
5034 /* Build the function call to GOMP_task to actually
5035 generate the task operation. BB is the block where to insert the code. */
5038 expand_task_call (basic_block bb
, gomp_task
*entry_stmt
)
5040 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
5041 gimple_stmt_iterator gsi
;
5042 location_t loc
= gimple_location (entry_stmt
);
5044 clauses
= gimple_omp_task_clauses (entry_stmt
);
5046 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
5048 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
5050 cond
= boolean_true_node
;
5052 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
5053 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
5054 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
5055 flags
= build_int_cst (unsigned_type_node
,
5056 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
5058 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
5061 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
5062 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
5063 build_int_cst (unsigned_type_node
, 2),
5064 build_int_cst (unsigned_type_node
, 0));
5065 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
5068 depend
= OMP_CLAUSE_DECL (depend
);
5070 depend
= build_int_cst (ptr_type_node
, 0);
5072 gsi
= gsi_last_bb (bb
);
5073 t
= gimple_omp_task_data_arg (entry_stmt
);
5075 t2
= null_pointer_node
;
5077 t2
= build_fold_addr_expr_loc (loc
, t
);
5078 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
5079 t
= gimple_omp_task_copy_fn (entry_stmt
);
5081 t3
= null_pointer_node
;
5083 t3
= build_fold_addr_expr_loc (loc
, t
);
5085 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
5087 gimple_omp_task_arg_size (entry_stmt
),
5088 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
5091 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5092 false, GSI_CONTINUE_LINKING
);
5096 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5097 catch handler and return it. This prevents programs from violating the
5098 structured block semantics with throws. */
5101 maybe_catch_exception (gimple_seq body
)
5106 if (!flag_exceptions
)
5109 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
5110 decl
= lang_hooks
.eh_protect_cleanup_actions ();
5112 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
5114 g
= gimple_build_eh_must_not_throw (decl
);
5115 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
5118 return gimple_seq_alloc_with_stmt (g
);
5121 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5124 vec2chain (vec
<tree
, va_gc
> *v
)
5126 tree chain
= NULL_TREE
, t
;
5129 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
5131 DECL_CHAIN (t
) = chain
;
5139 /* Remove barriers in REGION->EXIT's block. Note that this is only
5140 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5141 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5142 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5146 remove_exit_barrier (struct omp_region
*region
)
5148 gimple_stmt_iterator gsi
;
5149 basic_block exit_bb
;
5153 int any_addressable_vars
= -1;
5155 exit_bb
= region
->exit
;
5157 /* If the parallel region doesn't return, we don't have REGION->EXIT
5162 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5163 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5164 statements that can appear in between are extremely limited -- no
5165 memory operations at all. Here, we allow nothing at all, so the
5166 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5167 gsi
= gsi_last_bb (exit_bb
);
5168 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5170 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
5173 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
5175 gsi
= gsi_last_bb (e
->src
);
5176 if (gsi_end_p (gsi
))
5178 stmt
= gsi_stmt (gsi
);
5179 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
5180 && !gimple_omp_return_nowait_p (stmt
))
5182 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5183 in many cases. If there could be tasks queued, the barrier
5184 might be needed to let the tasks run before some local
5185 variable of the parallel that the task uses as shared
5186 runs out of scope. The task can be spawned either
5187 from within current function (this would be easy to check)
5188 or from some function it calls and gets passed an address
5189 of such a variable. */
5190 if (any_addressable_vars
< 0)
5192 gomp_parallel
*parallel_stmt
5193 = as_a
<gomp_parallel
*> (last_stmt (region
->entry
));
5194 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
5195 tree local_decls
, block
, decl
;
5198 any_addressable_vars
= 0;
5199 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
5200 if (TREE_ADDRESSABLE (decl
))
5202 any_addressable_vars
= 1;
5205 for (block
= gimple_block (stmt
);
5206 !any_addressable_vars
5208 && TREE_CODE (block
) == BLOCK
;
5209 block
= BLOCK_SUPERCONTEXT (block
))
5211 for (local_decls
= BLOCK_VARS (block
);
5213 local_decls
= DECL_CHAIN (local_decls
))
5214 if (TREE_ADDRESSABLE (local_decls
))
5216 any_addressable_vars
= 1;
5219 if (block
== gimple_block (parallel_stmt
))
5223 if (!any_addressable_vars
)
5224 gimple_omp_return_set_nowait (stmt
);
5230 remove_exit_barriers (struct omp_region
*region
)
5232 if (region
->type
== GIMPLE_OMP_PARALLEL
)
5233 remove_exit_barrier (region
);
5237 region
= region
->inner
;
5238 remove_exit_barriers (region
);
5239 while (region
->next
)
5241 region
= region
->next
;
5242 remove_exit_barriers (region
);
5247 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5248 calls. These can't be declared as const functions, but
5249 within one parallel body they are constant, so they can be
5250 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5251 which are declared const. Similarly for task body, except
5252 that in untied task omp_get_thread_num () can change at any task
5253 scheduling point. */
5256 optimize_omp_library_calls (gimple entry_stmt
)
5259 gimple_stmt_iterator gsi
;
5260 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5261 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
5262 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5263 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
5264 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
5265 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
5266 OMP_CLAUSE_UNTIED
) != NULL
);
5268 FOR_EACH_BB_FN (bb
, cfun
)
5269 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5271 gimple call
= gsi_stmt (gsi
);
5274 if (is_gimple_call (call
)
5275 && (decl
= gimple_call_fndecl (call
))
5276 && DECL_EXTERNAL (decl
)
5277 && TREE_PUBLIC (decl
)
5278 && DECL_INITIAL (decl
) == NULL
)
5282 if (DECL_NAME (decl
) == thr_num_id
)
5284 /* In #pragma omp task untied omp_get_thread_num () can change
5285 during the execution of the task region. */
5288 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5290 else if (DECL_NAME (decl
) == num_thr_id
)
5291 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5295 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
5296 || gimple_call_num_args (call
) != 0)
5299 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
5302 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
5303 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
5304 TREE_TYPE (TREE_TYPE (built_in
))))
5307 gimple_call_set_fndecl (call
, built_in
);
5312 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5316 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
5320 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5321 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
5324 if (TREE_CODE (t
) == ADDR_EXPR
)
5325 recompute_tree_invariant_for_addr_expr (t
);
5327 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
5331 /* Prepend TO = FROM assignment before *GSI_P. */
5334 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
5336 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
5337 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
5338 true, GSI_SAME_STMT
);
5339 gimple stmt
= gimple_build_assign (to
, from
);
5340 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
5341 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
5342 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
5344 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
5345 gimple_regimplify_operands (stmt
, &gsi
);
5349 /* Expand the OpenMP parallel or task directive starting at REGION. */
5352 expand_omp_taskreg (struct omp_region
*region
)
5354 basic_block entry_bb
, exit_bb
, new_bb
;
5355 struct function
*child_cfun
;
5356 tree child_fn
, block
, t
;
5357 gimple_stmt_iterator gsi
;
5358 gimple entry_stmt
, stmt
;
5360 vec
<tree
, va_gc
> *ws_args
;
5362 entry_stmt
= last_stmt (region
->entry
);
5363 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
5364 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
5366 entry_bb
= region
->entry
;
5367 if (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
)
5368 exit_bb
= region
->cont
;
5370 exit_bb
= region
->exit
;
5374 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
5375 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
5376 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
5379 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5380 and the inner statement contains the name of the built-in function
5382 ws_args
= region
->inner
->ws_args
;
5383 else if (is_combined_parallel (region
))
5384 ws_args
= region
->ws_args
;
5388 if (child_cfun
->cfg
)
5390 /* Due to inlining, it may happen that we have already outlined
5391 the region, in which case all we need to do is make the
5392 sub-graph unreachable and emit the parallel call. */
5393 edge entry_succ_e
, exit_succ_e
;
5395 entry_succ_e
= single_succ_edge (entry_bb
);
5397 gsi
= gsi_last_bb (entry_bb
);
5398 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
5399 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
5400 gsi_remove (&gsi
, true);
5405 exit_succ_e
= single_succ_edge (exit_bb
);
5406 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
5408 remove_edge_and_dominated_blocks (entry_succ_e
);
5412 unsigned srcidx
, dstidx
, num
;
5414 /* If the parallel region needs data sent from the parent
5415 function, then the very first statement (except possible
5416 tree profile counter updates) of the parallel body
5417 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5418 &.OMP_DATA_O is passed as an argument to the child function,
5419 we need to replace it with the argument as seen by the child
5422 In most cases, this will end up being the identity assignment
5423 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5424 a function call that has been inlined, the original PARM_DECL
5425 .OMP_DATA_I may have been converted into a different local
5426 variable. In which case, we need to keep the assignment. */
5427 if (gimple_omp_taskreg_data_arg (entry_stmt
))
5429 basic_block entry_succ_bb
5430 = single_succ_p (entry_bb
) ? single_succ (entry_bb
)
5431 : FALLTHRU_EDGE (entry_bb
)->dest
;
5433 gimple parcopy_stmt
= NULL
;
5435 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
5439 gcc_assert (!gsi_end_p (gsi
));
5440 stmt
= gsi_stmt (gsi
);
5441 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
5444 if (gimple_num_ops (stmt
) == 2)
5446 tree arg
= gimple_assign_rhs1 (stmt
);
5448 /* We're ignore the subcode because we're
5449 effectively doing a STRIP_NOPS. */
5451 if (TREE_CODE (arg
) == ADDR_EXPR
5452 && TREE_OPERAND (arg
, 0)
5453 == gimple_omp_taskreg_data_arg (entry_stmt
))
5455 parcopy_stmt
= stmt
;
5461 gcc_assert (parcopy_stmt
!= NULL
);
5462 arg
= DECL_ARGUMENTS (child_fn
);
5464 if (!gimple_in_ssa_p (cfun
))
5466 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
5467 gsi_remove (&gsi
, true);
5470 /* ?? Is setting the subcode really necessary ?? */
5471 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
5472 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
5477 tree lhs
= gimple_assign_lhs (parcopy_stmt
);
5478 gcc_assert (SSA_NAME_VAR (lhs
) == arg
);
5479 /* We'd like to set the rhs to the default def in the child_fn,
5480 but it's too early to create ssa names in the child_fn.
5481 Instead, we set the rhs to the parm. In
5482 move_sese_region_to_fn, we introduce a default def for the
5483 parm, map the parm to it's default def, and once we encounter
5484 this stmt, replace the parm with the default def. */
5485 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
5486 update_stmt (parcopy_stmt
);
5490 /* Declare local variables needed in CHILD_CFUN. */
5491 block
= DECL_INITIAL (child_fn
);
5492 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
5493 /* The gimplifier could record temporaries in parallel/task block
5494 rather than in containing function's local_decls chain,
5495 which would mean cgraph missed finalizing them. Do it now. */
5496 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
5497 if (TREE_CODE (t
) == VAR_DECL
5499 && !DECL_EXTERNAL (t
))
5500 varpool_node::finalize_decl (t
);
5501 DECL_SAVED_TREE (child_fn
) = NULL
;
5502 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5503 gimple_set_body (child_fn
, NULL
);
5504 TREE_USED (block
) = 1;
5506 /* Reset DECL_CONTEXT on function arguments. */
5507 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
5508 DECL_CONTEXT (t
) = child_fn
;
5510 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5511 so that it can be moved to the child function. */
5512 gsi
= gsi_last_bb (entry_bb
);
5513 stmt
= gsi_stmt (gsi
);
5514 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
5515 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
5516 e
= split_block (entry_bb
, stmt
);
5517 gsi_remove (&gsi
, true);
5520 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5521 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5524 e2
= make_edge (e
->src
, BRANCH_EDGE (entry_bb
)->dest
, EDGE_ABNORMAL
);
5525 gcc_assert (e2
->dest
== region
->exit
);
5526 remove_edge (BRANCH_EDGE (entry_bb
));
5527 set_immediate_dominator (CDI_DOMINATORS
, e2
->dest
, e
->src
);
5528 gsi
= gsi_last_bb (region
->exit
);
5529 gcc_assert (!gsi_end_p (gsi
)
5530 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5531 gsi_remove (&gsi
, true);
5534 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5537 gsi
= gsi_last_bb (exit_bb
);
5538 gcc_assert (!gsi_end_p (gsi
)
5539 && (gimple_code (gsi_stmt (gsi
))
5540 == (e2
? GIMPLE_OMP_CONTINUE
: GIMPLE_OMP_RETURN
)));
5541 stmt
= gimple_build_return (NULL
);
5542 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5543 gsi_remove (&gsi
, true);
5546 /* Move the parallel region into CHILD_CFUN. */
5548 if (gimple_in_ssa_p (cfun
))
5550 init_tree_ssa (child_cfun
);
5551 init_ssa_operands (child_cfun
);
5552 child_cfun
->gimple_df
->in_ssa_p
= true;
5556 block
= gimple_block (entry_stmt
);
5558 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
5560 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
5563 basic_block dest_bb
= e2
->dest
;
5565 make_edge (new_bb
, dest_bb
, EDGE_FALLTHRU
);
5567 set_immediate_dominator (CDI_DOMINATORS
, dest_bb
, new_bb
);
5569 /* When the OMP expansion process cannot guarantee an up-to-date
5570 loop tree arrange for the child function to fixup loops. */
5571 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5572 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
5574 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5575 num
= vec_safe_length (child_cfun
->local_decls
);
5576 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
5578 t
= (*child_cfun
->local_decls
)[srcidx
];
5579 if (DECL_CONTEXT (t
) == cfun
->decl
)
5581 if (srcidx
!= dstidx
)
5582 (*child_cfun
->local_decls
)[dstidx
] = t
;
5586 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
5588 /* Inform the callgraph about the new function. */
5589 child_cfun
->curr_properties
= cfun
->curr_properties
;
5590 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
5591 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
5592 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
5593 node
->parallelized_function
= 1;
5594 cgraph_node::add_new_function (child_fn
, true);
5596 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5597 fixed in a following pass. */
5598 push_cfun (child_cfun
);
5600 optimize_omp_library_calls (entry_stmt
);
5601 cgraph_edge::rebuild_edges ();
5603 /* Some EH regions might become dead, see PR34608. If
5604 pass_cleanup_cfg isn't the first pass to happen with the
5605 new child, these dead EH edges might cause problems.
5606 Clean them up now. */
5607 if (flag_exceptions
)
5610 bool changed
= false;
5612 FOR_EACH_BB_FN (bb
, cfun
)
5613 changed
|= gimple_purge_dead_eh_edges (bb
);
5615 cleanup_tree_cfg ();
5617 if (gimple_in_ssa_p (cfun
))
5618 update_ssa (TODO_update_ssa
);
5619 #ifdef ENABLE_CHECKING
5620 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5621 verify_loop_structure ();
5626 /* Emit a library call to launch the children threads. */
5628 expand_cilk_for_call (new_bb
,
5629 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5630 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5631 expand_parallel_call (region
, new_bb
,
5632 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5634 expand_task_call (new_bb
, as_a
<gomp_task
*> (entry_stmt
));
5635 if (gimple_in_ssa_p (cfun
))
5636 update_ssa (TODO_update_ssa_only_virtuals
);
5640 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5641 of the combined collapse > 1 loop constructs, generate code like:
5642 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5647 count3 = (adj + N32 - N31) / STEP3;
5648 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5653 count2 = (adj + N22 - N21) / STEP2;
5654 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5659 count1 = (adj + N12 - N11) / STEP1;
5660 count = count1 * count2 * count3;
5661 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5663 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5664 of the combined loop constructs, just initialize COUNTS array
5665 from the _looptemp_ clauses. */
5667 /* NOTE: It *could* be better to moosh all of the BBs together,
5668 creating one larger BB with all the computation and the unexpected
5669 jump at the end. I.e.
5671 bool zero3, zero2, zero1, zero;
5674 count3 = (N32 - N31) /[cl] STEP3;
5676 count2 = (N22 - N21) /[cl] STEP2;
5678 count1 = (N12 - N11) /[cl] STEP1;
5679 zero = zero3 || zero2 || zero1;
5680 count = count1 * count2 * count3;
5681 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5683 After all, we expect the zero=false, and thus we expect to have to
5684 evaluate all of the comparison expressions, so short-circuiting
5685 oughtn't be a win. Since the condition isn't protecting a
5686 denominator, we're not concerned about divide-by-zero, so we can
5687 fully evaluate count even if a numerator turned out to be wrong.
5689 It seems like putting this all together would create much better
5690 scheduling opportunities, and less pressure on the chip's branch
5694 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5695 basic_block
&entry_bb
, tree
*counts
,
5696 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5697 basic_block
&l2_dom_bb
)
5699 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5703 /* Collapsed loops need work for expansion into SSA form. */
5704 gcc_assert (!gimple_in_ssa_p (cfun
));
5706 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5707 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5709 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5710 isn't supposed to be handled, as the inner loop doesn't
5712 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5713 OMP_CLAUSE__LOOPTEMP_
);
5714 gcc_assert (innerc
);
5715 for (i
= 0; i
< fd
->collapse
; i
++)
5717 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5718 OMP_CLAUSE__LOOPTEMP_
);
5719 gcc_assert (innerc
);
5721 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5723 counts
[0] = NULL_TREE
;
5728 for (i
= 0; i
< fd
->collapse
; i
++)
5730 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5732 if (SSA_VAR_P (fd
->loop
.n2
)
5733 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5734 fold_convert (itype
, fd
->loops
[i
].n1
),
5735 fold_convert (itype
, fd
->loops
[i
].n2
)))
5736 == NULL_TREE
|| !integer_onep (t
)))
5740 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5741 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5742 true, GSI_SAME_STMT
);
5743 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5744 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5745 true, GSI_SAME_STMT
);
5746 cond_stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5747 NULL_TREE
, NULL_TREE
);
5748 gsi_insert_before (gsi
, cond_stmt
, GSI_SAME_STMT
);
5749 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
5750 expand_omp_regimplify_p
, NULL
, NULL
)
5751 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
5752 expand_omp_regimplify_p
, NULL
, NULL
))
5754 *gsi
= gsi_for_stmt (cond_stmt
);
5755 gimple_regimplify_operands (cond_stmt
, gsi
);
5757 e
= split_block (entry_bb
, cond_stmt
);
5758 if (zero_iter_bb
== NULL
)
5760 gassign
*assign_stmt
;
5761 first_zero_iter
= i
;
5762 zero_iter_bb
= create_empty_bb (entry_bb
);
5763 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5764 *gsi
= gsi_after_labels (zero_iter_bb
);
5765 assign_stmt
= gimple_build_assign (fd
->loop
.n2
,
5766 build_zero_cst (type
));
5767 gsi_insert_before (gsi
, assign_stmt
, GSI_SAME_STMT
);
5768 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5771 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5772 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5773 e
->flags
= EDGE_TRUE_VALUE
;
5774 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5775 if (l2_dom_bb
== NULL
)
5776 l2_dom_bb
= entry_bb
;
5778 *gsi
= gsi_last_bb (entry_bb
);
5781 if (POINTER_TYPE_P (itype
))
5782 itype
= signed_type_for (itype
);
5783 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5785 t
= fold_build2 (PLUS_EXPR
, itype
,
5786 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5787 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5788 fold_convert (itype
, fd
->loops
[i
].n2
));
5789 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5790 fold_convert (itype
, fd
->loops
[i
].n1
));
5791 /* ?? We could probably use CEIL_DIV_EXPR instead of
5792 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5793 generate the same code in the end because generically we
5794 don't know that the values involved must be negative for
5796 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5797 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5798 fold_build1 (NEGATE_EXPR
, itype
, t
),
5799 fold_build1 (NEGATE_EXPR
, itype
,
5800 fold_convert (itype
,
5801 fd
->loops
[i
].step
)));
5803 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5804 fold_convert (itype
, fd
->loops
[i
].step
));
5805 t
= fold_convert (type
, t
);
5806 if (TREE_CODE (t
) == INTEGER_CST
)
5810 counts
[i
] = create_tmp_reg (type
, ".count");
5811 expand_omp_build_assign (gsi
, counts
[i
], t
);
5813 if (SSA_VAR_P (fd
->loop
.n2
))
5818 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5819 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5825 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5827 V3 = N31 + (T % count3) * STEP3;
5829 V2 = N21 + (T % count2) * STEP2;
5831 V1 = N11 + T * STEP1;
5832 if this loop doesn't have an inner loop construct combined with it.
5833 If it does have an inner loop construct combined with it and the
5834 iteration count isn't known constant, store values from counts array
5835 into its _looptemp_ temporaries instead. */
5838 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5839 tree
*counts
, gimple inner_stmt
, tree startvar
)
5842 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5844 /* If fd->loop.n2 is constant, then no propagation of the counts
5845 is needed, they are constant. */
5846 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5849 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5850 ? gimple_omp_parallel_clauses (inner_stmt
)
5851 : gimple_omp_for_clauses (inner_stmt
);
5852 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5853 isn't supposed to be handled, as the inner loop doesn't
5855 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5856 gcc_assert (innerc
);
5857 for (i
= 0; i
< fd
->collapse
; i
++)
5859 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5860 OMP_CLAUSE__LOOPTEMP_
);
5861 gcc_assert (innerc
);
5864 tree tem
= OMP_CLAUSE_DECL (innerc
);
5865 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5866 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5867 false, GSI_CONTINUE_LINKING
);
5868 gassign
*stmt
= gimple_build_assign (tem
, t
);
5869 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5875 tree type
= TREE_TYPE (fd
->loop
.v
);
5876 tree tem
= create_tmp_reg (type
, ".tem");
5877 gassign
*stmt
= gimple_build_assign (tem
, startvar
);
5878 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5880 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5882 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5884 if (POINTER_TYPE_P (vtype
))
5885 itype
= signed_type_for (vtype
);
5887 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5890 t
= fold_convert (itype
, t
);
5891 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5892 fold_convert (itype
, fd
->loops
[i
].step
));
5893 if (POINTER_TYPE_P (vtype
))
5894 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5896 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5897 t
= force_gimple_operand_gsi (gsi
, t
,
5898 DECL_P (fd
->loops
[i
].v
)
5899 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5901 GSI_CONTINUE_LINKING
);
5902 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5903 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5906 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5907 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5908 false, GSI_CONTINUE_LINKING
);
5909 stmt
= gimple_build_assign (tem
, t
);
5910 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5916 /* Helper function for expand_omp_for_*. Generate code like:
5919 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5923 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5930 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5931 basic_block body_bb
)
5933 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5935 gimple_stmt_iterator gsi
;
5941 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5943 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5945 bb
= create_empty_bb (last_bb
);
5946 add_bb_to_loop (bb
, last_bb
->loop_father
);
5947 gsi
= gsi_start_bb (bb
);
5949 if (i
< fd
->collapse
- 1)
5951 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5952 e
->probability
= REG_BR_PROB_BASE
/ 8;
5954 t
= fd
->loops
[i
+ 1].n1
;
5955 t
= force_gimple_operand_gsi (&gsi
, t
,
5956 DECL_P (fd
->loops
[i
+ 1].v
)
5957 && TREE_ADDRESSABLE (fd
->loops
[i
5960 GSI_CONTINUE_LINKING
);
5961 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5962 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5967 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5969 if (POINTER_TYPE_P (vtype
))
5970 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5972 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5973 t
= force_gimple_operand_gsi (&gsi
, t
,
5974 DECL_P (fd
->loops
[i
].v
)
5975 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5976 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5977 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5978 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5982 t
= fd
->loops
[i
].n2
;
5983 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5984 false, GSI_CONTINUE_LINKING
);
5985 tree v
= fd
->loops
[i
].v
;
5986 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5987 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5988 false, GSI_CONTINUE_LINKING
);
5989 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5990 stmt
= gimple_build_cond_empty (t
);
5991 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5992 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5993 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5996 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
6004 /* A subroutine of expand_omp_for. Generate code for a parallel
6005 loop with any schedule. Given parameters:
6007 for (V = N1; V cond N2; V += STEP) BODY;
6009 where COND is "<" or ">", we generate pseudocode
6011 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6012 if (more) goto L0; else goto L3;
6019 if (V cond iend) goto L1; else goto L2;
6021 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6024 If this is a combined omp parallel loop, instead of the call to
6025 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6026 If this is gimple_omp_for_combined_p loop, then instead of assigning
6027 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6028 inner GIMPLE_OMP_FOR and V += STEP; and
6029 if (V cond iend) goto L1; else goto L2; are removed.
6031 For collapsed loops, given parameters:
6033 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6034 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6035 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6038 we generate pseudocode
6040 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6045 count3 = (adj + N32 - N31) / STEP3;
6046 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6051 count2 = (adj + N22 - N21) / STEP2;
6052 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6057 count1 = (adj + N12 - N11) / STEP1;
6058 count = count1 * count2 * count3;
6063 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6064 if (more) goto L0; else goto L3;
6068 V3 = N31 + (T % count3) * STEP3;
6070 V2 = N21 + (T % count2) * STEP2;
6072 V1 = N11 + T * STEP1;
6077 if (V < iend) goto L10; else goto L2;
6080 if (V3 cond3 N32) goto L1; else goto L11;
6084 if (V2 cond2 N22) goto L1; else goto L12;
6090 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6096 expand_omp_for_generic (struct omp_region
*region
,
6097 struct omp_for_data
*fd
,
6098 enum built_in_function start_fn
,
6099 enum built_in_function next_fn
,
6102 tree type
, istart0
, iend0
, iend
;
6103 tree t
, vmain
, vback
, bias
= NULL_TREE
;
6104 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
6105 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
6106 gimple_stmt_iterator gsi
;
6107 gassign
*assign_stmt
;
6108 bool in_combined_parallel
= is_combined_parallel (region
);
6109 bool broken_loop
= region
->cont
== NULL
;
6111 tree
*counts
= NULL
;
6114 gcc_assert (!broken_loop
|| !in_combined_parallel
);
6115 gcc_assert (fd
->iter_type
== long_integer_type_node
6116 || !in_combined_parallel
);
6118 type
= TREE_TYPE (fd
->loop
.v
);
6119 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
6120 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
6121 TREE_ADDRESSABLE (istart0
) = 1;
6122 TREE_ADDRESSABLE (iend0
) = 1;
6124 /* See if we need to bias by LLONG_MIN. */
6125 if (fd
->iter_type
== long_long_unsigned_type_node
6126 && TREE_CODE (type
) == INTEGER_TYPE
6127 && !TYPE_UNSIGNED (type
))
6131 if (fd
->loop
.cond_code
== LT_EXPR
)
6134 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6138 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6141 if (TREE_CODE (n1
) != INTEGER_CST
6142 || TREE_CODE (n2
) != INTEGER_CST
6143 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
6144 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
6147 entry_bb
= region
->entry
;
6148 cont_bb
= region
->cont
;
6150 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6151 gcc_assert (broken_loop
6152 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6153 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6154 l1_bb
= single_succ (l0_bb
);
6157 l2_bb
= create_empty_bb (cont_bb
);
6158 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
6159 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6163 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6164 exit_bb
= region
->exit
;
6166 gsi
= gsi_last_bb (entry_bb
);
6168 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6169 if (fd
->collapse
> 1)
6171 int first_zero_iter
= -1;
6172 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
6174 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6175 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6176 zero_iter_bb
, first_zero_iter
,
6181 /* Some counts[i] vars might be uninitialized if
6182 some loop has zero iterations. But the body shouldn't
6183 be executed in that case, so just avoid uninit warnings. */
6184 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
6185 if (SSA_VAR_P (counts
[i
]))
6186 TREE_NO_WARNING (counts
[i
]) = 1;
6188 e
= split_block (entry_bb
, gsi_stmt (gsi
));
6190 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
6191 gsi
= gsi_last_bb (entry_bb
);
6192 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
6193 get_immediate_dominator (CDI_DOMINATORS
,
6197 if (in_combined_parallel
)
6199 /* In a combined parallel loop, emit a call to
6200 GOMP_loop_foo_next. */
6201 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6202 build_fold_addr_expr (istart0
),
6203 build_fold_addr_expr (iend0
));
6207 tree t0
, t1
, t2
, t3
, t4
;
6208 /* If this is not a combined parallel loop, emit a call to
6209 GOMP_loop_foo_start in ENTRY_BB. */
6210 t4
= build_fold_addr_expr (iend0
);
6211 t3
= build_fold_addr_expr (istart0
);
6212 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
6215 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6217 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6218 OMP_CLAUSE__LOOPTEMP_
);
6219 gcc_assert (innerc
);
6220 t0
= OMP_CLAUSE_DECL (innerc
);
6221 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6222 OMP_CLAUSE__LOOPTEMP_
);
6223 gcc_assert (innerc
);
6224 t1
= OMP_CLAUSE_DECL (innerc
);
6226 if (POINTER_TYPE_P (TREE_TYPE (t0
))
6227 && TYPE_PRECISION (TREE_TYPE (t0
))
6228 != TYPE_PRECISION (fd
->iter_type
))
6230 /* Avoid casting pointers to integer of a different size. */
6231 tree itype
= signed_type_for (type
);
6232 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
6233 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
6237 t1
= fold_convert (fd
->iter_type
, t1
);
6238 t0
= fold_convert (fd
->iter_type
, t0
);
6242 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
6243 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
6245 if (fd
->iter_type
== long_integer_type_node
)
6249 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6250 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6251 6, t0
, t1
, t2
, t
, t3
, t4
);
6254 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6255 5, t0
, t1
, t2
, t3
, t4
);
6263 /* The GOMP_loop_ull_*start functions have additional boolean
6264 argument, true for < loops and false for > loops.
6265 In Fortran, the C bool type can be different from
6266 boolean_type_node. */
6267 bfn_decl
= builtin_decl_explicit (start_fn
);
6268 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
6269 t5
= build_int_cst (c_bool_type
,
6270 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
6273 tree bfn_decl
= builtin_decl_explicit (start_fn
);
6274 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6275 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
6278 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6279 6, t5
, t0
, t1
, t2
, t3
, t4
);
6282 if (TREE_TYPE (t
) != boolean_type_node
)
6283 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6284 t
, build_int_cst (TREE_TYPE (t
), 0));
6285 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6286 true, GSI_SAME_STMT
);
6287 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6289 /* Remove the GIMPLE_OMP_FOR statement. */
6290 gsi_remove (&gsi
, true);
6292 /* Iteration setup for sequential loop goes in L0_BB. */
6293 tree startvar
= fd
->loop
.v
;
6294 tree endvar
= NULL_TREE
;
6296 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6298 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
6299 && gimple_omp_for_kind (inner_stmt
)
6300 == GF_OMP_FOR_KIND_SIMD
);
6301 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
6302 OMP_CLAUSE__LOOPTEMP_
);
6303 gcc_assert (innerc
);
6304 startvar
= OMP_CLAUSE_DECL (innerc
);
6305 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6306 OMP_CLAUSE__LOOPTEMP_
);
6307 gcc_assert (innerc
);
6308 endvar
= OMP_CLAUSE_DECL (innerc
);
6311 gsi
= gsi_start_bb (l0_bb
);
6314 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6315 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6316 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6317 t
= fold_convert (TREE_TYPE (startvar
), t
);
6318 t
= force_gimple_operand_gsi (&gsi
, t
,
6320 && TREE_ADDRESSABLE (startvar
),
6321 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6322 assign_stmt
= gimple_build_assign (startvar
, t
);
6323 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6327 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6328 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6329 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6330 t
= fold_convert (TREE_TYPE (startvar
), t
);
6331 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6332 false, GSI_CONTINUE_LINKING
);
6335 assign_stmt
= gimple_build_assign (endvar
, iend
);
6336 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6337 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
6338 assign_stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
6340 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, iend
);
6341 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6343 if (fd
->collapse
> 1)
6344 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6348 /* Code to control the increment and predicate for the sequential
6349 loop goes in the CONT_BB. */
6350 gsi
= gsi_last_bb (cont_bb
);
6351 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6352 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6353 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6354 vback
= gimple_omp_continue_control_def (cont_stmt
);
6356 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6358 if (POINTER_TYPE_P (type
))
6359 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
6361 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
6362 t
= force_gimple_operand_gsi (&gsi
, t
,
6364 && TREE_ADDRESSABLE (vback
),
6365 NULL_TREE
, true, GSI_SAME_STMT
);
6366 assign_stmt
= gimple_build_assign (vback
, t
);
6367 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6369 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6370 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
6372 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6373 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6376 /* Remove GIMPLE_OMP_CONTINUE. */
6377 gsi_remove (&gsi
, true);
6379 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6380 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
6382 /* Emit code to get the next parallel iteration in L2_BB. */
6383 gsi
= gsi_start_bb (l2_bb
);
6385 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6386 build_fold_addr_expr (istart0
),
6387 build_fold_addr_expr (iend0
));
6388 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6389 false, GSI_CONTINUE_LINKING
);
6390 if (TREE_TYPE (t
) != boolean_type_node
)
6391 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6392 t
, build_int_cst (TREE_TYPE (t
), 0));
6393 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6394 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
6397 /* Add the loop cleanup function. */
6398 gsi
= gsi_last_bb (exit_bb
);
6399 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6400 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
6401 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6402 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
6404 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
6405 gcall
*call_stmt
= gimple_build_call (t
, 0);
6406 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6407 gimple_call_set_lhs (call_stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
6408 gsi_insert_after (&gsi
, call_stmt
, GSI_SAME_STMT
);
6409 gsi_remove (&gsi
, true);
6411 /* Connect the new blocks. */
6412 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
6413 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
6419 e
= find_edge (cont_bb
, l3_bb
);
6420 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
6422 phis
= phi_nodes (l3_bb
);
6423 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
6425 gimple phi
= gsi_stmt (gsi
);
6426 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
6427 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
6431 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
6432 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
6433 e
= find_edge (cont_bb
, l1_bb
);
6434 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6439 else if (fd
->collapse
> 1)
6442 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6445 e
->flags
= EDGE_TRUE_VALUE
;
6448 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6449 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
6453 e
= find_edge (cont_bb
, l2_bb
);
6454 e
->flags
= EDGE_FALLTHRU
;
6456 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6458 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
6459 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
6460 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
6461 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
6462 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
6463 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
6464 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
6465 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
6467 struct loop
*outer_loop
= alloc_loop ();
6468 outer_loop
->header
= l0_bb
;
6469 outer_loop
->latch
= l2_bb
;
6470 add_loop (outer_loop
, l0_bb
->loop_father
);
6472 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6474 struct loop
*loop
= alloc_loop ();
6475 loop
->header
= l1_bb
;
6476 /* The loop may have multiple latches. */
6477 add_loop (loop
, outer_loop
);
6483 /* A subroutine of expand_omp_for. Generate code for a parallel
6484 loop with static schedule and no specified chunk size. Given
6487 for (V = N1; V cond N2; V += STEP) BODY;
6489 where COND is "<" or ">", we generate pseudocode
6491 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6496 if ((__typeof (V)) -1 > 0 && cond is >)
6497 n = -(adj + N2 - N1) / -STEP;
6499 n = (adj + N2 - N1) / STEP;
6502 if (threadid < tt) goto L3; else goto L4;
6507 s0 = q * threadid + tt;
6510 if (s0 >= e0) goto L2; else goto L0;
6516 if (V cond e) goto L1;
6521 expand_omp_for_static_nochunk (struct omp_region
*region
,
6522 struct omp_for_data
*fd
,
6525 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
6526 tree type
, itype
, vmain
, vback
;
6527 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
6528 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
6530 gimple_stmt_iterator gsi
;
6532 bool broken_loop
= region
->cont
== NULL
;
6533 tree
*counts
= NULL
;
6536 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6537 != GF_OMP_FOR_KIND_OACC_LOOP
)
6540 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6541 if (POINTER_TYPE_P (type
))
6542 itype
= signed_type_for (type
);
6544 entry_bb
= region
->entry
;
6545 cont_bb
= region
->cont
;
6546 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6547 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6548 gcc_assert (broken_loop
6549 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
6550 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6551 body_bb
= single_succ (seq_start_bb
);
6554 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
6555 || single_succ (BRANCH_EDGE (cont_bb
)->dest
) == body_bb
);
6556 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6558 exit_bb
= region
->exit
;
6560 /* Iteration space partitioning goes in ENTRY_BB. */
6561 gsi
= gsi_last_bb (entry_bb
);
6562 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6564 if (fd
->collapse
> 1)
6566 int first_zero_iter
= -1;
6567 basic_block l2_dom_bb
= NULL
;
6569 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6570 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6571 fin_bb
, first_zero_iter
,
6575 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6576 t
= integer_one_node
;
6578 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6579 fold_convert (type
, fd
->loop
.n1
),
6580 fold_convert (type
, fd
->loop
.n2
));
6581 if (fd
->collapse
== 1
6582 && TYPE_UNSIGNED (type
)
6583 && (t
== NULL_TREE
|| !integer_onep (t
)))
6585 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6586 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6587 true, GSI_SAME_STMT
);
6588 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6589 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6590 true, GSI_SAME_STMT
);
6591 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6592 NULL_TREE
, NULL_TREE
);
6593 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6594 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6595 expand_omp_regimplify_p
, NULL
, NULL
)
6596 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6597 expand_omp_regimplify_p
, NULL
, NULL
))
6599 gsi
= gsi_for_stmt (cond_stmt
);
6600 gimple_regimplify_operands (cond_stmt
, &gsi
);
6602 ep
= split_block (entry_bb
, cond_stmt
);
6603 ep
->flags
= EDGE_TRUE_VALUE
;
6604 entry_bb
= ep
->dest
;
6605 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6606 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6607 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6608 if (gimple_in_ssa_p (cfun
))
6610 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6611 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6612 !gsi_end_p (gpi
); gsi_next (&gpi
))
6614 gphi
*phi
= gpi
.phi ();
6615 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6616 ep
, UNKNOWN_LOCATION
);
6619 gsi
= gsi_last_bb (entry_bb
);
6622 switch (gimple_omp_for_kind (fd
->for_stmt
))
6624 case GF_OMP_FOR_KIND_FOR
:
6625 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
6626 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
6628 case GF_OMP_FOR_KIND_DISTRIBUTE
:
6629 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
6630 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
6632 case GF_OMP_FOR_KIND_OACC_LOOP
:
6633 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
6634 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
6639 nthreads
= build_call_expr (nthreads
, 0);
6640 nthreads
= fold_convert (itype
, nthreads
);
6641 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
6642 true, GSI_SAME_STMT
);
6643 threadid
= build_call_expr (threadid
, 0);
6644 threadid
= fold_convert (itype
, threadid
);
6645 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
6646 true, GSI_SAME_STMT
);
6650 step
= fd
->loop
.step
;
6651 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6653 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6654 OMP_CLAUSE__LOOPTEMP_
);
6655 gcc_assert (innerc
);
6656 n1
= OMP_CLAUSE_DECL (innerc
);
6657 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6658 OMP_CLAUSE__LOOPTEMP_
);
6659 gcc_assert (innerc
);
6660 n2
= OMP_CLAUSE_DECL (innerc
);
6662 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6663 true, NULL_TREE
, true, GSI_SAME_STMT
);
6664 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6665 true, NULL_TREE
, true, GSI_SAME_STMT
);
6666 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6667 true, NULL_TREE
, true, GSI_SAME_STMT
);
6669 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6670 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6671 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6672 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6673 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6674 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6675 fold_build1 (NEGATE_EXPR
, itype
, t
),
6676 fold_build1 (NEGATE_EXPR
, itype
, step
));
6678 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6679 t
= fold_convert (itype
, t
);
6680 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6682 q
= create_tmp_reg (itype
, "q");
6683 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
6684 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6685 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
6687 tt
= create_tmp_reg (itype
, "tt");
6688 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
6689 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6690 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
6692 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
6693 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6694 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6696 second_bb
= split_block (entry_bb
, cond_stmt
)->dest
;
6697 gsi
= gsi_last_bb (second_bb
);
6698 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6700 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
6702 gassign
*assign_stmt
6703 = gimple_build_assign (q
, PLUS_EXPR
, q
, build_int_cst (itype
, 1));
6704 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6706 third_bb
= split_block (second_bb
, assign_stmt
)->dest
;
6707 gsi
= gsi_last_bb (third_bb
);
6708 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6710 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6711 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6712 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6714 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6715 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6717 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6718 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6720 /* Remove the GIMPLE_OMP_FOR statement. */
6721 gsi_remove (&gsi
, true);
6723 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6724 gsi
= gsi_start_bb (seq_start_bb
);
6726 tree startvar
= fd
->loop
.v
;
6727 tree endvar
= NULL_TREE
;
6729 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6731 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6732 ? gimple_omp_parallel_clauses (inner_stmt
)
6733 : gimple_omp_for_clauses (inner_stmt
);
6734 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6735 gcc_assert (innerc
);
6736 startvar
= OMP_CLAUSE_DECL (innerc
);
6737 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6738 OMP_CLAUSE__LOOPTEMP_
);
6739 gcc_assert (innerc
);
6740 endvar
= OMP_CLAUSE_DECL (innerc
);
6742 t
= fold_convert (itype
, s0
);
6743 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6744 if (POINTER_TYPE_P (type
))
6745 t
= fold_build_pointer_plus (n1
, t
);
6747 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6748 t
= fold_convert (TREE_TYPE (startvar
), t
);
6749 t
= force_gimple_operand_gsi (&gsi
, t
,
6751 && TREE_ADDRESSABLE (startvar
),
6752 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6753 assign_stmt
= gimple_build_assign (startvar
, t
);
6754 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6756 t
= fold_convert (itype
, e0
);
6757 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6758 if (POINTER_TYPE_P (type
))
6759 t
= fold_build_pointer_plus (n1
, t
);
6761 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6762 t
= fold_convert (TREE_TYPE (startvar
), t
);
6763 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6764 false, GSI_CONTINUE_LINKING
);
6767 assign_stmt
= gimple_build_assign (endvar
, e
);
6768 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6769 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6770 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6772 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
6773 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6775 if (fd
->collapse
> 1)
6776 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6780 /* The code controlling the sequential loop replaces the
6781 GIMPLE_OMP_CONTINUE. */
6782 gsi
= gsi_last_bb (cont_bb
);
6783 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6784 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6785 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6786 vback
= gimple_omp_continue_control_def (cont_stmt
);
6788 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6790 if (POINTER_TYPE_P (type
))
6791 t
= fold_build_pointer_plus (vmain
, step
);
6793 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6794 t
= force_gimple_operand_gsi (&gsi
, t
,
6796 && TREE_ADDRESSABLE (vback
),
6797 NULL_TREE
, true, GSI_SAME_STMT
);
6798 assign_stmt
= gimple_build_assign (vback
, t
);
6799 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6801 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6802 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6804 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6807 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6808 gsi_remove (&gsi
, true);
6810 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6811 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6814 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6815 gsi
= gsi_last_bb (exit_bb
);
6816 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6818 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6819 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
6820 gcc_checking_assert (t
== NULL_TREE
);
6822 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6824 gsi_remove (&gsi
, true);
6826 /* Connect all the blocks. */
6827 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6828 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6829 ep
= find_edge (entry_bb
, second_bb
);
6830 ep
->flags
= EDGE_TRUE_VALUE
;
6831 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6832 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6833 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6837 ep
= find_edge (cont_bb
, body_bb
);
6840 ep
= BRANCH_EDGE (cont_bb
);
6841 gcc_assert (single_succ (ep
->dest
) == body_bb
);
6843 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6848 else if (fd
->collapse
> 1)
6851 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6854 ep
->flags
= EDGE_TRUE_VALUE
;
6855 find_edge (cont_bb
, fin_bb
)->flags
6856 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6859 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6860 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6861 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6863 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6864 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6865 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6866 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6868 struct loop
*loop
= body_bb
->loop_father
;
6869 if (loop
!= entry_bb
->loop_father
)
6871 gcc_assert (loop
->header
== body_bb
);
6872 gcc_assert (broken_loop
6873 || loop
->latch
== region
->cont
6874 || single_pred (loop
->latch
) == region
->cont
);
6878 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6880 loop
= alloc_loop ();
6881 loop
->header
= body_bb
;
6882 if (collapse_bb
== NULL
)
6883 loop
->latch
= cont_bb
;
6884 add_loop (loop
, body_bb
->loop_father
);
6888 /* Return phi in E->DEST with ARG on edge E. */
6891 find_phi_with_arg_on_edge (tree arg
, edge e
)
6893 basic_block bb
= e
->dest
;
6895 for (gphi_iterator gpi
= gsi_start_phis (bb
);
6899 gphi
*phi
= gpi
.phi ();
6900 if (PHI_ARG_DEF_FROM_EDGE (phi
, e
) == arg
)
6907 /* A subroutine of expand_omp_for. Generate code for a parallel
6908 loop with static schedule and a specified chunk size. Given
6911 for (V = N1; V cond N2; V += STEP) BODY;
6913 where COND is "<" or ">", we generate pseudocode
6915 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6920 if ((__typeof (V)) -1 > 0 && cond is >)
6921 n = -(adj + N2 - N1) / -STEP;
6923 n = (adj + N2 - N1) / STEP;
6925 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6926 here so that V is defined
6927 if the loop is not entered
6929 s0 = (trip * nthreads + threadid) * CHUNK;
6930 e0 = min(s0 + CHUNK, n);
6931 if (s0 < n) goto L1; else goto L4;
6938 if (V cond e) goto L2; else goto L3;
6946 expand_omp_for_static_chunk (struct omp_region
*region
,
6947 struct omp_for_data
*fd
, gimple inner_stmt
)
6949 tree n
, s0
, e0
, e
, t
;
6950 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6951 tree type
, itype
, vmain
, vback
, vextra
;
6952 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6953 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6954 gimple_stmt_iterator gsi
;
6956 bool broken_loop
= region
->cont
== NULL
;
6957 tree
*counts
= NULL
;
6960 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6961 != GF_OMP_FOR_KIND_OACC_LOOP
)
6964 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6965 if (POINTER_TYPE_P (type
))
6966 itype
= signed_type_for (type
);
6968 entry_bb
= region
->entry
;
6969 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6971 iter_part_bb
= se
->dest
;
6972 cont_bb
= region
->cont
;
6973 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6974 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6975 gcc_assert (broken_loop
6976 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6977 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6978 body_bb
= single_succ (seq_start_bb
);
6981 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
6982 || single_succ (BRANCH_EDGE (cont_bb
)->dest
) == body_bb
);
6983 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6984 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6986 exit_bb
= region
->exit
;
6988 /* Trip and adjustment setup goes in ENTRY_BB. */
6989 gsi
= gsi_last_bb (entry_bb
);
6990 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6992 if (fd
->collapse
> 1)
6994 int first_zero_iter
= -1;
6995 basic_block l2_dom_bb
= NULL
;
6997 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6998 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6999 fin_bb
, first_zero_iter
,
7003 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7004 t
= integer_one_node
;
7006 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
7007 fold_convert (type
, fd
->loop
.n1
),
7008 fold_convert (type
, fd
->loop
.n2
));
7009 if (fd
->collapse
== 1
7010 && TYPE_UNSIGNED (type
)
7011 && (t
== NULL_TREE
|| !integer_onep (t
)))
7013 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
7014 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
7015 true, GSI_SAME_STMT
);
7016 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
7017 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
7018 true, GSI_SAME_STMT
);
7019 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
7020 NULL_TREE
, NULL_TREE
);
7021 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
7022 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
7023 expand_omp_regimplify_p
, NULL
, NULL
)
7024 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
7025 expand_omp_regimplify_p
, NULL
, NULL
))
7027 gsi
= gsi_for_stmt (cond_stmt
);
7028 gimple_regimplify_operands (cond_stmt
, &gsi
);
7030 se
= split_block (entry_bb
, cond_stmt
);
7031 se
->flags
= EDGE_TRUE_VALUE
;
7032 entry_bb
= se
->dest
;
7033 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
7034 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
7035 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
7036 if (gimple_in_ssa_p (cfun
))
7038 int dest_idx
= find_edge (iter_part_bb
, fin_bb
)->dest_idx
;
7039 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
7040 !gsi_end_p (gpi
); gsi_next (&gpi
))
7042 gphi
*phi
= gpi
.phi ();
7043 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
7044 se
, UNKNOWN_LOCATION
);
7047 gsi
= gsi_last_bb (entry_bb
);
7050 switch (gimple_omp_for_kind (fd
->for_stmt
))
7052 case GF_OMP_FOR_KIND_FOR
:
7053 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
7054 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
7056 case GF_OMP_FOR_KIND_DISTRIBUTE
:
7057 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
7058 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
7060 case GF_OMP_FOR_KIND_OACC_LOOP
:
7061 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
7062 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
7067 nthreads
= build_call_expr (nthreads
, 0);
7068 nthreads
= fold_convert (itype
, nthreads
);
7069 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
7070 true, GSI_SAME_STMT
);
7071 threadid
= build_call_expr (threadid
, 0);
7072 threadid
= fold_convert (itype
, threadid
);
7073 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
7074 true, GSI_SAME_STMT
);
7078 step
= fd
->loop
.step
;
7079 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7081 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7082 OMP_CLAUSE__LOOPTEMP_
);
7083 gcc_assert (innerc
);
7084 n1
= OMP_CLAUSE_DECL (innerc
);
7085 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7086 OMP_CLAUSE__LOOPTEMP_
);
7087 gcc_assert (innerc
);
7088 n2
= OMP_CLAUSE_DECL (innerc
);
7090 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
7091 true, NULL_TREE
, true, GSI_SAME_STMT
);
7092 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
7093 true, NULL_TREE
, true, GSI_SAME_STMT
);
7094 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
7095 true, NULL_TREE
, true, GSI_SAME_STMT
);
7097 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
7098 true, NULL_TREE
, true, GSI_SAME_STMT
);
7100 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
7101 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
7102 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
7103 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
7104 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
7105 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
7106 fold_build1 (NEGATE_EXPR
, itype
, t
),
7107 fold_build1 (NEGATE_EXPR
, itype
, step
));
7109 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
7110 t
= fold_convert (itype
, t
);
7111 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7112 true, GSI_SAME_STMT
);
7114 trip_var
= create_tmp_reg (itype
, ".trip");
7115 if (gimple_in_ssa_p (cfun
))
7117 trip_init
= make_ssa_name (trip_var
);
7118 trip_main
= make_ssa_name (trip_var
);
7119 trip_back
= make_ssa_name (trip_var
);
7123 trip_init
= trip_var
;
7124 trip_main
= trip_var
;
7125 trip_back
= trip_var
;
7128 gassign
*assign_stmt
7129 = gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
7130 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7132 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
7133 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7134 if (POINTER_TYPE_P (type
))
7135 t
= fold_build_pointer_plus (n1
, t
);
7137 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7138 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7139 true, GSI_SAME_STMT
);
7141 /* Remove the GIMPLE_OMP_FOR. */
7142 gsi_remove (&gsi
, true);
7144 /* Iteration space partitioning goes in ITER_PART_BB. */
7145 gsi
= gsi_last_bb (iter_part_bb
);
7147 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
7148 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
7149 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
7150 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7151 false, GSI_CONTINUE_LINKING
);
7153 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
7154 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
7155 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7156 false, GSI_CONTINUE_LINKING
);
7158 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
7159 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
7161 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7162 gsi
= gsi_start_bb (seq_start_bb
);
7164 tree startvar
= fd
->loop
.v
;
7165 tree endvar
= NULL_TREE
;
7167 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7169 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
7170 ? gimple_omp_parallel_clauses (inner_stmt
)
7171 : gimple_omp_for_clauses (inner_stmt
);
7172 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
7173 gcc_assert (innerc
);
7174 startvar
= OMP_CLAUSE_DECL (innerc
);
7175 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7176 OMP_CLAUSE__LOOPTEMP_
);
7177 gcc_assert (innerc
);
7178 endvar
= OMP_CLAUSE_DECL (innerc
);
7181 t
= fold_convert (itype
, s0
);
7182 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7183 if (POINTER_TYPE_P (type
))
7184 t
= fold_build_pointer_plus (n1
, t
);
7186 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7187 t
= fold_convert (TREE_TYPE (startvar
), t
);
7188 t
= force_gimple_operand_gsi (&gsi
, t
,
7190 && TREE_ADDRESSABLE (startvar
),
7191 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
7192 assign_stmt
= gimple_build_assign (startvar
, t
);
7193 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7195 t
= fold_convert (itype
, e0
);
7196 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7197 if (POINTER_TYPE_P (type
))
7198 t
= fold_build_pointer_plus (n1
, t
);
7200 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7201 t
= fold_convert (TREE_TYPE (startvar
), t
);
7202 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7203 false, GSI_CONTINUE_LINKING
);
7206 assign_stmt
= gimple_build_assign (endvar
, e
);
7207 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7208 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
7209 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
7211 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
7212 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7214 if (fd
->collapse
> 1)
7215 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
7219 /* The code controlling the sequential loop goes in CONT_BB,
7220 replacing the GIMPLE_OMP_CONTINUE. */
7221 gsi
= gsi_last_bb (cont_bb
);
7222 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
7223 vmain
= gimple_omp_continue_control_use (cont_stmt
);
7224 vback
= gimple_omp_continue_control_def (cont_stmt
);
7226 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7228 if (POINTER_TYPE_P (type
))
7229 t
= fold_build_pointer_plus (vmain
, step
);
7231 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
7232 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
7233 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7234 true, GSI_SAME_STMT
);
7235 assign_stmt
= gimple_build_assign (vback
, t
);
7236 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7238 if (tree_int_cst_equal (fd
->chunk_size
, integer_one_node
))
7239 t
= build2 (EQ_EXPR
, boolean_type_node
,
7240 build_int_cst (itype
, 0),
7241 build_int_cst (itype
, 1));
7243 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
7244 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
7246 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
7249 /* Remove GIMPLE_OMP_CONTINUE. */
7250 gsi_remove (&gsi
, true);
7252 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
7253 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
7255 /* Trip update code goes into TRIP_UPDATE_BB. */
7256 gsi
= gsi_start_bb (trip_update_bb
);
7258 t
= build_int_cst (itype
, 1);
7259 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
7260 assign_stmt
= gimple_build_assign (trip_back
, t
);
7261 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7264 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7265 gsi
= gsi_last_bb (exit_bb
);
7266 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
7268 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
7269 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
7270 gcc_checking_assert (t
== NULL_TREE
);
7272 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
7274 gsi_remove (&gsi
, true);
7276 /* Connect the new blocks. */
7277 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
7278 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
7282 se
= find_edge (cont_bb
, body_bb
);
7285 se
= BRANCH_EDGE (cont_bb
);
7286 gcc_assert (single_succ (se
->dest
) == body_bb
);
7288 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7293 else if (fd
->collapse
> 1)
7296 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
7299 se
->flags
= EDGE_TRUE_VALUE
;
7300 find_edge (cont_bb
, trip_update_bb
)->flags
7301 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
7303 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
7306 if (gimple_in_ssa_p (cfun
))
7314 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
7316 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7317 remove arguments of the phi nodes in fin_bb. We need to create
7318 appropriate phi nodes in iter_part_bb instead. */
7319 se
= find_edge (iter_part_bb
, fin_bb
);
7320 re
= single_succ_edge (trip_update_bb
);
7321 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
7322 ene
= single_succ_edge (entry_bb
);
7324 psi
= gsi_start_phis (fin_bb
);
7325 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
7326 gsi_next (&psi
), ++i
)
7329 source_location locus
;
7332 t
= gimple_phi_result (phi
);
7333 gcc_assert (t
== redirect_edge_var_map_result (vm
));
7335 if (!single_pred_p (fin_bb
))
7336 t
= copy_ssa_name (t
, phi
);
7338 nphi
= create_phi_node (t
, iter_part_bb
);
7340 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
7341 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
7343 /* A special case -- fd->loop.v is not yet computed in
7344 iter_part_bb, we need to use vextra instead. */
7345 if (t
== fd
->loop
.v
)
7347 add_phi_arg (nphi
, t
, ene
, locus
);
7348 locus
= redirect_edge_var_map_location (vm
);
7349 tree back_arg
= redirect_edge_var_map_def (vm
);
7350 add_phi_arg (nphi
, back_arg
, re
, locus
);
7351 edge ce
= find_edge (cont_bb
, body_bb
);
7354 ce
= BRANCH_EDGE (cont_bb
);
7355 gcc_assert (single_succ (ce
->dest
) == body_bb
);
7356 ce
= single_succ_edge (ce
->dest
);
7358 gphi
*inner_loop_phi
= find_phi_with_arg_on_edge (back_arg
, ce
);
7359 gcc_assert (inner_loop_phi
!= NULL
);
7360 add_phi_arg (inner_loop_phi
, gimple_phi_result (nphi
),
7361 find_edge (seq_start_bb
, body_bb
), locus
);
7363 if (!single_pred_p (fin_bb
))
7364 add_phi_arg (phi
, gimple_phi_result (nphi
), se
, locus
);
7366 gcc_assert (gsi_end_p (psi
) && (head
== NULL
|| i
== head
->length ()));
7367 redirect_edge_var_map_clear (re
);
7368 if (single_pred_p (fin_bb
))
7371 psi
= gsi_start_phis (fin_bb
);
7372 if (gsi_end_p (psi
))
7374 remove_phi_node (&psi
, false);
7377 /* Make phi node for trip. */
7378 phi
= create_phi_node (trip_main
, iter_part_bb
);
7379 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
7381 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
7386 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
7387 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
7388 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
7389 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
7390 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
7391 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
7392 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
7393 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
7394 recompute_dominator (CDI_DOMINATORS
, body_bb
));
7398 struct loop
*loop
= body_bb
->loop_father
;
7399 struct loop
*trip_loop
= alloc_loop ();
7400 trip_loop
->header
= iter_part_bb
;
7401 trip_loop
->latch
= trip_update_bb
;
7402 add_loop (trip_loop
, iter_part_bb
->loop_father
);
7404 if (loop
!= entry_bb
->loop_father
)
7406 gcc_assert (loop
->header
== body_bb
);
7407 gcc_assert (loop
->latch
== region
->cont
7408 || single_pred (loop
->latch
) == region
->cont
);
7409 trip_loop
->inner
= loop
;
7413 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7415 loop
= alloc_loop ();
7416 loop
->header
= body_bb
;
7417 if (collapse_bb
== NULL
)
7418 loop
->latch
= cont_bb
;
7419 add_loop (loop
, trip_loop
);
7424 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7426 for (V = N1; V cond N2; V += STEP) BODY;
7428 where COND is "<" or ">" or "!=", we generate pseudocode
7430 for (ind_var = low; ind_var < high; ind_var++)
7432 V = n1 + (ind_var * STEP)
7437 In the above pseudocode, low and high are function parameters of the
7438 child function. In the function below, we are inserting a temp.
7439 variable that will be making a call to two OMP functions that will not be
7440 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7441 with _Cilk_for). These functions are replaced with low and high
7442 by the function that handles taskreg. */
7446 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
7448 bool broken_loop
= region
->cont
== NULL
;
7449 basic_block entry_bb
= region
->entry
;
7450 basic_block cont_bb
= region
->cont
;
7452 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7453 gcc_assert (broken_loop
7454 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7455 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7456 basic_block l1_bb
, l2_bb
;
7460 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7461 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7462 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7463 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7467 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7468 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7469 l2_bb
= single_succ (l1_bb
);
7471 basic_block exit_bb
= region
->exit
;
7472 basic_block l2_dom_bb
= NULL
;
7474 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
7476 /* Below statements until the "tree high_val = ..." are pseudo statements
7477 used to pass information to be used by expand_omp_taskreg.
7478 low_val and high_val will be replaced by the __low and __high
7479 parameter from the child function.
7481 The call_exprs part is a place-holder, it is mainly used
7482 to distinctly identify to the top-level part that this is
7483 where we should put low and high (reasoning given in header
7487 = gimple_omp_parallel_child_fn (
7488 as_a
<gomp_parallel
*> (last_stmt (region
->outer
->entry
)));
7489 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
7490 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
7492 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
7494 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
7497 gcc_assert (low_val
&& high_val
);
7499 tree type
= TREE_TYPE (low_val
);
7500 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
7501 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7503 /* Not needed in SSA form right now. */
7504 gcc_assert (!gimple_in_ssa_p (cfun
));
7505 if (l2_dom_bb
== NULL
)
7511 gimple stmt
= gimple_build_assign (ind_var
, n1
);
7513 /* Replace the GIMPLE_OMP_FOR statement. */
7514 gsi_replace (&gsi
, stmt
, true);
7518 /* Code to control the increment goes in the CONT_BB. */
7519 gsi
= gsi_last_bb (cont_bb
);
7520 stmt
= gsi_stmt (gsi
);
7521 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7522 stmt
= gimple_build_assign (ind_var
, PLUS_EXPR
, ind_var
,
7523 build_one_cst (type
));
7525 /* Replace GIMPLE_OMP_CONTINUE. */
7526 gsi_replace (&gsi
, stmt
, true);
7529 /* Emit the condition in L1_BB. */
7530 gsi
= gsi_after_labels (l1_bb
);
7531 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
7532 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
7534 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
7535 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7536 fd
->loop
.n1
, fold_convert (sizetype
, t
));
7538 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7539 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
7540 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
7541 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7543 /* The condition is always '<' since the runtime will fill in the low
7545 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
7546 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
7548 /* Remove GIMPLE_OMP_RETURN. */
7549 gsi
= gsi_last_bb (exit_bb
);
7550 gsi_remove (&gsi
, true);
7552 /* Connect the new blocks. */
7553 remove_edge (FALLTHRU_EDGE (entry_bb
));
7558 remove_edge (BRANCH_EDGE (entry_bb
));
7559 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7561 e
= BRANCH_EDGE (l1_bb
);
7562 ne
= FALLTHRU_EDGE (l1_bb
);
7563 e
->flags
= EDGE_TRUE_VALUE
;
7567 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7569 ne
= single_succ_edge (l1_bb
);
7570 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7573 ne
->flags
= EDGE_FALSE_VALUE
;
7574 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7575 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7577 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7578 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7579 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7583 struct loop
*loop
= alloc_loop ();
7584 loop
->header
= l1_bb
;
7585 loop
->latch
= cont_bb
;
7586 add_loop (loop
, l1_bb
->loop_father
);
7587 loop
->safelen
= INT_MAX
;
7590 /* Pick the correct library function based on the precision of the
7591 induction variable type. */
7592 tree lib_fun
= NULL_TREE
;
7593 if (TYPE_PRECISION (type
) == 32)
7594 lib_fun
= cilk_for_32_fndecl
;
7595 else if (TYPE_PRECISION (type
) == 64)
7596 lib_fun
= cilk_for_64_fndecl
;
7600 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
7602 /* WS_ARGS contains the library function flavor to call:
7603 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7604 user-defined grain value. If the user does not define one, then zero
7605 is passed in by the parser. */
7606 vec_alloc (region
->ws_args
, 2);
7607 region
->ws_args
->quick_push (lib_fun
);
7608 region
->ws_args
->quick_push (fd
->chunk_size
);
7611 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7612 loop. Given parameters:
7614 for (V = N1; V cond N2; V += STEP) BODY;
7616 where COND is "<" or ">", we generate pseudocode
7624 if (V cond N2) goto L0; else goto L2;
7627 For collapsed loops, given parameters:
7629 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7630 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7631 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7634 we generate pseudocode
7640 count3 = (adj + N32 - N31) / STEP3;
7645 count2 = (adj + N22 - N21) / STEP2;
7650 count1 = (adj + N12 - N11) / STEP1;
7651 count = count1 * count2 * count3;
7661 V2 += (V3 cond3 N32) ? 0 : STEP2;
7662 V3 = (V3 cond3 N32) ? V3 : N31;
7663 V1 += (V2 cond2 N22) ? 0 : STEP1;
7664 V2 = (V2 cond2 N22) ? V2 : N21;
7666 if (V < count) goto L0; else goto L2;
7672 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
7675 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
7676 gimple_stmt_iterator gsi
;
7679 bool broken_loop
= region
->cont
== NULL
;
7681 tree
*counts
= NULL
;
7683 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7684 OMP_CLAUSE_SAFELEN
);
7685 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7686 OMP_CLAUSE__SIMDUID_
);
7689 type
= TREE_TYPE (fd
->loop
.v
);
7690 entry_bb
= region
->entry
;
7691 cont_bb
= region
->cont
;
7692 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7693 gcc_assert (broken_loop
7694 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7695 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7698 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7699 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7700 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7701 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7705 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7706 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7707 l2_bb
= single_succ (l1_bb
);
7709 exit_bb
= region
->exit
;
7712 gsi
= gsi_last_bb (entry_bb
);
7714 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7715 /* Not needed in SSA form right now. */
7716 gcc_assert (!gimple_in_ssa_p (cfun
));
7717 if (fd
->collapse
> 1)
7719 int first_zero_iter
= -1;
7720 basic_block zero_iter_bb
= l2_bb
;
7722 counts
= XALLOCAVEC (tree
, fd
->collapse
);
7723 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7724 zero_iter_bb
, first_zero_iter
,
7727 if (l2_dom_bb
== NULL
)
7732 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7734 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7735 OMP_CLAUSE__LOOPTEMP_
);
7736 gcc_assert (innerc
);
7737 n1
= OMP_CLAUSE_DECL (innerc
);
7738 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7739 OMP_CLAUSE__LOOPTEMP_
);
7740 gcc_assert (innerc
);
7741 n2
= OMP_CLAUSE_DECL (innerc
);
7742 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7743 fold_convert (type
, n1
));
7744 if (fd
->collapse
> 1)
7747 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
7753 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7754 fold_convert (type
, fd
->loop
.n1
));
7755 if (fd
->collapse
> 1)
7756 for (i
= 0; i
< fd
->collapse
; i
++)
7758 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7759 if (POINTER_TYPE_P (itype
))
7760 itype
= signed_type_for (itype
);
7761 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
7762 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7766 /* Remove the GIMPLE_OMP_FOR statement. */
7767 gsi_remove (&gsi
, true);
7771 /* Code to control the increment goes in the CONT_BB. */
7772 gsi
= gsi_last_bb (cont_bb
);
7773 stmt
= gsi_stmt (gsi
);
7774 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7776 if (POINTER_TYPE_P (type
))
7777 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
7779 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
7780 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7782 if (fd
->collapse
> 1)
7784 i
= fd
->collapse
- 1;
7785 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7787 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
7788 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
7792 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
7794 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7797 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7799 for (i
= fd
->collapse
- 1; i
> 0; i
--)
7801 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7802 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
7803 if (POINTER_TYPE_P (itype2
))
7804 itype2
= signed_type_for (itype2
);
7805 t
= build3 (COND_EXPR
, itype2
,
7806 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7808 fold_convert (itype
, fd
->loops
[i
].n2
)),
7809 build_int_cst (itype2
, 0),
7810 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
7811 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
7812 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
7814 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
7815 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
7817 t
= build3 (COND_EXPR
, itype
,
7818 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7820 fold_convert (itype
, fd
->loops
[i
].n2
)),
7822 fold_convert (itype
, fd
->loops
[i
].n1
));
7823 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7827 /* Remove GIMPLE_OMP_CONTINUE. */
7828 gsi_remove (&gsi
, true);
7831 /* Emit the condition in L1_BB. */
7832 gsi
= gsi_start_bb (l1_bb
);
7834 t
= fold_convert (type
, n2
);
7835 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7836 false, GSI_CONTINUE_LINKING
);
7837 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
7838 cond_stmt
= gimple_build_cond_empty (t
);
7839 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
7840 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7842 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7845 gsi
= gsi_for_stmt (cond_stmt
);
7846 gimple_regimplify_operands (cond_stmt
, &gsi
);
7849 /* Remove GIMPLE_OMP_RETURN. */
7850 gsi
= gsi_last_bb (exit_bb
);
7851 gsi_remove (&gsi
, true);
7853 /* Connect the new blocks. */
7854 remove_edge (FALLTHRU_EDGE (entry_bb
));
7858 remove_edge (BRANCH_EDGE (entry_bb
));
7859 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7861 e
= BRANCH_EDGE (l1_bb
);
7862 ne
= FALLTHRU_EDGE (l1_bb
);
7863 e
->flags
= EDGE_TRUE_VALUE
;
7867 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7869 ne
= single_succ_edge (l1_bb
);
7870 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7873 ne
->flags
= EDGE_FALSE_VALUE
;
7874 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7875 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7877 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7878 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7879 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7883 struct loop
*loop
= alloc_loop ();
7884 loop
->header
= l1_bb
;
7885 loop
->latch
= cont_bb
;
7886 add_loop (loop
, l1_bb
->loop_father
);
7887 if (safelen
== NULL_TREE
)
7888 loop
->safelen
= INT_MAX
;
7891 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
7892 if (TREE_CODE (safelen
) != INTEGER_CST
)
7894 else if (!tree_fits_uhwi_p (safelen
)
7895 || tree_to_uhwi (safelen
) > INT_MAX
)
7896 loop
->safelen
= INT_MAX
;
7898 loop
->safelen
= tree_to_uhwi (safelen
);
7899 if (loop
->safelen
== 1)
7904 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
7905 cfun
->has_simduid_loops
= true;
7907 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7909 if ((flag_tree_loop_vectorize
7910 || (!global_options_set
.x_flag_tree_loop_vectorize
7911 && !global_options_set
.x_flag_tree_vectorize
))
7912 && flag_tree_loop_optimize
7913 && loop
->safelen
> 1)
7915 loop
->force_vectorize
= true;
7916 cfun
->has_force_vectorize_loops
= true;
7920 cfun
->has_simduid_loops
= true;
7924 /* Expand the OMP loop defined by REGION. */
7927 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
7929 struct omp_for_data fd
;
7930 struct omp_for_data_loop
*loops
;
7933 = (struct omp_for_data_loop
*)
7934 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
7935 * sizeof (struct omp_for_data_loop
));
7936 extract_omp_for_data (as_a
<gomp_for
*> (last_stmt (region
->entry
)),
7938 region
->sched_kind
= fd
.sched_kind
;
7940 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
7941 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7942 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7945 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
7946 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7947 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7950 /* If there isn't a continue then this is a degerate case where
7951 the introduction of abnormal edges during lowering will prevent
7952 original loops from being detected. Fix that up. */
7953 loops_state_set (LOOPS_NEED_FIXUP
);
7955 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
7956 expand_omp_simd (region
, &fd
);
7957 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
7958 expand_cilk_for (region
, &fd
);
7959 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
7960 && !fd
.have_ordered
)
7962 if (fd
.chunk_size
== NULL
)
7963 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
7965 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
7969 int fn_index
, start_ix
, next_ix
;
7971 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
7972 == GF_OMP_FOR_KIND_FOR
);
7973 if (fd
.chunk_size
== NULL
7974 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
7975 fd
.chunk_size
= integer_zero_node
;
7976 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
7977 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
7978 ? 3 : fd
.sched_kind
;
7979 fn_index
+= fd
.have_ordered
* 4;
7980 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
7981 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
7982 if (fd
.iter_type
== long_long_unsigned_type_node
)
7984 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7985 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
7986 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7987 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7989 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7990 (enum built_in_function
) next_ix
, inner_stmt
);
7993 if (gimple_in_ssa_p (cfun
))
7994 update_ssa (TODO_update_ssa_only_virtuals
);
7998 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
8000 v = GOMP_sections_start (n);
8017 v = GOMP_sections_next ();
8022 If this is a combined parallel sections, replace the call to
8023 GOMP_sections_start with call to GOMP_sections_next. */
8026 expand_omp_sections (struct omp_region
*region
)
8028 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
8030 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
8031 gimple_stmt_iterator si
, switch_si
;
8032 gomp_sections
*sections_stmt
;
8034 gomp_continue
*cont
;
8037 struct omp_region
*inner
;
8039 bool exit_reachable
= region
->cont
!= NULL
;
8041 gcc_assert (region
->exit
!= NULL
);
8042 entry_bb
= region
->entry
;
8043 l0_bb
= single_succ (entry_bb
);
8044 l1_bb
= region
->cont
;
8045 l2_bb
= region
->exit
;
8046 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
8047 l2
= gimple_block_label (l2_bb
);
8050 /* This can happen if there are reductions. */
8051 len
= EDGE_COUNT (l0_bb
->succs
);
8052 gcc_assert (len
> 0);
8053 e
= EDGE_SUCC (l0_bb
, len
- 1);
8054 si
= gsi_last_bb (e
->dest
);
8057 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
8058 l2
= gimple_block_label (e
->dest
);
8060 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
8062 si
= gsi_last_bb (e
->dest
);
8064 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
8066 l2
= gimple_block_label (e
->dest
);
8072 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
8074 default_bb
= create_empty_bb (l0_bb
);
8076 /* We will build a switch() with enough cases for all the
8077 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8078 and a default case to abort if something goes wrong. */
8079 len
= EDGE_COUNT (l0_bb
->succs
);
8081 /* Use vec::quick_push on label_vec throughout, since we know the size
8083 auto_vec
<tree
> label_vec (len
);
8085 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8086 GIMPLE_OMP_SECTIONS statement. */
8087 si
= gsi_last_bb (entry_bb
);
8088 sections_stmt
= as_a
<gomp_sections
*> (gsi_stmt (si
));
8089 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
8090 vin
= gimple_omp_sections_control (sections_stmt
);
8091 if (!is_combined_parallel (region
))
8093 /* If we are not inside a combined parallel+sections region,
8094 call GOMP_sections_start. */
8095 t
= build_int_cst (unsigned_type_node
, len
- 1);
8096 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
8097 stmt
= gimple_build_call (u
, 1, t
);
8101 /* Otherwise, call GOMP_sections_next. */
8102 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8103 stmt
= gimple_build_call (u
, 0);
8105 gimple_call_set_lhs (stmt
, vin
);
8106 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8107 gsi_remove (&si
, true);
8109 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8111 switch_si
= gsi_last_bb (l0_bb
);
8112 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
8115 cont
= as_a
<gomp_continue
*> (last_stmt (l1_bb
));
8116 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
8117 vmain
= gimple_omp_continue_control_use (cont
);
8118 vnext
= gimple_omp_continue_control_def (cont
);
8126 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
8127 label_vec
.quick_push (t
);
8130 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8131 for (inner
= region
->inner
, casei
= 1;
8133 inner
= inner
->next
, i
++, casei
++)
8135 basic_block s_entry_bb
, s_exit_bb
;
8137 /* Skip optional reduction region. */
8138 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
8145 s_entry_bb
= inner
->entry
;
8146 s_exit_bb
= inner
->exit
;
8148 t
= gimple_block_label (s_entry_bb
);
8149 u
= build_int_cst (unsigned_type_node
, casei
);
8150 u
= build_case_label (u
, NULL
, t
);
8151 label_vec
.quick_push (u
);
8153 si
= gsi_last_bb (s_entry_bb
);
8154 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
8155 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
8156 gsi_remove (&si
, true);
8157 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
8159 if (s_exit_bb
== NULL
)
8162 si
= gsi_last_bb (s_exit_bb
);
8163 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8164 gsi_remove (&si
, true);
8166 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
8169 /* Error handling code goes in DEFAULT_BB. */
8170 t
= gimple_block_label (default_bb
);
8171 u
= build_case_label (NULL
, NULL
, t
);
8172 make_edge (l0_bb
, default_bb
, 0);
8173 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
8175 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
8176 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
8177 gsi_remove (&switch_si
, true);
8179 si
= gsi_start_bb (default_bb
);
8180 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
8181 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
8187 /* Code to get the next section goes in L1_BB. */
8188 si
= gsi_last_bb (l1_bb
);
8189 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
8191 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8192 stmt
= gimple_build_call (bfn_decl
, 0);
8193 gimple_call_set_lhs (stmt
, vnext
);
8194 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8195 gsi_remove (&si
, true);
8197 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
8200 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8201 si
= gsi_last_bb (l2_bb
);
8202 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
8203 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
8204 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
8205 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
8207 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
8208 stmt
= gimple_build_call (t
, 0);
8209 if (gimple_omp_return_lhs (gsi_stmt (si
)))
8210 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
8211 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8212 gsi_remove (&si
, true);
8214 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
8218 /* Expand code for an OpenMP single directive. We've already expanded
8219 much of the code, here we simply place the GOMP_barrier call. */
8222 expand_omp_single (struct omp_region
*region
)
8224 basic_block entry_bb
, exit_bb
;
8225 gimple_stmt_iterator si
;
8227 entry_bb
= region
->entry
;
8228 exit_bb
= region
->exit
;
8230 si
= gsi_last_bb (entry_bb
);
8231 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
8232 gsi_remove (&si
, true);
8233 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8235 si
= gsi_last_bb (exit_bb
);
8236 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
8238 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
8239 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
8241 gsi_remove (&si
, true);
8242 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8246 /* Generic expansion for OpenMP synchronization directives: master,
8247 ordered and critical. All we need to do here is remove the entry
8248 and exit markers for REGION. */
8251 expand_omp_synch (struct omp_region
*region
)
8253 basic_block entry_bb
, exit_bb
;
8254 gimple_stmt_iterator si
;
8256 entry_bb
= region
->entry
;
8257 exit_bb
= region
->exit
;
8259 si
= gsi_last_bb (entry_bb
);
8260 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
8261 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
8262 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
8263 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
8264 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
8265 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
8266 gsi_remove (&si
, true);
8267 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8271 si
= gsi_last_bb (exit_bb
);
8272 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8273 gsi_remove (&si
, true);
8274 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8278 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8279 operation as a normal volatile load. */
8282 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
8283 tree loaded_val
, int index
)
8285 enum built_in_function tmpbase
;
8286 gimple_stmt_iterator gsi
;
8287 basic_block store_bb
;
8290 tree decl
, call
, type
, itype
;
8292 gsi
= gsi_last_bb (load_bb
);
8293 stmt
= gsi_stmt (gsi
);
8294 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8295 loc
= gimple_location (stmt
);
8297 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8298 is smaller than word size, then expand_atomic_load assumes that the load
8299 is atomic. We could avoid the builtin entirely in this case. */
8301 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8302 decl
= builtin_decl_explicit (tmpbase
);
8303 if (decl
== NULL_TREE
)
8306 type
= TREE_TYPE (loaded_val
);
8307 itype
= TREE_TYPE (TREE_TYPE (decl
));
8309 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
8310 build_int_cst (NULL
,
8311 gimple_omp_atomic_seq_cst_p (stmt
)
8313 : MEMMODEL_RELAXED
));
8314 if (!useless_type_conversion_p (type
, itype
))
8315 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8316 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8318 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8319 gsi_remove (&gsi
, true);
8321 store_bb
= single_succ (load_bb
);
8322 gsi
= gsi_last_bb (store_bb
);
8323 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8324 gsi_remove (&gsi
, true);
8326 if (gimple_in_ssa_p (cfun
))
8327 update_ssa (TODO_update_ssa_no_phi
);
8332 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8333 operation as a normal volatile store. */
8336 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
8337 tree loaded_val
, tree stored_val
, int index
)
8339 enum built_in_function tmpbase
;
8340 gimple_stmt_iterator gsi
;
8341 basic_block store_bb
= single_succ (load_bb
);
8344 tree decl
, call
, type
, itype
;
8348 gsi
= gsi_last_bb (load_bb
);
8349 stmt
= gsi_stmt (gsi
);
8350 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8352 /* If the load value is needed, then this isn't a store but an exchange. */
8353 exchange
= gimple_omp_atomic_need_value_p (stmt
);
8355 gsi
= gsi_last_bb (store_bb
);
8356 stmt
= gsi_stmt (gsi
);
8357 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
8358 loc
= gimple_location (stmt
);
8360 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8361 is smaller than word size, then expand_atomic_store assumes that the store
8362 is atomic. We could avoid the builtin entirely in this case. */
8364 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
8365 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
8366 decl
= builtin_decl_explicit (tmpbase
);
8367 if (decl
== NULL_TREE
)
8370 type
= TREE_TYPE (stored_val
);
8372 /* Dig out the type of the function's second argument. */
8373 itype
= TREE_TYPE (decl
);
8374 itype
= TYPE_ARG_TYPES (itype
);
8375 itype
= TREE_CHAIN (itype
);
8376 itype
= TREE_VALUE (itype
);
8377 imode
= TYPE_MODE (itype
);
8379 if (exchange
&& !can_atomic_exchange_p (imode
, true))
8382 if (!useless_type_conversion_p (itype
, type
))
8383 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
8384 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
8385 build_int_cst (NULL
,
8386 gimple_omp_atomic_seq_cst_p (stmt
)
8388 : MEMMODEL_RELAXED
));
8391 if (!useless_type_conversion_p (type
, itype
))
8392 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8393 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8396 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8397 gsi_remove (&gsi
, true);
8399 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8400 gsi
= gsi_last_bb (load_bb
);
8401 gsi_remove (&gsi
, true);
8403 if (gimple_in_ssa_p (cfun
))
8404 update_ssa (TODO_update_ssa_no_phi
);
8409 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8410 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8411 size of the data type, and thus usable to find the index of the builtin
8412 decl. Returns false if the expression is not of the proper form. */
8415 expand_omp_atomic_fetch_op (basic_block load_bb
,
8416 tree addr
, tree loaded_val
,
8417 tree stored_val
, int index
)
8419 enum built_in_function oldbase
, newbase
, tmpbase
;
8420 tree decl
, itype
, call
;
8422 basic_block store_bb
= single_succ (load_bb
);
8423 gimple_stmt_iterator gsi
;
8426 enum tree_code code
;
8427 bool need_old
, need_new
;
8431 /* We expect to find the following sequences:
8434 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8437 val = tmp OP something; (or: something OP tmp)
8438 GIMPLE_OMP_STORE (val)
8440 ???FIXME: Allow a more flexible sequence.
8441 Perhaps use data flow to pick the statements.
8445 gsi
= gsi_after_labels (store_bb
);
8446 stmt
= gsi_stmt (gsi
);
8447 loc
= gimple_location (stmt
);
8448 if (!is_gimple_assign (stmt
))
8451 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
8453 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
8454 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
8455 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
8456 gcc_checking_assert (!need_old
|| !need_new
);
8458 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
8461 /* Check for one of the supported fetch-op operations. */
8462 code
= gimple_assign_rhs_code (stmt
);
8466 case POINTER_PLUS_EXPR
:
8467 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
8468 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
8471 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
8472 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
8475 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
8476 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
8479 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
8480 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
8483 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
8484 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
8490 /* Make sure the expression is of the proper form. */
8491 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
8492 rhs
= gimple_assign_rhs2 (stmt
);
8493 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
8494 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
8495 rhs
= gimple_assign_rhs1 (stmt
);
8499 tmpbase
= ((enum built_in_function
)
8500 ((need_new
? newbase
: oldbase
) + index
+ 1));
8501 decl
= builtin_decl_explicit (tmpbase
);
8502 if (decl
== NULL_TREE
)
8504 itype
= TREE_TYPE (TREE_TYPE (decl
));
8505 imode
= TYPE_MODE (itype
);
8507 /* We could test all of the various optabs involved, but the fact of the
8508 matter is that (with the exception of i486 vs i586 and xadd) all targets
8509 that support any atomic operaton optab also implements compare-and-swap.
8510 Let optabs.c take care of expanding any compare-and-swap loop. */
8511 if (!can_compare_and_swap_p (imode
, true))
8514 gsi
= gsi_last_bb (load_bb
);
8515 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8517 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8518 It only requires that the operation happen atomically. Thus we can
8519 use the RELAXED memory model. */
8520 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
8521 fold_convert_loc (loc
, itype
, rhs
),
8522 build_int_cst (NULL
,
8523 seq_cst
? MEMMODEL_SEQ_CST
8524 : MEMMODEL_RELAXED
));
8526 if (need_old
|| need_new
)
8528 lhs
= need_old
? loaded_val
: stored_val
;
8529 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
8530 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
8533 call
= fold_convert_loc (loc
, void_type_node
, call
);
8534 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8535 gsi_remove (&gsi
, true);
8537 gsi
= gsi_last_bb (store_bb
);
8538 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8539 gsi_remove (&gsi
, true);
8540 gsi
= gsi_last_bb (store_bb
);
8541 gsi_remove (&gsi
, true);
8543 if (gimple_in_ssa_p (cfun
))
8544 update_ssa (TODO_update_ssa_no_phi
);
8549 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8553 newval = rhs; // with oldval replacing *addr in rhs
8554 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8555 if (oldval != newval)
8558 INDEX is log2 of the size of the data type, and thus usable to find the
8559 index of the builtin decl. */
8562 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
8563 tree addr
, tree loaded_val
, tree stored_val
,
8566 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
8567 tree type
, itype
, cmpxchg
, iaddr
;
8568 gimple_stmt_iterator si
;
8569 basic_block loop_header
= single_succ (load_bb
);
8572 enum built_in_function fncode
;
8574 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8575 order to use the RELAXED memory model effectively. */
8576 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8578 cmpxchg
= builtin_decl_explicit (fncode
);
8579 if (cmpxchg
== NULL_TREE
)
8581 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8582 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
8584 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
8587 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8588 si
= gsi_last_bb (load_bb
);
8589 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8591 /* For floating-point values, we'll need to view-convert them to integers
8592 so that we can perform the atomic compare and swap. Simplify the
8593 following code by always setting up the "i"ntegral variables. */
8594 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
8598 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
8601 = force_gimple_operand_gsi (&si
,
8602 fold_convert (TREE_TYPE (iaddr
), addr
),
8603 false, NULL_TREE
, true, GSI_SAME_STMT
);
8604 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
8605 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8606 loadedi
= create_tmp_var (itype
);
8607 if (gimple_in_ssa_p (cfun
))
8608 loadedi
= make_ssa_name (loadedi
);
8613 loadedi
= loaded_val
;
8616 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8617 tree loaddecl
= builtin_decl_explicit (fncode
);
8620 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
8621 build_call_expr (loaddecl
, 2, iaddr
,
8622 build_int_cst (NULL_TREE
,
8623 MEMMODEL_RELAXED
)));
8625 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
8626 build_int_cst (TREE_TYPE (iaddr
), 0));
8629 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
8632 /* Move the value to the LOADEDI temporary. */
8633 if (gimple_in_ssa_p (cfun
))
8635 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
8636 phi
= create_phi_node (loadedi
, loop_header
);
8637 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
8641 gsi_insert_before (&si
,
8642 gimple_build_assign (loadedi
, initial
),
8644 if (loadedi
!= loaded_val
)
8646 gimple_stmt_iterator gsi2
;
8649 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
8650 gsi2
= gsi_start_bb (loop_header
);
8651 if (gimple_in_ssa_p (cfun
))
8654 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8655 true, GSI_SAME_STMT
);
8656 stmt
= gimple_build_assign (loaded_val
, x
);
8657 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
8661 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
8662 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8663 true, GSI_SAME_STMT
);
8666 gsi_remove (&si
, true);
8668 si
= gsi_last_bb (store_bb
);
8669 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8672 storedi
= stored_val
;
8675 force_gimple_operand_gsi (&si
,
8676 build1 (VIEW_CONVERT_EXPR
, itype
,
8677 stored_val
), true, NULL_TREE
, true,
8680 /* Build the compare&swap statement. */
8681 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
8682 new_storedi
= force_gimple_operand_gsi (&si
,
8683 fold_convert (TREE_TYPE (loadedi
),
8686 true, GSI_SAME_STMT
);
8688 if (gimple_in_ssa_p (cfun
))
8692 old_vali
= create_tmp_var (TREE_TYPE (loadedi
));
8693 stmt
= gimple_build_assign (old_vali
, loadedi
);
8694 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8696 stmt
= gimple_build_assign (loadedi
, new_storedi
);
8697 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8700 /* Note that we always perform the comparison as an integer, even for
8701 floating point. This allows the atomic operation to properly
8702 succeed even with NaNs and -0.0. */
8703 stmt
= gimple_build_cond_empty
8704 (build2 (NE_EXPR
, boolean_type_node
,
8705 new_storedi
, old_vali
));
8706 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8709 e
= single_succ_edge (store_bb
);
8710 e
->flags
&= ~EDGE_FALLTHRU
;
8711 e
->flags
|= EDGE_FALSE_VALUE
;
8713 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
8715 /* Copy the new value to loadedi (we already did that before the condition
8716 if we are not in SSA). */
8717 if (gimple_in_ssa_p (cfun
))
8719 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
8720 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
8723 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8724 gsi_remove (&si
, true);
8726 struct loop
*loop
= alloc_loop ();
8727 loop
->header
= loop_header
;
8728 loop
->latch
= store_bb
;
8729 add_loop (loop
, loop_header
->loop_father
);
8731 if (gimple_in_ssa_p (cfun
))
8732 update_ssa (TODO_update_ssa_no_phi
);
8737 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8739 GOMP_atomic_start ();
8743 The result is not globally atomic, but works so long as all parallel
8744 references are within #pragma omp atomic directives. According to
8745 responses received from omp@openmp.org, appears to be within spec.
8746 Which makes sense, since that's how several other compilers handle
8747 this situation as well.
8748 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8749 expanding. STORED_VAL is the operand of the matching
8750 GIMPLE_OMP_ATOMIC_STORE.
8753 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8757 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8762 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
8763 tree addr
, tree loaded_val
, tree stored_val
)
8765 gimple_stmt_iterator si
;
8769 si
= gsi_last_bb (load_bb
);
8770 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8772 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
8773 t
= build_call_expr (t
, 0);
8774 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8776 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
8777 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8778 gsi_remove (&si
, true);
8780 si
= gsi_last_bb (store_bb
);
8781 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8783 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
8785 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8787 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
8788 t
= build_call_expr (t
, 0);
8789 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8790 gsi_remove (&si
, true);
8792 if (gimple_in_ssa_p (cfun
))
8793 update_ssa (TODO_update_ssa_no_phi
);
8797 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8798 using expand_omp_atomic_fetch_op. If it failed, we try to
8799 call expand_omp_atomic_pipeline, and if it fails too, the
8800 ultimate fallback is wrapping the operation in a mutex
8801 (expand_omp_atomic_mutex). REGION is the atomic region built
8802 by build_omp_regions_1(). */
8805 expand_omp_atomic (struct omp_region
*region
)
8807 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
8808 gomp_atomic_load
*load
= as_a
<gomp_atomic_load
*> (last_stmt (load_bb
));
8809 gomp_atomic_store
*store
= as_a
<gomp_atomic_store
*> (last_stmt (store_bb
));
8810 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
8811 tree addr
= gimple_omp_atomic_load_rhs (load
);
8812 tree stored_val
= gimple_omp_atomic_store_val (store
);
8813 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8814 HOST_WIDE_INT index
;
8816 /* Make sure the type is one of the supported sizes. */
8817 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
8818 index
= exact_log2 (index
);
8819 if (index
>= 0 && index
<= 4)
8821 unsigned int align
= TYPE_ALIGN_UNIT (type
);
8823 /* __sync builtins require strict data alignment. */
8824 if (exact_log2 (align
) >= index
)
8827 if (loaded_val
== stored_val
8828 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8829 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8830 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8831 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
8835 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8836 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8837 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8838 && store_bb
== single_succ (load_bb
)
8839 && first_stmt (store_bb
) == store
8840 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
8844 /* When possible, use specialized atomic update functions. */
8845 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
8846 && store_bb
== single_succ (load_bb
)
8847 && expand_omp_atomic_fetch_op (load_bb
, addr
,
8848 loaded_val
, stored_val
, index
))
8851 /* If we don't have specialized __sync builtins, try and implement
8852 as a compare and swap loop. */
8853 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
8854 loaded_val
, stored_val
, index
))
8859 /* The ultimate fallback is wrapping the operation in a mutex. */
8860 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
8864 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8867 expand_omp_target (struct omp_region
*region
)
8869 basic_block entry_bb
, exit_bb
, new_bb
;
8870 struct function
*child_cfun
;
8871 tree child_fn
, block
, t
;
8872 gimple_stmt_iterator gsi
;
8873 gomp_target
*entry_stmt
;
8876 bool offloaded
, data_region
;
8878 entry_stmt
= as_a
<gomp_target
*> (last_stmt (region
->entry
));
8879 new_bb
= region
->entry
;
8881 offloaded
= is_gimple_omp_offloaded (entry_stmt
);
8882 switch (gimple_omp_target_kind (entry_stmt
))
8884 case GF_OMP_TARGET_KIND_REGION
:
8885 case GF_OMP_TARGET_KIND_UPDATE
:
8886 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
8887 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
8888 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
8889 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
8890 data_region
= false;
8892 case GF_OMP_TARGET_KIND_DATA
:
8893 case GF_OMP_TARGET_KIND_OACC_DATA
:
8900 child_fn
= NULL_TREE
;
8904 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
8905 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
8908 /* Supported by expand_omp_taskreg, but not here. */
8909 if (child_cfun
!= NULL
)
8910 gcc_checking_assert (!child_cfun
->cfg
);
8911 gcc_checking_assert (!gimple_in_ssa_p (cfun
));
8913 entry_bb
= region
->entry
;
8914 exit_bb
= region
->exit
;
8918 unsigned srcidx
, dstidx
, num
;
8920 /* If the offloading region needs data sent from the parent
8921 function, then the very first statement (except possible
8922 tree profile counter updates) of the offloading body
8923 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8924 &.OMP_DATA_O is passed as an argument to the child function,
8925 we need to replace it with the argument as seen by the child
8928 In most cases, this will end up being the identity assignment
8929 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8930 a function call that has been inlined, the original PARM_DECL
8931 .OMP_DATA_I may have been converted into a different local
8932 variable. In which case, we need to keep the assignment. */
8933 tree data_arg
= gimple_omp_target_data_arg (entry_stmt
);
8936 basic_block entry_succ_bb
= single_succ (entry_bb
);
8937 gimple_stmt_iterator gsi
;
8939 gimple tgtcopy_stmt
= NULL
;
8940 tree sender
= TREE_VEC_ELT (data_arg
, 0);
8942 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
8944 gcc_assert (!gsi_end_p (gsi
));
8945 stmt
= gsi_stmt (gsi
);
8946 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
8949 if (gimple_num_ops (stmt
) == 2)
8951 tree arg
= gimple_assign_rhs1 (stmt
);
8953 /* We're ignoring the subcode because we're
8954 effectively doing a STRIP_NOPS. */
8956 if (TREE_CODE (arg
) == ADDR_EXPR
8957 && TREE_OPERAND (arg
, 0) == sender
)
8959 tgtcopy_stmt
= stmt
;
8965 gcc_assert (tgtcopy_stmt
!= NULL
);
8966 arg
= DECL_ARGUMENTS (child_fn
);
8968 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
8969 gsi_remove (&gsi
, true);
8972 /* Declare local variables needed in CHILD_CFUN. */
8973 block
= DECL_INITIAL (child_fn
);
8974 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
8975 /* The gimplifier could record temporaries in the offloading block
8976 rather than in containing function's local_decls chain,
8977 which would mean cgraph missed finalizing them. Do it now. */
8978 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
8979 if (TREE_CODE (t
) == VAR_DECL
8981 && !DECL_EXTERNAL (t
))
8982 varpool_node::finalize_decl (t
);
8983 DECL_SAVED_TREE (child_fn
) = NULL
;
8984 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8985 gimple_set_body (child_fn
, NULL
);
8986 TREE_USED (block
) = 1;
8988 /* Reset DECL_CONTEXT on function arguments. */
8989 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
8990 DECL_CONTEXT (t
) = child_fn
;
8992 /* Split ENTRY_BB at GIMPLE_*,
8993 so that it can be moved to the child function. */
8994 gsi
= gsi_last_bb (entry_bb
);
8995 stmt
= gsi_stmt (gsi
);
8997 && gimple_code (stmt
) == gimple_code (entry_stmt
));
8998 e
= split_block (entry_bb
, stmt
);
8999 gsi_remove (&gsi
, true);
9001 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
9003 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
9006 gsi
= gsi_last_bb (exit_bb
);
9007 gcc_assert (!gsi_end_p (gsi
)
9008 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
9009 stmt
= gimple_build_return (NULL
);
9010 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
9011 gsi_remove (&gsi
, true);
9014 /* Move the offloading region into CHILD_CFUN. */
9016 block
= gimple_block (entry_stmt
);
9018 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
9020 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
9021 /* When the OMP expansion process cannot guarantee an up-to-date
9022 loop tree arrange for the child function to fixup loops. */
9023 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
9024 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
9026 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9027 num
= vec_safe_length (child_cfun
->local_decls
);
9028 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
9030 t
= (*child_cfun
->local_decls
)[srcidx
];
9031 if (DECL_CONTEXT (t
) == cfun
->decl
)
9033 if (srcidx
!= dstidx
)
9034 (*child_cfun
->local_decls
)[dstidx
] = t
;
9038 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
9040 /* Inform the callgraph about the new function. */
9041 child_cfun
->curr_properties
= cfun
->curr_properties
;
9042 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
9043 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
9044 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
9045 node
->parallelized_function
= 1;
9046 cgraph_node::add_new_function (child_fn
, true);
9048 #ifdef ENABLE_OFFLOADING
9049 /* Add the new function to the offload table. */
9050 vec_safe_push (offload_funcs
, child_fn
);
9053 /* Fix the callgraph edges for child_cfun. Those for cfun will be
9054 fixed in a following pass. */
9055 push_cfun (child_cfun
);
9056 cgraph_edge::rebuild_edges ();
9058 #ifdef ENABLE_OFFLOADING
9059 /* Prevent IPA from removing child_fn as unreachable, since there are no
9060 refs from the parent function to child_fn in offload LTO mode. */
9061 cgraph_node::get (child_fn
)->mark_force_output ();
9064 /* Some EH regions might become dead, see PR34608. If
9065 pass_cleanup_cfg isn't the first pass to happen with the
9066 new child, these dead EH edges might cause problems.
9067 Clean them up now. */
9068 if (flag_exceptions
)
9071 bool changed
= false;
9073 FOR_EACH_BB_FN (bb
, cfun
)
9074 changed
|= gimple_purge_dead_eh_edges (bb
);
9076 cleanup_tree_cfg ();
9078 #ifdef ENABLE_CHECKING
9079 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
9080 verify_loop_structure ();
9085 /* Emit a library call to launch the offloading region, or do data
9087 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
9088 enum built_in_function start_ix
;
9089 location_t clause_loc
;
9091 switch (gimple_omp_target_kind (entry_stmt
))
9093 case GF_OMP_TARGET_KIND_REGION
:
9094 start_ix
= BUILT_IN_GOMP_TARGET
;
9096 case GF_OMP_TARGET_KIND_DATA
:
9097 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
9099 case GF_OMP_TARGET_KIND_UPDATE
:
9100 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
9102 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
9103 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
9104 start_ix
= BUILT_IN_GOACC_PARALLEL
;
9106 case GF_OMP_TARGET_KIND_OACC_DATA
:
9107 start_ix
= BUILT_IN_GOACC_DATA_START
;
9109 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9110 start_ix
= BUILT_IN_GOACC_UPDATE
;
9112 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9113 start_ix
= BUILT_IN_GOACC_ENTER_EXIT_DATA
;
9119 clauses
= gimple_omp_target_clauses (entry_stmt
);
9121 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9122 library choose) and there is no conditional. */
9124 device
= build_int_cst (integer_type_node
, GOMP_DEVICE_ICV
);
9126 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
9128 cond
= OMP_CLAUSE_IF_EXPR (c
);
9130 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
9133 /* Even if we pass it to all library function calls, it is currently only
9134 defined/used for the OpenMP target ones. */
9135 gcc_checking_assert (start_ix
== BUILT_IN_GOMP_TARGET
9136 || start_ix
== BUILT_IN_GOMP_TARGET_DATA
9137 || start_ix
== BUILT_IN_GOMP_TARGET_UPDATE
);
9139 device
= OMP_CLAUSE_DEVICE_ID (c
);
9140 clause_loc
= OMP_CLAUSE_LOCATION (c
);
9143 clause_loc
= gimple_location (entry_stmt
);
9145 /* Ensure 'device' is of the correct type. */
9146 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
9148 /* If we found the clause 'if (cond)', build
9149 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9152 cond
= gimple_boolify (cond
);
9154 basic_block cond_bb
, then_bb
, else_bb
;
9158 tmp_var
= create_tmp_var (TREE_TYPE (device
));
9160 e
= split_block_after_labels (new_bb
);
9163 gsi
= gsi_last_bb (new_bb
);
9165 e
= split_block (new_bb
, gsi_stmt (gsi
));
9171 then_bb
= create_empty_bb (cond_bb
);
9172 else_bb
= create_empty_bb (then_bb
);
9173 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
9174 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
9176 stmt
= gimple_build_cond_empty (cond
);
9177 gsi
= gsi_last_bb (cond_bb
);
9178 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9180 gsi
= gsi_start_bb (then_bb
);
9181 stmt
= gimple_build_assign (tmp_var
, device
);
9182 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9184 gsi
= gsi_start_bb (else_bb
);
9185 stmt
= gimple_build_assign (tmp_var
,
9186 build_int_cst (integer_type_node
,
9187 GOMP_DEVICE_HOST_FALLBACK
));
9188 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9190 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
9191 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
9192 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
9193 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
9194 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
9195 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
9200 gsi
= gsi_last_bb (new_bb
);
9201 t
= gimple_omp_target_data_arg (entry_stmt
);
9204 t1
= size_zero_node
;
9205 t2
= build_zero_cst (ptr_type_node
);
9211 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
9212 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
9213 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
9214 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
9215 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
9219 /* The maximum number used by any start_ix, without varargs. */
9220 auto_vec
<tree
, 11> args
;
9221 args
.quick_push (device
);
9223 args
.quick_push (build_fold_addr_expr (child_fn
));
9226 case BUILT_IN_GOMP_TARGET
:
9227 case BUILT_IN_GOMP_TARGET_DATA
:
9228 case BUILT_IN_GOMP_TARGET_UPDATE
:
9229 /* This const void * is part of the current ABI, but we're not actually
9231 args
.quick_push (build_zero_cst (ptr_type_node
));
9233 case BUILT_IN_GOACC_DATA_START
:
9234 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9235 case BUILT_IN_GOACC_PARALLEL
:
9236 case BUILT_IN_GOACC_UPDATE
:
9241 args
.quick_push (t1
);
9242 args
.quick_push (t2
);
9243 args
.quick_push (t3
);
9244 args
.quick_push (t4
);
9247 case BUILT_IN_GOACC_DATA_START
:
9248 case BUILT_IN_GOMP_TARGET
:
9249 case BUILT_IN_GOMP_TARGET_DATA
:
9250 case BUILT_IN_GOMP_TARGET_UPDATE
:
9252 case BUILT_IN_GOACC_PARALLEL
:
9254 tree t_num_gangs
, t_num_workers
, t_vector_length
;
9256 /* Default values for num_gangs, num_workers, and vector_length. */
9257 t_num_gangs
= t_num_workers
= t_vector_length
9258 = fold_convert_loc (gimple_location (entry_stmt
),
9259 integer_type_node
, integer_one_node
);
9260 /* ..., but if present, use the value specified by the respective
9261 clause, making sure that are of the correct type. */
9262 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
9264 t_num_gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9266 OMP_CLAUSE_NUM_GANGS_EXPR (c
));
9267 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_WORKERS
);
9269 t_num_workers
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9271 OMP_CLAUSE_NUM_WORKERS_EXPR (c
));
9272 c
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
9274 t_vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9276 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c
));
9277 args
.quick_push (t_num_gangs
);
9278 args
.quick_push (t_num_workers
);
9279 args
.quick_push (t_vector_length
);
9282 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9283 case BUILT_IN_GOACC_UPDATE
:
9288 /* Default values for t_async. */
9289 t_async
= fold_convert_loc (gimple_location (entry_stmt
),
9291 build_int_cst (integer_type_node
,
9293 /* ..., but if present, use the value specified by the respective
9294 clause, making sure that is of the correct type. */
9295 c
= find_omp_clause (clauses
, OMP_CLAUSE_ASYNC
);
9297 t_async
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9299 OMP_CLAUSE_ASYNC_EXPR (c
));
9301 args
.quick_push (t_async
);
9302 /* Save the index, and... */
9303 t_wait_idx
= args
.length ();
9304 /* ... push a default value. */
9305 args
.quick_push (fold_convert_loc (gimple_location (entry_stmt
),
9307 integer_zero_node
));
9308 c
= find_omp_clause (clauses
, OMP_CLAUSE_WAIT
);
9313 for (; c
; c
= OMP_CLAUSE_CHAIN (c
))
9315 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WAIT
)
9317 args
.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9319 OMP_CLAUSE_WAIT_EXPR (c
)));
9324 /* Now that we know the number, replace the default value. */
9325 args
.ordered_remove (t_wait_idx
);
9326 args
.quick_insert (t_wait_idx
,
9327 fold_convert_loc (gimple_location (entry_stmt
),
9329 build_int_cst (integer_type_node
, n
)));
9337 g
= gimple_build_call_vec (builtin_decl_explicit (start_ix
), args
);
9338 gimple_set_location (g
, gimple_location (entry_stmt
));
9339 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
9343 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
9344 gsi_remove (&gsi
, true);
9349 gsi
= gsi_last_bb (region
->exit
);
9351 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
9352 gsi_remove (&gsi
, true);
9357 /* Expand the parallel region tree rooted at REGION. Expansion
9358 proceeds in depth-first order. Innermost regions are expanded
9359 first. This way, parallel regions that require a new function to
9360 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9361 internal dependencies in their body. */
9364 expand_omp (struct omp_region
*region
)
9368 location_t saved_location
;
9369 gimple inner_stmt
= NULL
;
9371 /* First, determine whether this is a combined parallel+workshare
9373 if (region
->type
== GIMPLE_OMP_PARALLEL
)
9374 determine_parallel_type (region
);
9376 if (region
->type
== GIMPLE_OMP_FOR
9377 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
9378 inner_stmt
= last_stmt (region
->inner
->entry
);
9381 expand_omp (region
->inner
);
9383 saved_location
= input_location
;
9384 if (gimple_has_location (last_stmt (region
->entry
)))
9385 input_location
= gimple_location (last_stmt (region
->entry
));
9387 switch (region
->type
)
9389 case GIMPLE_OMP_PARALLEL
:
9390 case GIMPLE_OMP_TASK
:
9391 expand_omp_taskreg (region
);
9394 case GIMPLE_OMP_FOR
:
9395 expand_omp_for (region
, inner_stmt
);
9398 case GIMPLE_OMP_SECTIONS
:
9399 expand_omp_sections (region
);
9402 case GIMPLE_OMP_SECTION
:
9403 /* Individual omp sections are handled together with their
9404 parent GIMPLE_OMP_SECTIONS region. */
9407 case GIMPLE_OMP_SINGLE
:
9408 expand_omp_single (region
);
9411 case GIMPLE_OMP_MASTER
:
9412 case GIMPLE_OMP_TASKGROUP
:
9413 case GIMPLE_OMP_ORDERED
:
9414 case GIMPLE_OMP_CRITICAL
:
9415 case GIMPLE_OMP_TEAMS
:
9416 expand_omp_synch (region
);
9419 case GIMPLE_OMP_ATOMIC_LOAD
:
9420 expand_omp_atomic (region
);
9423 case GIMPLE_OMP_TARGET
:
9424 expand_omp_target (region
);
9431 input_location
= saved_location
;
9432 region
= region
->next
;
9437 /* Helper for build_omp_regions. Scan the dominator tree starting at
9438 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9439 true, the function ends once a single tree is built (otherwise, whole
9440 forest of OMP constructs may be built). */
9443 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
9446 gimple_stmt_iterator gsi
;
9450 gsi
= gsi_last_bb (bb
);
9451 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
9453 struct omp_region
*region
;
9454 enum gimple_code code
;
9456 stmt
= gsi_stmt (gsi
);
9457 code
= gimple_code (stmt
);
9458 if (code
== GIMPLE_OMP_RETURN
)
9460 /* STMT is the return point out of region PARENT. Mark it
9461 as the exit point and make PARENT the immediately
9462 enclosing region. */
9463 gcc_assert (parent
);
9466 parent
= parent
->outer
;
9468 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
9470 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9471 GIMPLE_OMP_RETURN, but matches with
9472 GIMPLE_OMP_ATOMIC_LOAD. */
9473 gcc_assert (parent
);
9474 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
9477 parent
= parent
->outer
;
9479 else if (code
== GIMPLE_OMP_CONTINUE
)
9481 gcc_assert (parent
);
9484 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
9486 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9487 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9491 region
= new_omp_region (bb
, code
, parent
);
9493 if (code
== GIMPLE_OMP_TARGET
)
9495 switch (gimple_omp_target_kind (stmt
))
9497 case GF_OMP_TARGET_KIND_REGION
:
9498 case GF_OMP_TARGET_KIND_DATA
:
9499 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
9500 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
9501 case GF_OMP_TARGET_KIND_OACC_DATA
:
9503 case GF_OMP_TARGET_KIND_UPDATE
:
9504 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9505 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9506 /* ..., other than for those stand-alone directives... */
9513 /* ..., this directive becomes the parent for a new region. */
9519 if (single_tree
&& !parent
)
9522 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
9524 son
= next_dom_son (CDI_DOMINATORS
, son
))
9525 build_omp_regions_1 (son
, parent
, single_tree
);
9528 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9532 build_omp_regions_root (basic_block root
)
9534 gcc_assert (root_omp_region
== NULL
);
9535 build_omp_regions_1 (root
, NULL
, true);
9536 gcc_assert (root_omp_region
!= NULL
);
9539 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9542 omp_expand_local (basic_block head
)
9544 build_omp_regions_root (head
);
9545 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
9547 fprintf (dump_file
, "\nOMP region tree\n\n");
9548 dump_omp_region (dump_file
, root_omp_region
, 0);
9549 fprintf (dump_file
, "\n");
9552 remove_exit_barriers (root_omp_region
);
9553 expand_omp (root_omp_region
);
9555 free_omp_regions ();
9558 /* Scan the CFG and build a tree of OMP regions. Return the root of
9559 the OMP region tree. */
9562 build_omp_regions (void)
9564 gcc_assert (root_omp_region
== NULL
);
9565 calculate_dominance_info (CDI_DOMINATORS
);
9566 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
9569 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9572 execute_expand_omp (void)
9574 build_omp_regions ();
9576 if (!root_omp_region
)
9581 fprintf (dump_file
, "\nOMP region tree\n\n");
9582 dump_omp_region (dump_file
, root_omp_region
, 0);
9583 fprintf (dump_file
, "\n");
9586 remove_exit_barriers (root_omp_region
);
9588 expand_omp (root_omp_region
);
9590 #ifdef ENABLE_CHECKING
9591 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
9592 verify_loop_structure ();
9594 cleanup_tree_cfg ();
9596 free_omp_regions ();
9601 /* OMP expansion -- the default pass, run before creation of SSA form. */
9605 const pass_data pass_data_expand_omp
=
9607 GIMPLE_PASS
, /* type */
9608 "ompexp", /* name */
9609 OPTGROUP_NONE
, /* optinfo_flags */
9610 TV_NONE
, /* tv_id */
9611 PROP_gimple_any
, /* properties_required */
9612 PROP_gimple_eomp
, /* properties_provided */
9613 0, /* properties_destroyed */
9614 0, /* todo_flags_start */
9615 0, /* todo_flags_finish */
9618 class pass_expand_omp
: public gimple_opt_pass
9621 pass_expand_omp (gcc::context
*ctxt
)
9622 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
9625 /* opt_pass methods: */
9626 virtual unsigned int execute (function
*)
9628 bool gate
= ((flag_cilkplus
!= 0 || flag_openacc
!= 0 || flag_openmp
!= 0
9629 || flag_openmp_simd
!= 0)
9632 /* This pass always runs, to provide PROP_gimple_eomp.
9633 But often, there is nothing to do. */
9637 return execute_expand_omp ();
9640 }; // class pass_expand_omp
9645 make_pass_expand_omp (gcc::context
*ctxt
)
9647 return new pass_expand_omp (ctxt
);
9652 const pass_data pass_data_expand_omp_ssa
=
9654 GIMPLE_PASS
, /* type */
9655 "ompexpssa", /* name */
9656 OPTGROUP_NONE
, /* optinfo_flags */
9657 TV_NONE
, /* tv_id */
9658 PROP_cfg
| PROP_ssa
, /* properties_required */
9659 PROP_gimple_eomp
, /* properties_provided */
9660 0, /* properties_destroyed */
9661 0, /* todo_flags_start */
9662 TODO_cleanup_cfg
| TODO_rebuild_alias
, /* todo_flags_finish */
9665 class pass_expand_omp_ssa
: public gimple_opt_pass
9668 pass_expand_omp_ssa (gcc::context
*ctxt
)
9669 : gimple_opt_pass (pass_data_expand_omp_ssa
, ctxt
)
9672 /* opt_pass methods: */
9673 virtual bool gate (function
*fun
)
9675 return !(fun
->curr_properties
& PROP_gimple_eomp
);
9677 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
9679 }; // class pass_expand_omp_ssa
9684 make_pass_expand_omp_ssa (gcc::context
*ctxt
)
9686 return new pass_expand_omp_ssa (ctxt
);
9689 /* Routines to lower OMP directives into OMP-GIMPLE. */
9691 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9692 convert it to gimple. */
9694 oacc_gimple_assign (tree dest
, tree_code op
, tree src
, gimple_seq
*seq
)
9698 if (TREE_CODE (TREE_TYPE (dest
)) != COMPLEX_TYPE
)
9700 stmt
= gimple_build_assign (dest
, op
, dest
, src
);
9701 gimple_seq_add_stmt (seq
, stmt
);
9705 tree t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9706 tree rdest
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9707 gimplify_assign (t
, rdest
, seq
);
9710 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9711 tree idest
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9712 gimplify_assign (t
, idest
, seq
);
9715 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9716 tree rsrc
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9717 gimplify_assign (t
, rsrc
, seq
);
9720 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9721 tree isrc
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9722 gimplify_assign (t
, isrc
, seq
);
9725 tree r
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9726 tree i
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9729 if (op
== PLUS_EXPR
)
9731 stmt
= gimple_build_assign (r
, op
, rdest
, rsrc
);
9732 gimple_seq_add_stmt (seq
, stmt
);
9734 stmt
= gimple_build_assign (i
, op
, idest
, isrc
);
9735 gimple_seq_add_stmt (seq
, stmt
);
9737 else if (op
== MULT_EXPR
)
9739 /* Let x = a + ib = dest, y = c + id = src.
9740 x * y = (ac - bd) + i(ad + bc) */
9741 tree ac
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9742 tree bd
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9743 tree ad
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9744 tree bc
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9746 stmt
= gimple_build_assign (ac
, MULT_EXPR
, rdest
, rsrc
);
9747 gimple_seq_add_stmt (seq
, stmt
);
9749 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, isrc
);
9750 gimple_seq_add_stmt (seq
, stmt
);
9752 stmt
= gimple_build_assign (r
, MINUS_EXPR
, ac
, bd
);
9753 gimple_seq_add_stmt (seq
, stmt
);
9755 stmt
= gimple_build_assign (ad
, MULT_EXPR
, rdest
, isrc
);
9756 gimple_seq_add_stmt (seq
, stmt
);
9758 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, rsrc
);
9759 gimple_seq_add_stmt (seq
, stmt
);
9761 stmt
= gimple_build_assign (i
, PLUS_EXPR
, ad
, bc
);
9762 gimple_seq_add_stmt (seq
, stmt
);
9767 result
= build2 (COMPLEX_EXPR
, TREE_TYPE (dest
), r
, i
);
9768 gimplify_assign (dest
, result
, seq
);
9771 /* Helper function to initialize local data for the reduction arrays.
9772 The reduction arrays need to be placed inside the calling function
9773 for accelerators, or else the host won't be able to preform the final
9777 oacc_initialize_reduction_data (tree clauses
, tree nthreads
,
9778 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9784 /* Find the innermost OpenACC parallel context. */
9785 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
9786 && (gimple_omp_target_kind (ctx
->stmt
)
9787 == GF_OMP_TARGET_KIND_OACC_PARALLEL
))
9791 gcc_checking_assert (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
9792 && (gimple_omp_target_kind (octx
->stmt
)
9793 == GF_OMP_TARGET_KIND_OACC_PARALLEL
));
9795 /* Extract the clauses. */
9796 oc
= gimple_omp_target_clauses (octx
->stmt
);
9798 /* Find the last outer clause. */
9799 for (; oc
&& OMP_CLAUSE_CHAIN (oc
); oc
= OMP_CLAUSE_CHAIN (oc
))
9802 /* Allocate arrays for each reduction variable. */
9803 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9805 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9808 tree var
= OMP_CLAUSE_DECL (c
);
9809 tree type
= get_base_type (var
);
9810 tree array
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
),
9814 /* Calculate size of the reduction array. */
9815 t
= create_tmp_var (TREE_TYPE (nthreads
));
9816 stmt
= gimple_build_assign (t
, MULT_EXPR
, nthreads
,
9817 fold_convert (TREE_TYPE (nthreads
),
9818 TYPE_SIZE_UNIT (type
)));
9819 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9821 size
= create_tmp_var (sizetype
);
9822 gimplify_assign (size
, fold_build1 (NOP_EXPR
, sizetype
, t
), stmt_seqp
);
9824 /* Now allocate memory for it. */
9825 call
= unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA
));
9826 stmt
= gimple_build_call (call
, 1, size
);
9827 gimple_call_set_lhs (stmt
, array
);
9828 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9830 /* Map this array into the accelerator. */
9832 /* Add the reduction array to the list of clauses. */
9834 t
= build_omp_clause (gimple_location (ctx
->stmt
), OMP_CLAUSE_MAP
);
9835 OMP_CLAUSE_SET_MAP_KIND (t
, GOMP_MAP_FORCE_FROM
);
9836 OMP_CLAUSE_DECL (t
) = x
;
9837 OMP_CLAUSE_CHAIN (t
) = NULL
;
9839 OMP_CLAUSE_CHAIN (oc
) = t
;
9841 gimple_omp_target_set_clauses (as_a
<gomp_target
*> (octx
->stmt
), t
);
9842 OMP_CLAUSE_SIZE (t
) = size
;
9847 /* Helper function to process the array of partial reductions. Nthreads
9848 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9849 cannot be used here, because nthreads on the host may be different than
9850 on the accelerator. */
9853 oacc_finalize_reduction_data (tree clauses
, tree nthreads
,
9854 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9856 tree c
, x
, var
, array
, loop_header
, loop_body
, loop_exit
, type
;
9861 let var = the original reduction variable
9862 let array = reduction variable array
9864 for (i = 0; i < nthreads; i++)
9868 loop_header
= create_artificial_label (UNKNOWN_LOCATION
);
9869 loop_body
= create_artificial_label (UNKNOWN_LOCATION
);
9870 loop_exit
= create_artificial_label (UNKNOWN_LOCATION
);
9872 /* Create and initialize an index variable. */
9873 tree ix
= create_tmp_var (sizetype
);
9874 gimplify_assign (ix
, fold_build1 (NOP_EXPR
, sizetype
, integer_zero_node
),
9877 /* Insert the loop header label here. */
9878 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_header
));
9880 /* Exit loop if ix >= nthreads. */
9881 x
= create_tmp_var (sizetype
);
9882 gimplify_assign (x
, fold_build1 (NOP_EXPR
, sizetype
, nthreads
), stmt_seqp
);
9883 stmt
= gimple_build_cond (GE_EXPR
, ix
, x
, loop_exit
, loop_body
);
9884 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9886 /* Insert the loop body label here. */
9887 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_body
));
9889 /* Collapse each reduction array, one element at a time. */
9890 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9892 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9895 tree_code reduction_code
= OMP_CLAUSE_REDUCTION_CODE (c
);
9897 /* reduction(-:var) sums up the partial results, so it acts
9898 identically to reduction(+:var). */
9899 if (reduction_code
== MINUS_EXPR
)
9900 reduction_code
= PLUS_EXPR
;
9902 /* Set up reduction variable var. */
9903 var
= OMP_CLAUSE_DECL (c
);
9904 type
= get_base_type (var
);
9905 array
= lookup_oacc_reduction (oacc_get_reduction_array_id
9906 (OMP_CLAUSE_DECL (c
)), ctx
);
9908 /* Calculate the array offset. */
9909 tree offset
= create_tmp_var (sizetype
);
9910 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
), stmt_seqp
);
9911 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, ix
);
9912 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9914 tree ptr
= create_tmp_var (TREE_TYPE (array
));
9915 stmt
= gimple_build_assign (ptr
, POINTER_PLUS_EXPR
, array
, offset
);
9916 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9918 /* Extract array[ix] into mem. */
9919 tree mem
= create_tmp_var (type
);
9920 gimplify_assign (mem
, build_simple_mem_ref (ptr
), stmt_seqp
);
9922 /* Find the original reduction variable. */
9923 if (is_reference (var
))
9924 var
= build_simple_mem_ref (var
);
9926 tree t
= create_tmp_var (type
);
9928 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, t
, var
);
9929 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9931 /* var = var op mem */
9932 switch (OMP_CLAUSE_REDUCTION_CODE (c
))
9934 case TRUTH_ANDIF_EXPR
:
9935 case TRUTH_ORIF_EXPR
:
9936 t
= fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c
), integer_type_node
,
9938 gimplify_and_add (t
, stmt_seqp
);
9941 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9942 oacc_gimple_assign (t
, OMP_CLAUSE_REDUCTION_CODE (c
), mem
,
9946 t
= fold_build1 (NOP_EXPR
, TREE_TYPE (var
), t
);
9947 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, var
, t
);
9948 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9951 /* Increment the induction variable. */
9952 tree one
= fold_build1 (NOP_EXPR
, sizetype
, integer_one_node
);
9953 stmt
= gimple_build_assign (ix
, PLUS_EXPR
, ix
, one
);
9954 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9956 /* Go back to the top of the loop. */
9957 gimple_seq_add_stmt (stmt_seqp
, gimple_build_goto (loop_header
));
9959 /* Place the loop exit label here. */
9960 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_exit
));
9963 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9964 scan that for reductions. */
9967 oacc_process_reduction_data (gimple_seq
*body
, gimple_seq
*in_stmt_seqp
,
9968 gimple_seq
*out_stmt_seqp
, omp_context
*ctx
)
9970 gimple_stmt_iterator gsi
;
9971 gimple_seq inner
= NULL
;
9973 /* A collapse clause may have inserted a new bind block. */
9974 gsi
= gsi_start (*body
);
9975 while (!gsi_end_p (gsi
))
9977 gimple stmt
= gsi_stmt (gsi
);
9978 if (gbind
*bind_stmt
= dyn_cast
<gbind
*> (stmt
))
9980 inner
= gimple_bind_body (bind_stmt
);
9982 gsi
= gsi_start (*body
);
9984 else if (dyn_cast
<gomp_for
*> (stmt
))
9990 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
9992 tree clauses
, nthreads
, t
, c
, acc_device
, acc_device_host
, call
,
9994 bool reduction_found
= false;
9996 gimple stmt
= gsi_stmt (gsi
);
9998 switch (gimple_code (stmt
))
10000 case GIMPLE_OMP_FOR
:
10001 clauses
= gimple_omp_for_clauses (stmt
);
10003 /* Search for a reduction clause. */
10004 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
10005 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
10007 reduction_found
= true;
10011 if (!reduction_found
)
10014 ctx
= maybe_lookup_ctx (stmt
);
10017 /* Extract the number of threads. */
10018 nthreads
= create_tmp_var (sizetype
);
10019 t
= oacc_max_threads (ctx
);
10020 gimplify_assign (nthreads
, t
, in_stmt_seqp
);
10022 /* Determine if this is kernel will be executed on the host. */
10023 call
= builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE
);
10024 acc_device
= create_tmp_var (integer_type_node
, ".acc_device_type");
10025 stmt
= gimple_build_call (call
, 0);
10026 gimple_call_set_lhs (stmt
, acc_device
);
10027 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
10029 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
10030 acc_device_host
= create_tmp_var (integer_type_node
,
10031 ".acc_device_host");
10032 gimplify_assign (acc_device_host
,
10033 build_int_cst (integer_type_node
,
10037 enter
= create_artificial_label (UNKNOWN_LOCATION
);
10038 exit
= create_artificial_label (UNKNOWN_LOCATION
);
10040 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
10042 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
10043 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
10044 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
10047 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
10049 oacc_initialize_reduction_data (clauses
, nthreads
, in_stmt_seqp
,
10051 oacc_finalize_reduction_data (clauses
, nthreads
, out_stmt_seqp
, ctx
);
10054 // Scan for other directives which support reduction here.
10060 /* If ctx is a worksharing context inside of a cancellable parallel
10061 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
10062 and conditional branch to parallel's cancel_label to handle
10063 cancellation in the implicit barrier. */
10066 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
10068 gimple omp_return
= gimple_seq_last_stmt (*body
);
10069 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
10070 if (gimple_omp_return_nowait_p (omp_return
))
10073 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
10074 && ctx
->outer
->cancellable
)
10076 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
10077 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
10078 tree lhs
= create_tmp_var (c_bool_type
);
10079 gimple_omp_return_set_lhs (omp_return
, lhs
);
10080 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
10081 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
10082 fold_convert (c_bool_type
,
10083 boolean_false_node
),
10084 ctx
->outer
->cancel_label
, fallthru_label
);
10085 gimple_seq_add_stmt (body
, g
);
10086 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
10090 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10091 CTX is the enclosing OMP context for the current statement. */
10094 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10096 tree block
, control
;
10097 gimple_stmt_iterator tgsi
;
10098 gomp_sections
*stmt
;
10100 gbind
*new_stmt
, *bind
;
10101 gimple_seq ilist
, dlist
, olist
, new_body
;
10103 stmt
= as_a
<gomp_sections
*> (gsi_stmt (*gsi_p
));
10105 push_gimplify_context ();
10109 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
10110 &ilist
, &dlist
, ctx
, NULL
);
10112 new_body
= gimple_omp_body (stmt
);
10113 gimple_omp_set_body (stmt
, NULL
);
10114 tgsi
= gsi_start (new_body
);
10115 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
10120 sec_start
= gsi_stmt (tgsi
);
10121 sctx
= maybe_lookup_ctx (sec_start
);
10124 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
10125 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
10126 GSI_CONTINUE_LINKING
);
10127 gimple_omp_set_body (sec_start
, NULL
);
10129 if (gsi_one_before_end_p (tgsi
))
10131 gimple_seq l
= NULL
;
10132 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
10134 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
10135 gimple_omp_section_set_last (sec_start
);
10138 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
10139 GSI_CONTINUE_LINKING
);
10142 block
= make_node (BLOCK
);
10143 bind
= gimple_build_bind (NULL
, new_body
, block
);
10146 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
10148 block
= make_node (BLOCK
);
10149 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10150 gsi_replace (gsi_p
, new_stmt
, true);
10152 pop_gimplify_context (new_stmt
);
10153 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10154 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10155 if (BLOCK_VARS (block
))
10156 TREE_USED (block
) = 1;
10159 gimple_seq_add_seq (&new_body
, ilist
);
10160 gimple_seq_add_stmt (&new_body
, stmt
);
10161 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
10162 gimple_seq_add_stmt (&new_body
, bind
);
10164 control
= create_tmp_var (unsigned_type_node
, ".section");
10165 t
= gimple_build_omp_continue (control
, control
);
10166 gimple_omp_sections_set_control (stmt
, control
);
10167 gimple_seq_add_stmt (&new_body
, t
);
10169 gimple_seq_add_seq (&new_body
, olist
);
10170 if (ctx
->cancellable
)
10171 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
10172 gimple_seq_add_seq (&new_body
, dlist
);
10174 new_body
= maybe_catch_exception (new_body
);
10176 t
= gimple_build_omp_return
10177 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
10178 OMP_CLAUSE_NOWAIT
));
10179 gimple_seq_add_stmt (&new_body
, t
);
10180 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
10182 gimple_bind_set_body (new_stmt
, new_body
);
10186 /* A subroutine of lower_omp_single. Expand the simple form of
10187 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10189 if (GOMP_single_start ())
10191 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10193 FIXME. It may be better to delay expanding the logic of this until
10194 pass_expand_omp. The expanded logic may make the job more difficult
10195 to a synchronization analysis pass. */
10198 lower_omp_single_simple (gomp_single
*single_stmt
, gimple_seq
*pre_p
)
10200 location_t loc
= gimple_location (single_stmt
);
10201 tree tlabel
= create_artificial_label (loc
);
10202 tree flabel
= create_artificial_label (loc
);
10206 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
10207 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)));
10208 call
= gimple_build_call (decl
, 0);
10209 gimple_call_set_lhs (call
, lhs
);
10210 gimple_seq_add_stmt (pre_p
, call
);
10212 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
10213 fold_convert_loc (loc
, TREE_TYPE (lhs
),
10214 boolean_true_node
),
10216 gimple_seq_add_stmt (pre_p
, cond
);
10217 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
10218 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10219 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
10223 /* A subroutine of lower_omp_single. Expand the simple form of
10224 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10226 #pragma omp single copyprivate (a, b, c)
10228 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10231 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10237 GOMP_single_copy_end (©out);
10248 FIXME. It may be better to delay expanding the logic of this until
10249 pass_expand_omp. The expanded logic may make the job more difficult
10250 to a synchronization analysis pass. */
10253 lower_omp_single_copy (gomp_single
*single_stmt
, gimple_seq
*pre_p
,
10256 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
10257 gimple_seq copyin_seq
;
10258 location_t loc
= gimple_location (single_stmt
);
10260 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
10262 ptr_type
= build_pointer_type (ctx
->record_type
);
10263 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
10265 l0
= create_artificial_label (loc
);
10266 l1
= create_artificial_label (loc
);
10267 l2
= create_artificial_label (loc
);
10269 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
10270 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
10271 t
= fold_convert_loc (loc
, ptr_type
, t
);
10272 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
10274 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
10275 build_int_cst (ptr_type
, 0));
10276 t
= build3 (COND_EXPR
, void_type_node
, t
,
10277 build_and_jump (&l0
), build_and_jump (&l1
));
10278 gimplify_and_add (t
, pre_p
);
10280 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
10282 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10285 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
10288 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10289 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
10290 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
10291 gimplify_and_add (t
, pre_p
);
10293 t
= build_and_jump (&l2
);
10294 gimplify_and_add (t
, pre_p
);
10296 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
10298 gimple_seq_add_seq (pre_p
, copyin_seq
);
10300 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
10304 /* Expand code for an OpenMP single directive. */
10307 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10311 gomp_single
*single_stmt
= as_a
<gomp_single
*> (gsi_stmt (*gsi_p
));
10313 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
10315 push_gimplify_context ();
10317 block
= make_node (BLOCK
);
10318 bind
= gimple_build_bind (NULL
, NULL
, block
);
10319 gsi_replace (gsi_p
, bind
, true);
10322 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
10323 &bind_body
, &dlist
, ctx
, NULL
);
10324 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
10326 gimple_seq_add_stmt (&bind_body
, single_stmt
);
10328 if (ctx
->record_type
)
10329 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
10331 lower_omp_single_simple (single_stmt
, &bind_body
);
10333 gimple_omp_set_body (single_stmt
, NULL
);
10335 gimple_seq_add_seq (&bind_body
, dlist
);
10337 bind_body
= maybe_catch_exception (bind_body
);
10339 t
= gimple_build_omp_return
10340 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
10341 OMP_CLAUSE_NOWAIT
));
10342 gimple_seq_add_stmt (&bind_body_tail
, t
);
10343 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
10344 if (ctx
->record_type
)
10346 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
10347 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
10348 TREE_THIS_VOLATILE (clobber
) = 1;
10349 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
10350 clobber
), GSI_SAME_STMT
);
10352 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
10353 gimple_bind_set_body (bind
, bind_body
);
10355 pop_gimplify_context (bind
);
10357 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10358 BLOCK_VARS (block
) = ctx
->block_vars
;
10359 if (BLOCK_VARS (block
))
10360 TREE_USED (block
) = 1;
10364 /* Expand code for an OpenMP master directive. */
10367 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10369 tree block
, lab
= NULL
, x
, bfn_decl
;
10370 gimple stmt
= gsi_stmt (*gsi_p
);
10372 location_t loc
= gimple_location (stmt
);
10375 push_gimplify_context ();
10377 block
= make_node (BLOCK
);
10378 bind
= gimple_build_bind (NULL
, NULL
, block
);
10379 gsi_replace (gsi_p
, bind
, true);
10380 gimple_bind_add_stmt (bind
, stmt
);
10382 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
10383 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
10384 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
10385 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
10387 gimplify_and_add (x
, &tseq
);
10388 gimple_bind_add_seq (bind
, tseq
);
10390 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10391 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10392 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10393 gimple_omp_set_body (stmt
, NULL
);
10395 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
10397 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10399 pop_gimplify_context (bind
);
10401 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10402 BLOCK_VARS (block
) = ctx
->block_vars
;
10406 /* Expand code for an OpenMP taskgroup directive. */
10409 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10411 gimple stmt
= gsi_stmt (*gsi_p
);
10414 tree block
= make_node (BLOCK
);
10416 bind
= gimple_build_bind (NULL
, NULL
, block
);
10417 gsi_replace (gsi_p
, bind
, true);
10418 gimple_bind_add_stmt (bind
, stmt
);
10420 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
10422 gimple_bind_add_stmt (bind
, x
);
10424 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10425 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10426 gimple_omp_set_body (stmt
, NULL
);
10428 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10430 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10431 BLOCK_VARS (block
) = ctx
->block_vars
;
10435 /* Expand code for an OpenMP ordered directive. */
10438 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10441 gimple stmt
= gsi_stmt (*gsi_p
);
10445 push_gimplify_context ();
10447 block
= make_node (BLOCK
);
10448 bind
= gimple_build_bind (NULL
, NULL
, block
);
10449 gsi_replace (gsi_p
, bind
, true);
10450 gimple_bind_add_stmt (bind
, stmt
);
10452 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
10454 gimple_bind_add_stmt (bind
, x
);
10456 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10457 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10458 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10459 gimple_omp_set_body (stmt
, NULL
);
10461 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
10462 gimple_bind_add_stmt (bind
, x
);
10464 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10466 pop_gimplify_context (bind
);
10468 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10469 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10473 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10474 substitution of a couple of function calls. But in the NAMED case,
10475 requires that languages coordinate a symbol name. It is therefore
10476 best put here in common code. */
10478 static GTY(()) hash_map
<tree
, tree
> *critical_name_mutexes
;
10481 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10484 tree name
, lock
, unlock
;
10485 gomp_critical
*stmt
= as_a
<gomp_critical
*> (gsi_stmt (*gsi_p
));
10487 location_t loc
= gimple_location (stmt
);
10490 name
= gimple_omp_critical_name (stmt
);
10495 if (!critical_name_mutexes
)
10496 critical_name_mutexes
= hash_map
<tree
, tree
>::create_ggc (10);
10498 tree
*n
= critical_name_mutexes
->get (name
);
10503 decl
= create_tmp_var_raw (ptr_type_node
);
10505 new_str
= ACONCAT ((".gomp_critical_user_",
10506 IDENTIFIER_POINTER (name
), NULL
));
10507 DECL_NAME (decl
) = get_identifier (new_str
);
10508 TREE_PUBLIC (decl
) = 1;
10509 TREE_STATIC (decl
) = 1;
10510 DECL_COMMON (decl
) = 1;
10511 DECL_ARTIFICIAL (decl
) = 1;
10512 DECL_IGNORED_P (decl
) = 1;
10514 varpool_node::finalize_decl (decl
);
10516 critical_name_mutexes
->put (name
, decl
);
10521 /* If '#pragma omp critical' is inside offloaded region or
10522 inside function marked as offloadable, the symbol must be
10523 marked as offloadable too. */
10525 if (cgraph_node::get (current_function_decl
)->offloadable
)
10526 varpool_node::get_create (decl
)->offloadable
= 1;
10528 for (octx
= ctx
->outer
; octx
; octx
= octx
->outer
)
10529 if (is_gimple_omp_offloaded (octx
->stmt
))
10531 varpool_node::get_create (decl
)->offloadable
= 1;
10535 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
10536 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
10538 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
10539 unlock
= build_call_expr_loc (loc
, unlock
, 1,
10540 build_fold_addr_expr_loc (loc
, decl
));
10544 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
10545 lock
= build_call_expr_loc (loc
, lock
, 0);
10547 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
10548 unlock
= build_call_expr_loc (loc
, unlock
, 0);
10551 push_gimplify_context ();
10553 block
= make_node (BLOCK
);
10554 bind
= gimple_build_bind (NULL
, NULL
, block
);
10555 gsi_replace (gsi_p
, bind
, true);
10556 gimple_bind_add_stmt (bind
, stmt
);
10558 tbody
= gimple_bind_body (bind
);
10559 gimplify_and_add (lock
, &tbody
);
10560 gimple_bind_set_body (bind
, tbody
);
10562 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10563 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10564 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10565 gimple_omp_set_body (stmt
, NULL
);
10567 tbody
= gimple_bind_body (bind
);
10568 gimplify_and_add (unlock
, &tbody
);
10569 gimple_bind_set_body (bind
, tbody
);
10571 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10573 pop_gimplify_context (bind
);
10574 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10575 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10579 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10580 for a lastprivate clause. Given a loop control predicate of (V
10581 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10582 is appended to *DLIST, iterator initialization is appended to
10586 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
10587 gimple_seq
*dlist
, struct omp_context
*ctx
)
10589 tree clauses
, cond
, vinit
;
10590 enum tree_code cond_code
;
10593 cond_code
= fd
->loop
.cond_code
;
10594 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
10596 /* When possible, use a strict equality expression. This can let VRP
10597 type optimizations deduce the value and remove a copy. */
10598 if (tree_fits_shwi_p (fd
->loop
.step
))
10600 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
10601 if (step
== 1 || step
== -1)
10602 cond_code
= EQ_EXPR
;
10605 tree n2
= fd
->loop
.n2
;
10606 if (fd
->collapse
> 1
10607 && TREE_CODE (n2
) != INTEGER_CST
10608 && gimple_omp_for_combined_into_p (fd
->for_stmt
)
10609 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_FOR
)
10611 gomp_for
*gfor
= as_a
<gomp_for
*> (ctx
->outer
->stmt
);
10612 if (gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_FOR
)
10614 struct omp_for_data outer_fd
;
10615 extract_omp_for_data (gfor
, &outer_fd
, NULL
);
10616 n2
= fold_convert (TREE_TYPE (n2
), outer_fd
.loop
.n2
);
10619 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, n2
);
10621 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
10623 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
10624 if (!gimple_seq_empty_p (stmts
))
10626 gimple_seq_add_seq (&stmts
, *dlist
);
10629 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10630 vinit
= fd
->loop
.n1
;
10631 if (cond_code
== EQ_EXPR
10632 && tree_fits_shwi_p (fd
->loop
.n2
)
10633 && ! integer_zerop (fd
->loop
.n2
))
10634 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
10636 vinit
= unshare_expr (vinit
);
10638 /* Initialize the iterator variable, so that threads that don't execute
10639 any iterations don't execute the lastprivate clauses by accident. */
10640 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
10645 /* Lower code for an OMP loop directive. */
10648 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10650 tree
*rhs_p
, block
;
10651 struct omp_for_data fd
, *fdp
= NULL
;
10652 gomp_for
*stmt
= as_a
<gomp_for
*> (gsi_stmt (*gsi_p
));
10654 gimple_seq omp_for_body
, body
, dlist
;
10657 push_gimplify_context ();
10659 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
10661 block
= make_node (BLOCK
);
10662 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10663 /* Replace at gsi right away, so that 'stmt' is no member
10664 of a sequence anymore as we're going to add to a different
10666 gsi_replace (gsi_p
, new_stmt
, true);
10668 /* Move declaration of temporaries in the loop body before we make
10670 omp_for_body
= gimple_omp_body (stmt
);
10671 if (!gimple_seq_empty_p (omp_for_body
)
10672 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
10675 = as_a
<gbind
*> (gimple_seq_first_stmt (omp_for_body
));
10676 tree vars
= gimple_bind_vars (inner_bind
);
10677 gimple_bind_append_vars (new_stmt
, vars
);
10678 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10679 keep them on the inner_bind and it's block. */
10680 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
10681 if (gimple_bind_block (inner_bind
))
10682 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
10685 if (gimple_omp_for_combined_into_p (stmt
))
10687 extract_omp_for_data (stmt
, &fd
, NULL
);
10690 /* We need two temporaries with fd.loop.v type (istart/iend)
10691 and then (fd.collapse - 1) temporaries with the same
10692 type for count2 ... countN-1 vars if not constant. */
10694 tree type
= fd
.iter_type
;
10695 if (fd
.collapse
> 1
10696 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
10697 count
+= fd
.collapse
- 1;
10698 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
10699 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
10700 tree clauses
= *pc
;
10703 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
10704 OMP_CLAUSE__LOOPTEMP_
);
10705 for (i
= 0; i
< count
; i
++)
10710 gcc_assert (outerc
);
10711 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
10712 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
10713 OMP_CLAUSE__LOOPTEMP_
);
10717 temp
= create_tmp_var (type
);
10718 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
10720 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
10721 OMP_CLAUSE_DECL (*pc
) = temp
;
10722 pc
= &OMP_CLAUSE_CHAIN (*pc
);
10727 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10730 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
10732 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
10734 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10736 /* Lower the header expressions. At this point, we can assume that
10737 the header is of the form:
10739 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10741 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10742 using the .omp_data_s mapping, if needed. */
10743 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
10745 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
10746 if (!is_gimple_min_invariant (*rhs_p
))
10747 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10749 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
10750 if (!is_gimple_min_invariant (*rhs_p
))
10751 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10753 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
10754 if (!is_gimple_min_invariant (*rhs_p
))
10755 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10758 /* Once lowered, extract the bounds and clauses. */
10759 extract_omp_for_data (stmt
, &fd
, NULL
);
10761 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
10763 gimple_seq_add_stmt (&body
, stmt
);
10764 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
10766 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
10769 /* After the loop, add exit clauses. */
10770 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
10772 if (ctx
->cancellable
)
10773 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
10775 gimple_seq_add_seq (&body
, dlist
);
10777 body
= maybe_catch_exception (body
);
10779 /* Region exit marker goes at the end of the loop body. */
10780 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
10781 maybe_add_implicit_barrier_cancel (ctx
, &body
);
10782 pop_gimplify_context (new_stmt
);
10784 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10785 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
10786 if (BLOCK_VARS (block
))
10787 TREE_USED (block
) = 1;
10789 gimple_bind_set_body (new_stmt
, body
);
10790 gimple_omp_set_body (stmt
, NULL
);
10791 gimple_omp_for_set_pre_body (stmt
, NULL
);
10794 /* Callback for walk_stmts. Check if the current statement only contains
10795 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10798 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
10799 bool *handled_ops_p
,
10800 struct walk_stmt_info
*wi
)
10802 int *info
= (int *) wi
->info
;
10803 gimple stmt
= gsi_stmt (*gsi_p
);
10805 *handled_ops_p
= true;
10806 switch (gimple_code (stmt
))
10810 case GIMPLE_OMP_FOR
:
10811 case GIMPLE_OMP_SECTIONS
:
10812 *info
= *info
== 0 ? 1 : -1;
10821 struct omp_taskcopy_context
10823 /* This field must be at the beginning, as we do "inheritance": Some
10824 callback functions for tree-inline.c (e.g., omp_copy_decl)
10825 receive a copy_body_data pointer that is up-casted to an
10826 omp_context pointer. */
10832 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
10834 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
10836 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
10837 return create_tmp_var (TREE_TYPE (var
));
10843 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
10845 tree name
, new_fields
= NULL
, type
, f
;
10847 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
10848 name
= DECL_NAME (TYPE_NAME (orig_type
));
10849 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
10850 TYPE_DECL
, name
, type
);
10851 TYPE_NAME (type
) = name
;
10853 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
10855 tree new_f
= copy_node (f
);
10856 DECL_CONTEXT (new_f
) = type
;
10857 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
10858 TREE_CHAIN (new_f
) = new_fields
;
10859 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10860 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10861 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
10863 new_fields
= new_f
;
10864 tcctx
->cb
.decl_map
->put (f
, new_f
);
10866 TYPE_FIELDS (type
) = nreverse (new_fields
);
10867 layout_type (type
);
10871 /* Create task copyfn. */
10874 create_task_copyfn (gomp_task
*task_stmt
, omp_context
*ctx
)
10876 struct function
*child_cfun
;
10877 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
10878 tree record_type
, srecord_type
, bind
, list
;
10879 bool record_needs_remap
= false, srecord_needs_remap
= false;
10881 struct omp_taskcopy_context tcctx
;
10882 location_t loc
= gimple_location (task_stmt
);
10884 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
10885 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
10886 gcc_assert (child_cfun
->cfg
== NULL
);
10887 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
10889 /* Reset DECL_CONTEXT on function arguments. */
10890 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
10891 DECL_CONTEXT (t
) = child_fn
;
10893 /* Populate the function. */
10894 push_gimplify_context ();
10895 push_cfun (child_cfun
);
10897 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
10898 TREE_SIDE_EFFECTS (bind
) = 1;
10900 DECL_SAVED_TREE (child_fn
) = bind
;
10901 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
10903 /* Remap src and dst argument types if needed. */
10904 record_type
= ctx
->record_type
;
10905 srecord_type
= ctx
->srecord_type
;
10906 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
10907 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10909 record_needs_remap
= true;
10912 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
10913 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10915 srecord_needs_remap
= true;
10919 if (record_needs_remap
|| srecord_needs_remap
)
10921 memset (&tcctx
, '\0', sizeof (tcctx
));
10922 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
10923 tcctx
.cb
.dst_fn
= child_fn
;
10924 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
10925 gcc_checking_assert (tcctx
.cb
.src_node
);
10926 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
10927 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
10928 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
10929 tcctx
.cb
.eh_lp_nr
= 0;
10930 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
10931 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
10934 if (record_needs_remap
)
10935 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
10936 if (srecord_needs_remap
)
10937 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
10940 tcctx
.cb
.decl_map
= NULL
;
10942 arg
= DECL_ARGUMENTS (child_fn
);
10943 TREE_TYPE (arg
) = build_pointer_type (record_type
);
10944 sarg
= DECL_CHAIN (arg
);
10945 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
10947 /* First pass: initialize temporaries used in record_type and srecord_type
10948 sizes and field offsets. */
10949 if (tcctx
.cb
.decl_map
)
10950 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10951 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
10955 decl
= OMP_CLAUSE_DECL (c
);
10956 p
= tcctx
.cb
.decl_map
->get (decl
);
10959 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10960 sf
= (tree
) n
->value
;
10961 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10962 src
= build_simple_mem_ref_loc (loc
, sarg
);
10963 src
= omp_build_component_ref (src
, sf
);
10964 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
10965 append_to_statement_list (t
, &list
);
10968 /* Second pass: copy shared var pointers and copy construct non-VLA
10969 firstprivate vars. */
10970 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10971 switch (OMP_CLAUSE_CODE (c
))
10973 case OMP_CLAUSE_SHARED
:
10974 decl
= OMP_CLAUSE_DECL (c
);
10975 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10978 f
= (tree
) n
->value
;
10979 if (tcctx
.cb
.decl_map
)
10980 f
= *tcctx
.cb
.decl_map
->get (f
);
10981 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10982 sf
= (tree
) n
->value
;
10983 if (tcctx
.cb
.decl_map
)
10984 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10985 src
= build_simple_mem_ref_loc (loc
, sarg
);
10986 src
= omp_build_component_ref (src
, sf
);
10987 dst
= build_simple_mem_ref_loc (loc
, arg
);
10988 dst
= omp_build_component_ref (dst
, f
);
10989 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
10990 append_to_statement_list (t
, &list
);
10992 case OMP_CLAUSE_FIRSTPRIVATE
:
10993 decl
= OMP_CLAUSE_DECL (c
);
10994 if (is_variable_sized (decl
))
10996 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10999 f
= (tree
) n
->value
;
11000 if (tcctx
.cb
.decl_map
)
11001 f
= *tcctx
.cb
.decl_map
->get (f
);
11002 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
11005 sf
= (tree
) n
->value
;
11006 if (tcctx
.cb
.decl_map
)
11007 sf
= *tcctx
.cb
.decl_map
->get (sf
);
11008 src
= build_simple_mem_ref_loc (loc
, sarg
);
11009 src
= omp_build_component_ref (src
, sf
);
11010 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
11011 src
= build_simple_mem_ref_loc (loc
, src
);
11015 dst
= build_simple_mem_ref_loc (loc
, arg
);
11016 dst
= omp_build_component_ref (dst
, f
);
11017 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
11018 append_to_statement_list (t
, &list
);
11020 case OMP_CLAUSE_PRIVATE
:
11021 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
11023 decl
= OMP_CLAUSE_DECL (c
);
11024 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
11025 f
= (tree
) n
->value
;
11026 if (tcctx
.cb
.decl_map
)
11027 f
= *tcctx
.cb
.decl_map
->get (f
);
11028 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
11031 sf
= (tree
) n
->value
;
11032 if (tcctx
.cb
.decl_map
)
11033 sf
= *tcctx
.cb
.decl_map
->get (sf
);
11034 src
= build_simple_mem_ref_loc (loc
, sarg
);
11035 src
= omp_build_component_ref (src
, sf
);
11036 if (use_pointer_for_field (decl
, NULL
))
11037 src
= build_simple_mem_ref_loc (loc
, src
);
11041 dst
= build_simple_mem_ref_loc (loc
, arg
);
11042 dst
= omp_build_component_ref (dst
, f
);
11043 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
11044 append_to_statement_list (t
, &list
);
11050 /* Last pass: handle VLA firstprivates. */
11051 if (tcctx
.cb
.decl_map
)
11052 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
11053 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
11057 decl
= OMP_CLAUSE_DECL (c
);
11058 if (!is_variable_sized (decl
))
11060 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
11063 f
= (tree
) n
->value
;
11064 f
= *tcctx
.cb
.decl_map
->get (f
);
11065 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
11066 ind
= DECL_VALUE_EXPR (decl
);
11067 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
11068 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
11069 n
= splay_tree_lookup (ctx
->sfield_map
,
11070 (splay_tree_key
) TREE_OPERAND (ind
, 0));
11071 sf
= (tree
) n
->value
;
11072 sf
= *tcctx
.cb
.decl_map
->get (sf
);
11073 src
= build_simple_mem_ref_loc (loc
, sarg
);
11074 src
= omp_build_component_ref (src
, sf
);
11075 src
= build_simple_mem_ref_loc (loc
, src
);
11076 dst
= build_simple_mem_ref_loc (loc
, arg
);
11077 dst
= omp_build_component_ref (dst
, f
);
11078 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
11079 append_to_statement_list (t
, &list
);
11080 n
= splay_tree_lookup (ctx
->field_map
,
11081 (splay_tree_key
) TREE_OPERAND (ind
, 0));
11082 df
= (tree
) n
->value
;
11083 df
= *tcctx
.cb
.decl_map
->get (df
);
11084 ptr
= build_simple_mem_ref_loc (loc
, arg
);
11085 ptr
= omp_build_component_ref (ptr
, df
);
11086 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
11087 build_fold_addr_expr_loc (loc
, dst
));
11088 append_to_statement_list (t
, &list
);
11091 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
11092 append_to_statement_list (t
, &list
);
11094 if (tcctx
.cb
.decl_map
)
11095 delete tcctx
.cb
.decl_map
;
11096 pop_gimplify_context (NULL
);
11097 BIND_EXPR_BODY (bind
) = list
;
11102 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
11106 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
11108 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
11109 OMP_CLAUSE_DEPEND
);
11110 gcc_assert (clauses
);
11111 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11112 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
11113 switch (OMP_CLAUSE_DEPEND_KIND (c
))
11115 case OMP_CLAUSE_DEPEND_IN
:
11118 case OMP_CLAUSE_DEPEND_OUT
:
11119 case OMP_CLAUSE_DEPEND_INOUT
:
11123 gcc_unreachable ();
11125 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
11126 tree array
= create_tmp_var (type
);
11127 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
11129 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
11130 gimple_seq_add_stmt (iseq
, g
);
11131 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
11133 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
11134 gimple_seq_add_stmt (iseq
, g
);
11135 for (i
= 0; i
< 2; i
++)
11137 if ((i
? n_in
: n_out
) == 0)
11139 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11140 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
11141 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
11143 tree t
= OMP_CLAUSE_DECL (c
);
11144 t
= fold_convert (ptr_type_node
, t
);
11145 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
11146 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
11147 NULL_TREE
, NULL_TREE
);
11148 g
= gimple_build_assign (r
, t
);
11149 gimple_seq_add_stmt (iseq
, g
);
11152 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
11153 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
11154 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
11155 OMP_CLAUSE_CHAIN (c
) = *p
;
11157 tree clobber
= build_constructor (type
, NULL
);
11158 TREE_THIS_VOLATILE (clobber
) = 1;
11159 g
= gimple_build_assign (array
, clobber
);
11160 gimple_seq_add_stmt (oseq
, g
);
11163 /* Lower the OpenMP parallel or task directive in the current statement
11164 in GSI_P. CTX holds context information for the directive. */
11167 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11171 gimple stmt
= gsi_stmt (*gsi_p
);
11172 gbind
*par_bind
, *bind
, *dep_bind
= NULL
;
11173 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
11174 location_t loc
= gimple_location (stmt
);
11176 clauses
= gimple_omp_taskreg_clauses (stmt
);
11178 = as_a
<gbind
*> (gimple_seq_first_stmt (gimple_omp_body (stmt
)));
11179 par_body
= gimple_bind_body (par_bind
);
11180 child_fn
= ctx
->cb
.dst_fn
;
11181 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
11182 && !gimple_omp_parallel_combined_p (stmt
))
11184 struct walk_stmt_info wi
;
11187 memset (&wi
, 0, sizeof (wi
));
11189 wi
.val_only
= true;
11190 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
11192 gimple_omp_parallel_set_combined_p (stmt
, true);
11194 gimple_seq dep_ilist
= NULL
;
11195 gimple_seq dep_olist
= NULL
;
11196 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
11197 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
11199 push_gimplify_context ();
11200 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
11201 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
11204 if (ctx
->srecord_type
)
11205 create_task_copyfn (as_a
<gomp_task
*> (stmt
), ctx
);
11207 push_gimplify_context ();
11212 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
11213 lower_omp (&par_body
, ctx
);
11214 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
11215 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
11217 /* Declare all the variables created by mapping and the variables
11218 declared in the scope of the parallel body. */
11219 record_vars_into (ctx
->block_vars
, child_fn
);
11220 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
11222 if (ctx
->record_type
)
11225 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
11226 : ctx
->record_type
, ".omp_data_o");
11227 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11228 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11229 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
11234 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
11235 lower_send_shared_vars (&ilist
, &olist
, ctx
);
11237 if (ctx
->record_type
)
11239 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
11240 TREE_THIS_VOLATILE (clobber
) = 1;
11241 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11245 /* Once all the expansions are done, sequence all the different
11246 fragments inside gimple_omp_body. */
11250 if (ctx
->record_type
)
11252 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11253 /* fixup_child_record_type might have changed receiver_decl's type. */
11254 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11255 gimple_seq_add_stmt (&new_body
,
11256 gimple_build_assign (ctx
->receiver_decl
, t
));
11259 gimple_seq_add_seq (&new_body
, par_ilist
);
11260 gimple_seq_add_seq (&new_body
, par_body
);
11261 gimple_seq_add_seq (&new_body
, par_rlist
);
11262 if (ctx
->cancellable
)
11263 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
11264 gimple_seq_add_seq (&new_body
, par_olist
);
11265 new_body
= maybe_catch_exception (new_body
);
11266 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
)
11267 gimple_seq_add_stmt (&new_body
,
11268 gimple_build_omp_continue (integer_zero_node
,
11269 integer_zero_node
));
11270 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11271 gimple_omp_set_body (stmt
, new_body
);
11273 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
11274 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
11275 gimple_bind_add_seq (bind
, ilist
);
11276 gimple_bind_add_stmt (bind
, stmt
);
11277 gimple_bind_add_seq (bind
, olist
);
11279 pop_gimplify_context (NULL
);
11283 gimple_bind_add_seq (dep_bind
, dep_ilist
);
11284 gimple_bind_add_stmt (dep_bind
, bind
);
11285 gimple_bind_add_seq (dep_bind
, dep_olist
);
11286 pop_gimplify_context (dep_bind
);
11290 /* Lower the GIMPLE_OMP_TARGET in the current statement
11291 in GSI_P. CTX holds context information for the directive. */
11294 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11297 tree child_fn
, t
, c
;
11298 gomp_target
*stmt
= as_a
<gomp_target
*> (gsi_stmt (*gsi_p
));
11299 gbind
*tgt_bind
, *bind
;
11300 gimple_seq tgt_body
, olist
, ilist
, orlist
, irlist
, new_body
;
11301 location_t loc
= gimple_location (stmt
);
11302 bool offloaded
, data_region
;
11303 unsigned int map_cnt
= 0;
11305 offloaded
= is_gimple_omp_offloaded (stmt
);
11306 switch (gimple_omp_target_kind (stmt
))
11308 case GF_OMP_TARGET_KIND_REGION
:
11309 case GF_OMP_TARGET_KIND_UPDATE
:
11310 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
11311 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
11312 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
11313 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
11314 data_region
= false;
11316 case GF_OMP_TARGET_KIND_DATA
:
11317 case GF_OMP_TARGET_KIND_OACC_DATA
:
11318 data_region
= true;
11321 gcc_unreachable ();
11324 clauses
= gimple_omp_target_clauses (stmt
);
11330 tgt_bind
= gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt
));
11331 tgt_body
= gimple_bind_body (tgt_bind
);
11333 else if (data_region
)
11334 tgt_body
= gimple_omp_body (stmt
);
11335 child_fn
= ctx
->cb
.dst_fn
;
11337 push_gimplify_context ();
11342 && is_gimple_omp_oacc (stmt
))
11343 oacc_process_reduction_data (&tgt_body
, &irlist
, &orlist
, ctx
);
11345 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11346 switch (OMP_CLAUSE_CODE (c
))
11352 case OMP_CLAUSE_MAP
:
11353 #ifdef ENABLE_CHECKING
11354 /* First check what we're prepared to handle in the following. */
11355 switch (OMP_CLAUSE_MAP_KIND (c
))
11357 case GOMP_MAP_ALLOC
:
11359 case GOMP_MAP_FROM
:
11360 case GOMP_MAP_TOFROM
:
11361 case GOMP_MAP_POINTER
:
11362 case GOMP_MAP_TO_PSET
:
11364 case GOMP_MAP_FORCE_ALLOC
:
11365 case GOMP_MAP_FORCE_TO
:
11366 case GOMP_MAP_FORCE_FROM
:
11367 case GOMP_MAP_FORCE_TOFROM
:
11368 case GOMP_MAP_FORCE_PRESENT
:
11369 case GOMP_MAP_FORCE_DEALLOC
:
11370 case GOMP_MAP_FORCE_DEVICEPTR
:
11371 gcc_assert (is_gimple_omp_oacc (stmt
));
11374 gcc_unreachable ();
11378 case OMP_CLAUSE_TO
:
11379 case OMP_CLAUSE_FROM
:
11380 var
= OMP_CLAUSE_DECL (c
);
11383 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
11384 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11389 if (DECL_SIZE (var
)
11390 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
11392 tree var2
= DECL_VALUE_EXPR (var
);
11393 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
11394 var2
= TREE_OPERAND (var2
, 0);
11395 gcc_assert (DECL_P (var2
));
11399 if (!maybe_lookup_field (var
, ctx
))
11404 x
= build_receiver_ref (var
, true, ctx
);
11405 tree new_var
= lookup_decl (var
, ctx
);
11406 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11407 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11408 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
11409 x
= build_simple_mem_ref (x
);
11410 SET_DECL_VALUE_EXPR (new_var
, x
);
11411 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
11418 target_nesting_level
++;
11419 lower_omp (&tgt_body
, ctx
);
11420 target_nesting_level
--;
11422 else if (data_region
)
11423 lower_omp (&tgt_body
, ctx
);
11427 /* Declare all the variables created by mapping and the variables
11428 declared in the scope of the target body. */
11429 record_vars_into (ctx
->block_vars
, child_fn
);
11430 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
11435 if (ctx
->record_type
)
11438 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
11439 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11440 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11441 t
= make_tree_vec (3);
11442 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
11443 TREE_VEC_ELT (t
, 1)
11444 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
11445 ".omp_data_sizes");
11446 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
11447 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
11448 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
11451 if (is_gimple_omp_oacc (stmt
))
11453 tkind_type
= short_unsigned_type_node
;
11458 tkind_type
= unsigned_char_type_node
;
11461 TREE_VEC_ELT (t
, 2)
11462 = create_tmp_var (build_array_type_nelts (tkind_type
, map_cnt
),
11463 ".omp_data_kinds");
11464 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
11465 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
11466 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
11467 gimple_omp_target_set_data_arg (stmt
, t
);
11469 vec
<constructor_elt
, va_gc
> *vsize
;
11470 vec
<constructor_elt
, va_gc
> *vkind
;
11471 vec_alloc (vsize
, map_cnt
);
11472 vec_alloc (vkind
, map_cnt
);
11473 unsigned int map_idx
= 0;
11475 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11476 switch (OMP_CLAUSE_CODE (c
))
11482 case OMP_CLAUSE_MAP
:
11483 case OMP_CLAUSE_TO
:
11484 case OMP_CLAUSE_FROM
:
11486 ovar
= OMP_CLAUSE_DECL (c
);
11487 if (!DECL_P (ovar
))
11489 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11490 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11492 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
11493 == get_base_address (ovar
));
11494 nc
= OMP_CLAUSE_CHAIN (c
);
11495 ovar
= OMP_CLAUSE_DECL (nc
);
11499 tree x
= build_sender_ref (ovar
, ctx
);
11501 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
11502 gimplify_assign (x
, v
, &ilist
);
11508 if (DECL_SIZE (ovar
)
11509 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
11511 tree ovar2
= DECL_VALUE_EXPR (ovar
);
11512 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
11513 ovar2
= TREE_OPERAND (ovar2
, 0);
11514 gcc_assert (DECL_P (ovar2
));
11517 if (!maybe_lookup_field (ovar
, ctx
))
11521 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
11522 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
11523 talign
= DECL_ALIGN_UNIT (ovar
);
11526 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
11527 tree x
= build_sender_ref (ovar
, ctx
);
11528 if (maybe_lookup_oacc_reduction (var
, ctx
))
11530 gcc_checking_assert (offloaded
11531 && is_gimple_omp_oacc (stmt
));
11532 gimplify_assign (x
, var
, &ilist
);
11534 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11535 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11536 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11537 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
11539 gcc_assert (offloaded
);
11541 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)));
11542 mark_addressable (avar
);
11543 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
11544 talign
= DECL_ALIGN_UNIT (avar
);
11545 avar
= build_fold_addr_expr (avar
);
11546 gimplify_assign (x
, avar
, &ilist
);
11548 else if (is_gimple_reg (var
))
11550 gcc_assert (offloaded
);
11551 tree avar
= create_tmp_var (TREE_TYPE (var
));
11552 mark_addressable (avar
);
11553 enum gomp_map_kind map_kind
= OMP_CLAUSE_MAP_KIND (c
);
11554 if (GOMP_MAP_COPY_TO_P (map_kind
)
11555 || map_kind
== GOMP_MAP_POINTER
11556 || map_kind
== GOMP_MAP_TO_PSET
11557 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11558 gimplify_assign (avar
, var
, &ilist
);
11559 avar
= build_fold_addr_expr (avar
);
11560 gimplify_assign (x
, avar
, &ilist
);
11561 if ((GOMP_MAP_COPY_FROM_P (map_kind
)
11562 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11563 && !TYPE_READONLY (TREE_TYPE (var
)))
11565 x
= build_sender_ref (ovar
, ctx
);
11566 x
= build_simple_mem_ref (x
);
11567 gimplify_assign (var
, x
, &olist
);
11572 var
= build_fold_addr_expr (var
);
11573 gimplify_assign (x
, var
, &ilist
);
11576 tree s
= OMP_CLAUSE_SIZE (c
);
11577 if (s
== NULL_TREE
)
11578 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
11579 s
= fold_convert (size_type_node
, s
);
11580 tree purpose
= size_int (map_idx
++);
11581 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
11582 if (TREE_CODE (s
) != INTEGER_CST
)
11583 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
11585 unsigned HOST_WIDE_INT tkind
;
11586 switch (OMP_CLAUSE_CODE (c
))
11588 case OMP_CLAUSE_MAP
:
11589 tkind
= OMP_CLAUSE_MAP_KIND (c
);
11591 case OMP_CLAUSE_TO
:
11592 tkind
= GOMP_MAP_TO
;
11594 case OMP_CLAUSE_FROM
:
11595 tkind
= GOMP_MAP_FROM
;
11598 gcc_unreachable ();
11600 gcc_checking_assert (tkind
11601 < (HOST_WIDE_INT_C (1U) << talign_shift
));
11602 talign
= ceil_log2 (talign
);
11603 tkind
|= talign
<< talign_shift
;
11604 gcc_checking_assert (tkind
11605 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
11606 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
11607 build_int_cstu (tkind_type
, tkind
));
11612 gcc_assert (map_idx
== map_cnt
);
11614 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
11615 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
11616 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
11617 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
11618 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
11620 gimple_seq initlist
= NULL
;
11621 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
11622 TREE_VEC_ELT (t
, 1)),
11623 &initlist
, true, NULL_TREE
);
11624 gimple_seq_add_seq (&ilist
, initlist
);
11626 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
11628 TREE_THIS_VOLATILE (clobber
) = 1;
11629 gimple_seq_add_stmt (&olist
,
11630 gimple_build_assign (TREE_VEC_ELT (t
, 1),
11634 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
11635 TREE_THIS_VOLATILE (clobber
) = 1;
11636 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11640 /* Once all the expansions are done, sequence all the different
11641 fragments inside gimple_omp_body. */
11646 && ctx
->record_type
)
11648 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11649 /* fixup_child_record_type might have changed receiver_decl's type. */
11650 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11651 gimple_seq_add_stmt (&new_body
,
11652 gimple_build_assign (ctx
->receiver_decl
, t
));
11657 gimple_seq_add_seq (&new_body
, tgt_body
);
11658 new_body
= maybe_catch_exception (new_body
);
11660 else if (data_region
)
11661 new_body
= tgt_body
;
11662 if (offloaded
|| data_region
)
11664 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11665 gimple_omp_set_body (stmt
, new_body
);
11668 bind
= gimple_build_bind (NULL
, NULL
,
11669 tgt_bind
? gimple_bind_block (tgt_bind
)
11671 gsi_replace (gsi_p
, bind
, true);
11672 gimple_bind_add_seq (bind
, irlist
);
11673 gimple_bind_add_seq (bind
, ilist
);
11674 gimple_bind_add_stmt (bind
, stmt
);
11675 gimple_bind_add_seq (bind
, olist
);
11676 gimple_bind_add_seq (bind
, orlist
);
11678 pop_gimplify_context (NULL
);
11681 /* Expand code for an OpenMP teams directive. */
11684 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11686 gomp_teams
*teams_stmt
= as_a
<gomp_teams
*> (gsi_stmt (*gsi_p
));
11687 push_gimplify_context ();
11689 tree block
= make_node (BLOCK
);
11690 gbind
*bind
= gimple_build_bind (NULL
, NULL
, block
);
11691 gsi_replace (gsi_p
, bind
, true);
11692 gimple_seq bind_body
= NULL
;
11693 gimple_seq dlist
= NULL
;
11694 gimple_seq olist
= NULL
;
11696 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11697 OMP_CLAUSE_NUM_TEAMS
);
11698 if (num_teams
== NULL_TREE
)
11699 num_teams
= build_int_cst (unsigned_type_node
, 0);
11702 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
11703 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
11704 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
11706 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11707 OMP_CLAUSE_THREAD_LIMIT
);
11708 if (thread_limit
== NULL_TREE
)
11709 thread_limit
= build_int_cst (unsigned_type_node
, 0);
11712 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
11713 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
11714 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
11718 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
11719 &bind_body
, &dlist
, ctx
, NULL
);
11720 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
11721 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
11722 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
11724 location_t loc
= gimple_location (teams_stmt
);
11725 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
11726 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
11727 gimple_set_location (call
, loc
);
11728 gimple_seq_add_stmt (&bind_body
, call
);
11730 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
11731 gimple_omp_set_body (teams_stmt
, NULL
);
11732 gimple_seq_add_seq (&bind_body
, olist
);
11733 gimple_seq_add_seq (&bind_body
, dlist
);
11734 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
11735 gimple_bind_set_body (bind
, bind_body
);
11737 pop_gimplify_context (bind
);
11739 gimple_bind_append_vars (bind
, ctx
->block_vars
);
11740 BLOCK_VARS (block
) = ctx
->block_vars
;
11741 if (BLOCK_VARS (block
))
11742 TREE_USED (block
) = 1;
11746 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11747 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11748 of OMP context, but with task_shared_vars set. */
11751 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
11756 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11757 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
11760 if (task_shared_vars
11762 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
11765 /* If a global variable has been privatized, TREE_CONSTANT on
11766 ADDR_EXPR might be wrong. */
11767 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
11768 recompute_tree_invariant_for_addr_expr (t
);
11770 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
11775 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11777 gimple stmt
= gsi_stmt (*gsi_p
);
11778 struct walk_stmt_info wi
;
11781 if (gimple_has_location (stmt
))
11782 input_location
= gimple_location (stmt
);
11784 if (task_shared_vars
)
11785 memset (&wi
, '\0', sizeof (wi
));
11787 /* If we have issued syntax errors, avoid doing any heavy lifting.
11788 Just replace the OMP directives with a NOP to avoid
11789 confusing RTL expansion. */
11790 if (seen_error () && is_gimple_omp (stmt
))
11792 gsi_replace (gsi_p
, gimple_build_nop (), true);
11796 switch (gimple_code (stmt
))
11800 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
11801 if ((ctx
|| task_shared_vars
)
11802 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
11803 lower_omp_regimplify_p
,
11804 ctx
? NULL
: &wi
, NULL
)
11805 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
11806 lower_omp_regimplify_p
,
11807 ctx
? NULL
: &wi
, NULL
)))
11808 gimple_regimplify_operands (cond_stmt
, gsi_p
);
11812 lower_omp (gimple_catch_handler_ptr (as_a
<gcatch
*> (stmt
)), ctx
);
11814 case GIMPLE_EH_FILTER
:
11815 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
11818 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
11819 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
11821 case GIMPLE_TRANSACTION
:
11822 lower_omp (gimple_transaction_body_ptr (
11823 as_a
<gtransaction
*> (stmt
)),
11827 lower_omp (gimple_bind_body_ptr (as_a
<gbind
*> (stmt
)), ctx
);
11829 case GIMPLE_OMP_PARALLEL
:
11830 case GIMPLE_OMP_TASK
:
11831 ctx
= maybe_lookup_ctx (stmt
);
11833 if (ctx
->cancellable
)
11834 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11835 lower_omp_taskreg (gsi_p
, ctx
);
11837 case GIMPLE_OMP_FOR
:
11838 ctx
= maybe_lookup_ctx (stmt
);
11840 if (ctx
->cancellable
)
11841 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11842 lower_omp_for (gsi_p
, ctx
);
11844 case GIMPLE_OMP_SECTIONS
:
11845 ctx
= maybe_lookup_ctx (stmt
);
11847 if (ctx
->cancellable
)
11848 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11849 lower_omp_sections (gsi_p
, ctx
);
11851 case GIMPLE_OMP_SINGLE
:
11852 ctx
= maybe_lookup_ctx (stmt
);
11854 lower_omp_single (gsi_p
, ctx
);
11856 case GIMPLE_OMP_MASTER
:
11857 ctx
= maybe_lookup_ctx (stmt
);
11859 lower_omp_master (gsi_p
, ctx
);
11861 case GIMPLE_OMP_TASKGROUP
:
11862 ctx
= maybe_lookup_ctx (stmt
);
11864 lower_omp_taskgroup (gsi_p
, ctx
);
11866 case GIMPLE_OMP_ORDERED
:
11867 ctx
= maybe_lookup_ctx (stmt
);
11869 lower_omp_ordered (gsi_p
, ctx
);
11871 case GIMPLE_OMP_CRITICAL
:
11872 ctx
= maybe_lookup_ctx (stmt
);
11874 lower_omp_critical (gsi_p
, ctx
);
11876 case GIMPLE_OMP_ATOMIC_LOAD
:
11877 if ((ctx
|| task_shared_vars
)
11878 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11879 as_a
<gomp_atomic_load
*> (stmt
)),
11880 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
11881 gimple_regimplify_operands (stmt
, gsi_p
);
11883 case GIMPLE_OMP_TARGET
:
11884 ctx
= maybe_lookup_ctx (stmt
);
11886 lower_omp_target (gsi_p
, ctx
);
11888 case GIMPLE_OMP_TEAMS
:
11889 ctx
= maybe_lookup_ctx (stmt
);
11891 lower_omp_teams (gsi_p
, ctx
);
11895 call_stmt
= as_a
<gcall
*> (stmt
);
11896 fndecl
= gimple_call_fndecl (call_stmt
);
11898 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
11899 switch (DECL_FUNCTION_CODE (fndecl
))
11901 case BUILT_IN_GOMP_BARRIER
:
11905 case BUILT_IN_GOMP_CANCEL
:
11906 case BUILT_IN_GOMP_CANCELLATION_POINT
:
11909 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
11910 cctx
= cctx
->outer
;
11911 gcc_assert (gimple_call_lhs (call_stmt
) == NULL_TREE
);
11912 if (!cctx
->cancellable
)
11914 if (DECL_FUNCTION_CODE (fndecl
)
11915 == BUILT_IN_GOMP_CANCELLATION_POINT
)
11917 stmt
= gimple_build_nop ();
11918 gsi_replace (gsi_p
, stmt
, false);
11922 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
11924 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
11925 gimple_call_set_fndecl (call_stmt
, fndecl
);
11926 gimple_call_set_fntype (call_stmt
, TREE_TYPE (fndecl
));
11929 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)));
11930 gimple_call_set_lhs (call_stmt
, lhs
);
11931 tree fallthru_label
;
11932 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
11934 g
= gimple_build_label (fallthru_label
);
11935 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11936 g
= gimple_build_cond (NE_EXPR
, lhs
,
11937 fold_convert (TREE_TYPE (lhs
),
11938 boolean_false_node
),
11939 cctx
->cancel_label
, fallthru_label
);
11940 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11947 if ((ctx
|| task_shared_vars
)
11948 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
11951 /* Just remove clobbers, this should happen only if we have
11952 "privatized" local addressable variables in SIMD regions,
11953 the clobber isn't needed in that case and gimplifying address
11954 of the ARRAY_REF into a pointer and creating MEM_REF based
11955 clobber would create worse code than we get with the clobber
11957 if (gimple_clobber_p (stmt
))
11959 gsi_replace (gsi_p
, gimple_build_nop (), true);
11962 gimple_regimplify_operands (stmt
, gsi_p
);
11969 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
11971 location_t saved_location
= input_location
;
11972 gimple_stmt_iterator gsi
;
11973 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11974 lower_omp_1 (&gsi
, ctx
);
11975 /* During gimplification, we haven't folded statments inside offloading
11976 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
11977 if (target_nesting_level
|| taskreg_nesting_level
)
11978 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11980 input_location
= saved_location
;
11983 /* Main entry point. */
11985 static unsigned int
11986 execute_lower_omp (void)
11992 /* This pass always runs, to provide PROP_gimple_lomp.
11993 But often, there is nothing to do. */
11994 if (flag_cilkplus
== 0 && flag_openacc
== 0 && flag_openmp
== 0
11995 && flag_openmp_simd
== 0)
11998 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
11999 delete_omp_context
);
12001 body
= gimple_body (current_function_decl
);
12002 scan_omp (&body
, NULL
);
12003 gcc_assert (taskreg_nesting_level
== 0);
12004 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
12005 finish_taskreg_scan (ctx
);
12006 taskreg_contexts
.release ();
12008 if (all_contexts
->root
)
12010 if (task_shared_vars
)
12011 push_gimplify_context ();
12012 lower_omp (&body
, NULL
);
12013 if (task_shared_vars
)
12014 pop_gimplify_context (NULL
);
12019 splay_tree_delete (all_contexts
);
12020 all_contexts
= NULL
;
12022 BITMAP_FREE (task_shared_vars
);
12028 const pass_data pass_data_lower_omp
=
12030 GIMPLE_PASS
, /* type */
12031 "omplower", /* name */
12032 OPTGROUP_NONE
, /* optinfo_flags */
12033 TV_NONE
, /* tv_id */
12034 PROP_gimple_any
, /* properties_required */
12035 PROP_gimple_lomp
, /* properties_provided */
12036 0, /* properties_destroyed */
12037 0, /* todo_flags_start */
12038 0, /* todo_flags_finish */
12041 class pass_lower_omp
: public gimple_opt_pass
12044 pass_lower_omp (gcc::context
*ctxt
)
12045 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
12048 /* opt_pass methods: */
12049 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
12051 }; // class pass_lower_omp
12053 } // anon namespace
12056 make_pass_lower_omp (gcc::context
*ctxt
)
12058 return new pass_lower_omp (ctxt
);
12061 /* The following is a utility to diagnose structured block violations.
12062 It is not part of the "omplower" pass, as that's invoked too late. It
12063 should be invoked by the respective front ends after gimplification. */
12065 static splay_tree all_labels
;
12067 /* Check for mismatched contexts and generate an error if needed. Return
12068 true if an error is detected. */
12071 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
12072 gimple branch_ctx
, gimple label_ctx
)
12074 gcc_checking_assert (!branch_ctx
|| is_gimple_omp (branch_ctx
));
12075 gcc_checking_assert (!label_ctx
|| is_gimple_omp (label_ctx
));
12077 if (label_ctx
== branch_ctx
)
12080 const char* kind
= NULL
;
12085 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
12086 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
12088 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
12089 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
12090 kind
= "Cilk Plus";
12094 if ((branch_ctx
&& is_gimple_omp_oacc (branch_ctx
))
12095 || (label_ctx
&& is_gimple_omp_oacc (label_ctx
)))
12097 gcc_checking_assert (kind
== NULL
);
12103 gcc_checking_assert (flag_openmp
);
12108 Previously we kept track of the label's entire context in diagnose_sb_[12]
12109 so we could traverse it and issue a correct "exit" or "enter" error
12110 message upon a structured block violation.
12112 We built the context by building a list with tree_cons'ing, but there is
12113 no easy counterpart in gimple tuples. It seems like far too much work
12114 for issuing exit/enter error messages. If someone really misses the
12115 distinct error message... patches welcome.
12119 /* Try to avoid confusing the user by producing and error message
12120 with correct "exit" or "enter" verbiage. We prefer "exit"
12121 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12122 if (branch_ctx
== NULL
)
12128 if (TREE_VALUE (label_ctx
) == branch_ctx
)
12133 label_ctx
= TREE_CHAIN (label_ctx
);
12138 error ("invalid exit from %s structured block", kind
);
12140 error ("invalid entry to %s structured block", kind
);
12143 /* If it's obvious we have an invalid entry, be specific about the error. */
12144 if (branch_ctx
== NULL
)
12145 error ("invalid entry to %s structured block", kind
);
12148 /* Otherwise, be vague and lazy, but efficient. */
12149 error ("invalid branch to/from %s structured block", kind
);
12152 gsi_replace (gsi_p
, gimple_build_nop (), false);
12156 /* Pass 1: Create a minimal tree of structured blocks, and record
12157 where each label is found. */
12160 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12161 struct walk_stmt_info
*wi
)
12163 gimple context
= (gimple
) wi
->info
;
12164 gimple inner_context
;
12165 gimple stmt
= gsi_stmt (*gsi_p
);
12167 *handled_ops_p
= true;
12169 switch (gimple_code (stmt
))
12173 case GIMPLE_OMP_PARALLEL
:
12174 case GIMPLE_OMP_TASK
:
12175 case GIMPLE_OMP_SECTIONS
:
12176 case GIMPLE_OMP_SINGLE
:
12177 case GIMPLE_OMP_SECTION
:
12178 case GIMPLE_OMP_MASTER
:
12179 case GIMPLE_OMP_ORDERED
:
12180 case GIMPLE_OMP_CRITICAL
:
12181 case GIMPLE_OMP_TARGET
:
12182 case GIMPLE_OMP_TEAMS
:
12183 case GIMPLE_OMP_TASKGROUP
:
12184 /* The minimal context here is just the current OMP construct. */
12185 inner_context
= stmt
;
12186 wi
->info
= inner_context
;
12187 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12188 wi
->info
= context
;
12191 case GIMPLE_OMP_FOR
:
12192 inner_context
= stmt
;
12193 wi
->info
= inner_context
;
12194 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12196 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
12197 diagnose_sb_1
, NULL
, wi
);
12198 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12199 wi
->info
= context
;
12203 splay_tree_insert (all_labels
,
12204 (splay_tree_key
) gimple_label_label (
12205 as_a
<glabel
*> (stmt
)),
12206 (splay_tree_value
) context
);
12216 /* Pass 2: Check each branch and see if its context differs from that of
12217 the destination label's context. */
12220 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12221 struct walk_stmt_info
*wi
)
12223 gimple context
= (gimple
) wi
->info
;
12225 gimple stmt
= gsi_stmt (*gsi_p
);
12227 *handled_ops_p
= true;
12229 switch (gimple_code (stmt
))
12233 case GIMPLE_OMP_PARALLEL
:
12234 case GIMPLE_OMP_TASK
:
12235 case GIMPLE_OMP_SECTIONS
:
12236 case GIMPLE_OMP_SINGLE
:
12237 case GIMPLE_OMP_SECTION
:
12238 case GIMPLE_OMP_MASTER
:
12239 case GIMPLE_OMP_ORDERED
:
12240 case GIMPLE_OMP_CRITICAL
:
12241 case GIMPLE_OMP_TARGET
:
12242 case GIMPLE_OMP_TEAMS
:
12243 case GIMPLE_OMP_TASKGROUP
:
12245 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12246 wi
->info
= context
;
12249 case GIMPLE_OMP_FOR
:
12251 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12253 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
12254 diagnose_sb_2
, NULL
, wi
);
12255 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12256 wi
->info
= context
;
12261 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
12262 tree lab
= gimple_cond_true_label (cond_stmt
);
12265 n
= splay_tree_lookup (all_labels
,
12266 (splay_tree_key
) lab
);
12267 diagnose_sb_0 (gsi_p
, context
,
12268 n
? (gimple
) n
->value
: NULL
);
12270 lab
= gimple_cond_false_label (cond_stmt
);
12273 n
= splay_tree_lookup (all_labels
,
12274 (splay_tree_key
) lab
);
12275 diagnose_sb_0 (gsi_p
, context
,
12276 n
? (gimple
) n
->value
: NULL
);
12283 tree lab
= gimple_goto_dest (stmt
);
12284 if (TREE_CODE (lab
) != LABEL_DECL
)
12287 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12288 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
12292 case GIMPLE_SWITCH
:
12294 gswitch
*switch_stmt
= as_a
<gswitch
*> (stmt
);
12296 for (i
= 0; i
< gimple_switch_num_labels (switch_stmt
); ++i
)
12298 tree lab
= CASE_LABEL (gimple_switch_label (switch_stmt
, i
));
12299 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12300 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
12306 case GIMPLE_RETURN
:
12307 diagnose_sb_0 (gsi_p
, context
, NULL
);
12317 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12320 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
12323 gimple last
= last_stmt (bb
);
12324 enum gimple_code code
= gimple_code (last
);
12325 struct omp_region
*cur_region
= *region
;
12326 bool fallthru
= false;
12330 case GIMPLE_OMP_PARALLEL
:
12331 case GIMPLE_OMP_TASK
:
12332 case GIMPLE_OMP_FOR
:
12333 case GIMPLE_OMP_SINGLE
:
12334 case GIMPLE_OMP_TEAMS
:
12335 case GIMPLE_OMP_MASTER
:
12336 case GIMPLE_OMP_TASKGROUP
:
12337 case GIMPLE_OMP_ORDERED
:
12338 case GIMPLE_OMP_CRITICAL
:
12339 case GIMPLE_OMP_SECTION
:
12340 cur_region
= new_omp_region (bb
, code
, cur_region
);
12344 case GIMPLE_OMP_TARGET
:
12345 cur_region
= new_omp_region (bb
, code
, cur_region
);
12347 switch (gimple_omp_target_kind (last
))
12349 case GF_OMP_TARGET_KIND_REGION
:
12350 case GF_OMP_TARGET_KIND_DATA
:
12351 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
12352 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
12353 case GF_OMP_TARGET_KIND_OACC_DATA
:
12355 case GF_OMP_TARGET_KIND_UPDATE
:
12356 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
12357 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
12358 cur_region
= cur_region
->outer
;
12361 gcc_unreachable ();
12365 case GIMPLE_OMP_SECTIONS
:
12366 cur_region
= new_omp_region (bb
, code
, cur_region
);
12370 case GIMPLE_OMP_SECTIONS_SWITCH
:
12374 case GIMPLE_OMP_ATOMIC_LOAD
:
12375 case GIMPLE_OMP_ATOMIC_STORE
:
12379 case GIMPLE_OMP_RETURN
:
12380 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12381 somewhere other than the next block. This will be
12383 cur_region
->exit
= bb
;
12384 if (cur_region
->type
== GIMPLE_OMP_TASK
)
12385 /* Add an edge corresponding to not scheduling the task
12387 make_edge (cur_region
->entry
, bb
, EDGE_ABNORMAL
);
12388 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
12389 cur_region
= cur_region
->outer
;
12392 case GIMPLE_OMP_CONTINUE
:
12393 cur_region
->cont
= bb
;
12394 switch (cur_region
->type
)
12396 case GIMPLE_OMP_FOR
:
12397 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12398 succs edges as abnormal to prevent splitting
12400 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
12401 /* Make the loopback edge. */
12402 make_edge (bb
, single_succ (cur_region
->entry
),
12405 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12406 corresponds to the case that the body of the loop
12407 is not executed at all. */
12408 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
12409 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
12413 case GIMPLE_OMP_SECTIONS
:
12414 /* Wire up the edges into and out of the nested sections. */
12416 basic_block switch_bb
= single_succ (cur_region
->entry
);
12418 struct omp_region
*i
;
12419 for (i
= cur_region
->inner
; i
; i
= i
->next
)
12421 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
12422 make_edge (switch_bb
, i
->entry
, 0);
12423 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
12426 /* Make the loopback edge to the block with
12427 GIMPLE_OMP_SECTIONS_SWITCH. */
12428 make_edge (bb
, switch_bb
, 0);
12430 /* Make the edge from the switch to exit. */
12431 make_edge (switch_bb
, bb
->next_bb
, 0);
12436 case GIMPLE_OMP_TASK
:
12441 gcc_unreachable ();
12446 gcc_unreachable ();
12449 if (*region
!= cur_region
)
12451 *region
= cur_region
;
12453 *region_idx
= cur_region
->entry
->index
;
12461 static unsigned int
12462 diagnose_omp_structured_block_errors (void)
12464 struct walk_stmt_info wi
;
12465 gimple_seq body
= gimple_body (current_function_decl
);
12467 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
12469 memset (&wi
, 0, sizeof (wi
));
12470 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
12472 memset (&wi
, 0, sizeof (wi
));
12473 wi
.want_locations
= true;
12474 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
12476 gimple_set_body (current_function_decl
, body
);
12478 splay_tree_delete (all_labels
);
12486 const pass_data pass_data_diagnose_omp_blocks
=
12488 GIMPLE_PASS
, /* type */
12489 "*diagnose_omp_blocks", /* name */
12490 OPTGROUP_NONE
, /* optinfo_flags */
12491 TV_NONE
, /* tv_id */
12492 PROP_gimple_any
, /* properties_required */
12493 0, /* properties_provided */
12494 0, /* properties_destroyed */
12495 0, /* todo_flags_start */
12496 0, /* todo_flags_finish */
12499 class pass_diagnose_omp_blocks
: public gimple_opt_pass
12502 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12503 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
12506 /* opt_pass methods: */
12507 virtual bool gate (function
*)
12509 return flag_cilkplus
|| flag_openacc
|| flag_openmp
;
12511 virtual unsigned int execute (function
*)
12513 return diagnose_omp_structured_block_errors ();
12516 }; // class pass_diagnose_omp_blocks
12518 } // anon namespace
12521 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12523 return new pass_diagnose_omp_blocks (ctxt
);
12526 /* SIMD clone supporting code. */
12528 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12529 of arguments to reserve space for. */
12531 static struct cgraph_simd_clone
*
12532 simd_clone_struct_alloc (int nargs
)
12534 struct cgraph_simd_clone
*clone_info
;
12535 size_t len
= (sizeof (struct cgraph_simd_clone
)
12536 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
12537 clone_info
= (struct cgraph_simd_clone
*)
12538 ggc_internal_cleared_alloc (len
);
12542 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12545 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
12546 struct cgraph_simd_clone
*from
)
12548 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
12549 + ((from
->nargs
- from
->inbranch
)
12550 * sizeof (struct cgraph_simd_clone_arg
))));
12553 /* Return vector of parameter types of function FNDECL. This uses
12554 TYPE_ARG_TYPES if available, otherwise falls back to types of
12555 DECL_ARGUMENTS types. */
12558 simd_clone_vector_of_formal_parm_types (tree fndecl
)
12560 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
12561 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
12562 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
12565 FOR_EACH_VEC_ELT (args
, i
, arg
)
12566 args
[i
] = TREE_TYPE (args
[i
]);
12570 /* Given a simd function in NODE, extract the simd specific
12571 information from the OMP clauses passed in CLAUSES, and return
12572 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12573 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12574 otherwise set to FALSE. */
12576 static struct cgraph_simd_clone
*
12577 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
12578 bool *inbranch_specified
)
12580 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12583 *inbranch_specified
= false;
12585 n
= args
.length ();
12586 if (n
> 0 && args
.last () == void_type_node
)
12589 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12590 be cloned have a distinctive artificial label in addition to "omp
12594 && lookup_attribute ("cilk simd function",
12595 DECL_ATTRIBUTES (node
->decl
)));
12597 /* Allocate one more than needed just in case this is an in-branch
12598 clone which will require a mask argument. */
12599 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
12600 clone_info
->nargs
= n
;
12601 clone_info
->cilk_elemental
= cilk_clone
;
12608 clauses
= TREE_VALUE (clauses
);
12609 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
12612 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
12614 switch (OMP_CLAUSE_CODE (t
))
12616 case OMP_CLAUSE_INBRANCH
:
12617 clone_info
->inbranch
= 1;
12618 *inbranch_specified
= true;
12620 case OMP_CLAUSE_NOTINBRANCH
:
12621 clone_info
->inbranch
= 0;
12622 *inbranch_specified
= true;
12624 case OMP_CLAUSE_SIMDLEN
:
12625 clone_info
->simdlen
12626 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
12628 case OMP_CLAUSE_LINEAR
:
12630 tree decl
= OMP_CLAUSE_DECL (t
);
12631 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
12632 int argno
= TREE_INT_CST_LOW (decl
);
12633 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
12635 clone_info
->args
[argno
].arg_type
12636 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
12637 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12638 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
12639 && clone_info
->args
[argno
].linear_step
< n
);
12643 if (POINTER_TYPE_P (args
[argno
]))
12644 step
= fold_convert (ssizetype
, step
);
12645 if (!tree_fits_shwi_p (step
))
12647 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12648 "ignoring large linear step");
12652 else if (integer_zerop (step
))
12654 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12655 "ignoring zero linear step");
12661 clone_info
->args
[argno
].arg_type
12662 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
12663 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12668 case OMP_CLAUSE_UNIFORM
:
12670 tree decl
= OMP_CLAUSE_DECL (t
);
12671 int argno
= tree_to_uhwi (decl
);
12672 clone_info
->args
[argno
].arg_type
12673 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
12676 case OMP_CLAUSE_ALIGNED
:
12678 tree decl
= OMP_CLAUSE_DECL (t
);
12679 int argno
= tree_to_uhwi (decl
);
12680 clone_info
->args
[argno
].alignment
12681 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
12692 /* Given a SIMD clone in NODE, calculate the characteristic data
12693 type and return the coresponding type. The characteristic data
12694 type is computed as described in the Intel Vector ABI. */
12697 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
12698 struct cgraph_simd_clone
*clone_info
)
12700 tree type
= integer_type_node
;
12701 tree fndecl
= node
->decl
;
12703 /* a) For non-void function, the characteristic data type is the
12705 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
12706 type
= TREE_TYPE (TREE_TYPE (fndecl
));
12708 /* b) If the function has any non-uniform, non-linear parameters,
12709 then the characteristic data type is the type of the first
12713 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
12714 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
12715 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
12723 /* c) If the characteristic data type determined by a) or b) above
12724 is struct, union, or class type which is pass-by-value (except
12725 for the type that maps to the built-in complex data type), the
12726 characteristic data type is int. */
12727 if (RECORD_OR_UNION_TYPE_P (type
)
12728 && !aggregate_value_p (type
, NULL
)
12729 && TREE_CODE (type
) != COMPLEX_TYPE
)
12730 return integer_type_node
;
12732 /* d) If none of the above three classes is applicable, the
12733 characteristic data type is int. */
12737 /* e) For Intel Xeon Phi native and offload compilation, if the
12738 resulting characteristic data type is 8-bit or 16-bit integer
12739 data type, the characteristic data type is int. */
12740 /* Well, we don't handle Xeon Phi yet. */
12744 simd_clone_mangle (struct cgraph_node
*node
,
12745 struct cgraph_simd_clone
*clone_info
)
12747 char vecsize_mangle
= clone_info
->vecsize_mangle
;
12748 char mask
= clone_info
->inbranch
? 'M' : 'N';
12749 unsigned int simdlen
= clone_info
->simdlen
;
12753 gcc_assert (vecsize_mangle
&& simdlen
);
12755 pp_string (&pp
, "_ZGV");
12756 pp_character (&pp
, vecsize_mangle
);
12757 pp_character (&pp
, mask
);
12758 pp_decimal_int (&pp
, simdlen
);
12760 for (n
= 0; n
< clone_info
->nargs
; ++n
)
12762 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
12764 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
12765 pp_character (&pp
, 'u');
12766 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
12768 gcc_assert (arg
.linear_step
!= 0);
12769 pp_character (&pp
, 'l');
12770 if (arg
.linear_step
> 1)
12771 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12772 else if (arg
.linear_step
< 0)
12774 pp_character (&pp
, 'n');
12775 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
12779 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
12781 pp_character (&pp
, 's');
12782 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12785 pp_character (&pp
, 'v');
12788 pp_character (&pp
, 'a');
12789 pp_decimal_int (&pp
, arg
.alignment
);
12793 pp_underscore (&pp
);
12794 const char *str
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
));
12797 pp_string (&pp
, str
);
12798 str
= pp_formatted_text (&pp
);
12800 /* If there already is a SIMD clone with the same mangled name, don't
12801 add another one. This can happen e.g. for
12802 #pragma omp declare simd
12803 #pragma omp declare simd simdlen(8)
12804 int foo (int, int);
12805 if the simdlen is assumed to be 8 for the first one, etc. */
12806 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
12807 clone
= clone
->simdclone
->next_clone
)
12808 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
12812 return get_identifier (str
);
12815 /* Create a simd clone of OLD_NODE and return it. */
12817 static struct cgraph_node
*
12818 simd_clone_create (struct cgraph_node
*old_node
)
12820 struct cgraph_node
*new_node
;
12821 if (old_node
->definition
)
12823 if (!old_node
->has_gimple_body_p ())
12825 old_node
->get_body ();
12826 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
12832 tree old_decl
= old_node
->decl
;
12833 tree new_decl
= copy_node (old_node
->decl
);
12834 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
12835 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
12836 SET_DECL_RTL (new_decl
, NULL
);
12837 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
12838 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
12839 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
12840 symtab
->call_cgraph_insertion_hooks (new_node
);
12842 if (new_node
== NULL
)
12845 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
12847 /* The function cgraph_function_versioning () will force the new
12848 symbol local. Undo this, and inherit external visability from
12850 new_node
->local
.local
= old_node
->local
.local
;
12851 new_node
->externally_visible
= old_node
->externally_visible
;
12856 /* Adjust the return type of the given function to its appropriate
12857 vector counterpart. Returns a simd array to be used throughout the
12858 function as a return value. */
12861 simd_clone_adjust_return_type (struct cgraph_node
*node
)
12863 tree fndecl
= node
->decl
;
12864 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
12865 unsigned int veclen
;
12868 /* Adjust the function return type. */
12869 if (orig_rettype
== void_type_node
)
12871 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
12872 t
= TREE_TYPE (TREE_TYPE (fndecl
));
12873 if (INTEGRAL_TYPE_P (t
) || POINTER_TYPE_P (t
))
12874 veclen
= node
->simdclone
->vecsize_int
;
12876 veclen
= node
->simdclone
->vecsize_float
;
12877 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (t
));
12878 if (veclen
> node
->simdclone
->simdlen
)
12879 veclen
= node
->simdclone
->simdlen
;
12880 if (POINTER_TYPE_P (t
))
12881 t
= pointer_sized_int_node
;
12882 if (veclen
== node
->simdclone
->simdlen
)
12883 t
= build_vector_type (t
, node
->simdclone
->simdlen
);
12886 t
= build_vector_type (t
, veclen
);
12887 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
12889 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
12890 if (!node
->definition
)
12893 t
= DECL_RESULT (fndecl
);
12894 /* Adjust the DECL_RESULT. */
12895 gcc_assert (TREE_TYPE (t
) != void_type_node
);
12896 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
12899 tree atype
= build_array_type_nelts (orig_rettype
,
12900 node
->simdclone
->simdlen
);
12901 if (veclen
!= node
->simdclone
->simdlen
)
12902 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
12904 /* Set up a SIMD array to use as the return value. */
12905 tree retval
= create_tmp_var_raw (atype
, "retval");
12906 gimple_add_tmp_var (retval
);
12910 /* Each vector argument has a corresponding array to be used locally
12911 as part of the eventual loop. Create such temporary array and
12914 PREFIX is the prefix to be used for the temporary.
12916 TYPE is the inner element type.
12918 SIMDLEN is the number of elements. */
12921 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
12923 tree atype
= build_array_type_nelts (type
, simdlen
);
12924 tree avar
= create_tmp_var_raw (atype
, prefix
);
12925 gimple_add_tmp_var (avar
);
12929 /* Modify the function argument types to their corresponding vector
12930 counterparts if appropriate. Also, create one array for each simd
12931 argument to be used locally when using the function arguments as
12934 NODE is the function whose arguments are to be adjusted.
12936 Returns an adjustment vector that will be filled describing how the
12937 argument types will be adjusted. */
12939 static ipa_parm_adjustment_vec
12940 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
12943 ipa_parm_adjustment_vec adjustments
;
12945 if (node
->definition
)
12946 args
= ipa_get_vector_of_formal_parms (node
->decl
);
12948 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12949 adjustments
.create (args
.length ());
12950 unsigned i
, j
, veclen
;
12951 struct ipa_parm_adjustment adj
;
12952 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
12954 memset (&adj
, 0, sizeof (adj
));
12955 tree parm
= args
[i
];
12956 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
12957 adj
.base_index
= i
;
12960 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
12961 node
->simdclone
->args
[i
].orig_type
= parm_type
;
12963 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
12965 /* No adjustment necessary for scalar arguments. */
12966 adj
.op
= IPA_PARM_OP_COPY
;
12970 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
12971 veclen
= node
->simdclone
->vecsize_int
;
12973 veclen
= node
->simdclone
->vecsize_float
;
12974 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
12975 if (veclen
> node
->simdclone
->simdlen
)
12976 veclen
= node
->simdclone
->simdlen
;
12977 adj
.arg_prefix
= "simd";
12978 if (POINTER_TYPE_P (parm_type
))
12979 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
12981 adj
.type
= build_vector_type (parm_type
, veclen
);
12982 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
12983 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
12985 adjustments
.safe_push (adj
);
12988 memset (&adj
, 0, sizeof (adj
));
12989 adj
.op
= IPA_PARM_OP_NEW
;
12990 adj
.arg_prefix
= "simd";
12991 adj
.base_index
= i
;
12992 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
12996 if (node
->definition
)
12997 node
->simdclone
->args
[i
].simd_array
12998 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
12999 parm_type
, node
->simdclone
->simdlen
);
13001 adjustments
.safe_push (adj
);
13004 if (node
->simdclone
->inbranch
)
13007 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
13010 memset (&adj
, 0, sizeof (adj
));
13011 adj
.op
= IPA_PARM_OP_NEW
;
13012 adj
.arg_prefix
= "mask";
13014 adj
.base_index
= i
;
13015 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
13016 veclen
= node
->simdclone
->vecsize_int
;
13018 veclen
= node
->simdclone
->vecsize_float
;
13019 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
13020 if (veclen
> node
->simdclone
->simdlen
)
13021 veclen
= node
->simdclone
->simdlen
;
13022 if (POINTER_TYPE_P (base_type
))
13023 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
13025 adj
.type
= build_vector_type (base_type
, veclen
);
13026 adjustments
.safe_push (adj
);
13028 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
13029 adjustments
.safe_push (adj
);
13031 /* We have previously allocated one extra entry for the mask. Use
13033 struct cgraph_simd_clone
*sc
= node
->simdclone
;
13035 if (node
->definition
)
13037 sc
->args
[i
].orig_arg
13038 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
13039 sc
->args
[i
].simd_array
13040 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
13042 sc
->args
[i
].orig_type
= base_type
;
13043 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
13046 if (node
->definition
)
13047 ipa_modify_formal_parameters (node
->decl
, adjustments
);
13050 tree new_arg_types
= NULL_TREE
, new_reversed
;
13051 bool last_parm_void
= false;
13052 if (args
.length () > 0 && args
.last () == void_type_node
)
13053 last_parm_void
= true;
13055 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
13056 j
= adjustments
.length ();
13057 for (i
= 0; i
< j
; i
++)
13059 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
13061 if (adj
->op
== IPA_PARM_OP_COPY
)
13062 ptype
= args
[adj
->base_index
];
13065 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
13067 new_reversed
= nreverse (new_arg_types
);
13068 if (last_parm_void
)
13071 TREE_CHAIN (new_arg_types
) = void_list_node
;
13073 new_reversed
= void_list_node
;
13076 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
13077 TYPE_ARG_TYPES (new_type
) = new_reversed
;
13078 TREE_TYPE (node
->decl
) = new_type
;
13080 adjustments
.release ();
13083 return adjustments
;
13086 /* Initialize and copy the function arguments in NODE to their
13087 corresponding local simd arrays. Returns a fresh gimple_seq with
13088 the instruction sequence generated. */
13091 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
13092 ipa_parm_adjustment_vec adjustments
)
13094 gimple_seq seq
= NULL
;
13095 unsigned i
= 0, j
= 0, k
;
13097 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
13099 arg
= DECL_CHAIN (arg
), i
++, j
++)
13101 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
13104 node
->simdclone
->args
[i
].vector_arg
= arg
;
13106 tree array
= node
->simdclone
->args
[i
].simd_array
;
13107 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
13109 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
13110 tree ptr
= build_fold_addr_expr (array
);
13111 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
13112 build_int_cst (ptype
, 0));
13113 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
13114 gimplify_and_add (t
, &seq
);
13118 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
13119 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
13120 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
13122 tree ptr
= build_fold_addr_expr (array
);
13126 arg
= DECL_CHAIN (arg
);
13130 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
13131 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
13132 build_int_cst (ptype
, k
* elemsize
));
13133 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
13134 gimplify_and_add (t
, &seq
);
13141 /* Callback info for ipa_simd_modify_stmt_ops below. */
13143 struct modify_stmt_info
{
13144 ipa_parm_adjustment_vec adjustments
;
13146 /* True if the parent statement was modified by
13147 ipa_simd_modify_stmt_ops. */
13151 /* Callback for walk_gimple_op.
13153 Adjust operands from a given statement as specified in the
13154 adjustments vector in the callback data. */
13157 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
13159 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
13160 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
13161 tree
*orig_tp
= tp
;
13162 if (TREE_CODE (*tp
) == ADDR_EXPR
)
13163 tp
= &TREE_OPERAND (*tp
, 0);
13164 struct ipa_parm_adjustment
*cand
= NULL
;
13165 if (TREE_CODE (*tp
) == PARM_DECL
)
13166 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
13170 *walk_subtrees
= 0;
13173 tree repl
= NULL_TREE
;
13175 repl
= unshare_expr (cand
->new_decl
);
13180 *walk_subtrees
= 0;
13181 bool modified
= info
->modified
;
13182 info
->modified
= false;
13183 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
13184 if (!info
->modified
)
13186 info
->modified
= modified
;
13189 info
->modified
= modified
;
13198 repl
= build_fold_addr_expr (repl
);
13200 if (is_gimple_debug (info
->stmt
))
13202 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
13203 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
13204 DECL_ARTIFICIAL (vexpr
) = 1;
13205 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
13206 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
13211 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
)), repl
);
13212 repl
= gimple_assign_lhs (stmt
);
13214 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
13215 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13218 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
13220 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
13226 info
->modified
= true;
13230 /* Traverse the function body and perform all modifications as
13231 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13232 modified such that the replacement/reduction value will now be an
13233 offset into the corresponding simd_array.
13235 This function will replace all function argument uses with their
13236 corresponding simd array elements, and ajust the return values
13240 ipa_simd_modify_function_body (struct cgraph_node
*node
,
13241 ipa_parm_adjustment_vec adjustments
,
13242 tree retval_array
, tree iter
)
13245 unsigned int i
, j
, l
;
13247 /* Re-use the adjustments array, but this time use it to replace
13248 every function argument use to an offset into the corresponding
13250 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
13252 if (!node
->simdclone
->args
[i
].vector_arg
)
13255 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
13256 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
13257 adjustments
[j
].new_decl
13258 = build4 (ARRAY_REF
,
13260 node
->simdclone
->args
[i
].simd_array
,
13262 NULL_TREE
, NULL_TREE
);
13263 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
13264 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
13265 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
13268 l
= adjustments
.length ();
13269 for (i
= 1; i
< num_ssa_names
; i
++)
13271 tree name
= ssa_name (i
);
13273 && SSA_NAME_VAR (name
)
13274 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
13276 for (j
= 0; j
< l
; j
++)
13277 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
13278 && adjustments
[j
].new_decl
)
13281 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
13284 = copy_var_decl (adjustments
[j
].base
,
13285 DECL_NAME (adjustments
[j
].base
),
13286 TREE_TYPE (adjustments
[j
].base
));
13287 adjustments
[j
].new_ssa_base
= base_var
;
13290 base_var
= adjustments
[j
].new_ssa_base
;
13291 if (SSA_NAME_IS_DEFAULT_DEF (name
))
13293 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13294 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
13295 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
13296 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
13297 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13298 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
13299 gimple stmt
= gimple_build_assign (name
, new_decl
);
13300 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13303 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13308 struct modify_stmt_info info
;
13309 info
.adjustments
= adjustments
;
13311 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
13313 gimple_stmt_iterator gsi
;
13315 gsi
= gsi_start_bb (bb
);
13316 while (!gsi_end_p (gsi
))
13318 gimple stmt
= gsi_stmt (gsi
);
13320 struct walk_stmt_info wi
;
13322 memset (&wi
, 0, sizeof (wi
));
13323 info
.modified
= false;
13325 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
13327 if (greturn
*return_stmt
= dyn_cast
<greturn
*> (stmt
))
13329 tree retval
= gimple_return_retval (return_stmt
);
13332 gsi_remove (&gsi
, true);
13336 /* Replace `return foo' with `retval_array[iter] = foo'. */
13337 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
13338 retval_array
, iter
, NULL
, NULL
);
13339 stmt
= gimple_build_assign (ref
, retval
);
13340 gsi_replace (&gsi
, stmt
, true);
13341 info
.modified
= true;
13346 update_stmt (stmt
);
13347 if (maybe_clean_eh_stmt (stmt
))
13348 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
13355 /* Adjust the argument types in NODE to their appropriate vector
13359 simd_clone_adjust (struct cgraph_node
*node
)
13361 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
13363 targetm
.simd_clone
.adjust (node
);
13365 tree retval
= simd_clone_adjust_return_type (node
);
13366 ipa_parm_adjustment_vec adjustments
13367 = simd_clone_adjust_argument_types (node
);
13369 push_gimplify_context ();
13371 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
13373 /* Adjust all uses of vector arguments accordingly. Adjust all
13374 return values accordingly. */
13375 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
13376 tree iter1
= make_ssa_name (iter
);
13377 tree iter2
= make_ssa_name (iter
);
13378 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
13380 /* Initialize the iteration variable. */
13381 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13382 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
13383 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
13384 /* Insert the SIMD array and iv initialization at function
13386 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
13388 pop_gimplify_context (NULL
);
13390 /* Create a new BB right before the original exit BB, to hold the
13391 iteration increment and the condition/branch. */
13392 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
13393 basic_block incr_bb
= create_empty_bb (orig_exit
);
13394 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
13395 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13396 flag. Set it now to be a FALLTHRU_EDGE. */
13397 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
13398 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
13399 for (unsigned i
= 0;
13400 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
13402 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
13403 redirect_edge_succ (e
, incr_bb
);
13405 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
13406 e
->probability
= REG_BR_PROB_BASE
;
13407 gsi
= gsi_last_bb (incr_bb
);
13408 gimple g
= gimple_build_assign (iter2
, PLUS_EXPR
, iter1
,
13409 build_int_cst (unsigned_type_node
, 1));
13410 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13412 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13413 struct loop
*loop
= alloc_loop ();
13414 cfun
->has_force_vectorize_loops
= true;
13415 loop
->safelen
= node
->simdclone
->simdlen
;
13416 loop
->force_vectorize
= true;
13417 loop
->header
= body_bb
;
13419 /* Branch around the body if the mask applies. */
13420 if (node
->simdclone
->inbranch
)
13422 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
13424 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
13425 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)));
13426 tree aref
= build4 (ARRAY_REF
,
13427 TREE_TYPE (TREE_TYPE (mask_array
)),
13430 g
= gimple_build_assign (mask
, aref
);
13431 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13432 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
13433 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
13435 aref
= build1 (VIEW_CONVERT_EXPR
,
13436 build_nonstandard_integer_type (bitsize
, 0), mask
);
13437 mask
= make_ssa_name (TREE_TYPE (aref
));
13438 g
= gimple_build_assign (mask
, aref
);
13439 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13442 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
13444 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13445 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
13446 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
13449 /* Generate the condition. */
13450 g
= gimple_build_cond (LT_EXPR
,
13452 build_int_cst (unsigned_type_node
,
13453 node
->simdclone
->simdlen
),
13455 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13456 e
= split_block (incr_bb
, gsi_stmt (gsi
));
13457 basic_block latch_bb
= e
->dest
;
13458 basic_block new_exit_bb
;
13459 new_exit_bb
= split_block_after_labels (latch_bb
)->dest
;
13460 loop
->latch
= latch_bb
;
13462 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
13464 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
13465 /* The successor of incr_bb is already pointing to latch_bb; just
13467 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13468 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
13470 gphi
*phi
= create_phi_node (iter1
, body_bb
);
13471 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
13472 edge latch_edge
= single_succ_edge (latch_bb
);
13473 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
13475 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13477 /* Generate the new return. */
13478 gsi
= gsi_last_bb (new_exit_bb
);
13480 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
13481 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
13482 retval
= TREE_OPERAND (retval
, 0);
13485 retval
= build1 (VIEW_CONVERT_EXPR
,
13486 TREE_TYPE (TREE_TYPE (node
->decl
)),
13488 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
13489 false, GSI_CONTINUE_LINKING
);
13491 g
= gimple_build_return (retval
);
13492 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13494 /* Handle aligned clauses by replacing default defs of the aligned
13495 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13496 lhs. Handle linear by adding PHIs. */
13497 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
13498 if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
13499 && (TREE_ADDRESSABLE (node
->simdclone
->args
[i
].orig_arg
)
13500 || !is_gimple_reg_type
13501 (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
13503 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13504 if (is_gimple_reg_type (TREE_TYPE (orig_arg
)))
13505 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
13508 iter1
= create_tmp_var_raw (TREE_TYPE (orig_arg
));
13509 gimple_add_tmp_var (iter1
);
13511 gsi
= gsi_after_labels (entry_bb
);
13512 g
= gimple_build_assign (iter1
, orig_arg
);
13513 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13514 gsi
= gsi_after_labels (body_bb
);
13515 g
= gimple_build_assign (orig_arg
, iter1
);
13516 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13518 else if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
13519 && DECL_BY_REFERENCE (node
->simdclone
->args
[i
].orig_arg
)
13520 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
13522 && TREE_ADDRESSABLE
13523 (TREE_TYPE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
13525 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13526 tree def
= ssa_default_def (cfun
, orig_arg
);
13527 if (def
&& !has_zero_uses (def
))
13529 iter1
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg
)));
13530 gimple_add_tmp_var (iter1
);
13531 gsi
= gsi_after_labels (entry_bb
);
13532 g
= gimple_build_assign (iter1
, build_simple_mem_ref (def
));
13533 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13534 gsi
= gsi_after_labels (body_bb
);
13535 g
= gimple_build_assign (build_simple_mem_ref (def
), iter1
);
13536 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13539 else if (node
->simdclone
->args
[i
].alignment
13540 && node
->simdclone
->args
[i
].arg_type
13541 == SIMD_CLONE_ARG_TYPE_UNIFORM
13542 && (node
->simdclone
->args
[i
].alignment
13543 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
13544 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
13547 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
13548 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13549 tree def
= ssa_default_def (cfun
, orig_arg
);
13550 if (def
&& !has_zero_uses (def
))
13552 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
13553 gimple_seq seq
= NULL
;
13554 bool need_cvt
= false;
13556 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
13558 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
13561 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
);
13562 gimple_call_set_lhs (g
, t
);
13563 gimple_seq_add_stmt_without_update (&seq
, g
);
13566 t
= make_ssa_name (orig_arg
);
13567 g
= gimple_build_assign (t
, NOP_EXPR
, gimple_call_lhs (g
));
13568 gimple_seq_add_stmt_without_update (&seq
, g
);
13570 gsi_insert_seq_on_edge_immediate
13571 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
13573 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13574 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
13576 node
->create_edge (cgraph_node::get_create (fn
),
13577 call
, entry_bb
->count
, freq
);
13579 imm_use_iterator iter
;
13580 use_operand_p use_p
;
13582 tree repl
= gimple_get_lhs (g
);
13583 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13584 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
13587 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13588 SET_USE (use_p
, repl
);
13591 else if (node
->simdclone
->args
[i
].arg_type
13592 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
13594 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13595 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13596 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
13597 tree def
= NULL_TREE
;
13598 if (TREE_ADDRESSABLE (orig_arg
))
13600 def
= make_ssa_name (TREE_TYPE (orig_arg
));
13601 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
13602 iter2
= make_ssa_name (TREE_TYPE (orig_arg
));
13603 gsi
= gsi_after_labels (entry_bb
);
13604 g
= gimple_build_assign (def
, orig_arg
);
13605 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13609 def
= ssa_default_def (cfun
, orig_arg
);
13610 if (!def
|| has_zero_uses (def
))
13614 iter1
= make_ssa_name (orig_arg
);
13615 iter2
= make_ssa_name (orig_arg
);
13620 phi
= create_phi_node (iter1
, body_bb
);
13621 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
13622 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13623 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13624 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
13625 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13626 ? TREE_TYPE (orig_arg
) : sizetype
;
13628 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
13629 g
= gimple_build_assign (iter2
, code
, iter1
, addcst
);
13630 gsi
= gsi_last_bb (incr_bb
);
13631 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
13633 imm_use_iterator iter
;
13634 use_operand_p use_p
;
13636 if (TREE_ADDRESSABLE (orig_arg
))
13638 gsi
= gsi_after_labels (body_bb
);
13639 g
= gimple_build_assign (orig_arg
, iter1
);
13640 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13643 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13644 if (use_stmt
== phi
)
13647 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13648 SET_USE (use_p
, iter1
);
13652 calculate_dominance_info (CDI_DOMINATORS
);
13653 add_loop (loop
, loop
->header
->loop_father
);
13654 update_ssa (TODO_update_ssa
);
13659 /* If the function in NODE is tagged as an elemental SIMD function,
13660 create the appropriate SIMD clones. */
13663 expand_simd_clones (struct cgraph_node
*node
)
13665 tree attr
= lookup_attribute ("omp declare simd",
13666 DECL_ATTRIBUTES (node
->decl
));
13667 if (attr
== NULL_TREE
13668 || node
->global
.inlined_to
13669 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
13673 #pragma omp declare simd
13675 in C, there we don't know the argument types at all. */
13676 if (!node
->definition
13677 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
13682 /* Start with parsing the "omp declare simd" attribute(s). */
13683 bool inbranch_clause_specified
;
13684 struct cgraph_simd_clone
*clone_info
13685 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
13686 &inbranch_clause_specified
);
13687 if (clone_info
== NULL
)
13690 int orig_simdlen
= clone_info
->simdlen
;
13691 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
13692 /* The target can return 0 (no simd clones should be created),
13693 1 (just one ISA of simd clones should be created) or higher
13694 count of ISA variants. In that case, clone_info is initialized
13695 for the first ISA variant. */
13697 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
13702 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13703 also create one inbranch and one !inbranch clone of it. */
13704 for (int i
= 0; i
< count
* 2; i
++)
13706 struct cgraph_simd_clone
*clone
= clone_info
;
13707 if (inbranch_clause_specified
&& (i
& 1) != 0)
13712 clone
= simd_clone_struct_alloc (clone_info
->nargs
13714 simd_clone_struct_copy (clone
, clone_info
);
13715 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13716 and simd_clone_adjust_argument_types did to the first
13718 clone
->nargs
-= clone_info
->inbranch
;
13719 clone
->simdlen
= orig_simdlen
;
13720 /* And call the target hook again to get the right ISA. */
13721 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
13725 clone
->inbranch
= 1;
13728 /* simd_clone_mangle might fail if such a clone has been created
13730 tree id
= simd_clone_mangle (node
, clone
);
13731 if (id
== NULL_TREE
)
13734 /* Only when we are sure we want to create the clone actually
13735 clone the function (or definitions) or create another
13736 extern FUNCTION_DECL (for prototypes without definitions). */
13737 struct cgraph_node
*n
= simd_clone_create (node
);
13741 n
->simdclone
= clone
;
13742 clone
->origin
= node
;
13743 clone
->next_clone
= NULL
;
13744 if (node
->simd_clones
== NULL
)
13746 clone
->prev_clone
= n
;
13747 node
->simd_clones
= n
;
13751 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
13752 clone
->prev_clone
->simdclone
->next_clone
= n
;
13753 node
->simd_clones
->simdclone
->prev_clone
= n
;
13755 symtab
->change_decl_assembler_name (n
->decl
, id
);
13756 /* And finally adjust the return type, parameters and for
13757 definitions also function body. */
13758 if (node
->definition
)
13759 simd_clone_adjust (n
);
13762 simd_clone_adjust_return_type (n
);
13763 simd_clone_adjust_argument_types (n
);
13767 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
13770 /* Entry point for IPA simd clone creation pass. */
13772 static unsigned int
13773 ipa_omp_simd_clone (void)
13775 struct cgraph_node
*node
;
13776 FOR_EACH_FUNCTION (node
)
13777 expand_simd_clones (node
);
13783 const pass_data pass_data_omp_simd_clone
=
13785 SIMPLE_IPA_PASS
, /* type */
13786 "simdclone", /* name */
13787 OPTGROUP_NONE
, /* optinfo_flags */
13788 TV_NONE
, /* tv_id */
13789 ( PROP_ssa
| PROP_cfg
), /* properties_required */
13790 0, /* properties_provided */
13791 0, /* properties_destroyed */
13792 0, /* todo_flags_start */
13793 0, /* todo_flags_finish */
13796 class pass_omp_simd_clone
: public simple_ipa_opt_pass
13799 pass_omp_simd_clone(gcc::context
*ctxt
)
13800 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
13803 /* opt_pass methods: */
13804 virtual bool gate (function
*);
13805 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
13809 pass_omp_simd_clone::gate (function
*)
13811 return ((flag_openmp
|| flag_openmp_simd
13813 || (in_lto_p
&& !flag_wpa
))
13814 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
13817 } // anon namespace
13819 simple_ipa_opt_pass
*
13820 make_pass_omp_simd_clone (gcc::context
*ctxt
)
13822 return new pass_omp_simd_clone (ctxt
);
13825 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13826 adds their addresses and sizes to constructor-vector V_CTOR. */
13828 add_decls_addresses_to_decl_constructor (vec
<tree
, va_gc
> *v_decls
,
13829 vec
<constructor_elt
, va_gc
> *v_ctor
)
13831 unsigned len
= vec_safe_length (v_decls
);
13832 for (unsigned i
= 0; i
< len
; i
++)
13834 tree it
= (*v_decls
)[i
];
13835 bool is_function
= TREE_CODE (it
) != VAR_DECL
;
13837 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, build_fold_addr_expr (it
));
13839 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
,
13840 fold_convert (const_ptr_type_node
,
13841 DECL_SIZE_UNIT (it
)));
13845 /* Create new symbols containing (address, size) pairs for global variables,
13846 marked with "omp declare target" attribute, as well as addresses for the
13847 functions, which are outlined offloading regions. */
13849 omp_finish_file (void)
13851 unsigned num_funcs
= vec_safe_length (offload_funcs
);
13852 unsigned num_vars
= vec_safe_length (offload_vars
);
13854 if (num_funcs
== 0 && num_vars
== 0)
13857 if (targetm_common
.have_named_sections
)
13859 vec
<constructor_elt
, va_gc
> *v_f
, *v_v
;
13860 vec_alloc (v_f
, num_funcs
);
13861 vec_alloc (v_v
, num_vars
* 2);
13863 add_decls_addresses_to_decl_constructor (offload_funcs
, v_f
);
13864 add_decls_addresses_to_decl_constructor (offload_vars
, v_v
);
13866 tree vars_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13868 tree funcs_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13870 TYPE_ALIGN (vars_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13871 TYPE_ALIGN (funcs_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13872 tree ctor_v
= build_constructor (vars_decl_type
, v_v
);
13873 tree ctor_f
= build_constructor (funcs_decl_type
, v_f
);
13874 TREE_CONSTANT (ctor_v
) = TREE_CONSTANT (ctor_f
) = 1;
13875 TREE_STATIC (ctor_v
) = TREE_STATIC (ctor_f
) = 1;
13876 tree funcs_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13877 get_identifier (".offload_func_table"),
13879 tree vars_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13880 get_identifier (".offload_var_table"),
13882 TREE_STATIC (funcs_decl
) = TREE_STATIC (vars_decl
) = 1;
13883 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13884 otherwise a joint table in a binary will contain padding between
13885 tables from multiple object files. */
13886 DECL_USER_ALIGN (funcs_decl
) = DECL_USER_ALIGN (vars_decl
) = 1;
13887 DECL_ALIGN (funcs_decl
) = TYPE_ALIGN (funcs_decl_type
);
13888 DECL_ALIGN (vars_decl
) = TYPE_ALIGN (vars_decl_type
);
13889 DECL_INITIAL (funcs_decl
) = ctor_f
;
13890 DECL_INITIAL (vars_decl
) = ctor_v
;
13891 set_decl_section_name (funcs_decl
, OFFLOAD_FUNC_TABLE_SECTION_NAME
);
13892 set_decl_section_name (vars_decl
, OFFLOAD_VAR_TABLE_SECTION_NAME
);
13894 varpool_node::finalize_decl (vars_decl
);
13895 varpool_node::finalize_decl (funcs_decl
);
13899 for (unsigned i
= 0; i
< num_funcs
; i
++)
13901 tree it
= (*offload_funcs
)[i
];
13902 targetm
.record_offload_symbol (it
);
13904 for (unsigned i
= 0; i
< num_vars
; i
++)
13906 tree it
= (*offload_vars
)[i
];
13907 targetm
.record_offload_symbol (it
);
13912 #include "gt-omp-low.h"