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"
32 #include "fold-const.h"
33 #include "stringpool.h"
34 #include "stor-layout.h"
37 #include "hard-reg-set.h"
39 #include "dominance.h"
42 #include "basic-block.h"
43 #include "tree-ssa-alias.h"
44 #include "internal-fn.h"
45 #include "gimple-fold.h"
46 #include "gimple-expr.h"
49 #include "gimple-iterator.h"
50 #include "gimplify-me.h"
51 #include "gimple-walk.h"
52 #include "tree-iterator.h"
53 #include "tree-inline.h"
54 #include "langhooks.h"
55 #include "diagnostic-core.h"
56 #include "gimple-ssa.h"
59 #include "tree-phinodes.h"
60 #include "ssa-iterators.h"
61 #include "tree-ssanames.h"
62 #include "tree-into-ssa.h"
64 #include "insn-config.h"
75 #include "tree-pass.h"
77 #include "splay-tree.h"
78 #include "insn-codes.h"
82 #include "common/common-target.h"
84 #include "gimple-low.h"
85 #include "tree-cfgcleanup.h"
86 #include "pretty-print.h"
87 #include "alloc-pool.h"
88 #include "symbol-summary.h"
90 #include "tree-nested.h"
94 #include "lto-section-names.h"
95 #include "gomp-constants.h"
98 /* Lowering of OMP parallel and workshare constructs proceeds in two
99 phases. The first phase scans the function looking for OMP statements
100 and then for variables that must be replaced to satisfy data sharing
101 clauses. The second phase expands code for the constructs, as well as
102 re-gimplifying things when variables have been replaced with complex
105 Final code generation is done by pass_expand_omp. The flowgraph is
106 scanned for regions which are then moved to a new
107 function, to be invoked by the thread library, or offloaded. */
109 /* OMP region information. Every parallel and workshare
110 directive is enclosed between two markers, the OMP_* directive
111 and a corresponding OMP_RETURN statement. */
115 /* The enclosing region. */
116 struct omp_region
*outer
;
118 /* First child region. */
119 struct omp_region
*inner
;
121 /* Next peer region. */
122 struct omp_region
*next
;
124 /* Block containing the omp directive as its last stmt. */
127 /* Block containing the OMP_RETURN as its last stmt. */
130 /* Block containing the OMP_CONTINUE as its last stmt. */
133 /* If this is a combined parallel+workshare region, this is a list
134 of additional arguments needed by the combined parallel+workshare
136 vec
<tree
, va_gc
> *ws_args
;
138 /* The code for the omp directive of this region. */
139 enum gimple_code type
;
141 /* Schedule kind, only used for OMP_FOR type regions. */
142 enum omp_clause_schedule_kind sched_kind
;
144 /* True if this is a combined parallel+workshare region. */
145 bool is_combined_parallel
;
148 /* Levels of parallelism as defined by OpenACC. Increasing numbers
149 correspond to deeper loop nesting levels. */
151 #define MASK_WORKER 2
152 #define MASK_VECTOR 4
154 /* Context structure. Used to store information about each parallel
155 directive in the code. */
157 typedef struct omp_context
159 /* This field must be at the beginning, as we do "inheritance": Some
160 callback functions for tree-inline.c (e.g., omp_copy_decl)
161 receive a copy_body_data pointer that is up-casted to an
162 omp_context pointer. */
165 /* The tree of contexts corresponding to the encountered constructs. */
166 struct omp_context
*outer
;
169 /* Map variables to fields in a structure that allows communication
170 between sending and receiving threads. */
171 splay_tree field_map
;
176 /* These are used just by task contexts, if task firstprivate fn is
177 needed. srecord_type is used to communicate from the thread
178 that encountered the task construct to task firstprivate fn,
179 record_type is allocated by GOMP_task, initialized by task firstprivate
180 fn and passed to the task body fn. */
181 splay_tree sfield_map
;
184 /* A chain of variables to add to the top-level block surrounding the
185 construct. In the case of a parallel, this is in the child function. */
188 /* A map of reduction pointer variables. For accelerators, each
189 reduction variable is replaced with an array. Each thread, in turn,
190 is assigned to a slot on that array. */
191 splay_tree reduction_map
;
193 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
194 barriers should jump to during omplower pass. */
197 /* What to do with variables with implicitly determined sharing
199 enum omp_clause_default_kind default_kind
;
201 /* Nesting depth of this context. Used to beautify error messages re
202 invalid gotos. The outermost ctx is depth 1, with depth 0 being
203 reserved for the main body of the function. */
206 /* True if this parallel directive is nested within another. */
209 /* True if this construct can be cancelled. */
212 /* For OpenACC loops, a mask of gang, worker and vector used at
213 levels below this one. */
215 /* For OpenACC loops, a mask of gang, worker and vector used at
216 this level and above. For parallel and kernels clauses, a mask
217 indicating which of num_gangs/num_workers/num_vectors was used. */
221 /* A structure holding the elements of:
222 for (V = N1; V cond N2; V += STEP) [...] */
224 struct omp_for_data_loop
226 tree v
, n1
, n2
, step
;
227 enum tree_code cond_code
;
230 /* A structure describing the main elements of a parallel loop. */
234 struct omp_for_data_loop loop
;
239 bool have_nowait
, have_ordered
;
240 enum omp_clause_schedule_kind sched_kind
;
241 struct omp_for_data_loop
*loops
;
245 static splay_tree all_contexts
;
246 static int taskreg_nesting_level
;
247 static int target_nesting_level
;
248 static struct omp_region
*root_omp_region
;
249 static bitmap task_shared_vars
;
250 static vec
<omp_context
*> taskreg_contexts
;
252 static void scan_omp (gimple_seq
*, omp_context
*);
253 static tree
scan_omp_1_op (tree
*, int *, void *);
255 #define WALK_SUBSTMTS \
259 case GIMPLE_EH_FILTER: \
260 case GIMPLE_TRANSACTION: \
261 /* The sub-statements for these should be walked. */ \
262 *handled_ops_p = false; \
265 /* Helper function to get the name of the array containing the partial
266 reductions for OpenACC reductions. */
268 oacc_get_reduction_array_id (tree node
)
270 const char *id
= IDENTIFIER_POINTER (DECL_NAME (node
));
271 int len
= strlen ("OACC") + strlen (id
);
272 char *temp_name
= XALLOCAVEC (char, len
+ 1);
273 snprintf (temp_name
, len
+ 1, "OACC%s", id
);
274 return IDENTIFIER_POINTER (get_identifier (temp_name
));
277 /* Determine the number of threads OpenACC threads used to determine the
278 size of the array of partial reductions. Currently, this is num_gangs
279 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
280 because it is independed of the device used. */
283 oacc_max_threads (omp_context
*ctx
)
285 tree nthreads
, vector_length
, gangs
, clauses
;
287 gangs
= fold_convert (sizetype
, integer_one_node
);
288 vector_length
= gangs
;
290 /* The reduction clause may be nested inside a loop directive.
291 Scan for the innermost vector_length clause. */
292 for (omp_context
*oc
= ctx
; oc
; oc
= oc
->outer
)
294 if (gimple_code (oc
->stmt
) != GIMPLE_OMP_TARGET
295 || (gimple_omp_target_kind (oc
->stmt
)
296 != GF_OMP_TARGET_KIND_OACC_PARALLEL
))
299 clauses
= gimple_omp_target_clauses (oc
->stmt
);
301 vector_length
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
303 vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length
),
305 OMP_CLAUSE_VECTOR_LENGTH_EXPR
308 vector_length
= fold_convert (sizetype
, integer_one_node
);
310 gangs
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
312 gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (gangs
), sizetype
,
313 OMP_CLAUSE_NUM_GANGS_EXPR (gangs
));
315 gangs
= fold_convert (sizetype
, integer_one_node
);
320 nthreads
= fold_build2 (MULT_EXPR
, sizetype
, gangs
, vector_length
);
325 /* Holds offload tables with decls. */
326 vec
<tree
, va_gc
> *offload_funcs
, *offload_vars
;
328 /* Convenience function for calling scan_omp_1_op on tree operands. */
331 scan_omp_op (tree
*tp
, omp_context
*ctx
)
333 struct walk_stmt_info wi
;
335 memset (&wi
, 0, sizeof (wi
));
337 wi
.want_locations
= true;
339 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
342 static void lower_omp (gimple_seq
*, omp_context
*);
343 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
344 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
346 /* Find an OMP clause of type KIND within CLAUSES. */
349 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
351 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
352 if (OMP_CLAUSE_CODE (clauses
) == kind
)
358 /* Return true if CTX is for an omp parallel. */
361 is_parallel_ctx (omp_context
*ctx
)
363 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
367 /* Return true if CTX is for an omp task. */
370 is_task_ctx (omp_context
*ctx
)
372 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
376 /* Return true if CTX is for an omp parallel or omp task. */
379 is_taskreg_ctx (omp_context
*ctx
)
381 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
382 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
386 /* Return true if REGION is a combined parallel+workshare region. */
389 is_combined_parallel (struct omp_region
*region
)
391 return region
->is_combined_parallel
;
395 /* Extract the header elements of parallel loop FOR_STMT and store
399 extract_omp_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
400 struct omp_for_data_loop
*loops
)
402 tree t
, var
, *collapse_iter
, *collapse_count
;
403 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
404 struct omp_for_data_loop
*loop
;
406 struct omp_for_data_loop dummy_loop
;
407 location_t loc
= gimple_location (for_stmt
);
408 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
409 bool distribute
= gimple_omp_for_kind (for_stmt
)
410 == GF_OMP_FOR_KIND_DISTRIBUTE
;
412 fd
->for_stmt
= for_stmt
;
414 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
415 if (fd
->collapse
> 1)
418 fd
->loops
= &fd
->loop
;
420 fd
->have_nowait
= distribute
|| simd
;
421 fd
->have_ordered
= false;
422 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
423 fd
->chunk_size
= NULL_TREE
;
424 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
425 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
426 collapse_iter
= NULL
;
427 collapse_count
= NULL
;
429 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
430 switch (OMP_CLAUSE_CODE (t
))
432 case OMP_CLAUSE_NOWAIT
:
433 fd
->have_nowait
= true;
435 case OMP_CLAUSE_ORDERED
:
436 fd
->have_ordered
= true;
438 case OMP_CLAUSE_SCHEDULE
:
439 gcc_assert (!distribute
);
440 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
441 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
443 case OMP_CLAUSE_DIST_SCHEDULE
:
444 gcc_assert (distribute
);
445 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
447 case OMP_CLAUSE_COLLAPSE
:
448 if (fd
->collapse
> 1)
450 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
451 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
458 /* FIXME: for now map schedule(auto) to schedule(static).
459 There should be analysis to determine whether all iterations
460 are approximately the same amount of work (then schedule(static)
461 is best) or if it varies (then schedule(dynamic,N) is better). */
462 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
464 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
465 gcc_assert (fd
->chunk_size
== NULL
);
467 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
468 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
469 gcc_assert (fd
->chunk_size
== NULL
);
470 else if (fd
->chunk_size
== NULL
)
472 /* We only need to compute a default chunk size for ordered
473 static loops and dynamic loops. */
474 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
476 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
477 ? integer_zero_node
: integer_one_node
;
480 for (i
= 0; i
< fd
->collapse
; i
++)
482 if (fd
->collapse
== 1)
484 else if (loops
!= NULL
)
489 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
490 gcc_assert (SSA_VAR_P (loop
->v
));
491 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
492 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
493 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
494 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
496 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
497 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
498 switch (loop
->cond_code
)
504 gcc_assert (gimple_omp_for_kind (for_stmt
)
505 == GF_OMP_FOR_KIND_CILKSIMD
506 || (gimple_omp_for_kind (for_stmt
)
507 == GF_OMP_FOR_KIND_CILKFOR
));
510 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
511 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
513 loop
->n2
= fold_build2_loc (loc
,
514 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
515 build_int_cst (TREE_TYPE (loop
->n2
), 1));
516 loop
->cond_code
= LT_EXPR
;
519 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
520 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
522 loop
->n2
= fold_build2_loc (loc
,
523 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
524 build_int_cst (TREE_TYPE (loop
->n2
), 1));
525 loop
->cond_code
= GT_EXPR
;
531 t
= gimple_omp_for_incr (for_stmt
, i
);
532 gcc_assert (TREE_OPERAND (t
, 0) == var
);
533 switch (TREE_CODE (t
))
536 loop
->step
= TREE_OPERAND (t
, 1);
538 case POINTER_PLUS_EXPR
:
539 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
542 loop
->step
= TREE_OPERAND (t
, 1);
543 loop
->step
= fold_build1_loc (loc
,
544 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
552 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
553 && !fd
->have_ordered
))
555 if (fd
->collapse
== 1)
556 iter_type
= TREE_TYPE (loop
->v
);
558 || TYPE_PRECISION (iter_type
)
559 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
561 = build_nonstandard_integer_type
562 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
564 else if (iter_type
!= long_long_unsigned_type_node
)
566 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
567 iter_type
= long_long_unsigned_type_node
;
568 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
569 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
570 >= TYPE_PRECISION (iter_type
))
574 if (loop
->cond_code
== LT_EXPR
)
575 n
= fold_build2_loc (loc
,
576 PLUS_EXPR
, TREE_TYPE (loop
->v
),
577 loop
->n2
, loop
->step
);
580 if (TREE_CODE (n
) != INTEGER_CST
581 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
582 iter_type
= long_long_unsigned_type_node
;
584 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
585 > TYPE_PRECISION (iter_type
))
589 if (loop
->cond_code
== LT_EXPR
)
592 n2
= fold_build2_loc (loc
,
593 PLUS_EXPR
, TREE_TYPE (loop
->v
),
594 loop
->n2
, loop
->step
);
598 n1
= fold_build2_loc (loc
,
599 MINUS_EXPR
, TREE_TYPE (loop
->v
),
600 loop
->n2
, loop
->step
);
603 if (TREE_CODE (n1
) != INTEGER_CST
604 || TREE_CODE (n2
) != INTEGER_CST
605 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
606 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
607 iter_type
= long_long_unsigned_type_node
;
611 if (collapse_count
&& *collapse_count
== NULL
)
613 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
614 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
615 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
616 if (t
&& integer_zerop (t
))
617 count
= build_zero_cst (long_long_unsigned_type_node
);
618 else if ((i
== 0 || count
!= NULL_TREE
)
619 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
620 && TREE_CONSTANT (loop
->n1
)
621 && TREE_CONSTANT (loop
->n2
)
622 && TREE_CODE (loop
->step
) == INTEGER_CST
)
624 tree itype
= TREE_TYPE (loop
->v
);
626 if (POINTER_TYPE_P (itype
))
627 itype
= signed_type_for (itype
);
628 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
629 t
= fold_build2_loc (loc
,
631 fold_convert_loc (loc
, itype
, loop
->step
), t
);
632 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
633 fold_convert_loc (loc
, itype
, loop
->n2
));
634 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
635 fold_convert_loc (loc
, itype
, loop
->n1
));
636 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
637 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
638 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
639 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
640 fold_convert_loc (loc
, itype
,
643 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
644 fold_convert_loc (loc
, itype
, loop
->step
));
645 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
646 if (count
!= NULL_TREE
)
647 count
= fold_build2_loc (loc
,
648 MULT_EXPR
, long_long_unsigned_type_node
,
652 if (TREE_CODE (count
) != INTEGER_CST
)
655 else if (count
&& !integer_zerop (count
))
662 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
663 || fd
->have_ordered
))
665 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
666 iter_type
= long_long_unsigned_type_node
;
668 iter_type
= long_integer_type_node
;
670 else if (collapse_iter
&& *collapse_iter
!= NULL
)
671 iter_type
= TREE_TYPE (*collapse_iter
);
672 fd
->iter_type
= iter_type
;
673 if (collapse_iter
&& *collapse_iter
== NULL
)
674 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
675 if (collapse_count
&& *collapse_count
== NULL
)
678 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
680 *collapse_count
= create_tmp_var (iter_type
, ".count");
683 if (fd
->collapse
> 1)
685 fd
->loop
.v
= *collapse_iter
;
686 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
687 fd
->loop
.n2
= *collapse_count
;
688 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
689 fd
->loop
.cond_code
= LT_EXPR
;
692 /* For OpenACC loops, force a chunk size of one, as this avoids the default
693 scheduling where several subsequent iterations are being executed by the
695 if (gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
697 gcc_assert (fd
->chunk_size
== NULL_TREE
);
698 fd
->chunk_size
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
703 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
704 is the immediate dominator of PAR_ENTRY_BB, return true if there
705 are no data dependencies that would prevent expanding the parallel
706 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
708 When expanding a combined parallel+workshare region, the call to
709 the child function may need additional arguments in the case of
710 GIMPLE_OMP_FOR regions. In some cases, these arguments are
711 computed out of variables passed in from the parent to the child
712 via 'struct .omp_data_s'. For instance:
714 #pragma omp parallel for schedule (guided, i * 4)
719 # BLOCK 2 (PAR_ENTRY_BB)
721 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
723 # BLOCK 3 (WS_ENTRY_BB)
724 .omp_data_i = &.omp_data_o;
725 D.1667 = .omp_data_i->i;
727 #pragma omp for schedule (guided, D.1598)
729 When we outline the parallel region, the call to the child function
730 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
731 that value is computed *after* the call site. So, in principle we
732 cannot do the transformation.
734 To see whether the code in WS_ENTRY_BB blocks the combined
735 parallel+workshare call, we collect all the variables used in the
736 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
737 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
740 FIXME. If we had the SSA form built at this point, we could merely
741 hoist the code in block 3 into block 2 and be done with it. But at
742 this point we don't have dataflow information and though we could
743 hack something up here, it is really not worth the aggravation. */
746 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
748 struct omp_for_data fd
;
749 gimple ws_stmt
= last_stmt (ws_entry_bb
);
751 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
754 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
756 extract_omp_for_data (as_a
<gomp_for
*> (ws_stmt
), &fd
, NULL
);
758 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
760 if (fd
.iter_type
!= long_integer_type_node
)
763 /* FIXME. We give up too easily here. If any of these arguments
764 are not constants, they will likely involve variables that have
765 been mapped into fields of .omp_data_s for sharing with the child
766 function. With appropriate data flow, it would be possible to
768 if (!is_gimple_min_invariant (fd
.loop
.n1
)
769 || !is_gimple_min_invariant (fd
.loop
.n2
)
770 || !is_gimple_min_invariant (fd
.loop
.step
)
771 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
778 /* Collect additional arguments needed to emit a combined
779 parallel+workshare call. WS_STMT is the workshare directive being
782 static vec
<tree
, va_gc
> *
783 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
786 location_t loc
= gimple_location (ws_stmt
);
787 vec
<tree
, va_gc
> *ws_args
;
789 if (gomp_for
*for_stmt
= dyn_cast
<gomp_for
*> (ws_stmt
))
791 struct omp_for_data fd
;
794 extract_omp_for_data (for_stmt
, &fd
, NULL
);
798 if (gimple_omp_for_combined_into_p (for_stmt
))
801 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
802 OMP_CLAUSE__LOOPTEMP_
);
804 n1
= OMP_CLAUSE_DECL (innerc
);
805 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
806 OMP_CLAUSE__LOOPTEMP_
);
808 n2
= OMP_CLAUSE_DECL (innerc
);
811 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
813 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
814 ws_args
->quick_push (t
);
816 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
817 ws_args
->quick_push (t
);
819 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
820 ws_args
->quick_push (t
);
824 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
825 ws_args
->quick_push (t
);
830 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
832 /* Number of sections is equal to the number of edges from the
833 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
834 the exit of the sections region. */
835 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
836 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
837 vec_alloc (ws_args
, 1);
838 ws_args
->quick_push (t
);
846 /* Discover whether REGION is a combined parallel+workshare region. */
849 determine_parallel_type (struct omp_region
*region
)
851 basic_block par_entry_bb
, par_exit_bb
;
852 basic_block ws_entry_bb
, ws_exit_bb
;
854 if (region
== NULL
|| region
->inner
== NULL
855 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
856 || region
->inner
->cont
== NULL
)
859 /* We only support parallel+for and parallel+sections. */
860 if (region
->type
!= GIMPLE_OMP_PARALLEL
861 || (region
->inner
->type
!= GIMPLE_OMP_FOR
862 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
865 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
866 WS_EXIT_BB -> PAR_EXIT_BB. */
867 par_entry_bb
= region
->entry
;
868 par_exit_bb
= region
->exit
;
869 ws_entry_bb
= region
->inner
->entry
;
870 ws_exit_bb
= region
->inner
->exit
;
872 if (single_succ (par_entry_bb
) == ws_entry_bb
873 && single_succ (ws_exit_bb
) == par_exit_bb
874 && workshare_safe_to_combine_p (ws_entry_bb
)
875 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
876 || (last_and_only_stmt (ws_entry_bb
)
877 && last_and_only_stmt (par_exit_bb
))))
879 gimple par_stmt
= last_stmt (par_entry_bb
);
880 gimple ws_stmt
= last_stmt (ws_entry_bb
);
882 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
884 /* If this is a combined parallel loop, we need to determine
885 whether or not to use the combined library calls. There
886 are two cases where we do not apply the transformation:
887 static loops and any kind of ordered loop. In the first
888 case, we already open code the loop so there is no need
889 to do anything else. In the latter case, the combined
890 parallel loop call would still need extra synchronization
891 to implement ordered semantics, so there would not be any
892 gain in using the combined call. */
893 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
894 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
896 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
897 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
899 region
->is_combined_parallel
= false;
900 region
->inner
->is_combined_parallel
= false;
905 region
->is_combined_parallel
= true;
906 region
->inner
->is_combined_parallel
= true;
907 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
912 /* Return true if EXPR is variable sized. */
915 is_variable_sized (const_tree expr
)
917 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
920 /* Return true if DECL is a reference type. */
923 is_reference (tree decl
)
925 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
928 /* Return the type of a decl. If the decl is reference type,
929 return its base type. */
931 get_base_type (tree decl
)
933 tree type
= TREE_TYPE (decl
);
934 if (is_reference (decl
))
935 type
= TREE_TYPE (type
);
939 /* Lookup variables. The "maybe" form
940 allows for the variable form to not have been entered, otherwise we
941 assert that the variable must have been entered. */
944 lookup_decl (tree var
, omp_context
*ctx
)
946 tree
*n
= ctx
->cb
.decl_map
->get (var
);
951 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
953 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
954 return n
? *n
: NULL_TREE
;
958 lookup_field (tree var
, omp_context
*ctx
)
961 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
962 return (tree
) n
->value
;
966 lookup_sfield (tree var
, omp_context
*ctx
)
969 n
= splay_tree_lookup (ctx
->sfield_map
970 ? ctx
->sfield_map
: ctx
->field_map
,
971 (splay_tree_key
) var
);
972 return (tree
) n
->value
;
976 maybe_lookup_field (tree var
, omp_context
*ctx
)
979 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
980 return n
? (tree
) n
->value
: NULL_TREE
;
984 lookup_oacc_reduction (const char *id
, omp_context
*ctx
)
987 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) id
);
988 return (tree
) n
->value
;
992 maybe_lookup_oacc_reduction (tree var
, omp_context
*ctx
)
994 splay_tree_node n
= NULL
;
995 if (ctx
->reduction_map
)
996 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) var
);
997 return n
? (tree
) n
->value
: NULL_TREE
;
1000 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1001 the parallel context if DECL is to be shared. */
1004 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
1006 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
1009 /* We can only use copy-in/copy-out semantics for shared variables
1010 when we know the value is not accessible from an outer scope. */
1013 gcc_assert (!is_gimple_omp_oacc (shared_ctx
->stmt
));
1015 /* ??? Trivially accessible from anywhere. But why would we even
1016 be passing an address in this case? Should we simply assert
1017 this to be false, or should we have a cleanup pass that removes
1018 these from the list of mappings? */
1019 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
1022 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1023 without analyzing the expression whether or not its location
1024 is accessible to anyone else. In the case of nested parallel
1025 regions it certainly may be. */
1026 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
1029 /* Do not use copy-in/copy-out for variables that have their
1031 if (TREE_ADDRESSABLE (decl
))
1034 /* lower_send_shared_vars only uses copy-in, but not copy-out
1036 if (TREE_READONLY (decl
)
1037 || ((TREE_CODE (decl
) == RESULT_DECL
1038 || TREE_CODE (decl
) == PARM_DECL
)
1039 && DECL_BY_REFERENCE (decl
)))
1042 /* Disallow copy-in/out in nested parallel if
1043 decl is shared in outer parallel, otherwise
1044 each thread could store the shared variable
1045 in its own copy-in location, making the
1046 variable no longer really shared. */
1047 if (shared_ctx
->is_nested
)
1051 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
1052 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
1059 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
1060 c
; c
= OMP_CLAUSE_CHAIN (c
))
1061 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1062 && OMP_CLAUSE_DECL (c
) == decl
)
1066 goto maybe_mark_addressable_and_ret
;
1070 /* For tasks avoid using copy-in/out. As tasks can be
1071 deferred or executed in different thread, when GOMP_task
1072 returns, the task hasn't necessarily terminated. */
1073 if (is_task_ctx (shared_ctx
))
1076 maybe_mark_addressable_and_ret
:
1077 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
1078 if (is_gimple_reg (outer
))
1080 /* Taking address of OUTER in lower_send_shared_vars
1081 might need regimplification of everything that uses the
1083 if (!task_shared_vars
)
1084 task_shared_vars
= BITMAP_ALLOC (NULL
);
1085 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
1086 TREE_ADDRESSABLE (outer
) = 1;
1095 /* Construct a new automatic decl similar to VAR. */
1098 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
1100 tree copy
= copy_var_decl (var
, name
, type
);
1102 DECL_CONTEXT (copy
) = current_function_decl
;
1103 DECL_CHAIN (copy
) = ctx
->block_vars
;
1104 ctx
->block_vars
= copy
;
1110 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
1112 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
1115 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1118 omp_build_component_ref (tree obj
, tree field
)
1120 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
1121 if (TREE_THIS_VOLATILE (field
))
1122 TREE_THIS_VOLATILE (ret
) |= 1;
1123 if (TREE_READONLY (field
))
1124 TREE_READONLY (ret
) |= 1;
1128 /* Build tree nodes to access the field for VAR on the receiver side. */
1131 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1133 tree x
, field
= lookup_field (var
, ctx
);
1135 /* If the receiver record type was remapped in the child function,
1136 remap the field into the new record type. */
1137 x
= maybe_lookup_field (field
, ctx
);
1141 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1142 x
= omp_build_component_ref (x
, field
);
1144 x
= build_simple_mem_ref (x
);
1149 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1150 of a parallel, this is a component reference; for workshare constructs
1151 this is some variable. */
1154 build_outer_var_ref (tree var
, omp_context
*ctx
)
1158 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1160 else if (is_variable_sized (var
))
1162 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1163 x
= build_outer_var_ref (x
, ctx
);
1164 x
= build_simple_mem_ref (x
);
1166 else if (is_taskreg_ctx (ctx
))
1168 bool by_ref
= use_pointer_for_field (var
, NULL
);
1169 x
= build_receiver_ref (var
, by_ref
, ctx
);
1171 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1172 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1174 /* #pragma omp simd isn't a worksharing construct, and can reference even
1175 private vars in its linear etc. clauses. */
1177 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1178 x
= lookup_decl (var
, ctx
->outer
);
1179 else if (ctx
->outer
)
1180 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1184 else if (ctx
->outer
)
1185 x
= lookup_decl (var
, ctx
->outer
);
1186 else if (is_reference (var
))
1187 /* This can happen with orphaned constructs. If var is reference, it is
1188 possible it is shared and as such valid. */
1193 if (is_reference (var
))
1194 x
= build_simple_mem_ref (x
);
1199 /* Build tree nodes to access the field for VAR on the sender side. */
1202 build_sender_ref (tree var
, omp_context
*ctx
)
1204 tree field
= lookup_sfield (var
, ctx
);
1205 return omp_build_component_ref (ctx
->sender_decl
, field
);
1208 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1211 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1213 tree field
, type
, sfield
= NULL_TREE
;
1215 gcc_assert ((mask
& 1) == 0
1216 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1217 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1218 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1219 gcc_assert ((mask
& 3) == 3
1220 || !is_gimple_omp_oacc (ctx
->stmt
));
1222 type
= TREE_TYPE (var
);
1225 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1226 type
= build_pointer_type (build_pointer_type (type
));
1229 type
= build_pointer_type (type
);
1230 else if ((mask
& 3) == 1 && is_reference (var
))
1231 type
= TREE_TYPE (type
);
1233 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1234 FIELD_DECL
, DECL_NAME (var
), type
);
1236 /* Remember what variable this field was created for. This does have a
1237 side effect of making dwarf2out ignore this member, so for helpful
1238 debugging we clear it later in delete_omp_context. */
1239 DECL_ABSTRACT_ORIGIN (field
) = var
;
1240 if (type
== TREE_TYPE (var
))
1242 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1243 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1244 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1247 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1249 if ((mask
& 3) == 3)
1251 insert_field_into_struct (ctx
->record_type
, field
);
1252 if (ctx
->srecord_type
)
1254 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1255 FIELD_DECL
, DECL_NAME (var
), type
);
1256 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1257 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1258 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1259 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1260 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1265 if (ctx
->srecord_type
== NULL_TREE
)
1269 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1270 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1271 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1273 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1274 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1275 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1276 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1277 splay_tree_insert (ctx
->sfield_map
,
1278 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1279 (splay_tree_value
) sfield
);
1283 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1284 : ctx
->srecord_type
, field
);
1288 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1289 (splay_tree_value
) field
);
1290 if ((mask
& 2) && ctx
->sfield_map
)
1291 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1292 (splay_tree_value
) sfield
);
1296 install_var_local (tree var
, omp_context
*ctx
)
1298 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1299 insert_decl_map (&ctx
->cb
, var
, new_var
);
1303 /* Adjust the replacement for DECL in CTX for the new context. This means
1304 copying the DECL_VALUE_EXPR, and fixing up the type. */
1307 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1309 tree new_decl
, size
;
1311 new_decl
= lookup_decl (decl
, ctx
);
1313 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1315 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1316 && DECL_HAS_VALUE_EXPR_P (decl
))
1318 tree ve
= DECL_VALUE_EXPR (decl
);
1319 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1320 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1321 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1324 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1326 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1327 if (size
== error_mark_node
)
1328 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1329 DECL_SIZE (new_decl
) = size
;
1331 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1332 if (size
== error_mark_node
)
1333 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1334 DECL_SIZE_UNIT (new_decl
) = size
;
1338 /* The callback for remap_decl. Search all containing contexts for a
1339 mapping of the variable; this avoids having to duplicate the splay
1340 tree ahead of time. We know a mapping doesn't already exist in the
1341 given context. Create new mappings to implement default semantics. */
1344 omp_copy_decl (tree var
, copy_body_data
*cb
)
1346 omp_context
*ctx
= (omp_context
*) cb
;
1349 if (TREE_CODE (var
) == LABEL_DECL
)
1351 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1352 DECL_CONTEXT (new_var
) = current_function_decl
;
1353 insert_decl_map (&ctx
->cb
, var
, new_var
);
1357 while (!is_taskreg_ctx (ctx
))
1362 new_var
= maybe_lookup_decl (var
, ctx
);
1367 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1370 return error_mark_node
;
1374 /* Debugging dumps for parallel regions. */
1375 void dump_omp_region (FILE *, struct omp_region
*, int);
1376 void debug_omp_region (struct omp_region
*);
1377 void debug_all_omp_regions (void);
1379 /* Dump the parallel region tree rooted at REGION. */
1382 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1384 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1385 gimple_code_name
[region
->type
]);
1388 dump_omp_region (file
, region
->inner
, indent
+ 4);
1392 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1393 region
->cont
->index
);
1397 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1398 region
->exit
->index
);
1400 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1403 dump_omp_region (file
, region
->next
, indent
);
1407 debug_omp_region (struct omp_region
*region
)
1409 dump_omp_region (stderr
, region
, 0);
1413 debug_all_omp_regions (void)
1415 dump_omp_region (stderr
, root_omp_region
, 0);
1419 /* Create a new parallel region starting at STMT inside region PARENT. */
1421 static struct omp_region
*
1422 new_omp_region (basic_block bb
, enum gimple_code type
,
1423 struct omp_region
*parent
)
1425 struct omp_region
*region
= XCNEW (struct omp_region
);
1427 region
->outer
= parent
;
1429 region
->type
= type
;
1433 /* This is a nested region. Add it to the list of inner
1434 regions in PARENT. */
1435 region
->next
= parent
->inner
;
1436 parent
->inner
= region
;
1440 /* This is a toplevel region. Add it to the list of toplevel
1441 regions in ROOT_OMP_REGION. */
1442 region
->next
= root_omp_region
;
1443 root_omp_region
= region
;
1449 /* Release the memory associated with the region tree rooted at REGION. */
1452 free_omp_region_1 (struct omp_region
*region
)
1454 struct omp_region
*i
, *n
;
1456 for (i
= region
->inner
; i
; i
= n
)
1459 free_omp_region_1 (i
);
1465 /* Release the memory for the entire omp region tree. */
1468 free_omp_regions (void)
1470 struct omp_region
*r
, *n
;
1471 for (r
= root_omp_region
; r
; r
= n
)
1474 free_omp_region_1 (r
);
1476 root_omp_region
= NULL
;
1480 /* Create a new context, with OUTER_CTX being the surrounding context. */
1482 static omp_context
*
1483 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1485 omp_context
*ctx
= XCNEW (omp_context
);
1487 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1488 (splay_tree_value
) ctx
);
1493 ctx
->outer
= outer_ctx
;
1494 ctx
->cb
= outer_ctx
->cb
;
1495 ctx
->cb
.block
= NULL
;
1496 ctx
->depth
= outer_ctx
->depth
+ 1;
1497 ctx
->reduction_map
= outer_ctx
->reduction_map
;
1501 ctx
->cb
.src_fn
= current_function_decl
;
1502 ctx
->cb
.dst_fn
= current_function_decl
;
1503 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1504 gcc_checking_assert (ctx
->cb
.src_node
);
1505 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1506 ctx
->cb
.src_cfun
= cfun
;
1507 ctx
->cb
.copy_decl
= omp_copy_decl
;
1508 ctx
->cb
.eh_lp_nr
= 0;
1509 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1513 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1518 static gimple_seq
maybe_catch_exception (gimple_seq
);
1520 /* Finalize task copyfn. */
1523 finalize_task_copyfn (gomp_task
*task_stmt
)
1525 struct function
*child_cfun
;
1527 gimple_seq seq
= NULL
, new_seq
;
1530 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1531 if (child_fn
== NULL_TREE
)
1534 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1535 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1537 push_cfun (child_cfun
);
1538 bind
= gimplify_body (child_fn
, false);
1539 gimple_seq_add_stmt (&seq
, bind
);
1540 new_seq
= maybe_catch_exception (seq
);
1543 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1545 gimple_seq_add_stmt (&seq
, bind
);
1547 gimple_set_body (child_fn
, seq
);
1550 /* Inform the callgraph about the new function. */
1551 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
1552 node
->parallelized_function
= 1;
1553 cgraph_node::add_new_function (child_fn
, false);
1556 /* Destroy a omp_context data structures. Called through the splay tree
1557 value delete callback. */
1560 delete_omp_context (splay_tree_value value
)
1562 omp_context
*ctx
= (omp_context
*) value
;
1564 delete ctx
->cb
.decl_map
;
1567 splay_tree_delete (ctx
->field_map
);
1568 if (ctx
->sfield_map
)
1569 splay_tree_delete (ctx
->sfield_map
);
1570 /* Reduction map is copied to nested contexts, so only delete it in the
1572 if (ctx
->reduction_map
1573 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
1574 && is_gimple_omp_offloaded (ctx
->stmt
)
1575 && is_gimple_omp_oacc (ctx
->stmt
))
1576 splay_tree_delete (ctx
->reduction_map
);
1578 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1579 it produces corrupt debug information. */
1580 if (ctx
->record_type
)
1583 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1584 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1586 if (ctx
->srecord_type
)
1589 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1590 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1593 if (is_task_ctx (ctx
))
1594 finalize_task_copyfn (as_a
<gomp_task
*> (ctx
->stmt
));
1599 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1603 fixup_child_record_type (omp_context
*ctx
)
1605 tree f
, type
= ctx
->record_type
;
1607 /* ??? It isn't sufficient to just call remap_type here, because
1608 variably_modified_type_p doesn't work the way we expect for
1609 record types. Testing each field for whether it needs remapping
1610 and creating a new record by hand works, however. */
1611 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1612 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1616 tree name
, new_fields
= NULL
;
1618 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1619 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1620 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1621 TYPE_DECL
, name
, type
);
1622 TYPE_NAME (type
) = name
;
1624 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1626 tree new_f
= copy_node (f
);
1627 DECL_CONTEXT (new_f
) = type
;
1628 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1629 DECL_CHAIN (new_f
) = new_fields
;
1630 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1631 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1633 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1637 /* Arrange to be able to look up the receiver field
1638 given the sender field. */
1639 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1640 (splay_tree_value
) new_f
);
1642 TYPE_FIELDS (type
) = nreverse (new_fields
);
1646 TREE_TYPE (ctx
->receiver_decl
)
1647 = build_qualified_type (build_reference_type (type
), TYPE_QUAL_RESTRICT
);
1650 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1651 specified by CLAUSES. */
1654 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1657 bool scan_array_reductions
= false;
1659 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1663 switch (OMP_CLAUSE_CODE (c
))
1665 case OMP_CLAUSE_PRIVATE
:
1666 decl
= OMP_CLAUSE_DECL (c
);
1667 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1669 else if (!is_variable_sized (decl
))
1670 install_var_local (decl
, ctx
);
1673 case OMP_CLAUSE_SHARED
:
1674 decl
= OMP_CLAUSE_DECL (c
);
1675 /* Ignore shared directives in teams construct. */
1676 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1678 /* Global variables don't need to be copied,
1679 the receiver side will use them directly. */
1680 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1681 if (is_global_var (odecl
))
1683 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1686 gcc_assert (is_taskreg_ctx (ctx
));
1687 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1688 || !is_variable_sized (decl
));
1689 /* Global variables don't need to be copied,
1690 the receiver side will use them directly. */
1691 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1693 by_ref
= use_pointer_for_field (decl
, ctx
);
1694 if (! TREE_READONLY (decl
)
1695 || TREE_ADDRESSABLE (decl
)
1697 || is_reference (decl
))
1699 install_var_field (decl
, by_ref
, 3, ctx
);
1700 install_var_local (decl
, ctx
);
1703 /* We don't need to copy const scalar vars back. */
1704 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1707 case OMP_CLAUSE_LASTPRIVATE
:
1708 /* Let the corresponding firstprivate clause create
1710 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1714 case OMP_CLAUSE_FIRSTPRIVATE
:
1715 if (is_gimple_omp_oacc (ctx
->stmt
))
1717 sorry ("clause not supported yet");
1721 case OMP_CLAUSE_REDUCTION
:
1722 case OMP_CLAUSE_LINEAR
:
1723 decl
= OMP_CLAUSE_DECL (c
);
1725 if (is_variable_sized (decl
))
1727 if (is_task_ctx (ctx
))
1728 install_var_field (decl
, false, 1, ctx
);
1731 else if (is_taskreg_ctx (ctx
))
1734 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1735 by_ref
= use_pointer_for_field (decl
, NULL
);
1737 if (is_task_ctx (ctx
)
1738 && (global
|| by_ref
|| is_reference (decl
)))
1740 install_var_field (decl
, false, 1, ctx
);
1742 install_var_field (decl
, by_ref
, 2, ctx
);
1745 install_var_field (decl
, by_ref
, 3, ctx
);
1747 install_var_local (decl
, ctx
);
1748 if (is_gimple_omp_oacc (ctx
->stmt
)
1749 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
1751 /* Create a decl for the reduction array. */
1752 tree var
= OMP_CLAUSE_DECL (c
);
1753 tree type
= get_base_type (var
);
1754 tree ptype
= build_pointer_type (type
);
1755 tree array
= create_tmp_var (ptype
,
1756 oacc_get_reduction_array_id (var
));
1757 omp_context
*c
= (ctx
->field_map
? ctx
: ctx
->outer
);
1758 install_var_field (array
, true, 3, c
);
1759 install_var_local (array
, c
);
1761 /* Insert it into the current context. */
1762 splay_tree_insert (ctx
->reduction_map
, (splay_tree_key
)
1763 oacc_get_reduction_array_id (var
),
1764 (splay_tree_value
) array
);
1765 splay_tree_insert (ctx
->reduction_map
,
1766 (splay_tree_key
) array
,
1767 (splay_tree_value
) array
);
1771 case OMP_CLAUSE__LOOPTEMP_
:
1772 gcc_assert (is_parallel_ctx (ctx
));
1773 decl
= OMP_CLAUSE_DECL (c
);
1774 install_var_field (decl
, false, 3, ctx
);
1775 install_var_local (decl
, ctx
);
1778 case OMP_CLAUSE_COPYPRIVATE
:
1779 case OMP_CLAUSE_COPYIN
:
1780 decl
= OMP_CLAUSE_DECL (c
);
1781 by_ref
= use_pointer_for_field (decl
, NULL
);
1782 install_var_field (decl
, by_ref
, 3, ctx
);
1785 case OMP_CLAUSE_DEFAULT
:
1786 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1789 case OMP_CLAUSE_FINAL
:
1791 case OMP_CLAUSE_NUM_THREADS
:
1792 case OMP_CLAUSE_NUM_TEAMS
:
1793 case OMP_CLAUSE_THREAD_LIMIT
:
1794 case OMP_CLAUSE_DEVICE
:
1795 case OMP_CLAUSE_SCHEDULE
:
1796 case OMP_CLAUSE_DIST_SCHEDULE
:
1797 case OMP_CLAUSE_DEPEND
:
1798 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1799 case OMP_CLAUSE_NUM_GANGS
:
1800 case OMP_CLAUSE_NUM_WORKERS
:
1801 case OMP_CLAUSE_VECTOR_LENGTH
:
1803 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1807 case OMP_CLAUSE_FROM
:
1808 case OMP_CLAUSE_MAP
:
1810 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1811 decl
= OMP_CLAUSE_DECL (c
);
1812 /* Global variables with "omp declare target" attribute
1813 don't need to be copied, the receiver side will use them
1815 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1817 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1818 && varpool_node::get_create (decl
)->offloadable
)
1820 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1821 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
)
1823 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1824 not offloaded; there is nothing to map for those. */
1825 if (!is_gimple_omp_offloaded (ctx
->stmt
)
1826 && !POINTER_TYPE_P (TREE_TYPE (decl
))
1827 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
1832 if (DECL_SIZE (decl
)
1833 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1835 tree decl2
= DECL_VALUE_EXPR (decl
);
1836 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1837 decl2
= TREE_OPERAND (decl2
, 0);
1838 gcc_assert (DECL_P (decl2
));
1839 install_var_field (decl2
, true, 3, ctx
);
1840 install_var_local (decl2
, ctx
);
1841 install_var_local (decl
, ctx
);
1845 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1846 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1847 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1848 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1849 install_var_field (decl
, true, 7, ctx
);
1851 install_var_field (decl
, true, 3, ctx
);
1852 if (is_gimple_omp_offloaded (ctx
->stmt
))
1853 install_var_local (decl
, ctx
);
1858 tree base
= get_base_address (decl
);
1859 tree nc
= OMP_CLAUSE_CHAIN (c
);
1862 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1863 && OMP_CLAUSE_DECL (nc
) == base
1864 && OMP_CLAUSE_MAP_KIND (nc
) == GOMP_MAP_POINTER
1865 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1867 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1868 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1874 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1875 decl
= OMP_CLAUSE_DECL (c
);
1877 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1878 (splay_tree_key
) decl
));
1880 = build_decl (OMP_CLAUSE_LOCATION (c
),
1881 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1882 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1883 insert_field_into_struct (ctx
->record_type
, field
);
1884 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1885 (splay_tree_value
) field
);
1890 case OMP_CLAUSE_NOWAIT
:
1891 case OMP_CLAUSE_ORDERED
:
1892 case OMP_CLAUSE_COLLAPSE
:
1893 case OMP_CLAUSE_UNTIED
:
1894 case OMP_CLAUSE_MERGEABLE
:
1895 case OMP_CLAUSE_PROC_BIND
:
1896 case OMP_CLAUSE_SAFELEN
:
1897 case OMP_CLAUSE_ASYNC
:
1898 case OMP_CLAUSE_WAIT
:
1899 case OMP_CLAUSE_GANG
:
1900 case OMP_CLAUSE_WORKER
:
1901 case OMP_CLAUSE_VECTOR
:
1904 case OMP_CLAUSE_ALIGNED
:
1905 decl
= OMP_CLAUSE_DECL (c
);
1906 if (is_global_var (decl
)
1907 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1908 install_var_local (decl
, ctx
);
1911 case OMP_CLAUSE_DEVICE_RESIDENT
:
1912 case OMP_CLAUSE_USE_DEVICE
:
1913 case OMP_CLAUSE__CACHE_
:
1914 case OMP_CLAUSE_INDEPENDENT
:
1915 case OMP_CLAUSE_AUTO
:
1916 case OMP_CLAUSE_SEQ
:
1917 sorry ("Clause not supported yet");
1925 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1927 switch (OMP_CLAUSE_CODE (c
))
1929 case OMP_CLAUSE_LASTPRIVATE
:
1930 /* Let the corresponding firstprivate clause create
1932 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1933 scan_array_reductions
= true;
1934 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1938 case OMP_CLAUSE_FIRSTPRIVATE
:
1939 if (is_gimple_omp_oacc (ctx
->stmt
))
1941 sorry ("clause not supported yet");
1945 case OMP_CLAUSE_PRIVATE
:
1946 case OMP_CLAUSE_REDUCTION
:
1947 case OMP_CLAUSE_LINEAR
:
1948 decl
= OMP_CLAUSE_DECL (c
);
1949 if (is_variable_sized (decl
))
1950 install_var_local (decl
, ctx
);
1951 fixup_remapped_decl (decl
, ctx
,
1952 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1953 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1954 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1955 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1956 scan_array_reductions
= true;
1957 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1958 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1959 scan_array_reductions
= true;
1962 case OMP_CLAUSE_SHARED
:
1963 /* Ignore shared directives in teams construct. */
1964 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1966 decl
= OMP_CLAUSE_DECL (c
);
1967 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1968 fixup_remapped_decl (decl
, ctx
, false);
1971 case OMP_CLAUSE_MAP
:
1972 if (!is_gimple_omp_offloaded (ctx
->stmt
))
1974 decl
= OMP_CLAUSE_DECL (c
);
1976 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1977 && varpool_node::get_create (decl
)->offloadable
)
1981 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1982 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1983 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1985 tree new_decl
= lookup_decl (decl
, ctx
);
1986 TREE_TYPE (new_decl
)
1987 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1989 else if (DECL_SIZE (decl
)
1990 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1992 tree decl2
= DECL_VALUE_EXPR (decl
);
1993 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1994 decl2
= TREE_OPERAND (decl2
, 0);
1995 gcc_assert (DECL_P (decl2
));
1996 fixup_remapped_decl (decl2
, ctx
, false);
1997 fixup_remapped_decl (decl
, ctx
, true);
2000 fixup_remapped_decl (decl
, ctx
, false);
2004 case OMP_CLAUSE_COPYPRIVATE
:
2005 case OMP_CLAUSE_COPYIN
:
2006 case OMP_CLAUSE_DEFAULT
:
2008 case OMP_CLAUSE_NUM_THREADS
:
2009 case OMP_CLAUSE_NUM_TEAMS
:
2010 case OMP_CLAUSE_THREAD_LIMIT
:
2011 case OMP_CLAUSE_DEVICE
:
2012 case OMP_CLAUSE_SCHEDULE
:
2013 case OMP_CLAUSE_DIST_SCHEDULE
:
2014 case OMP_CLAUSE_NOWAIT
:
2015 case OMP_CLAUSE_ORDERED
:
2016 case OMP_CLAUSE_COLLAPSE
:
2017 case OMP_CLAUSE_UNTIED
:
2018 case OMP_CLAUSE_FINAL
:
2019 case OMP_CLAUSE_MERGEABLE
:
2020 case OMP_CLAUSE_PROC_BIND
:
2021 case OMP_CLAUSE_SAFELEN
:
2022 case OMP_CLAUSE_ALIGNED
:
2023 case OMP_CLAUSE_DEPEND
:
2024 case OMP_CLAUSE__LOOPTEMP_
:
2026 case OMP_CLAUSE_FROM
:
2027 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2028 case OMP_CLAUSE_ASYNC
:
2029 case OMP_CLAUSE_WAIT
:
2030 case OMP_CLAUSE_NUM_GANGS
:
2031 case OMP_CLAUSE_NUM_WORKERS
:
2032 case OMP_CLAUSE_VECTOR_LENGTH
:
2033 case OMP_CLAUSE_GANG
:
2034 case OMP_CLAUSE_WORKER
:
2035 case OMP_CLAUSE_VECTOR
:
2038 case OMP_CLAUSE_DEVICE_RESIDENT
:
2039 case OMP_CLAUSE_USE_DEVICE
:
2040 case OMP_CLAUSE__CACHE_
:
2041 case OMP_CLAUSE_INDEPENDENT
:
2042 case OMP_CLAUSE_AUTO
:
2043 case OMP_CLAUSE_SEQ
:
2044 sorry ("Clause not supported yet");
2052 gcc_checking_assert (!scan_array_reductions
2053 || !is_gimple_omp_oacc (ctx
->stmt
));
2054 if (scan_array_reductions
)
2055 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2056 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
2057 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2059 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
2060 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
2062 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2063 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2064 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
2065 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2066 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2067 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
2070 /* Create a new name for omp child function. Returns an identifier. If
2071 IS_CILK_FOR is true then the suffix for the child function is
2075 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
2078 return clone_function_name (current_function_decl
, "_cilk_for_fn");
2079 return clone_function_name (current_function_decl
,
2080 task_copy
? "_omp_cpyfn" : "_omp_fn");
2083 /* Returns the type of the induction variable for the child function for
2084 _Cilk_for and the types for _high and _low variables based on TYPE. */
2087 cilk_for_check_loop_diff_type (tree type
)
2089 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
2091 if (TYPE_UNSIGNED (type
))
2092 return uint32_type_node
;
2094 return integer_type_node
;
2098 if (TYPE_UNSIGNED (type
))
2099 return uint64_type_node
;
2101 return long_long_integer_type_node
;
2105 /* Build a decl for the omp child function. It'll not contain a body
2106 yet, just the bare decl. */
2109 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
2111 tree decl
, type
, name
, t
;
2114 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2115 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2116 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
2117 tree cilk_var_type
= NULL_TREE
;
2119 name
= create_omp_child_function_name (task_copy
,
2120 cilk_for_count
!= NULL_TREE
);
2122 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2123 ptr_type_node
, NULL_TREE
);
2124 else if (cilk_for_count
)
2126 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
2127 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
2128 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2129 cilk_var_type
, cilk_var_type
, NULL_TREE
);
2132 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
2134 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
2136 gcc_checking_assert (!is_gimple_omp_oacc (ctx
->stmt
)
2139 ctx
->cb
.dst_fn
= decl
;
2141 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
2143 TREE_STATIC (decl
) = 1;
2144 TREE_USED (decl
) = 1;
2145 DECL_ARTIFICIAL (decl
) = 1;
2146 DECL_IGNORED_P (decl
) = 0;
2147 TREE_PUBLIC (decl
) = 0;
2148 DECL_UNINLINABLE (decl
) = 1;
2149 DECL_EXTERNAL (decl
) = 0;
2150 DECL_CONTEXT (decl
) = NULL_TREE
;
2151 DECL_INITIAL (decl
) = make_node (BLOCK
);
2152 if (cgraph_node::get (current_function_decl
)->offloadable
)
2153 cgraph_node::get_create (decl
)->offloadable
= 1;
2157 for (octx
= ctx
; octx
; octx
= octx
->outer
)
2158 if (is_gimple_omp_offloaded (octx
->stmt
))
2160 cgraph_node::get_create (decl
)->offloadable
= 1;
2161 #ifdef ENABLE_OFFLOADING
2162 g
->have_offload
= true;
2168 if (cgraph_node::get_create (decl
)->offloadable
2169 && !lookup_attribute ("omp declare target",
2170 DECL_ATTRIBUTES (current_function_decl
)))
2171 DECL_ATTRIBUTES (decl
)
2172 = tree_cons (get_identifier ("omp target entrypoint"),
2173 NULL_TREE
, DECL_ATTRIBUTES (decl
));
2175 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2176 RESULT_DECL
, NULL_TREE
, void_type_node
);
2177 DECL_ARTIFICIAL (t
) = 1;
2178 DECL_IGNORED_P (t
) = 1;
2179 DECL_CONTEXT (t
) = decl
;
2180 DECL_RESULT (decl
) = t
;
2182 /* _Cilk_for's child function requires two extra parameters called
2183 __low and __high that are set the by Cilk runtime when it calls this
2187 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2188 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
2189 DECL_ARTIFICIAL (t
) = 1;
2190 DECL_NAMELESS (t
) = 1;
2191 DECL_ARG_TYPE (t
) = ptr_type_node
;
2192 DECL_CONTEXT (t
) = current_function_decl
;
2194 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2195 DECL_ARGUMENTS (decl
) = t
;
2197 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2198 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
2199 DECL_ARTIFICIAL (t
) = 1;
2200 DECL_NAMELESS (t
) = 1;
2201 DECL_ARG_TYPE (t
) = ptr_type_node
;
2202 DECL_CONTEXT (t
) = current_function_decl
;
2204 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2205 DECL_ARGUMENTS (decl
) = t
;
2208 tree data_name
= get_identifier (".omp_data_i");
2209 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
2211 DECL_ARTIFICIAL (t
) = 1;
2212 DECL_NAMELESS (t
) = 1;
2213 DECL_ARG_TYPE (t
) = ptr_type_node
;
2214 DECL_CONTEXT (t
) = current_function_decl
;
2217 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2218 DECL_ARGUMENTS (decl
) = t
;
2220 ctx
->receiver_decl
= t
;
2223 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2224 PARM_DECL
, get_identifier (".omp_data_o"),
2226 DECL_ARTIFICIAL (t
) = 1;
2227 DECL_NAMELESS (t
) = 1;
2228 DECL_ARG_TYPE (t
) = ptr_type_node
;
2229 DECL_CONTEXT (t
) = current_function_decl
;
2231 TREE_ADDRESSABLE (t
) = 1;
2232 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2233 DECL_ARGUMENTS (decl
) = t
;
2236 /* Allocate memory for the function structure. The call to
2237 allocate_struct_function clobbers CFUN, so we need to restore
2239 push_struct_function (decl
);
2240 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2244 /* Callback for walk_gimple_seq. Check if combined parallel
2245 contains gimple_omp_for_combined_into_p OMP_FOR. */
2248 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2249 bool *handled_ops_p
,
2250 struct walk_stmt_info
*wi
)
2252 gimple stmt
= gsi_stmt (*gsi_p
);
2254 *handled_ops_p
= true;
2255 switch (gimple_code (stmt
))
2259 case GIMPLE_OMP_FOR
:
2260 if (gimple_omp_for_combined_into_p (stmt
)
2261 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
2264 return integer_zero_node
;
2273 /* Scan an OpenMP parallel directive. */
2276 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2280 gomp_parallel
*stmt
= as_a
<gomp_parallel
*> (gsi_stmt (*gsi
));
2282 /* Ignore parallel directives with empty bodies, unless there
2283 are copyin clauses. */
2285 && empty_body_p (gimple_omp_body (stmt
))
2286 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2287 OMP_CLAUSE_COPYIN
) == NULL
)
2289 gsi_replace (gsi
, gimple_build_nop (), false);
2293 if (gimple_omp_parallel_combined_p (stmt
))
2295 struct walk_stmt_info wi
;
2297 memset (&wi
, 0, sizeof (wi
));
2299 walk_gimple_seq (gimple_omp_body (stmt
),
2300 find_combined_for
, NULL
, &wi
);
2303 gomp_for
*for_stmt
= as_a
<gomp_for
*> ((gimple
) wi
.info
);
2304 struct omp_for_data fd
;
2305 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2306 /* We need two temporaries with fd.loop.v type (istart/iend)
2307 and then (fd.collapse - 1) temporaries with the same
2308 type for count2 ... countN-1 vars if not constant. */
2309 size_t count
= 2, i
;
2310 tree type
= fd
.iter_type
;
2312 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2313 count
+= fd
.collapse
- 1;
2314 for (i
= 0; i
< count
; i
++)
2316 tree temp
= create_tmp_var (type
);
2317 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2318 OMP_CLAUSE__LOOPTEMP_
);
2319 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2320 OMP_CLAUSE_DECL (c
) = temp
;
2321 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2322 gimple_omp_parallel_set_clauses (stmt
, c
);
2327 ctx
= new_omp_context (stmt
, outer_ctx
);
2328 taskreg_contexts
.safe_push (ctx
);
2329 if (taskreg_nesting_level
> 1)
2330 ctx
->is_nested
= true;
2331 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2332 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2333 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2334 name
= create_tmp_var_name (".omp_data_s");
2335 name
= build_decl (gimple_location (stmt
),
2336 TYPE_DECL
, name
, ctx
->record_type
);
2337 DECL_ARTIFICIAL (name
) = 1;
2338 DECL_NAMELESS (name
) = 1;
2339 TYPE_NAME (ctx
->record_type
) = name
;
2340 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2341 create_omp_child_function (ctx
, false);
2342 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2344 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2345 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2347 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2348 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2351 /* Scan an OpenMP task directive. */
2354 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2358 gomp_task
*stmt
= as_a
<gomp_task
*> (gsi_stmt (*gsi
));
2360 /* Ignore task directives with empty bodies. */
2362 && empty_body_p (gimple_omp_body (stmt
)))
2364 gsi_replace (gsi
, gimple_build_nop (), false);
2368 ctx
= new_omp_context (stmt
, outer_ctx
);
2369 taskreg_contexts
.safe_push (ctx
);
2370 if (taskreg_nesting_level
> 1)
2371 ctx
->is_nested
= true;
2372 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2373 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2374 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2375 name
= create_tmp_var_name (".omp_data_s");
2376 name
= build_decl (gimple_location (stmt
),
2377 TYPE_DECL
, name
, ctx
->record_type
);
2378 DECL_ARTIFICIAL (name
) = 1;
2379 DECL_NAMELESS (name
) = 1;
2380 TYPE_NAME (ctx
->record_type
) = name
;
2381 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2382 create_omp_child_function (ctx
, false);
2383 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2385 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2387 if (ctx
->srecord_type
)
2389 name
= create_tmp_var_name (".omp_data_a");
2390 name
= build_decl (gimple_location (stmt
),
2391 TYPE_DECL
, name
, ctx
->srecord_type
);
2392 DECL_ARTIFICIAL (name
) = 1;
2393 DECL_NAMELESS (name
) = 1;
2394 TYPE_NAME (ctx
->srecord_type
) = name
;
2395 TYPE_ARTIFICIAL (ctx
->srecord_type
) = 1;
2396 create_omp_child_function (ctx
, true);
2399 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2401 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2403 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2404 t
= build_int_cst (long_integer_type_node
, 0);
2405 gimple_omp_task_set_arg_size (stmt
, t
);
2406 t
= build_int_cst (long_integer_type_node
, 1);
2407 gimple_omp_task_set_arg_align (stmt
, t
);
2412 /* If any decls have been made addressable during scan_omp,
2413 adjust their fields if needed, and layout record types
2414 of parallel/task constructs. */
2417 finish_taskreg_scan (omp_context
*ctx
)
2419 if (ctx
->record_type
== NULL_TREE
)
2422 /* If any task_shared_vars were needed, verify all
2423 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2424 statements if use_pointer_for_field hasn't changed
2425 because of that. If it did, update field types now. */
2426 if (task_shared_vars
)
2430 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2431 c
; c
= OMP_CLAUSE_CHAIN (c
))
2432 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
2434 tree decl
= OMP_CLAUSE_DECL (c
);
2436 /* Global variables don't need to be copied,
2437 the receiver side will use them directly. */
2438 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2440 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2441 || !use_pointer_for_field (decl
, ctx
))
2443 tree field
= lookup_field (decl
, ctx
);
2444 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2445 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2447 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2448 TREE_THIS_VOLATILE (field
) = 0;
2449 DECL_USER_ALIGN (field
) = 0;
2450 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2451 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2452 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2453 if (ctx
->srecord_type
)
2455 tree sfield
= lookup_sfield (decl
, ctx
);
2456 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2457 TREE_THIS_VOLATILE (sfield
) = 0;
2458 DECL_USER_ALIGN (sfield
) = 0;
2459 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2460 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2461 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2466 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2468 layout_type (ctx
->record_type
);
2469 fixup_child_record_type (ctx
);
2473 location_t loc
= gimple_location (ctx
->stmt
);
2474 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2475 /* Move VLA fields to the end. */
2476 p
= &TYPE_FIELDS (ctx
->record_type
);
2478 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2479 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2482 *p
= TREE_CHAIN (*p
);
2483 TREE_CHAIN (*q
) = NULL_TREE
;
2484 q
= &TREE_CHAIN (*q
);
2487 p
= &DECL_CHAIN (*p
);
2489 layout_type (ctx
->record_type
);
2490 fixup_child_record_type (ctx
);
2491 if (ctx
->srecord_type
)
2492 layout_type (ctx
->srecord_type
);
2493 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2494 TYPE_SIZE_UNIT (ctx
->record_type
));
2495 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2496 t
= build_int_cst (long_integer_type_node
,
2497 TYPE_ALIGN_UNIT (ctx
->record_type
));
2498 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2503 static omp_context
*
2504 enclosing_target_ctx (omp_context
*ctx
)
2507 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
2509 gcc_assert (ctx
!= NULL
);
2514 oacc_loop_or_target_p (gimple stmt
)
2516 enum gimple_code outer_type
= gimple_code (stmt
);
2517 return ((outer_type
== GIMPLE_OMP_TARGET
2518 && ((gimple_omp_target_kind (stmt
)
2519 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2520 || (gimple_omp_target_kind (stmt
)
2521 == GF_OMP_TARGET_KIND_OACC_KERNELS
)))
2522 || (outer_type
== GIMPLE_OMP_FOR
2523 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
));
2526 /* Scan a GIMPLE_OMP_FOR. */
2529 scan_omp_for (gomp_for
*stmt
, omp_context
*outer_ctx
)
2531 enum gimple_code outer_type
= GIMPLE_ERROR_MARK
;
2534 tree clauses
= gimple_omp_for_clauses (stmt
);
2537 outer_type
= gimple_code (outer_ctx
->stmt
);
2539 ctx
= new_omp_context (stmt
, outer_ctx
);
2541 if (is_gimple_omp_oacc (stmt
))
2543 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2544 ctx
->gwv_this
= outer_ctx
->gwv_this
;
2545 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2548 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_GANG
)
2550 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WORKER
)
2552 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR
)
2556 ctx
->gwv_this
|= val
;
2559 /* Skip; not nested inside a region. */
2562 if (!oacc_loop_or_target_p (outer_ctx
->stmt
))
2564 /* Skip; not nested inside an OpenACC region. */
2567 if (outer_type
== GIMPLE_OMP_FOR
)
2568 outer_ctx
->gwv_below
|= val
;
2569 if (OMP_CLAUSE_OPERAND (c
, 0) != NULL_TREE
)
2571 omp_context
*enclosing
= enclosing_target_ctx (outer_ctx
);
2572 if (gimple_omp_target_kind (enclosing
->stmt
)
2573 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2574 error_at (gimple_location (stmt
),
2575 "no arguments allowed to gang, worker and vector clauses inside parallel");
2580 scan_sharing_clauses (clauses
, ctx
);
2582 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2583 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2585 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2586 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2587 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2588 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2590 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2592 if (is_gimple_omp_oacc (stmt
))
2594 if (ctx
->gwv_this
& ctx
->gwv_below
)
2595 error_at (gimple_location (stmt
),
2596 "gang, worker and vector may occur only once in a loop nest");
2597 else if (ctx
->gwv_below
!= 0
2598 && ctx
->gwv_this
> ctx
->gwv_below
)
2599 error_at (gimple_location (stmt
),
2600 "gang, worker and vector must occur in this order in a loop nest");
2601 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2602 outer_ctx
->gwv_below
|= ctx
->gwv_below
;
2606 /* Scan an OpenMP sections directive. */
2609 scan_omp_sections (gomp_sections
*stmt
, omp_context
*outer_ctx
)
2613 ctx
= new_omp_context (stmt
, outer_ctx
);
2614 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2615 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2618 /* Scan an OpenMP single directive. */
2621 scan_omp_single (gomp_single
*stmt
, omp_context
*outer_ctx
)
2626 ctx
= new_omp_context (stmt
, outer_ctx
);
2627 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2628 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2629 name
= create_tmp_var_name (".omp_copy_s");
2630 name
= build_decl (gimple_location (stmt
),
2631 TYPE_DECL
, name
, ctx
->record_type
);
2632 TYPE_NAME (ctx
->record_type
) = name
;
2634 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2635 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2637 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2638 ctx
->record_type
= NULL
;
2640 layout_type (ctx
->record_type
);
2643 /* Scan a GIMPLE_OMP_TARGET. */
2646 scan_omp_target (gomp_target
*stmt
, omp_context
*outer_ctx
)
2650 bool offloaded
= is_gimple_omp_offloaded (stmt
);
2651 tree clauses
= gimple_omp_target_clauses (stmt
);
2653 ctx
= new_omp_context (stmt
, outer_ctx
);
2654 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2655 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2656 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2657 name
= create_tmp_var_name (".omp_data_t");
2658 name
= build_decl (gimple_location (stmt
),
2659 TYPE_DECL
, name
, ctx
->record_type
);
2660 DECL_ARTIFICIAL (name
) = 1;
2661 DECL_NAMELESS (name
) = 1;
2662 TYPE_NAME (ctx
->record_type
) = name
;
2663 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2666 if (is_gimple_omp_oacc (stmt
))
2667 ctx
->reduction_map
= splay_tree_new (splay_tree_compare_pointers
,
2670 create_omp_child_function (ctx
, false);
2671 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2674 if (is_gimple_omp_oacc (stmt
))
2676 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2678 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_GANGS
)
2679 ctx
->gwv_this
|= MASK_GANG
;
2680 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_WORKERS
)
2681 ctx
->gwv_this
|= MASK_WORKER
;
2682 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR_LENGTH
)
2683 ctx
->gwv_this
|= MASK_VECTOR
;
2687 scan_sharing_clauses (clauses
, ctx
);
2688 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2690 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2691 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2694 TYPE_FIELDS (ctx
->record_type
)
2695 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2696 #ifdef ENABLE_CHECKING
2698 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2699 for (field
= TYPE_FIELDS (ctx
->record_type
);
2701 field
= DECL_CHAIN (field
))
2702 gcc_assert (DECL_ALIGN (field
) == align
);
2704 layout_type (ctx
->record_type
);
2706 fixup_child_record_type (ctx
);
2710 /* Scan an OpenMP teams directive. */
2713 scan_omp_teams (gomp_teams
*stmt
, omp_context
*outer_ctx
)
2715 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2716 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2717 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2720 /* Check nesting restrictions. */
2722 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2724 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2725 inside an OpenACC CTX. */
2726 if (!(is_gimple_omp (stmt
)
2727 && is_gimple_omp_oacc (stmt
)))
2729 for (omp_context
*ctx_
= ctx
; ctx_
!= NULL
; ctx_
= ctx_
->outer
)
2730 if (is_gimple_omp (ctx_
->stmt
)
2731 && is_gimple_omp_oacc (ctx_
->stmt
))
2733 error_at (gimple_location (stmt
),
2734 "non-OpenACC construct inside of OpenACC region");
2741 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2742 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2744 error_at (gimple_location (stmt
),
2745 "OpenMP constructs may not be nested inside simd region");
2748 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2750 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2751 || (gimple_omp_for_kind (stmt
)
2752 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2753 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2755 error_at (gimple_location (stmt
),
2756 "only distribute or parallel constructs are allowed to "
2757 "be closely nested inside teams construct");
2762 switch (gimple_code (stmt
))
2764 case GIMPLE_OMP_FOR
:
2765 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2767 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2769 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2771 error_at (gimple_location (stmt
),
2772 "distribute construct must be closely nested inside "
2780 if (is_gimple_call (stmt
)
2781 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2782 == BUILT_IN_GOMP_CANCEL
2783 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2784 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2786 const char *bad
= NULL
;
2787 const char *kind
= NULL
;
2790 error_at (gimple_location (stmt
), "orphaned %qs construct",
2791 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2792 == BUILT_IN_GOMP_CANCEL
2793 ? "#pragma omp cancel"
2794 : "#pragma omp cancellation point");
2797 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2798 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2802 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2803 bad
= "#pragma omp parallel";
2804 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2805 == BUILT_IN_GOMP_CANCEL
2806 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2807 ctx
->cancellable
= true;
2811 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2812 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2813 bad
= "#pragma omp for";
2814 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2815 == BUILT_IN_GOMP_CANCEL
2816 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2818 ctx
->cancellable
= true;
2819 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2821 warning_at (gimple_location (stmt
), 0,
2822 "%<#pragma omp cancel for%> inside "
2823 "%<nowait%> for construct");
2824 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2825 OMP_CLAUSE_ORDERED
))
2826 warning_at (gimple_location (stmt
), 0,
2827 "%<#pragma omp cancel for%> inside "
2828 "%<ordered%> for construct");
2833 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2834 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2835 bad
= "#pragma omp sections";
2836 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2837 == BUILT_IN_GOMP_CANCEL
2838 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2840 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2842 ctx
->cancellable
= true;
2843 if (find_omp_clause (gimple_omp_sections_clauses
2846 warning_at (gimple_location (stmt
), 0,
2847 "%<#pragma omp cancel sections%> inside "
2848 "%<nowait%> sections construct");
2852 gcc_assert (ctx
->outer
2853 && gimple_code (ctx
->outer
->stmt
)
2854 == GIMPLE_OMP_SECTIONS
);
2855 ctx
->outer
->cancellable
= true;
2856 if (find_omp_clause (gimple_omp_sections_clauses
2859 warning_at (gimple_location (stmt
), 0,
2860 "%<#pragma omp cancel sections%> inside "
2861 "%<nowait%> sections construct");
2867 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2868 bad
= "#pragma omp task";
2870 ctx
->cancellable
= true;
2874 error_at (gimple_location (stmt
), "invalid arguments");
2879 error_at (gimple_location (stmt
),
2880 "%<%s %s%> construct not closely nested inside of %qs",
2881 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2882 == BUILT_IN_GOMP_CANCEL
2883 ? "#pragma omp cancel"
2884 : "#pragma omp cancellation point", kind
, bad
);
2889 case GIMPLE_OMP_SECTIONS
:
2890 case GIMPLE_OMP_SINGLE
:
2891 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2892 switch (gimple_code (ctx
->stmt
))
2894 case GIMPLE_OMP_FOR
:
2895 case GIMPLE_OMP_SECTIONS
:
2896 case GIMPLE_OMP_SINGLE
:
2897 case GIMPLE_OMP_ORDERED
:
2898 case GIMPLE_OMP_MASTER
:
2899 case GIMPLE_OMP_TASK
:
2900 case GIMPLE_OMP_CRITICAL
:
2901 if (is_gimple_call (stmt
))
2903 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2904 != BUILT_IN_GOMP_BARRIER
)
2906 error_at (gimple_location (stmt
),
2907 "barrier region may not be closely nested inside "
2908 "of work-sharing, critical, ordered, master or "
2909 "explicit task region");
2912 error_at (gimple_location (stmt
),
2913 "work-sharing region may not be closely nested inside "
2914 "of work-sharing, critical, ordered, master or explicit "
2917 case GIMPLE_OMP_PARALLEL
:
2923 case GIMPLE_OMP_MASTER
:
2924 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2925 switch (gimple_code (ctx
->stmt
))
2927 case GIMPLE_OMP_FOR
:
2928 case GIMPLE_OMP_SECTIONS
:
2929 case GIMPLE_OMP_SINGLE
:
2930 case GIMPLE_OMP_TASK
:
2931 error_at (gimple_location (stmt
),
2932 "master region may not be closely nested inside "
2933 "of work-sharing or explicit task region");
2935 case GIMPLE_OMP_PARALLEL
:
2941 case GIMPLE_OMP_ORDERED
:
2942 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2943 switch (gimple_code (ctx
->stmt
))
2945 case GIMPLE_OMP_CRITICAL
:
2946 case GIMPLE_OMP_TASK
:
2947 error_at (gimple_location (stmt
),
2948 "ordered region may not be closely nested inside "
2949 "of critical or explicit task region");
2951 case GIMPLE_OMP_FOR
:
2952 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2953 OMP_CLAUSE_ORDERED
) == NULL
)
2955 error_at (gimple_location (stmt
),
2956 "ordered region must be closely nested inside "
2957 "a loop region with an ordered clause");
2961 case GIMPLE_OMP_PARALLEL
:
2962 error_at (gimple_location (stmt
),
2963 "ordered region must be closely nested inside "
2964 "a loop region with an ordered clause");
2970 case GIMPLE_OMP_CRITICAL
:
2973 = gimple_omp_critical_name (as_a
<gomp_critical
*> (stmt
));
2974 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2975 if (gomp_critical
*other_crit
2976 = dyn_cast
<gomp_critical
*> (ctx
->stmt
))
2977 if (this_stmt_name
== gimple_omp_critical_name (other_crit
))
2979 error_at (gimple_location (stmt
),
2980 "critical region may not be nested inside a critical "
2981 "region with the same name");
2986 case GIMPLE_OMP_TEAMS
:
2988 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2989 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2991 error_at (gimple_location (stmt
),
2992 "teams construct not closely nested inside of target "
2997 case GIMPLE_OMP_TARGET
:
2998 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3000 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
3002 if (is_gimple_omp (stmt
)
3003 && is_gimple_omp_oacc (stmt
)
3004 && is_gimple_omp (ctx
->stmt
))
3006 error_at (gimple_location (stmt
),
3007 "OpenACC construct inside of non-OpenACC region");
3013 const char *stmt_name
, *ctx_stmt_name
;
3014 switch (gimple_omp_target_kind (stmt
))
3016 case GF_OMP_TARGET_KIND_REGION
: stmt_name
= "target"; break;
3017 case GF_OMP_TARGET_KIND_DATA
: stmt_name
= "target data"; break;
3018 case GF_OMP_TARGET_KIND_UPDATE
: stmt_name
= "target update"; break;
3019 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: stmt_name
= "parallel"; break;
3020 case GF_OMP_TARGET_KIND_OACC_KERNELS
: stmt_name
= "kernels"; break;
3021 case GF_OMP_TARGET_KIND_OACC_DATA
: stmt_name
= "data"; break;
3022 case GF_OMP_TARGET_KIND_OACC_UPDATE
: stmt_name
= "update"; break;
3023 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
: stmt_name
= "enter/exit data"; break;
3024 default: gcc_unreachable ();
3026 switch (gimple_omp_target_kind (ctx
->stmt
))
3028 case GF_OMP_TARGET_KIND_REGION
: ctx_stmt_name
= "target"; break;
3029 case GF_OMP_TARGET_KIND_DATA
: ctx_stmt_name
= "target data"; break;
3030 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: ctx_stmt_name
= "parallel"; break;
3031 case GF_OMP_TARGET_KIND_OACC_KERNELS
: ctx_stmt_name
= "kernels"; break;
3032 case GF_OMP_TARGET_KIND_OACC_DATA
: ctx_stmt_name
= "data"; break;
3033 default: gcc_unreachable ();
3036 /* OpenACC/OpenMP mismatch? */
3037 if (is_gimple_omp_oacc (stmt
)
3038 != is_gimple_omp_oacc (ctx
->stmt
))
3040 error_at (gimple_location (stmt
),
3041 "%s %s construct inside of %s %s region",
3042 (is_gimple_omp_oacc (stmt
)
3043 ? "OpenACC" : "OpenMP"), stmt_name
,
3044 (is_gimple_omp_oacc (ctx
->stmt
)
3045 ? "OpenACC" : "OpenMP"), ctx_stmt_name
);
3048 if (is_gimple_omp_offloaded (ctx
->stmt
))
3050 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3051 if (is_gimple_omp_oacc (ctx
->stmt
))
3053 error_at (gimple_location (stmt
),
3054 "%s construct inside of %s region",
3055 stmt_name
, ctx_stmt_name
);
3060 gcc_checking_assert (!is_gimple_omp_oacc (stmt
));
3061 warning_at (gimple_location (stmt
), 0,
3062 "%s construct inside of %s region",
3063 stmt_name
, ctx_stmt_name
);
3075 /* Helper function scan_omp.
3077 Callback for walk_tree or operators in walk_gimple_stmt used to
3078 scan for OMP directives in TP. */
3081 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
3083 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
3084 omp_context
*ctx
= (omp_context
*) wi
->info
;
3087 switch (TREE_CODE (t
))
3094 *tp
= remap_decl (t
, &ctx
->cb
);
3098 if (ctx
&& TYPE_P (t
))
3099 *tp
= remap_type (t
, &ctx
->cb
);
3100 else if (!DECL_P (t
))
3105 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
3106 if (tem
!= TREE_TYPE (t
))
3108 if (TREE_CODE (t
) == INTEGER_CST
)
3109 *tp
= wide_int_to_tree (tem
, t
);
3111 TREE_TYPE (t
) = tem
;
3121 /* Return true if FNDECL is a setjmp or a longjmp. */
3124 setjmp_or_longjmp_p (const_tree fndecl
)
3126 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
3127 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
3128 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
3131 tree declname
= DECL_NAME (fndecl
);
3134 const char *name
= IDENTIFIER_POINTER (declname
);
3135 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
3139 /* Helper function for scan_omp.
3141 Callback for walk_gimple_stmt used to scan for OMP directives in
3142 the current statement in GSI. */
3145 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
3146 struct walk_stmt_info
*wi
)
3148 gimple stmt
= gsi_stmt (*gsi
);
3149 omp_context
*ctx
= (omp_context
*) wi
->info
;
3151 if (gimple_has_location (stmt
))
3152 input_location
= gimple_location (stmt
);
3154 /* Check the nesting restrictions. */
3155 bool remove
= false;
3156 if (is_gimple_omp (stmt
))
3157 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3158 else if (is_gimple_call (stmt
))
3160 tree fndecl
= gimple_call_fndecl (stmt
);
3163 if (setjmp_or_longjmp_p (fndecl
)
3165 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3166 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3169 error_at (gimple_location (stmt
),
3170 "setjmp/longjmp inside simd construct");
3172 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
3173 switch (DECL_FUNCTION_CODE (fndecl
))
3175 case BUILT_IN_GOMP_BARRIER
:
3176 case BUILT_IN_GOMP_CANCEL
:
3177 case BUILT_IN_GOMP_CANCELLATION_POINT
:
3178 case BUILT_IN_GOMP_TASKYIELD
:
3179 case BUILT_IN_GOMP_TASKWAIT
:
3180 case BUILT_IN_GOMP_TASKGROUP_START
:
3181 case BUILT_IN_GOMP_TASKGROUP_END
:
3182 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3191 stmt
= gimple_build_nop ();
3192 gsi_replace (gsi
, stmt
, false);
3195 *handled_ops_p
= true;
3197 switch (gimple_code (stmt
))
3199 case GIMPLE_OMP_PARALLEL
:
3200 taskreg_nesting_level
++;
3201 scan_omp_parallel (gsi
, ctx
);
3202 taskreg_nesting_level
--;
3205 case GIMPLE_OMP_TASK
:
3206 taskreg_nesting_level
++;
3207 scan_omp_task (gsi
, ctx
);
3208 taskreg_nesting_level
--;
3211 case GIMPLE_OMP_FOR
:
3212 scan_omp_for (as_a
<gomp_for
*> (stmt
), ctx
);
3215 case GIMPLE_OMP_SECTIONS
:
3216 scan_omp_sections (as_a
<gomp_sections
*> (stmt
), ctx
);
3219 case GIMPLE_OMP_SINGLE
:
3220 scan_omp_single (as_a
<gomp_single
*> (stmt
), ctx
);
3223 case GIMPLE_OMP_SECTION
:
3224 case GIMPLE_OMP_MASTER
:
3225 case GIMPLE_OMP_TASKGROUP
:
3226 case GIMPLE_OMP_ORDERED
:
3227 case GIMPLE_OMP_CRITICAL
:
3228 ctx
= new_omp_context (stmt
, ctx
);
3229 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3232 case GIMPLE_OMP_TARGET
:
3233 scan_omp_target (as_a
<gomp_target
*> (stmt
), ctx
);
3236 case GIMPLE_OMP_TEAMS
:
3237 scan_omp_teams (as_a
<gomp_teams
*> (stmt
), ctx
);
3244 *handled_ops_p
= false;
3246 for (var
= gimple_bind_vars (as_a
<gbind
*> (stmt
));
3248 var
= DECL_CHAIN (var
))
3249 insert_decl_map (&ctx
->cb
, var
, var
);
3253 *handled_ops_p
= false;
3261 /* Scan all the statements starting at the current statement. CTX
3262 contains context information about the OMP directives and
3263 clauses found during the scan. */
3266 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
3268 location_t saved_location
;
3269 struct walk_stmt_info wi
;
3271 memset (&wi
, 0, sizeof (wi
));
3273 wi
.want_locations
= true;
3275 saved_location
= input_location
;
3276 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
3277 input_location
= saved_location
;
3280 /* Re-gimplification and code generation routines. */
3282 /* Build a call to GOMP_barrier. */
3285 build_omp_barrier (tree lhs
)
3287 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
3288 : BUILT_IN_GOMP_BARRIER
);
3289 gcall
*g
= gimple_build_call (fndecl
, 0);
3291 gimple_call_set_lhs (g
, lhs
);
3295 /* If a context was created for STMT when it was scanned, return it. */
3297 static omp_context
*
3298 maybe_lookup_ctx (gimple stmt
)
3301 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
3302 return n
? (omp_context
*) n
->value
: NULL
;
3306 /* Find the mapping for DECL in CTX or the immediately enclosing
3307 context that has a mapping for DECL.
3309 If CTX is a nested parallel directive, we may have to use the decl
3310 mappings created in CTX's parent context. Suppose that we have the
3311 following parallel nesting (variable UIDs showed for clarity):
3314 #omp parallel shared(iD.1562) -> outer parallel
3315 iD.1562 = iD.1562 + 1;
3317 #omp parallel shared (iD.1562) -> inner parallel
3318 iD.1562 = iD.1562 - 1;
3320 Each parallel structure will create a distinct .omp_data_s structure
3321 for copying iD.1562 in/out of the directive:
3323 outer parallel .omp_data_s.1.i -> iD.1562
3324 inner parallel .omp_data_s.2.i -> iD.1562
3326 A shared variable mapping will produce a copy-out operation before
3327 the parallel directive and a copy-in operation after it. So, in
3328 this case we would have:
3331 .omp_data_o.1.i = iD.1562;
3332 #omp parallel shared(iD.1562) -> outer parallel
3333 .omp_data_i.1 = &.omp_data_o.1
3334 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3336 .omp_data_o.2.i = iD.1562; -> **
3337 #omp parallel shared(iD.1562) -> inner parallel
3338 .omp_data_i.2 = &.omp_data_o.2
3339 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3342 ** This is a problem. The symbol iD.1562 cannot be referenced
3343 inside the body of the outer parallel region. But since we are
3344 emitting this copy operation while expanding the inner parallel
3345 directive, we need to access the CTX structure of the outer
3346 parallel directive to get the correct mapping:
3348 .omp_data_o.2.i = .omp_data_i.1->i
3350 Since there may be other workshare or parallel directives enclosing
3351 the parallel directive, it may be necessary to walk up the context
3352 parent chain. This is not a problem in general because nested
3353 parallelism happens only rarely. */
3356 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3361 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3362 t
= maybe_lookup_decl (decl
, up
);
3364 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
3366 return t
? t
: decl
;
3370 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3371 in outer contexts. */
3374 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3379 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3380 t
= maybe_lookup_decl (decl
, up
);
3382 return t
? t
: decl
;
3386 /* Construct the initialization value for reduction CLAUSE. */
3389 omp_reduction_init (tree clause
, tree type
)
3391 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
3392 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
3399 case TRUTH_ORIF_EXPR
:
3400 case TRUTH_XOR_EXPR
:
3402 return build_zero_cst (type
);
3405 case TRUTH_AND_EXPR
:
3406 case TRUTH_ANDIF_EXPR
:
3408 return fold_convert_loc (loc
, type
, integer_one_node
);
3411 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3414 if (SCALAR_FLOAT_TYPE_P (type
))
3416 REAL_VALUE_TYPE max
, min
;
3417 if (HONOR_INFINITIES (type
))
3420 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3423 real_maxval (&min
, 1, TYPE_MODE (type
));
3424 return build_real (type
, min
);
3428 gcc_assert (INTEGRAL_TYPE_P (type
));
3429 return TYPE_MIN_VALUE (type
);
3433 if (SCALAR_FLOAT_TYPE_P (type
))
3435 REAL_VALUE_TYPE max
;
3436 if (HONOR_INFINITIES (type
))
3439 real_maxval (&max
, 0, TYPE_MODE (type
));
3440 return build_real (type
, max
);
3444 gcc_assert (INTEGRAL_TYPE_P (type
));
3445 return TYPE_MAX_VALUE (type
);
3453 /* Return alignment to be assumed for var in CLAUSE, which should be
3454 OMP_CLAUSE_ALIGNED. */
3457 omp_clause_aligned_alignment (tree clause
)
3459 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3460 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3462 /* Otherwise return implementation defined alignment. */
3463 unsigned int al
= 1;
3464 machine_mode mode
, vmode
;
3465 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3467 vs
= 1 << floor_log2 (vs
);
3468 static enum mode_class classes
[]
3469 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3470 for (int i
= 0; i
< 4; i
+= 2)
3471 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3473 mode
= GET_MODE_WIDER_MODE (mode
))
3475 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3476 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3479 && GET_MODE_SIZE (vmode
) < vs
3480 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3481 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3483 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3484 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3486 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3487 / GET_MODE_SIZE (mode
));
3488 if (TYPE_MODE (type
) != vmode
)
3490 if (TYPE_ALIGN_UNIT (type
) > al
)
3491 al
= TYPE_ALIGN_UNIT (type
);
3493 return build_int_cst (integer_type_node
, al
);
3496 /* Return maximum possible vectorization factor for the target. */
3503 || !flag_tree_loop_optimize
3504 || (!flag_tree_loop_vectorize
3505 && (global_options_set
.x_flag_tree_loop_vectorize
3506 || global_options_set
.x_flag_tree_vectorize
)))
3509 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3512 vs
= 1 << floor_log2 (vs
);
3515 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
3516 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
3517 return GET_MODE_NUNITS (vqimode
);
3521 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3525 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
3526 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
3530 max_vf
= omp_max_vf ();
3533 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3534 OMP_CLAUSE_SAFELEN
);
3535 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3537 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3539 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3543 idx
= create_tmp_var (unsigned_type_node
);
3544 lane
= create_tmp_var (unsigned_type_node
);
3550 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3551 tree avar
= create_tmp_var_raw (atype
);
3552 if (TREE_ADDRESSABLE (new_var
))
3553 TREE_ADDRESSABLE (avar
) = 1;
3554 DECL_ATTRIBUTES (avar
)
3555 = tree_cons (get_identifier ("omp simd array"), NULL
,
3556 DECL_ATTRIBUTES (avar
));
3557 gimple_add_tmp_var (avar
);
3558 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3559 NULL_TREE
, NULL_TREE
);
3560 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3561 NULL_TREE
, NULL_TREE
);
3562 if (DECL_P (new_var
))
3564 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3565 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3570 /* Helper function of lower_rec_input_clauses. For a reference
3571 in simd reduction, add an underlying variable it will reference. */
3574 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3576 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3577 if (TREE_CONSTANT (z
))
3579 const char *name
= NULL
;
3580 if (DECL_NAME (new_vard
))
3581 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3583 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3584 gimple_add_tmp_var (z
);
3585 TREE_ADDRESSABLE (z
) = 1;
3586 z
= build_fold_addr_expr_loc (loc
, z
);
3587 gimplify_assign (new_vard
, z
, ilist
);
3591 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3592 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3593 private variables. Initialization statements go in ILIST, while calls
3594 to destructors go in DLIST. */
3597 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3598 omp_context
*ctx
, struct omp_for_data
*fd
)
3600 tree c
, dtor
, copyin_seq
, x
, ptr
;
3601 bool copyin_by_ref
= false;
3602 bool lastprivate_firstprivate
= false;
3603 bool reduction_omp_orig_ref
= false;
3605 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3606 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3608 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3609 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3610 gimple_seq llist
[2] = { NULL
, NULL
};
3614 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3615 with data sharing clauses referencing variable sized vars. That
3616 is unnecessarily hard to support and very unlikely to result in
3617 vectorized code anyway. */
3619 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3620 switch (OMP_CLAUSE_CODE (c
))
3622 case OMP_CLAUSE_LINEAR
:
3623 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3626 case OMP_CLAUSE_REDUCTION
:
3627 case OMP_CLAUSE_PRIVATE
:
3628 case OMP_CLAUSE_FIRSTPRIVATE
:
3629 case OMP_CLAUSE_LASTPRIVATE
:
3630 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3637 /* Do all the fixed sized types in the first pass, and the variable sized
3638 types in the second pass. This makes sure that the scalar arguments to
3639 the variable sized types are processed before we use them in the
3640 variable sized operations. */
3641 for (pass
= 0; pass
< 2; ++pass
)
3643 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3645 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3648 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3652 case OMP_CLAUSE_PRIVATE
:
3653 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3656 case OMP_CLAUSE_SHARED
:
3657 /* Ignore shared directives in teams construct. */
3658 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3660 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3662 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3665 case OMP_CLAUSE_FIRSTPRIVATE
:
3666 case OMP_CLAUSE_COPYIN
:
3667 case OMP_CLAUSE_LINEAR
:
3669 case OMP_CLAUSE_REDUCTION
:
3670 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3671 reduction_omp_orig_ref
= true;
3673 case OMP_CLAUSE__LOOPTEMP_
:
3674 /* Handle _looptemp_ clauses only on parallel. */
3678 case OMP_CLAUSE_LASTPRIVATE
:
3679 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3681 lastprivate_firstprivate
= true;
3685 /* Even without corresponding firstprivate, if
3686 decl is Fortran allocatable, it needs outer var
3689 && lang_hooks
.decls
.omp_private_outer_ref
3690 (OMP_CLAUSE_DECL (c
)))
3691 lastprivate_firstprivate
= true;
3693 case OMP_CLAUSE_ALIGNED
:
3696 var
= OMP_CLAUSE_DECL (c
);
3697 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3698 && !is_global_var (var
))
3700 new_var
= maybe_lookup_decl (var
, ctx
);
3701 if (new_var
== NULL_TREE
)
3702 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3703 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3704 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3705 omp_clause_aligned_alignment (c
));
3706 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3707 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3708 gimplify_and_add (x
, ilist
);
3710 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3711 && is_global_var (var
))
3713 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3714 new_var
= lookup_decl (var
, ctx
);
3715 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3716 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3717 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3718 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3719 omp_clause_aligned_alignment (c
));
3720 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3721 x
= create_tmp_var (ptype
);
3722 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3723 gimplify_and_add (t
, ilist
);
3724 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3725 SET_DECL_VALUE_EXPR (new_var
, t
);
3726 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3733 new_var
= var
= OMP_CLAUSE_DECL (c
);
3734 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3735 new_var
= lookup_decl (var
, ctx
);
3737 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3742 else if (is_variable_sized (var
))
3744 /* For variable sized types, we need to allocate the
3745 actual storage here. Call alloca and store the
3746 result in the pointer decl that we created elsewhere. */
3750 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3755 ptr
= DECL_VALUE_EXPR (new_var
);
3756 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3757 ptr
= TREE_OPERAND (ptr
, 0);
3758 gcc_assert (DECL_P (ptr
));
3759 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3761 /* void *tmp = __builtin_alloca */
3762 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3763 stmt
= gimple_build_call (atmp
, 1, x
);
3764 tmp
= create_tmp_var_raw (ptr_type_node
);
3765 gimple_add_tmp_var (tmp
);
3766 gimple_call_set_lhs (stmt
, tmp
);
3768 gimple_seq_add_stmt (ilist
, stmt
);
3770 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3771 gimplify_assign (ptr
, x
, ilist
);
3774 else if (is_reference (var
))
3776 /* For references that are being privatized for Fortran,
3777 allocate new backing storage for the new pointer
3778 variable. This allows us to avoid changing all the
3779 code that expects a pointer to something that expects
3780 a direct variable. */
3784 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3785 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3787 x
= build_receiver_ref (var
, false, ctx
);
3788 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3790 else if (TREE_CONSTANT (x
))
3792 /* For reduction in SIMD loop, defer adding the
3793 initialization of the reference, because if we decide
3794 to use SIMD array for it, the initilization could cause
3796 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3800 const char *name
= NULL
;
3801 if (DECL_NAME (var
))
3802 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3804 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3806 gimple_add_tmp_var (x
);
3807 TREE_ADDRESSABLE (x
) = 1;
3808 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3813 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3814 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3819 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3820 gimplify_assign (new_var
, x
, ilist
);
3823 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3825 else if (c_kind
== OMP_CLAUSE_REDUCTION
3826 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3834 switch (OMP_CLAUSE_CODE (c
))
3836 case OMP_CLAUSE_SHARED
:
3837 /* Ignore shared directives in teams construct. */
3838 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3840 /* Shared global vars are just accessed directly. */
3841 if (is_global_var (new_var
))
3843 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3844 needs to be delayed until after fixup_child_record_type so
3845 that we get the correct type during the dereference. */
3846 by_ref
= use_pointer_for_field (var
, ctx
);
3847 x
= build_receiver_ref (var
, by_ref
, ctx
);
3848 SET_DECL_VALUE_EXPR (new_var
, x
);
3849 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3851 /* ??? If VAR is not passed by reference, and the variable
3852 hasn't been initialized yet, then we'll get a warning for
3853 the store into the omp_data_s structure. Ideally, we'd be
3854 able to notice this and not store anything at all, but
3855 we're generating code too early. Suppress the warning. */
3857 TREE_NO_WARNING (var
) = 1;
3860 case OMP_CLAUSE_LASTPRIVATE
:
3861 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3865 case OMP_CLAUSE_PRIVATE
:
3866 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3867 x
= build_outer_var_ref (var
, ctx
);
3868 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3870 if (is_task_ctx (ctx
))
3871 x
= build_receiver_ref (var
, false, ctx
);
3873 x
= build_outer_var_ref (var
, ctx
);
3879 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3882 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3883 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3884 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3885 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3886 idx
, lane
, ivar
, lvar
))
3889 x
= lang_hooks
.decls
.omp_clause_default_ctor
3890 (c
, unshare_expr (ivar
), x
);
3892 gimplify_and_add (x
, &llist
[0]);
3895 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3898 gimple_seq tseq
= NULL
;
3901 gimplify_stmt (&dtor
, &tseq
);
3902 gimple_seq_add_seq (&llist
[1], tseq
);
3909 gimplify_and_add (nx
, ilist
);
3913 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3916 gimple_seq tseq
= NULL
;
3919 gimplify_stmt (&dtor
, &tseq
);
3920 gimple_seq_add_seq (dlist
, tseq
);
3924 case OMP_CLAUSE_LINEAR
:
3925 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3926 goto do_firstprivate
;
3927 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3930 x
= build_outer_var_ref (var
, ctx
);
3933 case OMP_CLAUSE_FIRSTPRIVATE
:
3934 if (is_task_ctx (ctx
))
3936 if (is_reference (var
) || is_variable_sized (var
))
3938 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3940 || use_pointer_for_field (var
, NULL
))
3942 x
= build_receiver_ref (var
, false, ctx
);
3943 SET_DECL_VALUE_EXPR (new_var
, x
);
3944 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3949 x
= build_outer_var_ref (var
, ctx
);
3952 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3953 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3955 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3956 tree stept
= TREE_TYPE (t
);
3957 tree ct
= find_omp_clause (clauses
,
3958 OMP_CLAUSE__LOOPTEMP_
);
3960 tree l
= OMP_CLAUSE_DECL (ct
);
3961 tree n1
= fd
->loop
.n1
;
3962 tree step
= fd
->loop
.step
;
3963 tree itype
= TREE_TYPE (l
);
3964 if (POINTER_TYPE_P (itype
))
3965 itype
= signed_type_for (itype
);
3966 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3967 if (TYPE_UNSIGNED (itype
)
3968 && fd
->loop
.cond_code
== GT_EXPR
)
3969 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3970 fold_build1 (NEGATE_EXPR
, itype
, l
),
3971 fold_build1 (NEGATE_EXPR
,
3974 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3975 t
= fold_build2 (MULT_EXPR
, stept
,
3976 fold_convert (stept
, l
), t
);
3978 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3980 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3982 gimplify_and_add (x
, ilist
);
3986 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3987 x
= fold_build2 (POINTER_PLUS_EXPR
,
3988 TREE_TYPE (x
), x
, t
);
3990 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3993 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3994 || TREE_ADDRESSABLE (new_var
))
3995 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3996 idx
, lane
, ivar
, lvar
))
3998 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
4000 tree iv
= create_tmp_var (TREE_TYPE (new_var
));
4001 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
4002 gimplify_and_add (x
, ilist
);
4003 gimple_stmt_iterator gsi
4004 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4006 = gimple_build_assign (unshare_expr (lvar
), iv
);
4007 gsi_insert_before_without_update (&gsi
, g
,
4009 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
4010 enum tree_code code
= PLUS_EXPR
;
4011 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
4012 code
= POINTER_PLUS_EXPR
;
4013 g
= gimple_build_assign (iv
, code
, iv
, t
);
4014 gsi_insert_before_without_update (&gsi
, g
,
4018 x
= lang_hooks
.decls
.omp_clause_copy_ctor
4019 (c
, unshare_expr (ivar
), x
);
4020 gimplify_and_add (x
, &llist
[0]);
4021 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4024 gimple_seq tseq
= NULL
;
4027 gimplify_stmt (&dtor
, &tseq
);
4028 gimple_seq_add_seq (&llist
[1], tseq
);
4033 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
4034 gimplify_and_add (x
, ilist
);
4037 case OMP_CLAUSE__LOOPTEMP_
:
4038 gcc_assert (is_parallel_ctx (ctx
));
4039 x
= build_outer_var_ref (var
, ctx
);
4040 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
4041 gimplify_and_add (x
, ilist
);
4044 case OMP_CLAUSE_COPYIN
:
4045 by_ref
= use_pointer_for_field (var
, NULL
);
4046 x
= build_receiver_ref (var
, by_ref
, ctx
);
4047 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
4048 append_to_statement_list (x
, ©in_seq
);
4049 copyin_by_ref
|= by_ref
;
4052 case OMP_CLAUSE_REDUCTION
:
4053 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4055 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4057 x
= build_outer_var_ref (var
, ctx
);
4059 if (is_reference (var
)
4060 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4062 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4063 SET_DECL_VALUE_EXPR (placeholder
, x
);
4064 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4065 tree new_vard
= new_var
;
4066 if (is_reference (var
))
4068 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4069 new_vard
= TREE_OPERAND (new_var
, 0);
4070 gcc_assert (DECL_P (new_vard
));
4073 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4074 idx
, lane
, ivar
, lvar
))
4076 if (new_vard
== new_var
)
4078 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
4079 SET_DECL_VALUE_EXPR (new_var
, ivar
);
4083 SET_DECL_VALUE_EXPR (new_vard
,
4084 build_fold_addr_expr (ivar
));
4085 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4087 x
= lang_hooks
.decls
.omp_clause_default_ctor
4088 (c
, unshare_expr (ivar
),
4089 build_outer_var_ref (var
, ctx
));
4091 gimplify_and_add (x
, &llist
[0]);
4092 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4094 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4095 lower_omp (&tseq
, ctx
);
4096 gimple_seq_add_seq (&llist
[0], tseq
);
4098 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4099 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4100 lower_omp (&tseq
, ctx
);
4101 gimple_seq_add_seq (&llist
[1], tseq
);
4102 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4103 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4104 if (new_vard
== new_var
)
4105 SET_DECL_VALUE_EXPR (new_var
, lvar
);
4107 SET_DECL_VALUE_EXPR (new_vard
,
4108 build_fold_addr_expr (lvar
));
4109 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4114 gimplify_stmt (&dtor
, &tseq
);
4115 gimple_seq_add_seq (&llist
[1], tseq
);
4119 /* If this is a reference to constant size reduction var
4120 with placeholder, we haven't emitted the initializer
4121 for it because it is undesirable if SIMD arrays are used.
4122 But if they aren't used, we need to emit the deferred
4123 initialization now. */
4124 else if (is_reference (var
) && is_simd
)
4125 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4126 x
= lang_hooks
.decls
.omp_clause_default_ctor
4127 (c
, unshare_expr (new_var
),
4128 build_outer_var_ref (var
, ctx
));
4130 gimplify_and_add (x
, ilist
);
4131 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4133 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4134 lower_omp (&tseq
, ctx
);
4135 gimple_seq_add_seq (ilist
, tseq
);
4137 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4140 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4141 lower_omp (&tseq
, ctx
);
4142 gimple_seq_add_seq (dlist
, tseq
);
4143 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4145 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4150 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
4151 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
4152 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4154 /* reduction(-:var) sums up the partial results, so it
4155 acts identically to reduction(+:var). */
4156 if (code
== MINUS_EXPR
)
4159 tree new_vard
= new_var
;
4160 if (is_simd
&& is_reference (var
))
4162 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4163 new_vard
= TREE_OPERAND (new_var
, 0);
4164 gcc_assert (DECL_P (new_vard
));
4167 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4168 idx
, lane
, ivar
, lvar
))
4170 tree ref
= build_outer_var_ref (var
, ctx
);
4172 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
4174 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
4175 ref
= build_outer_var_ref (var
, ctx
);
4176 gimplify_assign (ref
, x
, &llist
[1]);
4178 if (new_vard
!= new_var
)
4180 SET_DECL_VALUE_EXPR (new_vard
,
4181 build_fold_addr_expr (lvar
));
4182 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4187 if (is_reference (var
) && is_simd
)
4188 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4189 gimplify_assign (new_var
, x
, ilist
);
4192 tree ref
= build_outer_var_ref (var
, ctx
);
4194 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4195 ref
= build_outer_var_ref (var
, ctx
);
4196 gimplify_assign (ref
, x
, dlist
);
4210 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
4211 /* Don't want uninit warnings on simduid, it is always uninitialized,
4212 but we use it not for the value, but for the DECL_UID only. */
4213 TREE_NO_WARNING (uid
) = 1;
4215 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
4216 gimple_call_set_lhs (g
, lane
);
4217 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4218 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
4219 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
4220 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
4221 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4222 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4223 g
= gimple_build_assign (lane
, INTEGER_CST
,
4224 build_int_cst (unsigned_type_node
, 0));
4225 gimple_seq_add_stmt (ilist
, g
);
4226 for (int i
= 0; i
< 2; i
++)
4229 tree vf
= create_tmp_var (unsigned_type_node
);
4230 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
4231 gimple_call_set_lhs (g
, vf
);
4232 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
4233 gimple_seq_add_stmt (seq
, g
);
4234 tree t
= build_int_cst (unsigned_type_node
, 0);
4235 g
= gimple_build_assign (idx
, INTEGER_CST
, t
);
4236 gimple_seq_add_stmt (seq
, g
);
4237 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
4238 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
4239 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
4240 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
4241 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
4242 gimple_seq_add_seq (seq
, llist
[i
]);
4243 t
= build_int_cst (unsigned_type_node
, 1);
4244 g
= gimple_build_assign (idx
, PLUS_EXPR
, idx
, t
);
4245 gimple_seq_add_stmt (seq
, g
);
4246 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
4247 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
4248 gimple_seq_add_stmt (seq
, g
);
4249 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
4253 /* The copyin sequence is not to be executed by the main thread, since
4254 that would result in self-copies. Perhaps not visible to scalars,
4255 but it certainly is to C++ operator=. */
4258 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
4260 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
4261 build_int_cst (TREE_TYPE (x
), 0));
4262 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
4263 gimplify_and_add (x
, ilist
);
4266 /* If any copyin variable is passed by reference, we must ensure the
4267 master thread doesn't modify it before it is copied over in all
4268 threads. Similarly for variables in both firstprivate and
4269 lastprivate clauses we need to ensure the lastprivate copying
4270 happens after firstprivate copying in all threads. And similarly
4271 for UDRs if initializer expression refers to omp_orig. */
4272 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
4274 /* Don't add any barrier for #pragma omp simd or
4275 #pragma omp distribute. */
4276 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
4277 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
4278 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
4281 /* If max_vf is non-zero, then we can use only a vectorization factor
4282 up to the max_vf we chose. So stick it into the safelen clause. */
4285 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
4286 OMP_CLAUSE_SAFELEN
);
4288 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
4289 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
4292 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
4293 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
4295 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4296 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4302 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4303 both parallel and workshare constructs. PREDICATE may be NULL if it's
4307 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
4310 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
4311 bool par_clauses
= false;
4312 tree simduid
= NULL
, lastlane
= NULL
;
4314 /* Early exit if there are no lastprivate or linear clauses. */
4315 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
4316 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
4317 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
4318 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
4320 if (clauses
== NULL
)
4322 /* If this was a workshare clause, see if it had been combined
4323 with its parallel. In that case, look for the clauses on the
4324 parallel statement itself. */
4325 if (is_parallel_ctx (ctx
))
4329 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4332 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4333 OMP_CLAUSE_LASTPRIVATE
);
4334 if (clauses
== NULL
)
4342 tree label_true
, arm1
, arm2
;
4344 label
= create_artificial_label (UNKNOWN_LOCATION
);
4345 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
4346 arm1
= TREE_OPERAND (predicate
, 0);
4347 arm2
= TREE_OPERAND (predicate
, 1);
4348 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4349 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4350 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
4352 gimple_seq_add_stmt (stmt_list
, stmt
);
4353 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
4356 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4357 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4359 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
4361 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
4364 for (c
= clauses
; c
;)
4367 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4369 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4370 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4371 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
4373 var
= OMP_CLAUSE_DECL (c
);
4374 new_var
= lookup_decl (var
, ctx
);
4376 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
4378 tree val
= DECL_VALUE_EXPR (new_var
);
4379 if (TREE_CODE (val
) == ARRAY_REF
4380 && VAR_P (TREE_OPERAND (val
, 0))
4381 && lookup_attribute ("omp simd array",
4382 DECL_ATTRIBUTES (TREE_OPERAND (val
,
4385 if (lastlane
== NULL
)
4387 lastlane
= create_tmp_var (unsigned_type_node
);
4389 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
4391 TREE_OPERAND (val
, 1));
4392 gimple_call_set_lhs (g
, lastlane
);
4393 gimple_seq_add_stmt (stmt_list
, g
);
4395 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
4396 TREE_OPERAND (val
, 0), lastlane
,
4397 NULL_TREE
, NULL_TREE
);
4401 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4402 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
4404 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
4405 gimple_seq_add_seq (stmt_list
,
4406 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
4407 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
4409 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4410 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
4412 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
4413 gimple_seq_add_seq (stmt_list
,
4414 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
4415 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
4418 x
= build_outer_var_ref (var
, ctx
);
4419 if (is_reference (var
))
4420 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4421 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
4422 gimplify_and_add (x
, stmt_list
);
4424 c
= OMP_CLAUSE_CHAIN (c
);
4425 if (c
== NULL
&& !par_clauses
)
4427 /* If this was a workshare clause, see if it had been combined
4428 with its parallel. In that case, continue looking for the
4429 clauses also on the parallel statement itself. */
4430 if (is_parallel_ctx (ctx
))
4434 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4437 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4438 OMP_CLAUSE_LASTPRIVATE
);
4444 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
4448 oacc_lower_reduction_var_helper (gimple_seq
*stmt_seqp
, omp_context
*ctx
,
4449 tree tid
, tree var
, tree new_var
)
4451 /* The atomic add at the end of the sum creates unnecessary
4452 write contention on accelerators. To work around this,
4453 create an array to store the partial reductions. Later, in
4454 lower_omp_for (for openacc), the values of array will be
4457 tree t
= NULL_TREE
, array
, x
;
4458 tree type
= get_base_type (var
);
4461 /* Now insert the partial reductions into the array. */
4463 /* Find the reduction array. */
4465 tree ptype
= build_pointer_type (type
);
4467 t
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
), ctx
);
4468 t
= build_receiver_ref (t
, false, ctx
->outer
);
4470 array
= create_tmp_var (ptype
);
4471 gimplify_assign (array
, t
, stmt_seqp
);
4473 tree ptr
= create_tmp_var (TREE_TYPE (array
));
4475 /* Find the reduction array. */
4477 /* testing a unary conversion. */
4478 tree offset
= create_tmp_var (sizetype
);
4479 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
),
4481 t
= create_tmp_var (sizetype
);
4482 gimplify_assign (t
, unshare_expr (fold_build1 (NOP_EXPR
, sizetype
, tid
)),
4484 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, t
);
4485 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4487 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4488 of adding sizeof(var) to the array? */
4489 ptr
= create_tmp_var (ptype
);
4490 stmt
= gimple_build_assign (unshare_expr (ptr
), POINTER_PLUS_EXPR
, array
,
4492 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4494 /* Move the local sum to gfc$sum[i]. */
4495 x
= unshare_expr (build_simple_mem_ref (ptr
));
4496 stmt
= gimplify_assign (x
, new_var
, stmt_seqp
);
4499 /* Generate code to implement the REDUCTION clauses. */
4502 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
4504 gimple_seq sub_seq
= NULL
;
4506 tree x
, c
, tid
= NULL_TREE
;
4509 /* SIMD reductions are handled in lower_rec_input_clauses. */
4510 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4511 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4514 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4515 update in that case, otherwise use a lock. */
4516 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
4517 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
4519 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4521 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4531 /* Initialize thread info for OpenACC. */
4532 if (is_gimple_omp_oacc (ctx
->stmt
))
4534 /* Get the current thread id. */
4535 tree call
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
4536 tid
= create_tmp_var (TREE_TYPE (TREE_TYPE (call
)));
4537 gimple stmt
= gimple_build_call (call
, 0);
4538 gimple_call_set_lhs (stmt
, tid
);
4539 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4542 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4544 tree var
, ref
, new_var
;
4545 enum tree_code code
;
4546 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4548 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
4551 var
= OMP_CLAUSE_DECL (c
);
4552 new_var
= lookup_decl (var
, ctx
);
4553 if (is_reference (var
))
4554 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4555 ref
= build_outer_var_ref (var
, ctx
);
4556 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4558 /* reduction(-:var) sums up the partial results, so it acts
4559 identically to reduction(+:var). */
4560 if (code
== MINUS_EXPR
)
4563 if (is_gimple_omp_oacc (ctx
->stmt
))
4565 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
));
4567 oacc_lower_reduction_var_helper (stmt_seqp
, ctx
, tid
, var
, new_var
);
4569 else if (count
== 1)
4571 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
4573 addr
= save_expr (addr
);
4574 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
4575 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
4576 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
4577 gimplify_and_add (x
, stmt_seqp
);
4580 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4582 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4584 if (is_reference (var
)
4585 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4587 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
4588 SET_DECL_VALUE_EXPR (placeholder
, ref
);
4589 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4590 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
4591 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
4592 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4593 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
4597 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4598 ref
= build_outer_var_ref (var
, ctx
);
4599 gimplify_assign (ref
, x
, &sub_seq
);
4603 if (is_gimple_omp_oacc (ctx
->stmt
))
4606 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4608 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4610 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4612 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4614 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4618 /* Generate code to implement the COPYPRIVATE clauses. */
4621 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4626 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4628 tree var
, new_var
, ref
, x
;
4630 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4632 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4635 var
= OMP_CLAUSE_DECL (c
);
4636 by_ref
= use_pointer_for_field (var
, NULL
);
4638 ref
= build_sender_ref (var
, ctx
);
4639 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4642 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4643 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4645 gimplify_assign (ref
, x
, slist
);
4647 ref
= build_receiver_ref (var
, false, ctx
);
4650 ref
= fold_convert_loc (clause_loc
,
4651 build_pointer_type (TREE_TYPE (new_var
)),
4653 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4655 if (is_reference (var
))
4657 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4658 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4659 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4661 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4662 gimplify_and_add (x
, rlist
);
4667 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4668 and REDUCTION from the sender (aka parent) side. */
4671 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4676 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4678 tree val
, ref
, x
, var
;
4679 bool by_ref
, do_in
= false, do_out
= false;
4680 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4682 switch (OMP_CLAUSE_CODE (c
))
4684 case OMP_CLAUSE_PRIVATE
:
4685 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4688 case OMP_CLAUSE_FIRSTPRIVATE
:
4689 case OMP_CLAUSE_COPYIN
:
4690 case OMP_CLAUSE_LASTPRIVATE
:
4691 case OMP_CLAUSE_REDUCTION
:
4692 case OMP_CLAUSE__LOOPTEMP_
:
4698 val
= OMP_CLAUSE_DECL (c
);
4699 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4701 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4702 && is_global_var (var
))
4704 if (is_variable_sized (val
))
4706 by_ref
= use_pointer_for_field (val
, NULL
);
4708 switch (OMP_CLAUSE_CODE (c
))
4710 case OMP_CLAUSE_PRIVATE
:
4711 case OMP_CLAUSE_FIRSTPRIVATE
:
4712 case OMP_CLAUSE_COPYIN
:
4713 case OMP_CLAUSE__LOOPTEMP_
:
4717 case OMP_CLAUSE_LASTPRIVATE
:
4718 if (by_ref
|| is_reference (val
))
4720 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4727 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4732 case OMP_CLAUSE_REDUCTION
:
4734 do_out
= !(by_ref
|| is_reference (val
));
4743 ref
= build_sender_ref (val
, ctx
);
4744 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4745 gimplify_assign (ref
, x
, ilist
);
4746 if (is_task_ctx (ctx
))
4747 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4752 ref
= build_sender_ref (val
, ctx
);
4753 gimplify_assign (var
, ref
, olist
);
4758 /* Generate code to implement SHARED from the sender (aka parent)
4759 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4760 list things that got automatically shared. */
4763 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4765 tree var
, ovar
, nvar
, f
, x
, record_type
;
4767 if (ctx
->record_type
== NULL
)
4770 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4771 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4773 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4774 nvar
= maybe_lookup_decl (ovar
, ctx
);
4775 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4778 /* If CTX is a nested parallel directive. Find the immediately
4779 enclosing parallel or workshare construct that contains a
4780 mapping for OVAR. */
4781 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4783 if (use_pointer_for_field (ovar
, ctx
))
4785 x
= build_sender_ref (ovar
, ctx
);
4786 var
= build_fold_addr_expr (var
);
4787 gimplify_assign (x
, var
, ilist
);
4791 x
= build_sender_ref (ovar
, ctx
);
4792 gimplify_assign (x
, var
, ilist
);
4794 if (!TREE_READONLY (var
)
4795 /* We don't need to receive a new reference to a result
4796 or parm decl. In fact we may not store to it as we will
4797 invalidate any pending RSO and generate wrong gimple
4799 && !((TREE_CODE (var
) == RESULT_DECL
4800 || TREE_CODE (var
) == PARM_DECL
)
4801 && DECL_BY_REFERENCE (var
)))
4803 x
= build_sender_ref (ovar
, ctx
);
4804 gimplify_assign (var
, x
, olist
);
4811 /* A convenience function to build an empty GIMPLE_COND with just the
4815 gimple_build_cond_empty (tree cond
)
4817 enum tree_code pred_code
;
4820 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4821 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4825 /* Build the function calls to GOMP_parallel_start etc to actually
4826 generate the parallel operation. REGION is the parallel region
4827 being expanded. BB is the block where to insert the code. WS_ARGS
4828 will be set if this is a call to a combined parallel+workshare
4829 construct, it contains the list of additional arguments needed by
4830 the workshare construct. */
4833 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4834 gomp_parallel
*entry_stmt
,
4835 vec
<tree
, va_gc
> *ws_args
)
4837 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4838 gimple_stmt_iterator gsi
;
4840 enum built_in_function start_ix
;
4842 location_t clause_loc
;
4843 vec
<tree
, va_gc
> *args
;
4845 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4847 /* Determine what flavor of GOMP_parallel we will be
4849 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4850 if (is_combined_parallel (region
))
4852 switch (region
->inner
->type
)
4854 case GIMPLE_OMP_FOR
:
4855 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4856 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4857 + (region
->inner
->sched_kind
4858 == OMP_CLAUSE_SCHEDULE_RUNTIME
4859 ? 3 : region
->inner
->sched_kind
));
4860 start_ix
= (enum built_in_function
)start_ix2
;
4862 case GIMPLE_OMP_SECTIONS
:
4863 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4870 /* By default, the value of NUM_THREADS is zero (selected at run time)
4871 and there is no conditional. */
4873 val
= build_int_cst (unsigned_type_node
, 0);
4874 flags
= build_int_cst (unsigned_type_node
, 0);
4876 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4878 cond
= OMP_CLAUSE_IF_EXPR (c
);
4880 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4883 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4884 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4887 clause_loc
= gimple_location (entry_stmt
);
4889 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4891 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4893 /* Ensure 'val' is of the correct type. */
4894 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4896 /* If we found the clause 'if (cond)', build either
4897 (cond != 0) or (cond ? val : 1u). */
4900 cond
= gimple_boolify (cond
);
4902 if (integer_zerop (val
))
4903 val
= fold_build2_loc (clause_loc
,
4904 EQ_EXPR
, unsigned_type_node
, cond
,
4905 build_int_cst (TREE_TYPE (cond
), 0));
4908 basic_block cond_bb
, then_bb
, else_bb
;
4909 edge e
, e_then
, e_else
;
4910 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4912 tmp_var
= create_tmp_var (TREE_TYPE (val
));
4913 if (gimple_in_ssa_p (cfun
))
4915 tmp_then
= make_ssa_name (tmp_var
);
4916 tmp_else
= make_ssa_name (tmp_var
);
4917 tmp_join
= make_ssa_name (tmp_var
);
4926 e
= split_block_after_labels (bb
);
4931 then_bb
= create_empty_bb (cond_bb
);
4932 else_bb
= create_empty_bb (then_bb
);
4933 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4934 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4936 stmt
= gimple_build_cond_empty (cond
);
4937 gsi
= gsi_start_bb (cond_bb
);
4938 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4940 gsi
= gsi_start_bb (then_bb
);
4941 stmt
= gimple_build_assign (tmp_then
, val
);
4942 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4944 gsi
= gsi_start_bb (else_bb
);
4945 stmt
= gimple_build_assign
4946 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4947 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4949 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4950 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4951 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4952 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4953 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4954 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4956 if (gimple_in_ssa_p (cfun
))
4958 gphi
*phi
= create_phi_node (tmp_join
, bb
);
4959 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4960 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4966 gsi
= gsi_start_bb (bb
);
4967 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4968 false, GSI_CONTINUE_LINKING
);
4971 gsi
= gsi_last_bb (bb
);
4972 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4974 t1
= null_pointer_node
;
4976 t1
= build_fold_addr_expr (t
);
4977 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4979 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4980 args
->quick_push (t2
);
4981 args
->quick_push (t1
);
4982 args
->quick_push (val
);
4984 args
->splice (*ws_args
);
4985 args
->quick_push (flags
);
4987 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4988 builtin_decl_explicit (start_ix
), args
);
4990 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4991 false, GSI_CONTINUE_LINKING
);
4994 /* Insert a function call whose name is FUNC_NAME with the information from
4995 ENTRY_STMT into the basic_block BB. */
4998 expand_cilk_for_call (basic_block bb
, gomp_parallel
*entry_stmt
,
4999 vec
<tree
, va_gc
> *ws_args
)
5002 gimple_stmt_iterator gsi
;
5003 vec
<tree
, va_gc
> *args
;
5005 gcc_assert (vec_safe_length (ws_args
) == 2);
5006 tree func_name
= (*ws_args
)[0];
5007 tree grain
= (*ws_args
)[1];
5009 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
5010 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
5011 gcc_assert (count
!= NULL_TREE
);
5012 count
= OMP_CLAUSE_OPERAND (count
, 0);
5014 gsi
= gsi_last_bb (bb
);
5015 t
= gimple_omp_parallel_data_arg (entry_stmt
);
5017 t1
= null_pointer_node
;
5019 t1
= build_fold_addr_expr (t
);
5020 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
5022 vec_alloc (args
, 4);
5023 args
->quick_push (t2
);
5024 args
->quick_push (t1
);
5025 args
->quick_push (count
);
5026 args
->quick_push (grain
);
5027 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
5029 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
5030 GSI_CONTINUE_LINKING
);
5033 /* Build the function call to GOMP_task to actually
5034 generate the task operation. BB is the block where to insert the code. */
5037 expand_task_call (basic_block bb
, gomp_task
*entry_stmt
)
5039 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
5040 gimple_stmt_iterator gsi
;
5041 location_t loc
= gimple_location (entry_stmt
);
5043 clauses
= gimple_omp_task_clauses (entry_stmt
);
5045 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
5047 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
5049 cond
= boolean_true_node
;
5051 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
5052 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
5053 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
5054 flags
= build_int_cst (unsigned_type_node
,
5055 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
5057 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
5060 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
5061 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
5062 build_int_cst (unsigned_type_node
, 2),
5063 build_int_cst (unsigned_type_node
, 0));
5064 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
5067 depend
= OMP_CLAUSE_DECL (depend
);
5069 depend
= build_int_cst (ptr_type_node
, 0);
5071 gsi
= gsi_last_bb (bb
);
5072 t
= gimple_omp_task_data_arg (entry_stmt
);
5074 t2
= null_pointer_node
;
5076 t2
= build_fold_addr_expr_loc (loc
, t
);
5077 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
5078 t
= gimple_omp_task_copy_fn (entry_stmt
);
5080 t3
= null_pointer_node
;
5082 t3
= build_fold_addr_expr_loc (loc
, t
);
5084 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
5086 gimple_omp_task_arg_size (entry_stmt
),
5087 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
5090 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5091 false, GSI_CONTINUE_LINKING
);
5095 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5096 catch handler and return it. This prevents programs from violating the
5097 structured block semantics with throws. */
5100 maybe_catch_exception (gimple_seq body
)
5105 if (!flag_exceptions
)
5108 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
5109 decl
= lang_hooks
.eh_protect_cleanup_actions ();
5111 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
5113 g
= gimple_build_eh_must_not_throw (decl
);
5114 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
5117 return gimple_seq_alloc_with_stmt (g
);
5120 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5123 vec2chain (vec
<tree
, va_gc
> *v
)
5125 tree chain
= NULL_TREE
, t
;
5128 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
5130 DECL_CHAIN (t
) = chain
;
5138 /* Remove barriers in REGION->EXIT's block. Note that this is only
5139 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5140 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5141 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5145 remove_exit_barrier (struct omp_region
*region
)
5147 gimple_stmt_iterator gsi
;
5148 basic_block exit_bb
;
5152 int any_addressable_vars
= -1;
5154 exit_bb
= region
->exit
;
5156 /* If the parallel region doesn't return, we don't have REGION->EXIT
5161 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5162 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5163 statements that can appear in between are extremely limited -- no
5164 memory operations at all. Here, we allow nothing at all, so the
5165 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5166 gsi
= gsi_last_bb (exit_bb
);
5167 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5169 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
5172 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
5174 gsi
= gsi_last_bb (e
->src
);
5175 if (gsi_end_p (gsi
))
5177 stmt
= gsi_stmt (gsi
);
5178 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
5179 && !gimple_omp_return_nowait_p (stmt
))
5181 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5182 in many cases. If there could be tasks queued, the barrier
5183 might be needed to let the tasks run before some local
5184 variable of the parallel that the task uses as shared
5185 runs out of scope. The task can be spawned either
5186 from within current function (this would be easy to check)
5187 or from some function it calls and gets passed an address
5188 of such a variable. */
5189 if (any_addressable_vars
< 0)
5191 gomp_parallel
*parallel_stmt
5192 = as_a
<gomp_parallel
*> (last_stmt (region
->entry
));
5193 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
5194 tree local_decls
, block
, decl
;
5197 any_addressable_vars
= 0;
5198 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
5199 if (TREE_ADDRESSABLE (decl
))
5201 any_addressable_vars
= 1;
5204 for (block
= gimple_block (stmt
);
5205 !any_addressable_vars
5207 && TREE_CODE (block
) == BLOCK
;
5208 block
= BLOCK_SUPERCONTEXT (block
))
5210 for (local_decls
= BLOCK_VARS (block
);
5212 local_decls
= DECL_CHAIN (local_decls
))
5213 if (TREE_ADDRESSABLE (local_decls
))
5215 any_addressable_vars
= 1;
5218 if (block
== gimple_block (parallel_stmt
))
5222 if (!any_addressable_vars
)
5223 gimple_omp_return_set_nowait (stmt
);
5229 remove_exit_barriers (struct omp_region
*region
)
5231 if (region
->type
== GIMPLE_OMP_PARALLEL
)
5232 remove_exit_barrier (region
);
5236 region
= region
->inner
;
5237 remove_exit_barriers (region
);
5238 while (region
->next
)
5240 region
= region
->next
;
5241 remove_exit_barriers (region
);
5246 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5247 calls. These can't be declared as const functions, but
5248 within one parallel body they are constant, so they can be
5249 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5250 which are declared const. Similarly for task body, except
5251 that in untied task omp_get_thread_num () can change at any task
5252 scheduling point. */
5255 optimize_omp_library_calls (gimple entry_stmt
)
5258 gimple_stmt_iterator gsi
;
5259 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5260 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
5261 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5262 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
5263 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
5264 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
5265 OMP_CLAUSE_UNTIED
) != NULL
);
5267 FOR_EACH_BB_FN (bb
, cfun
)
5268 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5270 gimple call
= gsi_stmt (gsi
);
5273 if (is_gimple_call (call
)
5274 && (decl
= gimple_call_fndecl (call
))
5275 && DECL_EXTERNAL (decl
)
5276 && TREE_PUBLIC (decl
)
5277 && DECL_INITIAL (decl
) == NULL
)
5281 if (DECL_NAME (decl
) == thr_num_id
)
5283 /* In #pragma omp task untied omp_get_thread_num () can change
5284 during the execution of the task region. */
5287 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5289 else if (DECL_NAME (decl
) == num_thr_id
)
5290 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5294 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
5295 || gimple_call_num_args (call
) != 0)
5298 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
5301 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
5302 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
5303 TREE_TYPE (TREE_TYPE (built_in
))))
5306 gimple_call_set_fndecl (call
, built_in
);
5311 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5315 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
5319 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5320 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
5323 if (TREE_CODE (t
) == ADDR_EXPR
)
5324 recompute_tree_invariant_for_addr_expr (t
);
5326 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
5330 /* Prepend TO = FROM assignment before *GSI_P. */
5333 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
5335 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
5336 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
5337 true, GSI_SAME_STMT
);
5338 gimple stmt
= gimple_build_assign (to
, from
);
5339 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
5340 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
5341 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
5343 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
5344 gimple_regimplify_operands (stmt
, &gsi
);
5348 /* Expand the OpenMP parallel or task directive starting at REGION. */
5351 expand_omp_taskreg (struct omp_region
*region
)
5353 basic_block entry_bb
, exit_bb
, new_bb
;
5354 struct function
*child_cfun
;
5355 tree child_fn
, block
, t
;
5356 gimple_stmt_iterator gsi
;
5357 gimple entry_stmt
, stmt
;
5359 vec
<tree
, va_gc
> *ws_args
;
5361 entry_stmt
= last_stmt (region
->entry
);
5362 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
5363 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
5365 entry_bb
= region
->entry
;
5366 if (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
)
5367 exit_bb
= region
->cont
;
5369 exit_bb
= region
->exit
;
5373 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
5374 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
5375 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
5378 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5379 and the inner statement contains the name of the built-in function
5381 ws_args
= region
->inner
->ws_args
;
5382 else if (is_combined_parallel (region
))
5383 ws_args
= region
->ws_args
;
5387 if (child_cfun
->cfg
)
5389 /* Due to inlining, it may happen that we have already outlined
5390 the region, in which case all we need to do is make the
5391 sub-graph unreachable and emit the parallel call. */
5392 edge entry_succ_e
, exit_succ_e
;
5394 entry_succ_e
= single_succ_edge (entry_bb
);
5396 gsi
= gsi_last_bb (entry_bb
);
5397 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
5398 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
5399 gsi_remove (&gsi
, true);
5404 exit_succ_e
= single_succ_edge (exit_bb
);
5405 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
5407 remove_edge_and_dominated_blocks (entry_succ_e
);
5411 unsigned srcidx
, dstidx
, num
;
5413 /* If the parallel region needs data sent from the parent
5414 function, then the very first statement (except possible
5415 tree profile counter updates) of the parallel body
5416 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5417 &.OMP_DATA_O is passed as an argument to the child function,
5418 we need to replace it with the argument as seen by the child
5421 In most cases, this will end up being the identity assignment
5422 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5423 a function call that has been inlined, the original PARM_DECL
5424 .OMP_DATA_I may have been converted into a different local
5425 variable. In which case, we need to keep the assignment. */
5426 if (gimple_omp_taskreg_data_arg (entry_stmt
))
5428 basic_block entry_succ_bb
5429 = single_succ_p (entry_bb
) ? single_succ (entry_bb
)
5430 : FALLTHRU_EDGE (entry_bb
)->dest
;
5432 gimple parcopy_stmt
= NULL
;
5434 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
5438 gcc_assert (!gsi_end_p (gsi
));
5439 stmt
= gsi_stmt (gsi
);
5440 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
5443 if (gimple_num_ops (stmt
) == 2)
5445 tree arg
= gimple_assign_rhs1 (stmt
);
5447 /* We're ignore the subcode because we're
5448 effectively doing a STRIP_NOPS. */
5450 if (TREE_CODE (arg
) == ADDR_EXPR
5451 && TREE_OPERAND (arg
, 0)
5452 == gimple_omp_taskreg_data_arg (entry_stmt
))
5454 parcopy_stmt
= stmt
;
5460 gcc_assert (parcopy_stmt
!= NULL
);
5461 arg
= DECL_ARGUMENTS (child_fn
);
5463 if (!gimple_in_ssa_p (cfun
))
5465 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
5466 gsi_remove (&gsi
, true);
5469 /* ?? Is setting the subcode really necessary ?? */
5470 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
5471 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
5476 /* If we are in ssa form, we must load the value from the default
5477 definition of the argument. That should not be defined now,
5478 since the argument is not used uninitialized. */
5479 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
5480 narg
= make_ssa_name (arg
, gimple_build_nop ());
5481 set_ssa_default_def (cfun
, arg
, narg
);
5482 /* ?? Is setting the subcode really necessary ?? */
5483 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
5484 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
5485 update_stmt (parcopy_stmt
);
5489 /* Declare local variables needed in CHILD_CFUN. */
5490 block
= DECL_INITIAL (child_fn
);
5491 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
5492 /* The gimplifier could record temporaries in parallel/task block
5493 rather than in containing function's local_decls chain,
5494 which would mean cgraph missed finalizing them. Do it now. */
5495 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
5496 if (TREE_CODE (t
) == VAR_DECL
5498 && !DECL_EXTERNAL (t
))
5499 varpool_node::finalize_decl (t
);
5500 DECL_SAVED_TREE (child_fn
) = NULL
;
5501 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5502 gimple_set_body (child_fn
, NULL
);
5503 TREE_USED (block
) = 1;
5505 /* Reset DECL_CONTEXT on function arguments. */
5506 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
5507 DECL_CONTEXT (t
) = child_fn
;
5509 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5510 so that it can be moved to the child function. */
5511 gsi
= gsi_last_bb (entry_bb
);
5512 stmt
= gsi_stmt (gsi
);
5513 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
5514 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
5515 e
= split_block (entry_bb
, stmt
);
5516 gsi_remove (&gsi
, true);
5519 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5520 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5523 e2
= make_edge (e
->src
, BRANCH_EDGE (entry_bb
)->dest
, EDGE_ABNORMAL
);
5524 gcc_assert (e2
->dest
== region
->exit
);
5525 remove_edge (BRANCH_EDGE (entry_bb
));
5526 set_immediate_dominator (CDI_DOMINATORS
, e2
->dest
, e
->src
);
5527 gsi
= gsi_last_bb (region
->exit
);
5528 gcc_assert (!gsi_end_p (gsi
)
5529 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5530 gsi_remove (&gsi
, true);
5533 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5536 gsi
= gsi_last_bb (exit_bb
);
5537 gcc_assert (!gsi_end_p (gsi
)
5538 && (gimple_code (gsi_stmt (gsi
))
5539 == (e2
? GIMPLE_OMP_CONTINUE
: GIMPLE_OMP_RETURN
)));
5540 stmt
= gimple_build_return (NULL
);
5541 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5542 gsi_remove (&gsi
, true);
5545 /* Move the parallel region into CHILD_CFUN. */
5547 if (gimple_in_ssa_p (cfun
))
5549 init_tree_ssa (child_cfun
);
5550 init_ssa_operands (child_cfun
);
5551 child_cfun
->gimple_df
->in_ssa_p
= true;
5555 block
= gimple_block (entry_stmt
);
5557 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
5559 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
5562 basic_block dest_bb
= e2
->dest
;
5564 make_edge (new_bb
, dest_bb
, EDGE_FALLTHRU
);
5566 set_immediate_dominator (CDI_DOMINATORS
, dest_bb
, new_bb
);
5568 /* When the OMP expansion process cannot guarantee an up-to-date
5569 loop tree arrange for the child function to fixup loops. */
5570 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5571 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
5573 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5574 num
= vec_safe_length (child_cfun
->local_decls
);
5575 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
5577 t
= (*child_cfun
->local_decls
)[srcidx
];
5578 if (DECL_CONTEXT (t
) == cfun
->decl
)
5580 if (srcidx
!= dstidx
)
5581 (*child_cfun
->local_decls
)[dstidx
] = t
;
5585 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
5587 /* Inform the callgraph about the new function. */
5588 child_cfun
->curr_properties
= cfun
->curr_properties
;
5589 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
5590 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
5591 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
5592 node
->parallelized_function
= 1;
5593 cgraph_node::add_new_function (child_fn
, true);
5595 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5596 fixed in a following pass. */
5597 push_cfun (child_cfun
);
5599 optimize_omp_library_calls (entry_stmt
);
5600 cgraph_edge::rebuild_edges ();
5602 /* Some EH regions might become dead, see PR34608. If
5603 pass_cleanup_cfg isn't the first pass to happen with the
5604 new child, these dead EH edges might cause problems.
5605 Clean them up now. */
5606 if (flag_exceptions
)
5609 bool changed
= false;
5611 FOR_EACH_BB_FN (bb
, cfun
)
5612 changed
|= gimple_purge_dead_eh_edges (bb
);
5614 cleanup_tree_cfg ();
5616 if (gimple_in_ssa_p (cfun
))
5617 update_ssa (TODO_update_ssa
);
5621 /* Emit a library call to launch the children threads. */
5623 expand_cilk_for_call (new_bb
,
5624 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5625 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5626 expand_parallel_call (region
, new_bb
,
5627 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5629 expand_task_call (new_bb
, as_a
<gomp_task
*> (entry_stmt
));
5630 if (gimple_in_ssa_p (cfun
))
5631 update_ssa (TODO_update_ssa_only_virtuals
);
5635 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5636 of the combined collapse > 1 loop constructs, generate code like:
5637 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5642 count3 = (adj + N32 - N31) / STEP3;
5643 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5648 count2 = (adj + N22 - N21) / STEP2;
5649 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5654 count1 = (adj + N12 - N11) / STEP1;
5655 count = count1 * count2 * count3;
5656 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5658 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5659 of the combined loop constructs, just initialize COUNTS array
5660 from the _looptemp_ clauses. */
5662 /* NOTE: It *could* be better to moosh all of the BBs together,
5663 creating one larger BB with all the computation and the unexpected
5664 jump at the end. I.e.
5666 bool zero3, zero2, zero1, zero;
5669 count3 = (N32 - N31) /[cl] STEP3;
5671 count2 = (N22 - N21) /[cl] STEP2;
5673 count1 = (N12 - N11) /[cl] STEP1;
5674 zero = zero3 || zero2 || zero1;
5675 count = count1 * count2 * count3;
5676 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5678 After all, we expect the zero=false, and thus we expect to have to
5679 evaluate all of the comparison expressions, so short-circuiting
5680 oughtn't be a win. Since the condition isn't protecting a
5681 denominator, we're not concerned about divide-by-zero, so we can
5682 fully evaluate count even if a numerator turned out to be wrong.
5684 It seems like putting this all together would create much better
5685 scheduling opportunities, and less pressure on the chip's branch
5689 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5690 basic_block
&entry_bb
, tree
*counts
,
5691 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5692 basic_block
&l2_dom_bb
)
5694 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5698 /* Collapsed loops need work for expansion into SSA form. */
5699 gcc_assert (!gimple_in_ssa_p (cfun
));
5701 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5702 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5704 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5705 isn't supposed to be handled, as the inner loop doesn't
5707 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5708 OMP_CLAUSE__LOOPTEMP_
);
5709 gcc_assert (innerc
);
5710 for (i
= 0; i
< fd
->collapse
; i
++)
5712 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5713 OMP_CLAUSE__LOOPTEMP_
);
5714 gcc_assert (innerc
);
5716 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5718 counts
[0] = NULL_TREE
;
5723 for (i
= 0; i
< fd
->collapse
; i
++)
5725 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5727 if (SSA_VAR_P (fd
->loop
.n2
)
5728 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5729 fold_convert (itype
, fd
->loops
[i
].n1
),
5730 fold_convert (itype
, fd
->loops
[i
].n2
)))
5731 == NULL_TREE
|| !integer_onep (t
)))
5735 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5736 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5737 true, GSI_SAME_STMT
);
5738 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5739 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5740 true, GSI_SAME_STMT
);
5741 cond_stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5742 NULL_TREE
, NULL_TREE
);
5743 gsi_insert_before (gsi
, cond_stmt
, GSI_SAME_STMT
);
5744 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
5745 expand_omp_regimplify_p
, NULL
, NULL
)
5746 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
5747 expand_omp_regimplify_p
, NULL
, NULL
))
5749 *gsi
= gsi_for_stmt (cond_stmt
);
5750 gimple_regimplify_operands (cond_stmt
, gsi
);
5752 e
= split_block (entry_bb
, cond_stmt
);
5753 if (zero_iter_bb
== NULL
)
5755 gassign
*assign_stmt
;
5756 first_zero_iter
= i
;
5757 zero_iter_bb
= create_empty_bb (entry_bb
);
5758 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5759 *gsi
= gsi_after_labels (zero_iter_bb
);
5760 assign_stmt
= gimple_build_assign (fd
->loop
.n2
,
5761 build_zero_cst (type
));
5762 gsi_insert_before (gsi
, assign_stmt
, GSI_SAME_STMT
);
5763 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5766 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5767 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5768 e
->flags
= EDGE_TRUE_VALUE
;
5769 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5770 if (l2_dom_bb
== NULL
)
5771 l2_dom_bb
= entry_bb
;
5773 *gsi
= gsi_last_bb (entry_bb
);
5776 if (POINTER_TYPE_P (itype
))
5777 itype
= signed_type_for (itype
);
5778 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5780 t
= fold_build2 (PLUS_EXPR
, itype
,
5781 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5782 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5783 fold_convert (itype
, fd
->loops
[i
].n2
));
5784 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5785 fold_convert (itype
, fd
->loops
[i
].n1
));
5786 /* ?? We could probably use CEIL_DIV_EXPR instead of
5787 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5788 generate the same code in the end because generically we
5789 don't know that the values involved must be negative for
5791 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5792 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5793 fold_build1 (NEGATE_EXPR
, itype
, t
),
5794 fold_build1 (NEGATE_EXPR
, itype
,
5795 fold_convert (itype
,
5796 fd
->loops
[i
].step
)));
5798 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5799 fold_convert (itype
, fd
->loops
[i
].step
));
5800 t
= fold_convert (type
, t
);
5801 if (TREE_CODE (t
) == INTEGER_CST
)
5805 counts
[i
] = create_tmp_reg (type
, ".count");
5806 expand_omp_build_assign (gsi
, counts
[i
], t
);
5808 if (SSA_VAR_P (fd
->loop
.n2
))
5813 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5814 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5820 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5822 V3 = N31 + (T % count3) * STEP3;
5824 V2 = N21 + (T % count2) * STEP2;
5826 V1 = N11 + T * STEP1;
5827 if this loop doesn't have an inner loop construct combined with it.
5828 If it does have an inner loop construct combined with it and the
5829 iteration count isn't known constant, store values from counts array
5830 into its _looptemp_ temporaries instead. */
5833 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5834 tree
*counts
, gimple inner_stmt
, tree startvar
)
5837 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5839 /* If fd->loop.n2 is constant, then no propagation of the counts
5840 is needed, they are constant. */
5841 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5844 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5845 ? gimple_omp_parallel_clauses (inner_stmt
)
5846 : gimple_omp_for_clauses (inner_stmt
);
5847 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5848 isn't supposed to be handled, as the inner loop doesn't
5850 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5851 gcc_assert (innerc
);
5852 for (i
= 0; i
< fd
->collapse
; i
++)
5854 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5855 OMP_CLAUSE__LOOPTEMP_
);
5856 gcc_assert (innerc
);
5859 tree tem
= OMP_CLAUSE_DECL (innerc
);
5860 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5861 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5862 false, GSI_CONTINUE_LINKING
);
5863 gassign
*stmt
= gimple_build_assign (tem
, t
);
5864 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5870 tree type
= TREE_TYPE (fd
->loop
.v
);
5871 tree tem
= create_tmp_reg (type
, ".tem");
5872 gassign
*stmt
= gimple_build_assign (tem
, startvar
);
5873 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5875 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5877 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5879 if (POINTER_TYPE_P (vtype
))
5880 itype
= signed_type_for (vtype
);
5882 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5885 t
= fold_convert (itype
, t
);
5886 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5887 fold_convert (itype
, fd
->loops
[i
].step
));
5888 if (POINTER_TYPE_P (vtype
))
5889 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5891 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5892 t
= force_gimple_operand_gsi (gsi
, t
,
5893 DECL_P (fd
->loops
[i
].v
)
5894 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5896 GSI_CONTINUE_LINKING
);
5897 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5898 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5901 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5902 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5903 false, GSI_CONTINUE_LINKING
);
5904 stmt
= gimple_build_assign (tem
, t
);
5905 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5911 /* Helper function for expand_omp_for_*. Generate code like:
5914 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5918 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5925 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5926 basic_block body_bb
)
5928 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5930 gimple_stmt_iterator gsi
;
5936 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5938 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5940 bb
= create_empty_bb (last_bb
);
5941 add_bb_to_loop (bb
, last_bb
->loop_father
);
5942 gsi
= gsi_start_bb (bb
);
5944 if (i
< fd
->collapse
- 1)
5946 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5947 e
->probability
= REG_BR_PROB_BASE
/ 8;
5949 t
= fd
->loops
[i
+ 1].n1
;
5950 t
= force_gimple_operand_gsi (&gsi
, t
,
5951 DECL_P (fd
->loops
[i
+ 1].v
)
5952 && TREE_ADDRESSABLE (fd
->loops
[i
5955 GSI_CONTINUE_LINKING
);
5956 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5957 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5962 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5964 if (POINTER_TYPE_P (vtype
))
5965 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5967 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5968 t
= force_gimple_operand_gsi (&gsi
, t
,
5969 DECL_P (fd
->loops
[i
].v
)
5970 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5971 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5972 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5973 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5977 t
= fd
->loops
[i
].n2
;
5978 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5979 false, GSI_CONTINUE_LINKING
);
5980 tree v
= fd
->loops
[i
].v
;
5981 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5982 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5983 false, GSI_CONTINUE_LINKING
);
5984 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5985 stmt
= gimple_build_cond_empty (t
);
5986 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5987 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5988 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5991 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5999 /* A subroutine of expand_omp_for. Generate code for a parallel
6000 loop with any schedule. Given parameters:
6002 for (V = N1; V cond N2; V += STEP) BODY;
6004 where COND is "<" or ">", we generate pseudocode
6006 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6007 if (more) goto L0; else goto L3;
6014 if (V cond iend) goto L1; else goto L2;
6016 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6019 If this is a combined omp parallel loop, instead of the call to
6020 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6021 If this is gimple_omp_for_combined_p loop, then instead of assigning
6022 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6023 inner GIMPLE_OMP_FOR and V += STEP; and
6024 if (V cond iend) goto L1; else goto L2; are removed.
6026 For collapsed loops, given parameters:
6028 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6029 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6030 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6033 we generate pseudocode
6035 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6040 count3 = (adj + N32 - N31) / STEP3;
6041 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6046 count2 = (adj + N22 - N21) / STEP2;
6047 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6052 count1 = (adj + N12 - N11) / STEP1;
6053 count = count1 * count2 * count3;
6058 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6059 if (more) goto L0; else goto L3;
6063 V3 = N31 + (T % count3) * STEP3;
6065 V2 = N21 + (T % count2) * STEP2;
6067 V1 = N11 + T * STEP1;
6072 if (V < iend) goto L10; else goto L2;
6075 if (V3 cond3 N32) goto L1; else goto L11;
6079 if (V2 cond2 N22) goto L1; else goto L12;
6085 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6091 expand_omp_for_generic (struct omp_region
*region
,
6092 struct omp_for_data
*fd
,
6093 enum built_in_function start_fn
,
6094 enum built_in_function next_fn
,
6097 tree type
, istart0
, iend0
, iend
;
6098 tree t
, vmain
, vback
, bias
= NULL_TREE
;
6099 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
6100 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
6101 gimple_stmt_iterator gsi
;
6102 gassign
*assign_stmt
;
6103 bool in_combined_parallel
= is_combined_parallel (region
);
6104 bool broken_loop
= region
->cont
== NULL
;
6106 tree
*counts
= NULL
;
6109 gcc_assert (!broken_loop
|| !in_combined_parallel
);
6110 gcc_assert (fd
->iter_type
== long_integer_type_node
6111 || !in_combined_parallel
);
6113 type
= TREE_TYPE (fd
->loop
.v
);
6114 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
6115 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
6116 TREE_ADDRESSABLE (istart0
) = 1;
6117 TREE_ADDRESSABLE (iend0
) = 1;
6119 /* See if we need to bias by LLONG_MIN. */
6120 if (fd
->iter_type
== long_long_unsigned_type_node
6121 && TREE_CODE (type
) == INTEGER_TYPE
6122 && !TYPE_UNSIGNED (type
))
6126 if (fd
->loop
.cond_code
== LT_EXPR
)
6129 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6133 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6136 if (TREE_CODE (n1
) != INTEGER_CST
6137 || TREE_CODE (n2
) != INTEGER_CST
6138 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
6139 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
6142 entry_bb
= region
->entry
;
6143 cont_bb
= region
->cont
;
6145 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6146 gcc_assert (broken_loop
6147 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6148 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6149 l1_bb
= single_succ (l0_bb
);
6152 l2_bb
= create_empty_bb (cont_bb
);
6153 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
6154 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6158 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6159 exit_bb
= region
->exit
;
6161 gsi
= gsi_last_bb (entry_bb
);
6163 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6164 if (fd
->collapse
> 1)
6166 int first_zero_iter
= -1;
6167 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
6169 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6170 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6171 zero_iter_bb
, first_zero_iter
,
6176 /* Some counts[i] vars might be uninitialized if
6177 some loop has zero iterations. But the body shouldn't
6178 be executed in that case, so just avoid uninit warnings. */
6179 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
6180 if (SSA_VAR_P (counts
[i
]))
6181 TREE_NO_WARNING (counts
[i
]) = 1;
6183 e
= split_block (entry_bb
, gsi_stmt (gsi
));
6185 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
6186 gsi
= gsi_last_bb (entry_bb
);
6187 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
6188 get_immediate_dominator (CDI_DOMINATORS
,
6192 if (in_combined_parallel
)
6194 /* In a combined parallel loop, emit a call to
6195 GOMP_loop_foo_next. */
6196 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6197 build_fold_addr_expr (istart0
),
6198 build_fold_addr_expr (iend0
));
6202 tree t0
, t1
, t2
, t3
, t4
;
6203 /* If this is not a combined parallel loop, emit a call to
6204 GOMP_loop_foo_start in ENTRY_BB. */
6205 t4
= build_fold_addr_expr (iend0
);
6206 t3
= build_fold_addr_expr (istart0
);
6207 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
6210 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6212 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6213 OMP_CLAUSE__LOOPTEMP_
);
6214 gcc_assert (innerc
);
6215 t0
= OMP_CLAUSE_DECL (innerc
);
6216 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6217 OMP_CLAUSE__LOOPTEMP_
);
6218 gcc_assert (innerc
);
6219 t1
= OMP_CLAUSE_DECL (innerc
);
6221 if (POINTER_TYPE_P (TREE_TYPE (t0
))
6222 && TYPE_PRECISION (TREE_TYPE (t0
))
6223 != TYPE_PRECISION (fd
->iter_type
))
6225 /* Avoid casting pointers to integer of a different size. */
6226 tree itype
= signed_type_for (type
);
6227 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
6228 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
6232 t1
= fold_convert (fd
->iter_type
, t1
);
6233 t0
= fold_convert (fd
->iter_type
, t0
);
6237 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
6238 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
6240 if (fd
->iter_type
== long_integer_type_node
)
6244 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6245 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6246 6, t0
, t1
, t2
, t
, t3
, t4
);
6249 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6250 5, t0
, t1
, t2
, t3
, t4
);
6258 /* The GOMP_loop_ull_*start functions have additional boolean
6259 argument, true for < loops and false for > loops.
6260 In Fortran, the C bool type can be different from
6261 boolean_type_node. */
6262 bfn_decl
= builtin_decl_explicit (start_fn
);
6263 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
6264 t5
= build_int_cst (c_bool_type
,
6265 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
6268 tree bfn_decl
= builtin_decl_explicit (start_fn
);
6269 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6270 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
6273 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6274 6, t5
, t0
, t1
, t2
, t3
, t4
);
6277 if (TREE_TYPE (t
) != boolean_type_node
)
6278 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6279 t
, build_int_cst (TREE_TYPE (t
), 0));
6280 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6281 true, GSI_SAME_STMT
);
6282 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6284 /* Remove the GIMPLE_OMP_FOR statement. */
6285 gsi_remove (&gsi
, true);
6287 /* Iteration setup for sequential loop goes in L0_BB. */
6288 tree startvar
= fd
->loop
.v
;
6289 tree endvar
= NULL_TREE
;
6291 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6293 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
6294 && gimple_omp_for_kind (inner_stmt
)
6295 == GF_OMP_FOR_KIND_SIMD
);
6296 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
6297 OMP_CLAUSE__LOOPTEMP_
);
6298 gcc_assert (innerc
);
6299 startvar
= OMP_CLAUSE_DECL (innerc
);
6300 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6301 OMP_CLAUSE__LOOPTEMP_
);
6302 gcc_assert (innerc
);
6303 endvar
= OMP_CLAUSE_DECL (innerc
);
6306 gsi
= gsi_start_bb (l0_bb
);
6309 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6310 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6311 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6312 t
= fold_convert (TREE_TYPE (startvar
), t
);
6313 t
= force_gimple_operand_gsi (&gsi
, t
,
6315 && TREE_ADDRESSABLE (startvar
),
6316 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6317 assign_stmt
= gimple_build_assign (startvar
, t
);
6318 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6322 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6323 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6324 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6325 t
= fold_convert (TREE_TYPE (startvar
), t
);
6326 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6327 false, GSI_CONTINUE_LINKING
);
6330 assign_stmt
= gimple_build_assign (endvar
, iend
);
6331 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6332 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
6333 assign_stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
6335 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, iend
);
6336 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6338 if (fd
->collapse
> 1)
6339 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6343 /* Code to control the increment and predicate for the sequential
6344 loop goes in the CONT_BB. */
6345 gsi
= gsi_last_bb (cont_bb
);
6346 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6347 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6348 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6349 vback
= gimple_omp_continue_control_def (cont_stmt
);
6351 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6353 if (POINTER_TYPE_P (type
))
6354 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
6356 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
6357 t
= force_gimple_operand_gsi (&gsi
, t
,
6359 && TREE_ADDRESSABLE (vback
),
6360 NULL_TREE
, true, GSI_SAME_STMT
);
6361 assign_stmt
= gimple_build_assign (vback
, t
);
6362 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6364 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6365 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
6367 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6368 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6371 /* Remove GIMPLE_OMP_CONTINUE. */
6372 gsi_remove (&gsi
, true);
6374 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6375 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
6377 /* Emit code to get the next parallel iteration in L2_BB. */
6378 gsi
= gsi_start_bb (l2_bb
);
6380 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6381 build_fold_addr_expr (istart0
),
6382 build_fold_addr_expr (iend0
));
6383 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6384 false, GSI_CONTINUE_LINKING
);
6385 if (TREE_TYPE (t
) != boolean_type_node
)
6386 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6387 t
, build_int_cst (TREE_TYPE (t
), 0));
6388 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6389 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
6392 /* Add the loop cleanup function. */
6393 gsi
= gsi_last_bb (exit_bb
);
6394 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6395 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
6396 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6397 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
6399 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
6400 gcall
*call_stmt
= gimple_build_call (t
, 0);
6401 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6402 gimple_call_set_lhs (call_stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
6403 gsi_insert_after (&gsi
, call_stmt
, GSI_SAME_STMT
);
6404 gsi_remove (&gsi
, true);
6406 /* Connect the new blocks. */
6407 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
6408 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
6414 e
= find_edge (cont_bb
, l3_bb
);
6415 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
6417 phis
= phi_nodes (l3_bb
);
6418 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
6420 gimple phi
= gsi_stmt (gsi
);
6421 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
6422 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
6426 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
6427 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
6428 e
= find_edge (cont_bb
, l1_bb
);
6429 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6434 else if (fd
->collapse
> 1)
6437 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6440 e
->flags
= EDGE_TRUE_VALUE
;
6443 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6444 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
6448 e
= find_edge (cont_bb
, l2_bb
);
6449 e
->flags
= EDGE_FALLTHRU
;
6451 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6453 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
6454 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
6455 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
6456 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
6457 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
6458 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
6459 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
6460 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
6462 struct loop
*outer_loop
= alloc_loop ();
6463 outer_loop
->header
= l0_bb
;
6464 outer_loop
->latch
= l2_bb
;
6465 add_loop (outer_loop
, l0_bb
->loop_father
);
6467 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6469 struct loop
*loop
= alloc_loop ();
6470 loop
->header
= l1_bb
;
6471 /* The loop may have multiple latches. */
6472 add_loop (loop
, outer_loop
);
6478 /* A subroutine of expand_omp_for. Generate code for a parallel
6479 loop with static schedule and no specified chunk size. Given
6482 for (V = N1; V cond N2; V += STEP) BODY;
6484 where COND is "<" or ">", we generate pseudocode
6486 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6491 if ((__typeof (V)) -1 > 0 && cond is >)
6492 n = -(adj + N2 - N1) / -STEP;
6494 n = (adj + N2 - N1) / STEP;
6497 if (threadid < tt) goto L3; else goto L4;
6502 s0 = q * threadid + tt;
6505 if (s0 >= e0) goto L2; else goto L0;
6511 if (V cond e) goto L1;
6516 expand_omp_for_static_nochunk (struct omp_region
*region
,
6517 struct omp_for_data
*fd
,
6520 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
6521 tree type
, itype
, vmain
, vback
;
6522 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
6523 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
6525 gimple_stmt_iterator gsi
;
6527 bool broken_loop
= region
->cont
== NULL
;
6528 tree
*counts
= NULL
;
6531 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6532 != GF_OMP_FOR_KIND_OACC_LOOP
)
6535 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6536 if (POINTER_TYPE_P (type
))
6537 itype
= signed_type_for (type
);
6539 entry_bb
= region
->entry
;
6540 cont_bb
= region
->cont
;
6541 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6542 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6543 gcc_assert (broken_loop
6544 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
6545 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6546 body_bb
= single_succ (seq_start_bb
);
6549 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6550 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6552 exit_bb
= region
->exit
;
6554 /* Iteration space partitioning goes in ENTRY_BB. */
6555 gsi
= gsi_last_bb (entry_bb
);
6556 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6558 if (fd
->collapse
> 1)
6560 int first_zero_iter
= -1;
6561 basic_block l2_dom_bb
= NULL
;
6563 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6564 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6565 fin_bb
, first_zero_iter
,
6569 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6570 t
= integer_one_node
;
6572 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6573 fold_convert (type
, fd
->loop
.n1
),
6574 fold_convert (type
, fd
->loop
.n2
));
6575 if (fd
->collapse
== 1
6576 && TYPE_UNSIGNED (type
)
6577 && (t
== NULL_TREE
|| !integer_onep (t
)))
6579 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6580 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6581 true, GSI_SAME_STMT
);
6582 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6583 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6584 true, GSI_SAME_STMT
);
6585 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6586 NULL_TREE
, NULL_TREE
);
6587 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6588 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6589 expand_omp_regimplify_p
, NULL
, NULL
)
6590 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6591 expand_omp_regimplify_p
, NULL
, NULL
))
6593 gsi
= gsi_for_stmt (cond_stmt
);
6594 gimple_regimplify_operands (cond_stmt
, &gsi
);
6596 ep
= split_block (entry_bb
, cond_stmt
);
6597 ep
->flags
= EDGE_TRUE_VALUE
;
6598 entry_bb
= ep
->dest
;
6599 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6600 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6601 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6602 if (gimple_in_ssa_p (cfun
))
6604 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6605 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6606 !gsi_end_p (gpi
); gsi_next (&gpi
))
6608 gphi
*phi
= gpi
.phi ();
6609 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6610 ep
, UNKNOWN_LOCATION
);
6613 gsi
= gsi_last_bb (entry_bb
);
6616 switch (gimple_omp_for_kind (fd
->for_stmt
))
6618 case GF_OMP_FOR_KIND_FOR
:
6619 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
6620 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
6622 case GF_OMP_FOR_KIND_DISTRIBUTE
:
6623 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
6624 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
6626 case GF_OMP_FOR_KIND_OACC_LOOP
:
6627 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
6628 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
6633 nthreads
= build_call_expr (nthreads
, 0);
6634 nthreads
= fold_convert (itype
, nthreads
);
6635 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
6636 true, GSI_SAME_STMT
);
6637 threadid
= build_call_expr (threadid
, 0);
6638 threadid
= fold_convert (itype
, threadid
);
6639 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
6640 true, GSI_SAME_STMT
);
6644 step
= fd
->loop
.step
;
6645 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6647 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6648 OMP_CLAUSE__LOOPTEMP_
);
6649 gcc_assert (innerc
);
6650 n1
= OMP_CLAUSE_DECL (innerc
);
6651 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6652 OMP_CLAUSE__LOOPTEMP_
);
6653 gcc_assert (innerc
);
6654 n2
= OMP_CLAUSE_DECL (innerc
);
6656 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6657 true, NULL_TREE
, true, GSI_SAME_STMT
);
6658 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6659 true, NULL_TREE
, true, GSI_SAME_STMT
);
6660 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6661 true, NULL_TREE
, true, GSI_SAME_STMT
);
6663 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6664 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6665 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6666 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6667 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6668 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6669 fold_build1 (NEGATE_EXPR
, itype
, t
),
6670 fold_build1 (NEGATE_EXPR
, itype
, step
));
6672 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6673 t
= fold_convert (itype
, t
);
6674 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6676 q
= create_tmp_reg (itype
, "q");
6677 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
6678 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6679 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
6681 tt
= create_tmp_reg (itype
, "tt");
6682 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
6683 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6684 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
6686 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
6687 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6688 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6690 second_bb
= split_block (entry_bb
, cond_stmt
)->dest
;
6691 gsi
= gsi_last_bb (second_bb
);
6692 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6694 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
6696 gassign
*assign_stmt
6697 = gimple_build_assign (q
, PLUS_EXPR
, q
, build_int_cst (itype
, 1));
6698 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6700 third_bb
= split_block (second_bb
, assign_stmt
)->dest
;
6701 gsi
= gsi_last_bb (third_bb
);
6702 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6704 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6705 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6706 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6708 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6709 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6711 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6712 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6714 /* Remove the GIMPLE_OMP_FOR statement. */
6715 gsi_remove (&gsi
, true);
6717 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6718 gsi
= gsi_start_bb (seq_start_bb
);
6720 tree startvar
= fd
->loop
.v
;
6721 tree endvar
= NULL_TREE
;
6723 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6725 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6726 ? gimple_omp_parallel_clauses (inner_stmt
)
6727 : gimple_omp_for_clauses (inner_stmt
);
6728 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6729 gcc_assert (innerc
);
6730 startvar
= OMP_CLAUSE_DECL (innerc
);
6731 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6732 OMP_CLAUSE__LOOPTEMP_
);
6733 gcc_assert (innerc
);
6734 endvar
= OMP_CLAUSE_DECL (innerc
);
6736 t
= fold_convert (itype
, s0
);
6737 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6738 if (POINTER_TYPE_P (type
))
6739 t
= fold_build_pointer_plus (n1
, t
);
6741 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6742 t
= fold_convert (TREE_TYPE (startvar
), t
);
6743 t
= force_gimple_operand_gsi (&gsi
, t
,
6745 && TREE_ADDRESSABLE (startvar
),
6746 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6747 assign_stmt
= gimple_build_assign (startvar
, t
);
6748 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6750 t
= fold_convert (itype
, e0
);
6751 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6752 if (POINTER_TYPE_P (type
))
6753 t
= fold_build_pointer_plus (n1
, t
);
6755 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6756 t
= fold_convert (TREE_TYPE (startvar
), t
);
6757 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6758 false, GSI_CONTINUE_LINKING
);
6761 assign_stmt
= gimple_build_assign (endvar
, e
);
6762 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6763 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6764 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6766 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
6767 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6769 if (fd
->collapse
> 1)
6770 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6774 /* The code controlling the sequential loop replaces the
6775 GIMPLE_OMP_CONTINUE. */
6776 gsi
= gsi_last_bb (cont_bb
);
6777 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6778 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6779 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6780 vback
= gimple_omp_continue_control_def (cont_stmt
);
6782 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6784 if (POINTER_TYPE_P (type
))
6785 t
= fold_build_pointer_plus (vmain
, step
);
6787 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6788 t
= force_gimple_operand_gsi (&gsi
, t
,
6790 && TREE_ADDRESSABLE (vback
),
6791 NULL_TREE
, true, GSI_SAME_STMT
);
6792 assign_stmt
= gimple_build_assign (vback
, t
);
6793 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6795 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6796 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6798 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6801 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6802 gsi_remove (&gsi
, true);
6804 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6805 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6808 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6809 gsi
= gsi_last_bb (exit_bb
);
6810 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6812 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6813 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
6814 gcc_checking_assert (t
== NULL_TREE
);
6816 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6818 gsi_remove (&gsi
, true);
6820 /* Connect all the blocks. */
6821 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6822 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6823 ep
= find_edge (entry_bb
, second_bb
);
6824 ep
->flags
= EDGE_TRUE_VALUE
;
6825 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6826 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6827 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6831 ep
= find_edge (cont_bb
, body_bb
);
6832 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6837 else if (fd
->collapse
> 1)
6840 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6843 ep
->flags
= EDGE_TRUE_VALUE
;
6844 find_edge (cont_bb
, fin_bb
)->flags
6845 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6848 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6849 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6850 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6852 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6853 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6854 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6855 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6857 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6859 struct loop
*loop
= alloc_loop ();
6860 loop
->header
= body_bb
;
6861 if (collapse_bb
== NULL
)
6862 loop
->latch
= cont_bb
;
6863 add_loop (loop
, body_bb
->loop_father
);
6868 /* A subroutine of expand_omp_for. Generate code for a parallel
6869 loop with static schedule and a specified chunk size. Given
6872 for (V = N1; V cond N2; V += STEP) BODY;
6874 where COND is "<" or ">", we generate pseudocode
6876 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6881 if ((__typeof (V)) -1 > 0 && cond is >)
6882 n = -(adj + N2 - N1) / -STEP;
6884 n = (adj + N2 - N1) / STEP;
6886 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6887 here so that V is defined
6888 if the loop is not entered
6890 s0 = (trip * nthreads + threadid) * CHUNK;
6891 e0 = min(s0 + CHUNK, n);
6892 if (s0 < n) goto L1; else goto L4;
6899 if (V cond e) goto L2; else goto L3;
6907 expand_omp_for_static_chunk (struct omp_region
*region
,
6908 struct omp_for_data
*fd
, gimple inner_stmt
)
6910 tree n
, s0
, e0
, e
, t
;
6911 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6912 tree type
, itype
, vmain
, vback
, vextra
;
6913 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6914 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6915 gimple_stmt_iterator gsi
;
6917 bool broken_loop
= region
->cont
== NULL
;
6918 tree
*counts
= NULL
;
6921 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6922 != GF_OMP_FOR_KIND_OACC_LOOP
)
6925 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6926 if (POINTER_TYPE_P (type
))
6927 itype
= signed_type_for (type
);
6929 entry_bb
= region
->entry
;
6930 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6932 iter_part_bb
= se
->dest
;
6933 cont_bb
= region
->cont
;
6934 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6935 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6936 gcc_assert (broken_loop
6937 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6938 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6939 body_bb
= single_succ (seq_start_bb
);
6942 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6943 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6944 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6946 exit_bb
= region
->exit
;
6948 /* Trip and adjustment setup goes in ENTRY_BB. */
6949 gsi
= gsi_last_bb (entry_bb
);
6950 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6952 if (fd
->collapse
> 1)
6954 int first_zero_iter
= -1;
6955 basic_block l2_dom_bb
= NULL
;
6957 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6958 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6959 fin_bb
, first_zero_iter
,
6963 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6964 t
= integer_one_node
;
6966 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6967 fold_convert (type
, fd
->loop
.n1
),
6968 fold_convert (type
, fd
->loop
.n2
));
6969 if (fd
->collapse
== 1
6970 && TYPE_UNSIGNED (type
)
6971 && (t
== NULL_TREE
|| !integer_onep (t
)))
6973 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6974 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6975 true, GSI_SAME_STMT
);
6976 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6977 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6978 true, GSI_SAME_STMT
);
6979 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6980 NULL_TREE
, NULL_TREE
);
6981 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6982 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6983 expand_omp_regimplify_p
, NULL
, NULL
)
6984 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6985 expand_omp_regimplify_p
, NULL
, NULL
))
6987 gsi
= gsi_for_stmt (cond_stmt
);
6988 gimple_regimplify_operands (cond_stmt
, &gsi
);
6990 se
= split_block (entry_bb
, cond_stmt
);
6991 se
->flags
= EDGE_TRUE_VALUE
;
6992 entry_bb
= se
->dest
;
6993 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6994 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6995 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6996 if (gimple_in_ssa_p (cfun
))
6998 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6999 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
7000 !gsi_end_p (gpi
); gsi_next (&gpi
))
7002 gphi
*phi
= gpi
.phi ();
7003 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
7004 se
, UNKNOWN_LOCATION
);
7007 gsi
= gsi_last_bb (entry_bb
);
7010 switch (gimple_omp_for_kind (fd
->for_stmt
))
7012 case GF_OMP_FOR_KIND_FOR
:
7013 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
7014 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
7016 case GF_OMP_FOR_KIND_DISTRIBUTE
:
7017 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
7018 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
7020 case GF_OMP_FOR_KIND_OACC_LOOP
:
7021 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
7022 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
7027 nthreads
= build_call_expr (nthreads
, 0);
7028 nthreads
= fold_convert (itype
, nthreads
);
7029 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
7030 true, GSI_SAME_STMT
);
7031 threadid
= build_call_expr (threadid
, 0);
7032 threadid
= fold_convert (itype
, threadid
);
7033 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
7034 true, GSI_SAME_STMT
);
7038 step
= fd
->loop
.step
;
7039 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7041 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7042 OMP_CLAUSE__LOOPTEMP_
);
7043 gcc_assert (innerc
);
7044 n1
= OMP_CLAUSE_DECL (innerc
);
7045 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7046 OMP_CLAUSE__LOOPTEMP_
);
7047 gcc_assert (innerc
);
7048 n2
= OMP_CLAUSE_DECL (innerc
);
7050 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
7051 true, NULL_TREE
, true, GSI_SAME_STMT
);
7052 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
7053 true, NULL_TREE
, true, GSI_SAME_STMT
);
7054 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
7055 true, NULL_TREE
, true, GSI_SAME_STMT
);
7057 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
7058 true, NULL_TREE
, true, GSI_SAME_STMT
);
7060 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
7061 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
7062 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
7063 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
7064 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
7065 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
7066 fold_build1 (NEGATE_EXPR
, itype
, t
),
7067 fold_build1 (NEGATE_EXPR
, itype
, step
));
7069 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
7070 t
= fold_convert (itype
, t
);
7071 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7072 true, GSI_SAME_STMT
);
7074 trip_var
= create_tmp_reg (itype
, ".trip");
7075 if (gimple_in_ssa_p (cfun
))
7077 trip_init
= make_ssa_name (trip_var
);
7078 trip_main
= make_ssa_name (trip_var
);
7079 trip_back
= make_ssa_name (trip_var
);
7083 trip_init
= trip_var
;
7084 trip_main
= trip_var
;
7085 trip_back
= trip_var
;
7088 gassign
*assign_stmt
7089 = gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
7090 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7092 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
7093 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7094 if (POINTER_TYPE_P (type
))
7095 t
= fold_build_pointer_plus (n1
, t
);
7097 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7098 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7099 true, GSI_SAME_STMT
);
7101 /* Remove the GIMPLE_OMP_FOR. */
7102 gsi_remove (&gsi
, true);
7104 /* Iteration space partitioning goes in ITER_PART_BB. */
7105 gsi
= gsi_last_bb (iter_part_bb
);
7107 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
7108 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
7109 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
7110 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7111 false, GSI_CONTINUE_LINKING
);
7113 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
7114 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
7115 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7116 false, GSI_CONTINUE_LINKING
);
7118 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
7119 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
7121 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7122 gsi
= gsi_start_bb (seq_start_bb
);
7124 tree startvar
= fd
->loop
.v
;
7125 tree endvar
= NULL_TREE
;
7127 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7129 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
7130 ? gimple_omp_parallel_clauses (inner_stmt
)
7131 : gimple_omp_for_clauses (inner_stmt
);
7132 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
7133 gcc_assert (innerc
);
7134 startvar
= OMP_CLAUSE_DECL (innerc
);
7135 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7136 OMP_CLAUSE__LOOPTEMP_
);
7137 gcc_assert (innerc
);
7138 endvar
= OMP_CLAUSE_DECL (innerc
);
7141 t
= fold_convert (itype
, s0
);
7142 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7143 if (POINTER_TYPE_P (type
))
7144 t
= fold_build_pointer_plus (n1
, t
);
7146 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7147 t
= fold_convert (TREE_TYPE (startvar
), t
);
7148 t
= force_gimple_operand_gsi (&gsi
, t
,
7150 && TREE_ADDRESSABLE (startvar
),
7151 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
7152 assign_stmt
= gimple_build_assign (startvar
, t
);
7153 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7155 t
= fold_convert (itype
, e0
);
7156 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7157 if (POINTER_TYPE_P (type
))
7158 t
= fold_build_pointer_plus (n1
, t
);
7160 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7161 t
= fold_convert (TREE_TYPE (startvar
), t
);
7162 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7163 false, GSI_CONTINUE_LINKING
);
7166 assign_stmt
= gimple_build_assign (endvar
, e
);
7167 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7168 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
7169 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
7171 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
7172 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7174 if (fd
->collapse
> 1)
7175 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
7179 /* The code controlling the sequential loop goes in CONT_BB,
7180 replacing the GIMPLE_OMP_CONTINUE. */
7181 gsi
= gsi_last_bb (cont_bb
);
7182 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
7183 vmain
= gimple_omp_continue_control_use (cont_stmt
);
7184 vback
= gimple_omp_continue_control_def (cont_stmt
);
7186 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7188 if (POINTER_TYPE_P (type
))
7189 t
= fold_build_pointer_plus (vmain
, step
);
7191 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
7192 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
7193 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7194 true, GSI_SAME_STMT
);
7195 assign_stmt
= gimple_build_assign (vback
, t
);
7196 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7198 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
7199 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
7201 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
7204 /* Remove GIMPLE_OMP_CONTINUE. */
7205 gsi_remove (&gsi
, true);
7207 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
7208 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
7210 /* Trip update code goes into TRIP_UPDATE_BB. */
7211 gsi
= gsi_start_bb (trip_update_bb
);
7213 t
= build_int_cst (itype
, 1);
7214 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
7215 assign_stmt
= gimple_build_assign (trip_back
, t
);
7216 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7219 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7220 gsi
= gsi_last_bb (exit_bb
);
7221 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
7223 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
7224 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
7225 gcc_checking_assert (t
== NULL_TREE
);
7227 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
7229 gsi_remove (&gsi
, true);
7231 /* Connect the new blocks. */
7232 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
7233 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
7237 se
= find_edge (cont_bb
, body_bb
);
7238 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7243 else if (fd
->collapse
> 1)
7246 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
7249 se
->flags
= EDGE_TRUE_VALUE
;
7250 find_edge (cont_bb
, trip_update_bb
)->flags
7251 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
7253 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
7256 if (gimple_in_ssa_p (cfun
))
7264 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
7266 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7267 remove arguments of the phi nodes in fin_bb. We need to create
7268 appropriate phi nodes in iter_part_bb instead. */
7269 se
= single_pred_edge (fin_bb
);
7270 re
= single_succ_edge (trip_update_bb
);
7271 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
7272 ene
= single_succ_edge (entry_bb
);
7274 psi
= gsi_start_phis (fin_bb
);
7275 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
7276 gsi_next (&psi
), ++i
)
7279 source_location locus
;
7282 t
= gimple_phi_result (phi
);
7283 gcc_assert (t
== redirect_edge_var_map_result (vm
));
7284 nphi
= create_phi_node (t
, iter_part_bb
);
7286 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
7287 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
7289 /* A special case -- fd->loop.v is not yet computed in
7290 iter_part_bb, we need to use vextra instead. */
7291 if (t
== fd
->loop
.v
)
7293 add_phi_arg (nphi
, t
, ene
, locus
);
7294 locus
= redirect_edge_var_map_location (vm
);
7295 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
7297 gcc_assert (gsi_end_p (psi
) && i
== head
->length ());
7298 redirect_edge_var_map_clear (re
);
7301 psi
= gsi_start_phis (fin_bb
);
7302 if (gsi_end_p (psi
))
7304 remove_phi_node (&psi
, false);
7307 /* Make phi node for trip. */
7308 phi
= create_phi_node (trip_main
, iter_part_bb
);
7309 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
7311 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
7316 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
7317 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
7318 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
7319 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
7320 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
7321 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
7322 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
7323 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
7324 recompute_dominator (CDI_DOMINATORS
, body_bb
));
7328 struct loop
*trip_loop
= alloc_loop ();
7329 trip_loop
->header
= iter_part_bb
;
7330 trip_loop
->latch
= trip_update_bb
;
7331 add_loop (trip_loop
, iter_part_bb
->loop_father
);
7333 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7335 struct loop
*loop
= alloc_loop ();
7336 loop
->header
= body_bb
;
7337 if (collapse_bb
== NULL
)
7338 loop
->latch
= cont_bb
;
7339 add_loop (loop
, trip_loop
);
7344 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7346 for (V = N1; V cond N2; V += STEP) BODY;
7348 where COND is "<" or ">" or "!=", we generate pseudocode
7350 for (ind_var = low; ind_var < high; ind_var++)
7352 V = n1 + (ind_var * STEP)
7357 In the above pseudocode, low and high are function parameters of the
7358 child function. In the function below, we are inserting a temp.
7359 variable that will be making a call to two OMP functions that will not be
7360 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7361 with _Cilk_for). These functions are replaced with low and high
7362 by the function that handles taskreg. */
7366 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
7368 bool broken_loop
= region
->cont
== NULL
;
7369 basic_block entry_bb
= region
->entry
;
7370 basic_block cont_bb
= region
->cont
;
7372 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7373 gcc_assert (broken_loop
7374 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7375 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7376 basic_block l1_bb
, l2_bb
;
7380 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7381 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7382 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7383 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7387 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7388 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7389 l2_bb
= single_succ (l1_bb
);
7391 basic_block exit_bb
= region
->exit
;
7392 basic_block l2_dom_bb
= NULL
;
7394 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
7396 /* Below statements until the "tree high_val = ..." are pseudo statements
7397 used to pass information to be used by expand_omp_taskreg.
7398 low_val and high_val will be replaced by the __low and __high
7399 parameter from the child function.
7401 The call_exprs part is a place-holder, it is mainly used
7402 to distinctly identify to the top-level part that this is
7403 where we should put low and high (reasoning given in header
7407 = gimple_omp_parallel_child_fn (
7408 as_a
<gomp_parallel
*> (last_stmt (region
->outer
->entry
)));
7409 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
7410 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
7412 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
7414 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
7417 gcc_assert (low_val
&& high_val
);
7419 tree type
= TREE_TYPE (low_val
);
7420 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
7421 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7423 /* Not needed in SSA form right now. */
7424 gcc_assert (!gimple_in_ssa_p (cfun
));
7425 if (l2_dom_bb
== NULL
)
7431 gimple stmt
= gimple_build_assign (ind_var
, n1
);
7433 /* Replace the GIMPLE_OMP_FOR statement. */
7434 gsi_replace (&gsi
, stmt
, true);
7438 /* Code to control the increment goes in the CONT_BB. */
7439 gsi
= gsi_last_bb (cont_bb
);
7440 stmt
= gsi_stmt (gsi
);
7441 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7442 stmt
= gimple_build_assign (ind_var
, PLUS_EXPR
, ind_var
,
7443 build_one_cst (type
));
7445 /* Replace GIMPLE_OMP_CONTINUE. */
7446 gsi_replace (&gsi
, stmt
, true);
7449 /* Emit the condition in L1_BB. */
7450 gsi
= gsi_after_labels (l1_bb
);
7451 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
7452 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
7454 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
7455 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7456 fd
->loop
.n1
, fold_convert (sizetype
, t
));
7458 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7459 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
7460 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
7461 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7463 /* The condition is always '<' since the runtime will fill in the low
7465 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
7466 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
7468 /* Remove GIMPLE_OMP_RETURN. */
7469 gsi
= gsi_last_bb (exit_bb
);
7470 gsi_remove (&gsi
, true);
7472 /* Connect the new blocks. */
7473 remove_edge (FALLTHRU_EDGE (entry_bb
));
7478 remove_edge (BRANCH_EDGE (entry_bb
));
7479 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7481 e
= BRANCH_EDGE (l1_bb
);
7482 ne
= FALLTHRU_EDGE (l1_bb
);
7483 e
->flags
= EDGE_TRUE_VALUE
;
7487 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7489 ne
= single_succ_edge (l1_bb
);
7490 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7493 ne
->flags
= EDGE_FALSE_VALUE
;
7494 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7495 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7497 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7498 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7499 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7503 struct loop
*loop
= alloc_loop ();
7504 loop
->header
= l1_bb
;
7505 loop
->latch
= cont_bb
;
7506 add_loop (loop
, l1_bb
->loop_father
);
7507 loop
->safelen
= INT_MAX
;
7510 /* Pick the correct library function based on the precision of the
7511 induction variable type. */
7512 tree lib_fun
= NULL_TREE
;
7513 if (TYPE_PRECISION (type
) == 32)
7514 lib_fun
= cilk_for_32_fndecl
;
7515 else if (TYPE_PRECISION (type
) == 64)
7516 lib_fun
= cilk_for_64_fndecl
;
7520 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
7522 /* WS_ARGS contains the library function flavor to call:
7523 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7524 user-defined grain value. If the user does not define one, then zero
7525 is passed in by the parser. */
7526 vec_alloc (region
->ws_args
, 2);
7527 region
->ws_args
->quick_push (lib_fun
);
7528 region
->ws_args
->quick_push (fd
->chunk_size
);
7531 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7532 loop. Given parameters:
7534 for (V = N1; V cond N2; V += STEP) BODY;
7536 where COND is "<" or ">", we generate pseudocode
7544 if (V cond N2) goto L0; else goto L2;
7547 For collapsed loops, given parameters:
7549 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7550 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7551 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7554 we generate pseudocode
7560 count3 = (adj + N32 - N31) / STEP3;
7565 count2 = (adj + N22 - N21) / STEP2;
7570 count1 = (adj + N12 - N11) / STEP1;
7571 count = count1 * count2 * count3;
7581 V2 += (V3 cond3 N32) ? 0 : STEP2;
7582 V3 = (V3 cond3 N32) ? V3 : N31;
7583 V1 += (V2 cond2 N22) ? 0 : STEP1;
7584 V2 = (V2 cond2 N22) ? V2 : N21;
7586 if (V < count) goto L0; else goto L2;
7592 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
7595 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
7596 gimple_stmt_iterator gsi
;
7599 bool broken_loop
= region
->cont
== NULL
;
7601 tree
*counts
= NULL
;
7603 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7604 OMP_CLAUSE_SAFELEN
);
7605 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7606 OMP_CLAUSE__SIMDUID_
);
7609 type
= TREE_TYPE (fd
->loop
.v
);
7610 entry_bb
= region
->entry
;
7611 cont_bb
= region
->cont
;
7612 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7613 gcc_assert (broken_loop
7614 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7615 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7618 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7619 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7620 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7621 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7625 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7626 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7627 l2_bb
= single_succ (l1_bb
);
7629 exit_bb
= region
->exit
;
7632 gsi
= gsi_last_bb (entry_bb
);
7634 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7635 /* Not needed in SSA form right now. */
7636 gcc_assert (!gimple_in_ssa_p (cfun
));
7637 if (fd
->collapse
> 1)
7639 int first_zero_iter
= -1;
7640 basic_block zero_iter_bb
= l2_bb
;
7642 counts
= XALLOCAVEC (tree
, fd
->collapse
);
7643 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7644 zero_iter_bb
, first_zero_iter
,
7647 if (l2_dom_bb
== NULL
)
7652 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7654 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7655 OMP_CLAUSE__LOOPTEMP_
);
7656 gcc_assert (innerc
);
7657 n1
= OMP_CLAUSE_DECL (innerc
);
7658 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7659 OMP_CLAUSE__LOOPTEMP_
);
7660 gcc_assert (innerc
);
7661 n2
= OMP_CLAUSE_DECL (innerc
);
7662 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7663 fold_convert (type
, n1
));
7664 if (fd
->collapse
> 1)
7667 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
7673 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7674 fold_convert (type
, fd
->loop
.n1
));
7675 if (fd
->collapse
> 1)
7676 for (i
= 0; i
< fd
->collapse
; i
++)
7678 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7679 if (POINTER_TYPE_P (itype
))
7680 itype
= signed_type_for (itype
);
7681 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
7682 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7686 /* Remove the GIMPLE_OMP_FOR statement. */
7687 gsi_remove (&gsi
, true);
7691 /* Code to control the increment goes in the CONT_BB. */
7692 gsi
= gsi_last_bb (cont_bb
);
7693 stmt
= gsi_stmt (gsi
);
7694 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7696 if (POINTER_TYPE_P (type
))
7697 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
7699 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
7700 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7702 if (fd
->collapse
> 1)
7704 i
= fd
->collapse
- 1;
7705 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7707 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
7708 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
7712 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
7714 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7717 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7719 for (i
= fd
->collapse
- 1; i
> 0; i
--)
7721 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7722 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
7723 if (POINTER_TYPE_P (itype2
))
7724 itype2
= signed_type_for (itype2
);
7725 t
= build3 (COND_EXPR
, itype2
,
7726 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7728 fold_convert (itype
, fd
->loops
[i
].n2
)),
7729 build_int_cst (itype2
, 0),
7730 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
7731 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
7732 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
7734 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
7735 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
7737 t
= build3 (COND_EXPR
, itype
,
7738 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7740 fold_convert (itype
, fd
->loops
[i
].n2
)),
7742 fold_convert (itype
, fd
->loops
[i
].n1
));
7743 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7747 /* Remove GIMPLE_OMP_CONTINUE. */
7748 gsi_remove (&gsi
, true);
7751 /* Emit the condition in L1_BB. */
7752 gsi
= gsi_start_bb (l1_bb
);
7754 t
= fold_convert (type
, n2
);
7755 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7756 false, GSI_CONTINUE_LINKING
);
7757 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
7758 cond_stmt
= gimple_build_cond_empty (t
);
7759 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
7760 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7762 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7765 gsi
= gsi_for_stmt (cond_stmt
);
7766 gimple_regimplify_operands (cond_stmt
, &gsi
);
7769 /* Remove GIMPLE_OMP_RETURN. */
7770 gsi
= gsi_last_bb (exit_bb
);
7771 gsi_remove (&gsi
, true);
7773 /* Connect the new blocks. */
7774 remove_edge (FALLTHRU_EDGE (entry_bb
));
7778 remove_edge (BRANCH_EDGE (entry_bb
));
7779 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7781 e
= BRANCH_EDGE (l1_bb
);
7782 ne
= FALLTHRU_EDGE (l1_bb
);
7783 e
->flags
= EDGE_TRUE_VALUE
;
7787 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7789 ne
= single_succ_edge (l1_bb
);
7790 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7793 ne
->flags
= EDGE_FALSE_VALUE
;
7794 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7795 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7797 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7798 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7799 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7803 struct loop
*loop
= alloc_loop ();
7804 loop
->header
= l1_bb
;
7805 loop
->latch
= cont_bb
;
7806 add_loop (loop
, l1_bb
->loop_father
);
7807 if (safelen
== NULL_TREE
)
7808 loop
->safelen
= INT_MAX
;
7811 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
7812 if (TREE_CODE (safelen
) != INTEGER_CST
)
7814 else if (!tree_fits_uhwi_p (safelen
)
7815 || tree_to_uhwi (safelen
) > INT_MAX
)
7816 loop
->safelen
= INT_MAX
;
7818 loop
->safelen
= tree_to_uhwi (safelen
);
7819 if (loop
->safelen
== 1)
7824 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
7825 cfun
->has_simduid_loops
= true;
7827 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7829 if ((flag_tree_loop_vectorize
7830 || (!global_options_set
.x_flag_tree_loop_vectorize
7831 && !global_options_set
.x_flag_tree_vectorize
))
7832 && flag_tree_loop_optimize
7833 && loop
->safelen
> 1)
7835 loop
->force_vectorize
= true;
7836 cfun
->has_force_vectorize_loops
= true;
7840 cfun
->has_simduid_loops
= true;
7844 /* Expand the OMP loop defined by REGION. */
7847 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
7849 struct omp_for_data fd
;
7850 struct omp_for_data_loop
*loops
;
7853 = (struct omp_for_data_loop
*)
7854 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
7855 * sizeof (struct omp_for_data_loop
));
7856 extract_omp_for_data (as_a
<gomp_for
*> (last_stmt (region
->entry
)),
7858 region
->sched_kind
= fd
.sched_kind
;
7860 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
7861 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7862 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7865 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
7866 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7867 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7870 /* If there isn't a continue then this is a degerate case where
7871 the introduction of abnormal edges during lowering will prevent
7872 original loops from being detected. Fix that up. */
7873 loops_state_set (LOOPS_NEED_FIXUP
);
7875 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
7876 expand_omp_simd (region
, &fd
);
7877 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
7878 expand_cilk_for (region
, &fd
);
7879 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
7880 && !fd
.have_ordered
)
7882 if (fd
.chunk_size
== NULL
)
7883 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
7885 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
7889 int fn_index
, start_ix
, next_ix
;
7891 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
7892 == GF_OMP_FOR_KIND_FOR
);
7893 if (fd
.chunk_size
== NULL
7894 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
7895 fd
.chunk_size
= integer_zero_node
;
7896 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
7897 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
7898 ? 3 : fd
.sched_kind
;
7899 fn_index
+= fd
.have_ordered
* 4;
7900 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
7901 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
7902 if (fd
.iter_type
== long_long_unsigned_type_node
)
7904 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7905 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
7906 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7907 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7909 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7910 (enum built_in_function
) next_ix
, inner_stmt
);
7913 if (gimple_in_ssa_p (cfun
))
7914 update_ssa (TODO_update_ssa_only_virtuals
);
7918 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7920 v = GOMP_sections_start (n);
7937 v = GOMP_sections_next ();
7942 If this is a combined parallel sections, replace the call to
7943 GOMP_sections_start with call to GOMP_sections_next. */
7946 expand_omp_sections (struct omp_region
*region
)
7948 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7950 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7951 gimple_stmt_iterator si
, switch_si
;
7952 gomp_sections
*sections_stmt
;
7954 gomp_continue
*cont
;
7957 struct omp_region
*inner
;
7959 bool exit_reachable
= region
->cont
!= NULL
;
7961 gcc_assert (region
->exit
!= NULL
);
7962 entry_bb
= region
->entry
;
7963 l0_bb
= single_succ (entry_bb
);
7964 l1_bb
= region
->cont
;
7965 l2_bb
= region
->exit
;
7966 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7967 l2
= gimple_block_label (l2_bb
);
7970 /* This can happen if there are reductions. */
7971 len
= EDGE_COUNT (l0_bb
->succs
);
7972 gcc_assert (len
> 0);
7973 e
= EDGE_SUCC (l0_bb
, len
- 1);
7974 si
= gsi_last_bb (e
->dest
);
7977 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7978 l2
= gimple_block_label (e
->dest
);
7980 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7982 si
= gsi_last_bb (e
->dest
);
7984 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7986 l2
= gimple_block_label (e
->dest
);
7992 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7994 default_bb
= create_empty_bb (l0_bb
);
7996 /* We will build a switch() with enough cases for all the
7997 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7998 and a default case to abort if something goes wrong. */
7999 len
= EDGE_COUNT (l0_bb
->succs
);
8001 /* Use vec::quick_push on label_vec throughout, since we know the size
8003 auto_vec
<tree
> label_vec (len
);
8005 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8006 GIMPLE_OMP_SECTIONS statement. */
8007 si
= gsi_last_bb (entry_bb
);
8008 sections_stmt
= as_a
<gomp_sections
*> (gsi_stmt (si
));
8009 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
8010 vin
= gimple_omp_sections_control (sections_stmt
);
8011 if (!is_combined_parallel (region
))
8013 /* If we are not inside a combined parallel+sections region,
8014 call GOMP_sections_start. */
8015 t
= build_int_cst (unsigned_type_node
, len
- 1);
8016 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
8017 stmt
= gimple_build_call (u
, 1, t
);
8021 /* Otherwise, call GOMP_sections_next. */
8022 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8023 stmt
= gimple_build_call (u
, 0);
8025 gimple_call_set_lhs (stmt
, vin
);
8026 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8027 gsi_remove (&si
, true);
8029 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8031 switch_si
= gsi_last_bb (l0_bb
);
8032 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
8035 cont
= as_a
<gomp_continue
*> (last_stmt (l1_bb
));
8036 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
8037 vmain
= gimple_omp_continue_control_use (cont
);
8038 vnext
= gimple_omp_continue_control_def (cont
);
8046 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
8047 label_vec
.quick_push (t
);
8050 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8051 for (inner
= region
->inner
, casei
= 1;
8053 inner
= inner
->next
, i
++, casei
++)
8055 basic_block s_entry_bb
, s_exit_bb
;
8057 /* Skip optional reduction region. */
8058 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
8065 s_entry_bb
= inner
->entry
;
8066 s_exit_bb
= inner
->exit
;
8068 t
= gimple_block_label (s_entry_bb
);
8069 u
= build_int_cst (unsigned_type_node
, casei
);
8070 u
= build_case_label (u
, NULL
, t
);
8071 label_vec
.quick_push (u
);
8073 si
= gsi_last_bb (s_entry_bb
);
8074 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
8075 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
8076 gsi_remove (&si
, true);
8077 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
8079 if (s_exit_bb
== NULL
)
8082 si
= gsi_last_bb (s_exit_bb
);
8083 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8084 gsi_remove (&si
, true);
8086 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
8089 /* Error handling code goes in DEFAULT_BB. */
8090 t
= gimple_block_label (default_bb
);
8091 u
= build_case_label (NULL
, NULL
, t
);
8092 make_edge (l0_bb
, default_bb
, 0);
8093 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
8095 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
8096 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
8097 gsi_remove (&switch_si
, true);
8099 si
= gsi_start_bb (default_bb
);
8100 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
8101 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
8107 /* Code to get the next section goes in L1_BB. */
8108 si
= gsi_last_bb (l1_bb
);
8109 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
8111 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8112 stmt
= gimple_build_call (bfn_decl
, 0);
8113 gimple_call_set_lhs (stmt
, vnext
);
8114 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8115 gsi_remove (&si
, true);
8117 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
8120 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8121 si
= gsi_last_bb (l2_bb
);
8122 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
8123 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
8124 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
8125 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
8127 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
8128 stmt
= gimple_build_call (t
, 0);
8129 if (gimple_omp_return_lhs (gsi_stmt (si
)))
8130 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
8131 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8132 gsi_remove (&si
, true);
8134 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
8138 /* Expand code for an OpenMP single directive. We've already expanded
8139 much of the code, here we simply place the GOMP_barrier call. */
8142 expand_omp_single (struct omp_region
*region
)
8144 basic_block entry_bb
, exit_bb
;
8145 gimple_stmt_iterator si
;
8147 entry_bb
= region
->entry
;
8148 exit_bb
= region
->exit
;
8150 si
= gsi_last_bb (entry_bb
);
8151 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
8152 gsi_remove (&si
, true);
8153 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8155 si
= gsi_last_bb (exit_bb
);
8156 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
8158 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
8159 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
8161 gsi_remove (&si
, true);
8162 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8166 /* Generic expansion for OpenMP synchronization directives: master,
8167 ordered and critical. All we need to do here is remove the entry
8168 and exit markers for REGION. */
8171 expand_omp_synch (struct omp_region
*region
)
8173 basic_block entry_bb
, exit_bb
;
8174 gimple_stmt_iterator si
;
8176 entry_bb
= region
->entry
;
8177 exit_bb
= region
->exit
;
8179 si
= gsi_last_bb (entry_bb
);
8180 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
8181 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
8182 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
8183 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
8184 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
8185 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
8186 gsi_remove (&si
, true);
8187 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8191 si
= gsi_last_bb (exit_bb
);
8192 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8193 gsi_remove (&si
, true);
8194 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8198 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8199 operation as a normal volatile load. */
8202 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
8203 tree loaded_val
, int index
)
8205 enum built_in_function tmpbase
;
8206 gimple_stmt_iterator gsi
;
8207 basic_block store_bb
;
8210 tree decl
, call
, type
, itype
;
8212 gsi
= gsi_last_bb (load_bb
);
8213 stmt
= gsi_stmt (gsi
);
8214 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8215 loc
= gimple_location (stmt
);
8217 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8218 is smaller than word size, then expand_atomic_load assumes that the load
8219 is atomic. We could avoid the builtin entirely in this case. */
8221 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8222 decl
= builtin_decl_explicit (tmpbase
);
8223 if (decl
== NULL_TREE
)
8226 type
= TREE_TYPE (loaded_val
);
8227 itype
= TREE_TYPE (TREE_TYPE (decl
));
8229 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
8230 build_int_cst (NULL
,
8231 gimple_omp_atomic_seq_cst_p (stmt
)
8233 : MEMMODEL_RELAXED
));
8234 if (!useless_type_conversion_p (type
, itype
))
8235 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8236 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8238 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8239 gsi_remove (&gsi
, true);
8241 store_bb
= single_succ (load_bb
);
8242 gsi
= gsi_last_bb (store_bb
);
8243 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8244 gsi_remove (&gsi
, true);
8246 if (gimple_in_ssa_p (cfun
))
8247 update_ssa (TODO_update_ssa_no_phi
);
8252 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8253 operation as a normal volatile store. */
8256 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
8257 tree loaded_val
, tree stored_val
, int index
)
8259 enum built_in_function tmpbase
;
8260 gimple_stmt_iterator gsi
;
8261 basic_block store_bb
= single_succ (load_bb
);
8264 tree decl
, call
, type
, itype
;
8268 gsi
= gsi_last_bb (load_bb
);
8269 stmt
= gsi_stmt (gsi
);
8270 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8272 /* If the load value is needed, then this isn't a store but an exchange. */
8273 exchange
= gimple_omp_atomic_need_value_p (stmt
);
8275 gsi
= gsi_last_bb (store_bb
);
8276 stmt
= gsi_stmt (gsi
);
8277 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
8278 loc
= gimple_location (stmt
);
8280 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8281 is smaller than word size, then expand_atomic_store assumes that the store
8282 is atomic. We could avoid the builtin entirely in this case. */
8284 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
8285 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
8286 decl
= builtin_decl_explicit (tmpbase
);
8287 if (decl
== NULL_TREE
)
8290 type
= TREE_TYPE (stored_val
);
8292 /* Dig out the type of the function's second argument. */
8293 itype
= TREE_TYPE (decl
);
8294 itype
= TYPE_ARG_TYPES (itype
);
8295 itype
= TREE_CHAIN (itype
);
8296 itype
= TREE_VALUE (itype
);
8297 imode
= TYPE_MODE (itype
);
8299 if (exchange
&& !can_atomic_exchange_p (imode
, true))
8302 if (!useless_type_conversion_p (itype
, type
))
8303 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
8304 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
8305 build_int_cst (NULL
,
8306 gimple_omp_atomic_seq_cst_p (stmt
)
8308 : MEMMODEL_RELAXED
));
8311 if (!useless_type_conversion_p (type
, itype
))
8312 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8313 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8316 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8317 gsi_remove (&gsi
, true);
8319 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8320 gsi
= gsi_last_bb (load_bb
);
8321 gsi_remove (&gsi
, true);
8323 if (gimple_in_ssa_p (cfun
))
8324 update_ssa (TODO_update_ssa_no_phi
);
8329 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8330 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8331 size of the data type, and thus usable to find the index of the builtin
8332 decl. Returns false if the expression is not of the proper form. */
8335 expand_omp_atomic_fetch_op (basic_block load_bb
,
8336 tree addr
, tree loaded_val
,
8337 tree stored_val
, int index
)
8339 enum built_in_function oldbase
, newbase
, tmpbase
;
8340 tree decl
, itype
, call
;
8342 basic_block store_bb
= single_succ (load_bb
);
8343 gimple_stmt_iterator gsi
;
8346 enum tree_code code
;
8347 bool need_old
, need_new
;
8351 /* We expect to find the following sequences:
8354 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8357 val = tmp OP something; (or: something OP tmp)
8358 GIMPLE_OMP_STORE (val)
8360 ???FIXME: Allow a more flexible sequence.
8361 Perhaps use data flow to pick the statements.
8365 gsi
= gsi_after_labels (store_bb
);
8366 stmt
= gsi_stmt (gsi
);
8367 loc
= gimple_location (stmt
);
8368 if (!is_gimple_assign (stmt
))
8371 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
8373 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
8374 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
8375 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
8376 gcc_checking_assert (!need_old
|| !need_new
);
8378 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
8381 /* Check for one of the supported fetch-op operations. */
8382 code
= gimple_assign_rhs_code (stmt
);
8386 case POINTER_PLUS_EXPR
:
8387 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
8388 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
8391 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
8392 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
8395 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
8396 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
8399 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
8400 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
8403 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
8404 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
8410 /* Make sure the expression is of the proper form. */
8411 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
8412 rhs
= gimple_assign_rhs2 (stmt
);
8413 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
8414 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
8415 rhs
= gimple_assign_rhs1 (stmt
);
8419 tmpbase
= ((enum built_in_function
)
8420 ((need_new
? newbase
: oldbase
) + index
+ 1));
8421 decl
= builtin_decl_explicit (tmpbase
);
8422 if (decl
== NULL_TREE
)
8424 itype
= TREE_TYPE (TREE_TYPE (decl
));
8425 imode
= TYPE_MODE (itype
);
8427 /* We could test all of the various optabs involved, but the fact of the
8428 matter is that (with the exception of i486 vs i586 and xadd) all targets
8429 that support any atomic operaton optab also implements compare-and-swap.
8430 Let optabs.c take care of expanding any compare-and-swap loop. */
8431 if (!can_compare_and_swap_p (imode
, true))
8434 gsi
= gsi_last_bb (load_bb
);
8435 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8437 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8438 It only requires that the operation happen atomically. Thus we can
8439 use the RELAXED memory model. */
8440 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
8441 fold_convert_loc (loc
, itype
, rhs
),
8442 build_int_cst (NULL
,
8443 seq_cst
? MEMMODEL_SEQ_CST
8444 : MEMMODEL_RELAXED
));
8446 if (need_old
|| need_new
)
8448 lhs
= need_old
? loaded_val
: stored_val
;
8449 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
8450 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
8453 call
= fold_convert_loc (loc
, void_type_node
, call
);
8454 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8455 gsi_remove (&gsi
, true);
8457 gsi
= gsi_last_bb (store_bb
);
8458 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8459 gsi_remove (&gsi
, true);
8460 gsi
= gsi_last_bb (store_bb
);
8461 gsi_remove (&gsi
, true);
8463 if (gimple_in_ssa_p (cfun
))
8464 update_ssa (TODO_update_ssa_no_phi
);
8469 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8473 newval = rhs; // with oldval replacing *addr in rhs
8474 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8475 if (oldval != newval)
8478 INDEX is log2 of the size of the data type, and thus usable to find the
8479 index of the builtin decl. */
8482 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
8483 tree addr
, tree loaded_val
, tree stored_val
,
8486 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
8487 tree type
, itype
, cmpxchg
, iaddr
;
8488 gimple_stmt_iterator si
;
8489 basic_block loop_header
= single_succ (load_bb
);
8492 enum built_in_function fncode
;
8494 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8495 order to use the RELAXED memory model effectively. */
8496 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8498 cmpxchg
= builtin_decl_explicit (fncode
);
8499 if (cmpxchg
== NULL_TREE
)
8501 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8502 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
8504 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
8507 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8508 si
= gsi_last_bb (load_bb
);
8509 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8511 /* For floating-point values, we'll need to view-convert them to integers
8512 so that we can perform the atomic compare and swap. Simplify the
8513 following code by always setting up the "i"ntegral variables. */
8514 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
8518 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
8521 = force_gimple_operand_gsi (&si
,
8522 fold_convert (TREE_TYPE (iaddr
), addr
),
8523 false, NULL_TREE
, true, GSI_SAME_STMT
);
8524 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
8525 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8526 loadedi
= create_tmp_var (itype
);
8527 if (gimple_in_ssa_p (cfun
))
8528 loadedi
= make_ssa_name (loadedi
);
8533 loadedi
= loaded_val
;
8536 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8537 tree loaddecl
= builtin_decl_explicit (fncode
);
8540 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
8541 build_call_expr (loaddecl
, 2, iaddr
,
8542 build_int_cst (NULL_TREE
,
8543 MEMMODEL_RELAXED
)));
8545 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
8546 build_int_cst (TREE_TYPE (iaddr
), 0));
8549 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
8552 /* Move the value to the LOADEDI temporary. */
8553 if (gimple_in_ssa_p (cfun
))
8555 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
8556 phi
= create_phi_node (loadedi
, loop_header
);
8557 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
8561 gsi_insert_before (&si
,
8562 gimple_build_assign (loadedi
, initial
),
8564 if (loadedi
!= loaded_val
)
8566 gimple_stmt_iterator gsi2
;
8569 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
8570 gsi2
= gsi_start_bb (loop_header
);
8571 if (gimple_in_ssa_p (cfun
))
8574 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8575 true, GSI_SAME_STMT
);
8576 stmt
= gimple_build_assign (loaded_val
, x
);
8577 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
8581 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
8582 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8583 true, GSI_SAME_STMT
);
8586 gsi_remove (&si
, true);
8588 si
= gsi_last_bb (store_bb
);
8589 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8592 storedi
= stored_val
;
8595 force_gimple_operand_gsi (&si
,
8596 build1 (VIEW_CONVERT_EXPR
, itype
,
8597 stored_val
), true, NULL_TREE
, true,
8600 /* Build the compare&swap statement. */
8601 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
8602 new_storedi
= force_gimple_operand_gsi (&si
,
8603 fold_convert (TREE_TYPE (loadedi
),
8606 true, GSI_SAME_STMT
);
8608 if (gimple_in_ssa_p (cfun
))
8612 old_vali
= create_tmp_var (TREE_TYPE (loadedi
));
8613 stmt
= gimple_build_assign (old_vali
, loadedi
);
8614 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8616 stmt
= gimple_build_assign (loadedi
, new_storedi
);
8617 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8620 /* Note that we always perform the comparison as an integer, even for
8621 floating point. This allows the atomic operation to properly
8622 succeed even with NaNs and -0.0. */
8623 stmt
= gimple_build_cond_empty
8624 (build2 (NE_EXPR
, boolean_type_node
,
8625 new_storedi
, old_vali
));
8626 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8629 e
= single_succ_edge (store_bb
);
8630 e
->flags
&= ~EDGE_FALLTHRU
;
8631 e
->flags
|= EDGE_FALSE_VALUE
;
8633 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
8635 /* Copy the new value to loadedi (we already did that before the condition
8636 if we are not in SSA). */
8637 if (gimple_in_ssa_p (cfun
))
8639 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
8640 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
8643 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8644 gsi_remove (&si
, true);
8646 struct loop
*loop
= alloc_loop ();
8647 loop
->header
= loop_header
;
8648 loop
->latch
= store_bb
;
8649 add_loop (loop
, loop_header
->loop_father
);
8651 if (gimple_in_ssa_p (cfun
))
8652 update_ssa (TODO_update_ssa_no_phi
);
8657 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8659 GOMP_atomic_start ();
8663 The result is not globally atomic, but works so long as all parallel
8664 references are within #pragma omp atomic directives. According to
8665 responses received from omp@openmp.org, appears to be within spec.
8666 Which makes sense, since that's how several other compilers handle
8667 this situation as well.
8668 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8669 expanding. STORED_VAL is the operand of the matching
8670 GIMPLE_OMP_ATOMIC_STORE.
8673 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8677 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8682 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
8683 tree addr
, tree loaded_val
, tree stored_val
)
8685 gimple_stmt_iterator si
;
8689 si
= gsi_last_bb (load_bb
);
8690 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8692 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
8693 t
= build_call_expr (t
, 0);
8694 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8696 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
8697 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8698 gsi_remove (&si
, true);
8700 si
= gsi_last_bb (store_bb
);
8701 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8703 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
8705 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8707 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
8708 t
= build_call_expr (t
, 0);
8709 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8710 gsi_remove (&si
, true);
8712 if (gimple_in_ssa_p (cfun
))
8713 update_ssa (TODO_update_ssa_no_phi
);
8717 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8718 using expand_omp_atomic_fetch_op. If it failed, we try to
8719 call expand_omp_atomic_pipeline, and if it fails too, the
8720 ultimate fallback is wrapping the operation in a mutex
8721 (expand_omp_atomic_mutex). REGION is the atomic region built
8722 by build_omp_regions_1(). */
8725 expand_omp_atomic (struct omp_region
*region
)
8727 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
8728 gomp_atomic_load
*load
= as_a
<gomp_atomic_load
*> (last_stmt (load_bb
));
8729 gomp_atomic_store
*store
= as_a
<gomp_atomic_store
*> (last_stmt (store_bb
));
8730 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
8731 tree addr
= gimple_omp_atomic_load_rhs (load
);
8732 tree stored_val
= gimple_omp_atomic_store_val (store
);
8733 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8734 HOST_WIDE_INT index
;
8736 /* Make sure the type is one of the supported sizes. */
8737 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
8738 index
= exact_log2 (index
);
8739 if (index
>= 0 && index
<= 4)
8741 unsigned int align
= TYPE_ALIGN_UNIT (type
);
8743 /* __sync builtins require strict data alignment. */
8744 if (exact_log2 (align
) >= index
)
8747 if (loaded_val
== stored_val
8748 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8749 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8750 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8751 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
8755 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8756 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8757 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8758 && store_bb
== single_succ (load_bb
)
8759 && first_stmt (store_bb
) == store
8760 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
8764 /* When possible, use specialized atomic update functions. */
8765 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
8766 && store_bb
== single_succ (load_bb
)
8767 && expand_omp_atomic_fetch_op (load_bb
, addr
,
8768 loaded_val
, stored_val
, index
))
8771 /* If we don't have specialized __sync builtins, try and implement
8772 as a compare and swap loop. */
8773 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
8774 loaded_val
, stored_val
, index
))
8779 /* The ultimate fallback is wrapping the operation in a mutex. */
8780 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
8784 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8787 expand_omp_target (struct omp_region
*region
)
8789 basic_block entry_bb
, exit_bb
, new_bb
;
8790 struct function
*child_cfun
;
8791 tree child_fn
, block
, t
;
8792 gimple_stmt_iterator gsi
;
8793 gomp_target
*entry_stmt
;
8796 bool offloaded
, data_region
;
8798 entry_stmt
= as_a
<gomp_target
*> (last_stmt (region
->entry
));
8799 new_bb
= region
->entry
;
8801 offloaded
= is_gimple_omp_offloaded (entry_stmt
);
8802 switch (gimple_omp_target_kind (entry_stmt
))
8804 case GF_OMP_TARGET_KIND_REGION
:
8805 case GF_OMP_TARGET_KIND_UPDATE
:
8806 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
8807 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
8808 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
8809 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
8810 data_region
= false;
8812 case GF_OMP_TARGET_KIND_DATA
:
8813 case GF_OMP_TARGET_KIND_OACC_DATA
:
8820 child_fn
= NULL_TREE
;
8824 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
8825 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
8828 /* Supported by expand_omp_taskreg, but not here. */
8829 if (child_cfun
!= NULL
)
8830 gcc_checking_assert (!child_cfun
->cfg
);
8831 gcc_checking_assert (!gimple_in_ssa_p (cfun
));
8833 entry_bb
= region
->entry
;
8834 exit_bb
= region
->exit
;
8838 unsigned srcidx
, dstidx
, num
;
8840 /* If the offloading region needs data sent from the parent
8841 function, then the very first statement (except possible
8842 tree profile counter updates) of the offloading body
8843 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8844 &.OMP_DATA_O is passed as an argument to the child function,
8845 we need to replace it with the argument as seen by the child
8848 In most cases, this will end up being the identity assignment
8849 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8850 a function call that has been inlined, the original PARM_DECL
8851 .OMP_DATA_I may have been converted into a different local
8852 variable. In which case, we need to keep the assignment. */
8853 tree data_arg
= gimple_omp_target_data_arg (entry_stmt
);
8856 basic_block entry_succ_bb
= single_succ (entry_bb
);
8857 gimple_stmt_iterator gsi
;
8859 gimple tgtcopy_stmt
= NULL
;
8860 tree sender
= TREE_VEC_ELT (data_arg
, 0);
8862 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
8864 gcc_assert (!gsi_end_p (gsi
));
8865 stmt
= gsi_stmt (gsi
);
8866 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
8869 if (gimple_num_ops (stmt
) == 2)
8871 tree arg
= gimple_assign_rhs1 (stmt
);
8873 /* We're ignoring the subcode because we're
8874 effectively doing a STRIP_NOPS. */
8876 if (TREE_CODE (arg
) == ADDR_EXPR
8877 && TREE_OPERAND (arg
, 0) == sender
)
8879 tgtcopy_stmt
= stmt
;
8885 gcc_assert (tgtcopy_stmt
!= NULL
);
8886 arg
= DECL_ARGUMENTS (child_fn
);
8888 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
8889 gsi_remove (&gsi
, true);
8892 /* Declare local variables needed in CHILD_CFUN. */
8893 block
= DECL_INITIAL (child_fn
);
8894 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
8895 /* The gimplifier could record temporaries in the offloading block
8896 rather than in containing function's local_decls chain,
8897 which would mean cgraph missed finalizing them. Do it now. */
8898 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
8899 if (TREE_CODE (t
) == VAR_DECL
8901 && !DECL_EXTERNAL (t
))
8902 varpool_node::finalize_decl (t
);
8903 DECL_SAVED_TREE (child_fn
) = NULL
;
8904 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8905 gimple_set_body (child_fn
, NULL
);
8906 TREE_USED (block
) = 1;
8908 /* Reset DECL_CONTEXT on function arguments. */
8909 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
8910 DECL_CONTEXT (t
) = child_fn
;
8912 /* Split ENTRY_BB at GIMPLE_*,
8913 so that it can be moved to the child function. */
8914 gsi
= gsi_last_bb (entry_bb
);
8915 stmt
= gsi_stmt (gsi
);
8917 && gimple_code (stmt
) == gimple_code (entry_stmt
));
8918 e
= split_block (entry_bb
, stmt
);
8919 gsi_remove (&gsi
, true);
8921 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8923 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8926 gsi
= gsi_last_bb (exit_bb
);
8927 gcc_assert (!gsi_end_p (gsi
)
8928 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
8929 stmt
= gimple_build_return (NULL
);
8930 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
8931 gsi_remove (&gsi
, true);
8934 /* Move the offloading region into CHILD_CFUN. */
8936 block
= gimple_block (entry_stmt
);
8938 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
8940 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
8941 /* When the OMP expansion process cannot guarantee an up-to-date
8942 loop tree arrange for the child function to fixup loops. */
8943 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
8944 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
8946 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8947 num
= vec_safe_length (child_cfun
->local_decls
);
8948 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
8950 t
= (*child_cfun
->local_decls
)[srcidx
];
8951 if (DECL_CONTEXT (t
) == cfun
->decl
)
8953 if (srcidx
!= dstidx
)
8954 (*child_cfun
->local_decls
)[dstidx
] = t
;
8958 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
8960 /* Inform the callgraph about the new function. */
8961 child_cfun
->curr_properties
= cfun
->curr_properties
;
8962 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
8963 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
8964 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
8965 node
->parallelized_function
= 1;
8966 cgraph_node::add_new_function (child_fn
, true);
8968 #ifdef ENABLE_OFFLOADING
8969 /* Add the new function to the offload table. */
8970 vec_safe_push (offload_funcs
, child_fn
);
8973 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8974 fixed in a following pass. */
8975 push_cfun (child_cfun
);
8976 cgraph_edge::rebuild_edges ();
8978 #ifdef ENABLE_OFFLOADING
8979 /* Prevent IPA from removing child_fn as unreachable, since there are no
8980 refs from the parent function to child_fn in offload LTO mode. */
8981 cgraph_node::get (child_fn
)->mark_force_output ();
8984 /* Some EH regions might become dead, see PR34608. If
8985 pass_cleanup_cfg isn't the first pass to happen with the
8986 new child, these dead EH edges might cause problems.
8987 Clean them up now. */
8988 if (flag_exceptions
)
8991 bool changed
= false;
8993 FOR_EACH_BB_FN (bb
, cfun
)
8994 changed
|= gimple_purge_dead_eh_edges (bb
);
8996 cleanup_tree_cfg ();
9001 /* Emit a library call to launch the offloading region, or do data
9003 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
9004 enum built_in_function start_ix
;
9005 location_t clause_loc
;
9007 switch (gimple_omp_target_kind (entry_stmt
))
9009 case GF_OMP_TARGET_KIND_REGION
:
9010 start_ix
= BUILT_IN_GOMP_TARGET
;
9012 case GF_OMP_TARGET_KIND_DATA
:
9013 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
9015 case GF_OMP_TARGET_KIND_UPDATE
:
9016 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
9018 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
9019 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
9020 start_ix
= BUILT_IN_GOACC_PARALLEL
;
9022 case GF_OMP_TARGET_KIND_OACC_DATA
:
9023 start_ix
= BUILT_IN_GOACC_DATA_START
;
9025 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9026 start_ix
= BUILT_IN_GOACC_UPDATE
;
9028 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9029 start_ix
= BUILT_IN_GOACC_ENTER_EXIT_DATA
;
9035 clauses
= gimple_omp_target_clauses (entry_stmt
);
9037 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9038 library choose) and there is no conditional. */
9040 device
= build_int_cst (integer_type_node
, GOMP_DEVICE_ICV
);
9042 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
9044 cond
= OMP_CLAUSE_IF_EXPR (c
);
9046 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
9049 /* Even if we pass it to all library function calls, it is currently only
9050 defined/used for the OpenMP target ones. */
9051 gcc_checking_assert (start_ix
== BUILT_IN_GOMP_TARGET
9052 || start_ix
== BUILT_IN_GOMP_TARGET_DATA
9053 || start_ix
== BUILT_IN_GOMP_TARGET_UPDATE
);
9055 device
= OMP_CLAUSE_DEVICE_ID (c
);
9056 clause_loc
= OMP_CLAUSE_LOCATION (c
);
9059 clause_loc
= gimple_location (entry_stmt
);
9061 /* Ensure 'device' is of the correct type. */
9062 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
9064 /* If we found the clause 'if (cond)', build
9065 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9068 cond
= gimple_boolify (cond
);
9070 basic_block cond_bb
, then_bb
, else_bb
;
9074 tmp_var
= create_tmp_var (TREE_TYPE (device
));
9076 e
= split_block_after_labels (new_bb
);
9079 gsi
= gsi_last_bb (new_bb
);
9081 e
= split_block (new_bb
, gsi_stmt (gsi
));
9087 then_bb
= create_empty_bb (cond_bb
);
9088 else_bb
= create_empty_bb (then_bb
);
9089 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
9090 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
9092 stmt
= gimple_build_cond_empty (cond
);
9093 gsi
= gsi_last_bb (cond_bb
);
9094 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9096 gsi
= gsi_start_bb (then_bb
);
9097 stmt
= gimple_build_assign (tmp_var
, device
);
9098 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9100 gsi
= gsi_start_bb (else_bb
);
9101 stmt
= gimple_build_assign (tmp_var
,
9102 build_int_cst (integer_type_node
,
9103 GOMP_DEVICE_HOST_FALLBACK
));
9104 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9106 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
9107 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
9108 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
9109 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
9110 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
9111 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
9116 gsi
= gsi_last_bb (new_bb
);
9117 t
= gimple_omp_target_data_arg (entry_stmt
);
9120 t1
= size_zero_node
;
9121 t2
= build_zero_cst (ptr_type_node
);
9127 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
9128 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
9129 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
9130 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
9131 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
9135 /* The maximum number used by any start_ix, without varargs. */
9136 auto_vec
<tree
, 11> args
;
9137 args
.quick_push (device
);
9139 args
.quick_push (build_fold_addr_expr (child_fn
));
9142 case BUILT_IN_GOMP_TARGET
:
9143 case BUILT_IN_GOMP_TARGET_DATA
:
9144 case BUILT_IN_GOMP_TARGET_UPDATE
:
9145 /* This const void * is part of the current ABI, but we're not actually
9147 args
.quick_push (build_zero_cst (ptr_type_node
));
9149 case BUILT_IN_GOACC_DATA_START
:
9150 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9151 case BUILT_IN_GOACC_PARALLEL
:
9152 case BUILT_IN_GOACC_UPDATE
:
9157 args
.quick_push (t1
);
9158 args
.quick_push (t2
);
9159 args
.quick_push (t3
);
9160 args
.quick_push (t4
);
9163 case BUILT_IN_GOACC_DATA_START
:
9164 case BUILT_IN_GOMP_TARGET
:
9165 case BUILT_IN_GOMP_TARGET_DATA
:
9166 case BUILT_IN_GOMP_TARGET_UPDATE
:
9168 case BUILT_IN_GOACC_PARALLEL
:
9170 tree t_num_gangs
, t_num_workers
, t_vector_length
;
9172 /* Default values for num_gangs, num_workers, and vector_length. */
9173 t_num_gangs
= t_num_workers
= t_vector_length
9174 = fold_convert_loc (gimple_location (entry_stmt
),
9175 integer_type_node
, integer_one_node
);
9176 /* ..., but if present, use the value specified by the respective
9177 clause, making sure that are of the correct type. */
9178 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
9180 t_num_gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9182 OMP_CLAUSE_NUM_GANGS_EXPR (c
));
9183 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_WORKERS
);
9185 t_num_workers
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9187 OMP_CLAUSE_NUM_WORKERS_EXPR (c
));
9188 c
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
9190 t_vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9192 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c
));
9193 args
.quick_push (t_num_gangs
);
9194 args
.quick_push (t_num_workers
);
9195 args
.quick_push (t_vector_length
);
9198 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9199 case BUILT_IN_GOACC_UPDATE
:
9204 /* Default values for t_async. */
9205 t_async
= fold_convert_loc (gimple_location (entry_stmt
),
9207 build_int_cst (integer_type_node
,
9209 /* ..., but if present, use the value specified by the respective
9210 clause, making sure that is of the correct type. */
9211 c
= find_omp_clause (clauses
, OMP_CLAUSE_ASYNC
);
9213 t_async
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9215 OMP_CLAUSE_ASYNC_EXPR (c
));
9217 args
.quick_push (t_async
);
9218 /* Save the index, and... */
9219 t_wait_idx
= args
.length ();
9220 /* ... push a default value. */
9221 args
.quick_push (fold_convert_loc (gimple_location (entry_stmt
),
9223 integer_zero_node
));
9224 c
= find_omp_clause (clauses
, OMP_CLAUSE_WAIT
);
9229 for (; c
; c
= OMP_CLAUSE_CHAIN (c
))
9231 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WAIT
)
9233 args
.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9235 OMP_CLAUSE_WAIT_EXPR (c
)));
9240 /* Now that we know the number, replace the default value. */
9241 args
.ordered_remove (t_wait_idx
);
9242 args
.quick_insert (t_wait_idx
,
9243 fold_convert_loc (gimple_location (entry_stmt
),
9245 build_int_cst (integer_type_node
, n
)));
9253 g
= gimple_build_call_vec (builtin_decl_explicit (start_ix
), args
);
9254 gimple_set_location (g
, gimple_location (entry_stmt
));
9255 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
9259 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
9260 gsi_remove (&gsi
, true);
9265 gsi
= gsi_last_bb (region
->exit
);
9267 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
9268 gsi_remove (&gsi
, true);
9273 /* Expand the parallel region tree rooted at REGION. Expansion
9274 proceeds in depth-first order. Innermost regions are expanded
9275 first. This way, parallel regions that require a new function to
9276 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9277 internal dependencies in their body. */
9280 expand_omp (struct omp_region
*region
)
9284 location_t saved_location
;
9285 gimple inner_stmt
= NULL
;
9287 /* First, determine whether this is a combined parallel+workshare
9289 if (region
->type
== GIMPLE_OMP_PARALLEL
)
9290 determine_parallel_type (region
);
9292 if (region
->type
== GIMPLE_OMP_FOR
9293 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
9294 inner_stmt
= last_stmt (region
->inner
->entry
);
9297 expand_omp (region
->inner
);
9299 saved_location
= input_location
;
9300 if (gimple_has_location (last_stmt (region
->entry
)))
9301 input_location
= gimple_location (last_stmt (region
->entry
));
9303 switch (region
->type
)
9305 case GIMPLE_OMP_PARALLEL
:
9306 case GIMPLE_OMP_TASK
:
9307 expand_omp_taskreg (region
);
9310 case GIMPLE_OMP_FOR
:
9311 expand_omp_for (region
, inner_stmt
);
9314 case GIMPLE_OMP_SECTIONS
:
9315 expand_omp_sections (region
);
9318 case GIMPLE_OMP_SECTION
:
9319 /* Individual omp sections are handled together with their
9320 parent GIMPLE_OMP_SECTIONS region. */
9323 case GIMPLE_OMP_SINGLE
:
9324 expand_omp_single (region
);
9327 case GIMPLE_OMP_MASTER
:
9328 case GIMPLE_OMP_TASKGROUP
:
9329 case GIMPLE_OMP_ORDERED
:
9330 case GIMPLE_OMP_CRITICAL
:
9331 case GIMPLE_OMP_TEAMS
:
9332 expand_omp_synch (region
);
9335 case GIMPLE_OMP_ATOMIC_LOAD
:
9336 expand_omp_atomic (region
);
9339 case GIMPLE_OMP_TARGET
:
9340 expand_omp_target (region
);
9347 input_location
= saved_location
;
9348 region
= region
->next
;
9353 /* Helper for build_omp_regions. Scan the dominator tree starting at
9354 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9355 true, the function ends once a single tree is built (otherwise, whole
9356 forest of OMP constructs may be built). */
9359 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
9362 gimple_stmt_iterator gsi
;
9366 gsi
= gsi_last_bb (bb
);
9367 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
9369 struct omp_region
*region
;
9370 enum gimple_code code
;
9372 stmt
= gsi_stmt (gsi
);
9373 code
= gimple_code (stmt
);
9374 if (code
== GIMPLE_OMP_RETURN
)
9376 /* STMT is the return point out of region PARENT. Mark it
9377 as the exit point and make PARENT the immediately
9378 enclosing region. */
9379 gcc_assert (parent
);
9382 parent
= parent
->outer
;
9384 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
9386 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9387 GIMPLE_OMP_RETURN, but matches with
9388 GIMPLE_OMP_ATOMIC_LOAD. */
9389 gcc_assert (parent
);
9390 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
9393 parent
= parent
->outer
;
9395 else if (code
== GIMPLE_OMP_CONTINUE
)
9397 gcc_assert (parent
);
9400 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
9402 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9403 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9407 region
= new_omp_region (bb
, code
, parent
);
9409 if (code
== GIMPLE_OMP_TARGET
)
9411 switch (gimple_omp_target_kind (stmt
))
9413 case GF_OMP_TARGET_KIND_REGION
:
9414 case GF_OMP_TARGET_KIND_DATA
:
9415 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
9416 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
9417 case GF_OMP_TARGET_KIND_OACC_DATA
:
9419 case GF_OMP_TARGET_KIND_UPDATE
:
9420 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9421 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9422 /* ..., other than for those stand-alone directives... */
9429 /* ..., this directive becomes the parent for a new region. */
9435 if (single_tree
&& !parent
)
9438 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
9440 son
= next_dom_son (CDI_DOMINATORS
, son
))
9441 build_omp_regions_1 (son
, parent
, single_tree
);
9444 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9448 build_omp_regions_root (basic_block root
)
9450 gcc_assert (root_omp_region
== NULL
);
9451 build_omp_regions_1 (root
, NULL
, true);
9452 gcc_assert (root_omp_region
!= NULL
);
9455 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9458 omp_expand_local (basic_block head
)
9460 build_omp_regions_root (head
);
9461 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
9463 fprintf (dump_file
, "\nOMP region tree\n\n");
9464 dump_omp_region (dump_file
, root_omp_region
, 0);
9465 fprintf (dump_file
, "\n");
9468 remove_exit_barriers (root_omp_region
);
9469 expand_omp (root_omp_region
);
9471 free_omp_regions ();
9474 /* Scan the CFG and build a tree of OMP regions. Return the root of
9475 the OMP region tree. */
9478 build_omp_regions (void)
9480 gcc_assert (root_omp_region
== NULL
);
9481 calculate_dominance_info (CDI_DOMINATORS
);
9482 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
9485 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9488 execute_expand_omp (void)
9490 build_omp_regions ();
9492 if (!root_omp_region
)
9497 fprintf (dump_file
, "\nOMP region tree\n\n");
9498 dump_omp_region (dump_file
, root_omp_region
, 0);
9499 fprintf (dump_file
, "\n");
9502 remove_exit_barriers (root_omp_region
);
9504 expand_omp (root_omp_region
);
9506 cleanup_tree_cfg ();
9508 free_omp_regions ();
9513 /* OMP expansion -- the default pass, run before creation of SSA form. */
9517 const pass_data pass_data_expand_omp
=
9519 GIMPLE_PASS
, /* type */
9520 "ompexp", /* name */
9521 OPTGROUP_NONE
, /* optinfo_flags */
9522 TV_NONE
, /* tv_id */
9523 PROP_gimple_any
, /* properties_required */
9524 PROP_gimple_eomp
, /* properties_provided */
9525 0, /* properties_destroyed */
9526 0, /* todo_flags_start */
9527 0, /* todo_flags_finish */
9530 class pass_expand_omp
: public gimple_opt_pass
9533 pass_expand_omp (gcc::context
*ctxt
)
9534 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
9537 /* opt_pass methods: */
9538 virtual unsigned int execute (function
*)
9540 bool gate
= ((flag_cilkplus
!= 0 || flag_openacc
!= 0 || flag_openmp
!= 0
9541 || flag_openmp_simd
!= 0)
9544 /* This pass always runs, to provide PROP_gimple_eomp.
9545 But often, there is nothing to do. */
9549 return execute_expand_omp ();
9552 }; // class pass_expand_omp
9557 make_pass_expand_omp (gcc::context
*ctxt
)
9559 return new pass_expand_omp (ctxt
);
9564 const pass_data pass_data_expand_omp_ssa
=
9566 GIMPLE_PASS
, /* type */
9567 "ompexpssa", /* name */
9568 OPTGROUP_NONE
, /* optinfo_flags */
9569 TV_NONE
, /* tv_id */
9570 PROP_cfg
| PROP_ssa
, /* properties_required */
9571 PROP_gimple_eomp
, /* properties_provided */
9572 0, /* properties_destroyed */
9573 0, /* todo_flags_start */
9574 TODO_cleanup_cfg
| TODO_rebuild_alias
, /* todo_flags_finish */
9577 class pass_expand_omp_ssa
: public gimple_opt_pass
9580 pass_expand_omp_ssa (gcc::context
*ctxt
)
9581 : gimple_opt_pass (pass_data_expand_omp_ssa
, ctxt
)
9584 /* opt_pass methods: */
9585 virtual bool gate (function
*fun
)
9587 return !(fun
->curr_properties
& PROP_gimple_eomp
);
9589 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
9591 }; // class pass_expand_omp_ssa
9596 make_pass_expand_omp_ssa (gcc::context
*ctxt
)
9598 return new pass_expand_omp_ssa (ctxt
);
9601 /* Routines to lower OMP directives into OMP-GIMPLE. */
9603 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9604 convert it to gimple. */
9606 oacc_gimple_assign (tree dest
, tree_code op
, tree src
, gimple_seq
*seq
)
9610 if (TREE_CODE (TREE_TYPE (dest
)) != COMPLEX_TYPE
)
9612 stmt
= gimple_build_assign (dest
, op
, dest
, src
);
9613 gimple_seq_add_stmt (seq
, stmt
);
9617 tree t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9618 tree rdest
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9619 gimplify_assign (t
, rdest
, seq
);
9622 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9623 tree idest
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9624 gimplify_assign (t
, idest
, seq
);
9627 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9628 tree rsrc
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9629 gimplify_assign (t
, rsrc
, seq
);
9632 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9633 tree isrc
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9634 gimplify_assign (t
, isrc
, seq
);
9637 tree r
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9638 tree i
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9641 if (op
== PLUS_EXPR
)
9643 stmt
= gimple_build_assign (r
, op
, rdest
, rsrc
);
9644 gimple_seq_add_stmt (seq
, stmt
);
9646 stmt
= gimple_build_assign (i
, op
, idest
, isrc
);
9647 gimple_seq_add_stmt (seq
, stmt
);
9649 else if (op
== MULT_EXPR
)
9651 /* Let x = a + ib = dest, y = c + id = src.
9652 x * y = (ac - bd) + i(ad + bc) */
9653 tree ac
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9654 tree bd
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9655 tree ad
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9656 tree bc
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9658 stmt
= gimple_build_assign (ac
, MULT_EXPR
, rdest
, rsrc
);
9659 gimple_seq_add_stmt (seq
, stmt
);
9661 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, isrc
);
9662 gimple_seq_add_stmt (seq
, stmt
);
9664 stmt
= gimple_build_assign (r
, MINUS_EXPR
, ac
, bd
);
9665 gimple_seq_add_stmt (seq
, stmt
);
9667 stmt
= gimple_build_assign (ad
, MULT_EXPR
, rdest
, isrc
);
9668 gimple_seq_add_stmt (seq
, stmt
);
9670 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, rsrc
);
9671 gimple_seq_add_stmt (seq
, stmt
);
9673 stmt
= gimple_build_assign (i
, PLUS_EXPR
, ad
, bc
);
9674 gimple_seq_add_stmt (seq
, stmt
);
9679 result
= build2 (COMPLEX_EXPR
, TREE_TYPE (dest
), r
, i
);
9680 gimplify_assign (dest
, result
, seq
);
9683 /* Helper function to initialize local data for the reduction arrays.
9684 The reduction arrays need to be placed inside the calling function
9685 for accelerators, or else the host won't be able to preform the final
9689 oacc_initialize_reduction_data (tree clauses
, tree nthreads
,
9690 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9696 /* Find the innermost OpenACC parallel context. */
9697 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
9698 && (gimple_omp_target_kind (ctx
->stmt
)
9699 == GF_OMP_TARGET_KIND_OACC_PARALLEL
))
9703 gcc_checking_assert (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
9704 && (gimple_omp_target_kind (octx
->stmt
)
9705 == GF_OMP_TARGET_KIND_OACC_PARALLEL
));
9707 /* Extract the clauses. */
9708 oc
= gimple_omp_target_clauses (octx
->stmt
);
9710 /* Find the last outer clause. */
9711 for (; oc
&& OMP_CLAUSE_CHAIN (oc
); oc
= OMP_CLAUSE_CHAIN (oc
))
9714 /* Allocate arrays for each reduction variable. */
9715 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9717 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9720 tree var
= OMP_CLAUSE_DECL (c
);
9721 tree type
= get_base_type (var
);
9722 tree array
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
),
9726 /* Calculate size of the reduction array. */
9727 t
= create_tmp_var (TREE_TYPE (nthreads
));
9728 stmt
= gimple_build_assign (t
, MULT_EXPR
, nthreads
,
9729 fold_convert (TREE_TYPE (nthreads
),
9730 TYPE_SIZE_UNIT (type
)));
9731 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9733 size
= create_tmp_var (sizetype
);
9734 gimplify_assign (size
, fold_build1 (NOP_EXPR
, sizetype
, t
), stmt_seqp
);
9736 /* Now allocate memory for it. */
9737 call
= unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA
));
9738 stmt
= gimple_build_call (call
, 1, size
);
9739 gimple_call_set_lhs (stmt
, array
);
9740 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9742 /* Map this array into the accelerator. */
9744 /* Add the reduction array to the list of clauses. */
9746 t
= build_omp_clause (gimple_location (ctx
->stmt
), OMP_CLAUSE_MAP
);
9747 OMP_CLAUSE_SET_MAP_KIND (t
, GOMP_MAP_FORCE_FROM
);
9748 OMP_CLAUSE_DECL (t
) = x
;
9749 OMP_CLAUSE_CHAIN (t
) = NULL
;
9751 OMP_CLAUSE_CHAIN (oc
) = t
;
9753 gimple_omp_target_set_clauses (as_a
<gomp_target
*> (octx
->stmt
), t
);
9754 OMP_CLAUSE_SIZE (t
) = size
;
9759 /* Helper function to process the array of partial reductions. Nthreads
9760 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9761 cannot be used here, because nthreads on the host may be different than
9762 on the accelerator. */
9765 oacc_finalize_reduction_data (tree clauses
, tree nthreads
,
9766 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9768 tree c
, x
, var
, array
, loop_header
, loop_body
, loop_exit
, type
;
9773 let var = the original reduction variable
9774 let array = reduction variable array
9776 for (i = 0; i < nthreads; i++)
9780 loop_header
= create_artificial_label (UNKNOWN_LOCATION
);
9781 loop_body
= create_artificial_label (UNKNOWN_LOCATION
);
9782 loop_exit
= create_artificial_label (UNKNOWN_LOCATION
);
9784 /* Create and initialize an index variable. */
9785 tree ix
= create_tmp_var (sizetype
);
9786 gimplify_assign (ix
, fold_build1 (NOP_EXPR
, sizetype
, integer_zero_node
),
9789 /* Insert the loop header label here. */
9790 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_header
));
9792 /* Exit loop if ix >= nthreads. */
9793 x
= create_tmp_var (sizetype
);
9794 gimplify_assign (x
, fold_build1 (NOP_EXPR
, sizetype
, nthreads
), stmt_seqp
);
9795 stmt
= gimple_build_cond (GE_EXPR
, ix
, x
, loop_exit
, loop_body
);
9796 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9798 /* Insert the loop body label here. */
9799 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_body
));
9801 /* Collapse each reduction array, one element at a time. */
9802 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9804 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9807 tree_code reduction_code
= OMP_CLAUSE_REDUCTION_CODE (c
);
9809 /* reduction(-:var) sums up the partial results, so it acts
9810 identically to reduction(+:var). */
9811 if (reduction_code
== MINUS_EXPR
)
9812 reduction_code
= PLUS_EXPR
;
9814 /* Set up reduction variable var. */
9815 var
= OMP_CLAUSE_DECL (c
);
9816 type
= get_base_type (var
);
9817 array
= lookup_oacc_reduction (oacc_get_reduction_array_id
9818 (OMP_CLAUSE_DECL (c
)), ctx
);
9820 /* Calculate the array offset. */
9821 tree offset
= create_tmp_var (sizetype
);
9822 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
), stmt_seqp
);
9823 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, ix
);
9824 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9826 tree ptr
= create_tmp_var (TREE_TYPE (array
));
9827 stmt
= gimple_build_assign (ptr
, POINTER_PLUS_EXPR
, array
, offset
);
9828 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9830 /* Extract array[ix] into mem. */
9831 tree mem
= create_tmp_var (type
);
9832 gimplify_assign (mem
, build_simple_mem_ref (ptr
), stmt_seqp
);
9834 /* Find the original reduction variable. */
9835 if (is_reference (var
))
9836 var
= build_simple_mem_ref (var
);
9838 tree t
= create_tmp_var (type
);
9840 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, t
, var
);
9841 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9843 /* var = var op mem */
9844 switch (OMP_CLAUSE_REDUCTION_CODE (c
))
9846 case TRUTH_ANDIF_EXPR
:
9847 case TRUTH_ORIF_EXPR
:
9848 t
= fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c
), integer_type_node
,
9850 gimplify_and_add (t
, stmt_seqp
);
9853 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9854 oacc_gimple_assign (t
, OMP_CLAUSE_REDUCTION_CODE (c
), mem
,
9858 t
= fold_build1 (NOP_EXPR
, TREE_TYPE (var
), t
);
9859 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, var
, t
);
9860 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9863 /* Increment the induction variable. */
9864 tree one
= fold_build1 (NOP_EXPR
, sizetype
, integer_one_node
);
9865 stmt
= gimple_build_assign (ix
, PLUS_EXPR
, ix
, one
);
9866 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9868 /* Go back to the top of the loop. */
9869 gimple_seq_add_stmt (stmt_seqp
, gimple_build_goto (loop_header
));
9871 /* Place the loop exit label here. */
9872 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_exit
));
9875 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9876 scan that for reductions. */
9879 oacc_process_reduction_data (gimple_seq
*body
, gimple_seq
*in_stmt_seqp
,
9880 gimple_seq
*out_stmt_seqp
, omp_context
*ctx
)
9882 gimple_stmt_iterator gsi
;
9883 gimple_seq inner
= NULL
;
9885 /* A collapse clause may have inserted a new bind block. */
9886 gsi
= gsi_start (*body
);
9887 while (!gsi_end_p (gsi
))
9889 gimple stmt
= gsi_stmt (gsi
);
9890 if (gbind
*bind_stmt
= dyn_cast
<gbind
*> (stmt
))
9892 inner
= gimple_bind_body (bind_stmt
);
9894 gsi
= gsi_start (*body
);
9896 else if (dyn_cast
<gomp_for
*> (stmt
))
9902 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
9904 tree clauses
, nthreads
, t
, c
, acc_device
, acc_device_host
, call
,
9906 bool reduction_found
= false;
9908 gimple stmt
= gsi_stmt (gsi
);
9910 switch (gimple_code (stmt
))
9912 case GIMPLE_OMP_FOR
:
9913 clauses
= gimple_omp_for_clauses (stmt
);
9915 /* Search for a reduction clause. */
9916 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9917 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
9919 reduction_found
= true;
9923 if (!reduction_found
)
9926 ctx
= maybe_lookup_ctx (stmt
);
9929 /* Extract the number of threads. */
9930 nthreads
= create_tmp_var (sizetype
);
9931 t
= oacc_max_threads (ctx
);
9932 gimplify_assign (nthreads
, t
, in_stmt_seqp
);
9934 /* Determine if this is kernel will be executed on the host. */
9935 call
= builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE
);
9936 acc_device
= create_tmp_var (integer_type_node
, ".acc_device_type");
9937 stmt
= gimple_build_call (call
, 0);
9938 gimple_call_set_lhs (stmt
, acc_device
);
9939 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9941 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9942 acc_device_host
= create_tmp_var (integer_type_node
,
9943 ".acc_device_host");
9944 gimplify_assign (acc_device_host
,
9945 build_int_cst (integer_type_node
,
9949 enter
= create_artificial_label (UNKNOWN_LOCATION
);
9950 exit
= create_artificial_label (UNKNOWN_LOCATION
);
9952 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
9954 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9955 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
9956 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
9959 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
9961 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9962 gimplify_assign (acc_device_host
,
9963 build_int_cst (integer_type_node
,
9964 GOMP_DEVICE_HOST_NONSHM
),
9967 enter
= create_artificial_label (UNKNOWN_LOCATION
);
9968 exit
= create_artificial_label (UNKNOWN_LOCATION
);
9970 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
9972 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9973 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
9974 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
9977 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
9979 oacc_initialize_reduction_data (clauses
, nthreads
, in_stmt_seqp
,
9981 oacc_finalize_reduction_data (clauses
, nthreads
, out_stmt_seqp
, ctx
);
9984 // Scan for other directives which support reduction here.
9990 /* If ctx is a worksharing context inside of a cancellable parallel
9991 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9992 and conditional branch to parallel's cancel_label to handle
9993 cancellation in the implicit barrier. */
9996 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
9998 gimple omp_return
= gimple_seq_last_stmt (*body
);
9999 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
10000 if (gimple_omp_return_nowait_p (omp_return
))
10003 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
10004 && ctx
->outer
->cancellable
)
10006 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
10007 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
10008 tree lhs
= create_tmp_var (c_bool_type
);
10009 gimple_omp_return_set_lhs (omp_return
, lhs
);
10010 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
10011 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
10012 fold_convert (c_bool_type
,
10013 boolean_false_node
),
10014 ctx
->outer
->cancel_label
, fallthru_label
);
10015 gimple_seq_add_stmt (body
, g
);
10016 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
10020 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10021 CTX is the enclosing OMP context for the current statement. */
10024 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10026 tree block
, control
;
10027 gimple_stmt_iterator tgsi
;
10028 gomp_sections
*stmt
;
10030 gbind
*new_stmt
, *bind
;
10031 gimple_seq ilist
, dlist
, olist
, new_body
;
10033 stmt
= as_a
<gomp_sections
*> (gsi_stmt (*gsi_p
));
10035 push_gimplify_context ();
10039 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
10040 &ilist
, &dlist
, ctx
, NULL
);
10042 new_body
= gimple_omp_body (stmt
);
10043 gimple_omp_set_body (stmt
, NULL
);
10044 tgsi
= gsi_start (new_body
);
10045 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
10050 sec_start
= gsi_stmt (tgsi
);
10051 sctx
= maybe_lookup_ctx (sec_start
);
10054 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
10055 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
10056 GSI_CONTINUE_LINKING
);
10057 gimple_omp_set_body (sec_start
, NULL
);
10059 if (gsi_one_before_end_p (tgsi
))
10061 gimple_seq l
= NULL
;
10062 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
10064 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
10065 gimple_omp_section_set_last (sec_start
);
10068 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
10069 GSI_CONTINUE_LINKING
);
10072 block
= make_node (BLOCK
);
10073 bind
= gimple_build_bind (NULL
, new_body
, block
);
10076 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
10078 block
= make_node (BLOCK
);
10079 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10080 gsi_replace (gsi_p
, new_stmt
, true);
10082 pop_gimplify_context (new_stmt
);
10083 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10084 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10085 if (BLOCK_VARS (block
))
10086 TREE_USED (block
) = 1;
10089 gimple_seq_add_seq (&new_body
, ilist
);
10090 gimple_seq_add_stmt (&new_body
, stmt
);
10091 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
10092 gimple_seq_add_stmt (&new_body
, bind
);
10094 control
= create_tmp_var (unsigned_type_node
, ".section");
10095 t
= gimple_build_omp_continue (control
, control
);
10096 gimple_omp_sections_set_control (stmt
, control
);
10097 gimple_seq_add_stmt (&new_body
, t
);
10099 gimple_seq_add_seq (&new_body
, olist
);
10100 if (ctx
->cancellable
)
10101 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
10102 gimple_seq_add_seq (&new_body
, dlist
);
10104 new_body
= maybe_catch_exception (new_body
);
10106 t
= gimple_build_omp_return
10107 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
10108 OMP_CLAUSE_NOWAIT
));
10109 gimple_seq_add_stmt (&new_body
, t
);
10110 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
10112 gimple_bind_set_body (new_stmt
, new_body
);
10116 /* A subroutine of lower_omp_single. Expand the simple form of
10117 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10119 if (GOMP_single_start ())
10121 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10123 FIXME. It may be better to delay expanding the logic of this until
10124 pass_expand_omp. The expanded logic may make the job more difficult
10125 to a synchronization analysis pass. */
10128 lower_omp_single_simple (gomp_single
*single_stmt
, gimple_seq
*pre_p
)
10130 location_t loc
= gimple_location (single_stmt
);
10131 tree tlabel
= create_artificial_label (loc
);
10132 tree flabel
= create_artificial_label (loc
);
10136 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
10137 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)));
10138 call
= gimple_build_call (decl
, 0);
10139 gimple_call_set_lhs (call
, lhs
);
10140 gimple_seq_add_stmt (pre_p
, call
);
10142 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
10143 fold_convert_loc (loc
, TREE_TYPE (lhs
),
10144 boolean_true_node
),
10146 gimple_seq_add_stmt (pre_p
, cond
);
10147 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
10148 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10149 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
10153 /* A subroutine of lower_omp_single. Expand the simple form of
10154 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10156 #pragma omp single copyprivate (a, b, c)
10158 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10161 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10167 GOMP_single_copy_end (©out);
10178 FIXME. It may be better to delay expanding the logic of this until
10179 pass_expand_omp. The expanded logic may make the job more difficult
10180 to a synchronization analysis pass. */
10183 lower_omp_single_copy (gomp_single
*single_stmt
, gimple_seq
*pre_p
,
10186 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
10187 gimple_seq copyin_seq
;
10188 location_t loc
= gimple_location (single_stmt
);
10190 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
10192 ptr_type
= build_pointer_type (ctx
->record_type
);
10193 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
10195 l0
= create_artificial_label (loc
);
10196 l1
= create_artificial_label (loc
);
10197 l2
= create_artificial_label (loc
);
10199 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
10200 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
10201 t
= fold_convert_loc (loc
, ptr_type
, t
);
10202 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
10204 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
10205 build_int_cst (ptr_type
, 0));
10206 t
= build3 (COND_EXPR
, void_type_node
, t
,
10207 build_and_jump (&l0
), build_and_jump (&l1
));
10208 gimplify_and_add (t
, pre_p
);
10210 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
10212 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10215 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
10218 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10219 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
10220 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
10221 gimplify_and_add (t
, pre_p
);
10223 t
= build_and_jump (&l2
);
10224 gimplify_and_add (t
, pre_p
);
10226 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
10228 gimple_seq_add_seq (pre_p
, copyin_seq
);
10230 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
10234 /* Expand code for an OpenMP single directive. */
10237 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10241 gomp_single
*single_stmt
= as_a
<gomp_single
*> (gsi_stmt (*gsi_p
));
10243 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
10245 push_gimplify_context ();
10247 block
= make_node (BLOCK
);
10248 bind
= gimple_build_bind (NULL
, NULL
, block
);
10249 gsi_replace (gsi_p
, bind
, true);
10252 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
10253 &bind_body
, &dlist
, ctx
, NULL
);
10254 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
10256 gimple_seq_add_stmt (&bind_body
, single_stmt
);
10258 if (ctx
->record_type
)
10259 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
10261 lower_omp_single_simple (single_stmt
, &bind_body
);
10263 gimple_omp_set_body (single_stmt
, NULL
);
10265 gimple_seq_add_seq (&bind_body
, dlist
);
10267 bind_body
= maybe_catch_exception (bind_body
);
10269 t
= gimple_build_omp_return
10270 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
10271 OMP_CLAUSE_NOWAIT
));
10272 gimple_seq_add_stmt (&bind_body_tail
, t
);
10273 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
10274 if (ctx
->record_type
)
10276 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
10277 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
10278 TREE_THIS_VOLATILE (clobber
) = 1;
10279 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
10280 clobber
), GSI_SAME_STMT
);
10282 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
10283 gimple_bind_set_body (bind
, bind_body
);
10285 pop_gimplify_context (bind
);
10287 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10288 BLOCK_VARS (block
) = ctx
->block_vars
;
10289 if (BLOCK_VARS (block
))
10290 TREE_USED (block
) = 1;
10294 /* Expand code for an OpenMP master directive. */
10297 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10299 tree block
, lab
= NULL
, x
, bfn_decl
;
10300 gimple stmt
= gsi_stmt (*gsi_p
);
10302 location_t loc
= gimple_location (stmt
);
10305 push_gimplify_context ();
10307 block
= make_node (BLOCK
);
10308 bind
= gimple_build_bind (NULL
, NULL
, block
);
10309 gsi_replace (gsi_p
, bind
, true);
10310 gimple_bind_add_stmt (bind
, stmt
);
10312 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
10313 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
10314 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
10315 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
10317 gimplify_and_add (x
, &tseq
);
10318 gimple_bind_add_seq (bind
, tseq
);
10320 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10321 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10322 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10323 gimple_omp_set_body (stmt
, NULL
);
10325 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
10327 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10329 pop_gimplify_context (bind
);
10331 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10332 BLOCK_VARS (block
) = ctx
->block_vars
;
10336 /* Expand code for an OpenMP taskgroup directive. */
10339 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10341 gimple stmt
= gsi_stmt (*gsi_p
);
10344 tree block
= make_node (BLOCK
);
10346 bind
= gimple_build_bind (NULL
, NULL
, block
);
10347 gsi_replace (gsi_p
, bind
, true);
10348 gimple_bind_add_stmt (bind
, stmt
);
10350 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
10352 gimple_bind_add_stmt (bind
, x
);
10354 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10355 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10356 gimple_omp_set_body (stmt
, NULL
);
10358 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10360 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10361 BLOCK_VARS (block
) = ctx
->block_vars
;
10365 /* Expand code for an OpenMP ordered directive. */
10368 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10371 gimple stmt
= gsi_stmt (*gsi_p
);
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 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
10384 gimple_bind_add_stmt (bind
, x
);
10386 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10387 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10388 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10389 gimple_omp_set_body (stmt
, NULL
);
10391 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
10392 gimple_bind_add_stmt (bind
, x
);
10394 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10396 pop_gimplify_context (bind
);
10398 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10399 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10403 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10404 substitution of a couple of function calls. But in the NAMED case,
10405 requires that languages coordinate a symbol name. It is therefore
10406 best put here in common code. */
10408 static GTY(()) hash_map
<tree
, tree
> *critical_name_mutexes
;
10411 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10414 tree name
, lock
, unlock
;
10415 gomp_critical
*stmt
= as_a
<gomp_critical
*> (gsi_stmt (*gsi_p
));
10417 location_t loc
= gimple_location (stmt
);
10420 name
= gimple_omp_critical_name (stmt
);
10425 if (!critical_name_mutexes
)
10426 critical_name_mutexes
= hash_map
<tree
, tree
>::create_ggc (10);
10428 tree
*n
= critical_name_mutexes
->get (name
);
10433 decl
= create_tmp_var_raw (ptr_type_node
);
10435 new_str
= ACONCAT ((".gomp_critical_user_",
10436 IDENTIFIER_POINTER (name
), NULL
));
10437 DECL_NAME (decl
) = get_identifier (new_str
);
10438 TREE_PUBLIC (decl
) = 1;
10439 TREE_STATIC (decl
) = 1;
10440 DECL_COMMON (decl
) = 1;
10441 DECL_ARTIFICIAL (decl
) = 1;
10442 DECL_IGNORED_P (decl
) = 1;
10444 varpool_node::finalize_decl (decl
);
10446 critical_name_mutexes
->put (name
, decl
);
10451 /* If '#pragma omp critical' is inside offloaded region or
10452 inside function marked as offloadable, the symbol must be
10453 marked as offloadable too. */
10455 if (cgraph_node::get (current_function_decl
)->offloadable
)
10456 varpool_node::get_create (decl
)->offloadable
= 1;
10458 for (octx
= ctx
->outer
; octx
; octx
= octx
->outer
)
10459 if (is_gimple_omp_offloaded (octx
->stmt
))
10461 varpool_node::get_create (decl
)->offloadable
= 1;
10465 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
10466 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
10468 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
10469 unlock
= build_call_expr_loc (loc
, unlock
, 1,
10470 build_fold_addr_expr_loc (loc
, decl
));
10474 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
10475 lock
= build_call_expr_loc (loc
, lock
, 0);
10477 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
10478 unlock
= build_call_expr_loc (loc
, unlock
, 0);
10481 push_gimplify_context ();
10483 block
= make_node (BLOCK
);
10484 bind
= gimple_build_bind (NULL
, NULL
, block
);
10485 gsi_replace (gsi_p
, bind
, true);
10486 gimple_bind_add_stmt (bind
, stmt
);
10488 tbody
= gimple_bind_body (bind
);
10489 gimplify_and_add (lock
, &tbody
);
10490 gimple_bind_set_body (bind
, tbody
);
10492 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10493 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10494 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10495 gimple_omp_set_body (stmt
, NULL
);
10497 tbody
= gimple_bind_body (bind
);
10498 gimplify_and_add (unlock
, &tbody
);
10499 gimple_bind_set_body (bind
, tbody
);
10501 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10503 pop_gimplify_context (bind
);
10504 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10505 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10509 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10510 for a lastprivate clause. Given a loop control predicate of (V
10511 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10512 is appended to *DLIST, iterator initialization is appended to
10516 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
10517 gimple_seq
*dlist
, struct omp_context
*ctx
)
10519 tree clauses
, cond
, vinit
;
10520 enum tree_code cond_code
;
10523 cond_code
= fd
->loop
.cond_code
;
10524 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
10526 /* When possible, use a strict equality expression. This can let VRP
10527 type optimizations deduce the value and remove a copy. */
10528 if (tree_fits_shwi_p (fd
->loop
.step
))
10530 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
10531 if (step
== 1 || step
== -1)
10532 cond_code
= EQ_EXPR
;
10535 tree n2
= fd
->loop
.n2
;
10536 if (fd
->collapse
> 1
10537 && TREE_CODE (n2
) != INTEGER_CST
10538 && gimple_omp_for_combined_into_p (fd
->for_stmt
)
10539 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_FOR
)
10541 gomp_for
*gfor
= as_a
<gomp_for
*> (ctx
->outer
->stmt
);
10542 if (gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_FOR
)
10544 struct omp_for_data outer_fd
;
10545 extract_omp_for_data (gfor
, &outer_fd
, NULL
);
10546 n2
= fold_convert (TREE_TYPE (n2
), outer_fd
.loop
.n2
);
10549 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, n2
);
10551 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
10553 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
10554 if (!gimple_seq_empty_p (stmts
))
10556 gimple_seq_add_seq (&stmts
, *dlist
);
10559 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10560 vinit
= fd
->loop
.n1
;
10561 if (cond_code
== EQ_EXPR
10562 && tree_fits_shwi_p (fd
->loop
.n2
)
10563 && ! integer_zerop (fd
->loop
.n2
))
10564 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
10566 vinit
= unshare_expr (vinit
);
10568 /* Initialize the iterator variable, so that threads that don't execute
10569 any iterations don't execute the lastprivate clauses by accident. */
10570 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
10575 /* Lower code for an OMP loop directive. */
10578 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10580 tree
*rhs_p
, block
;
10581 struct omp_for_data fd
, *fdp
= NULL
;
10582 gomp_for
*stmt
= as_a
<gomp_for
*> (gsi_stmt (*gsi_p
));
10584 gimple_seq omp_for_body
, body
, dlist
;
10587 push_gimplify_context ();
10589 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
10591 block
= make_node (BLOCK
);
10592 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10593 /* Replace at gsi right away, so that 'stmt' is no member
10594 of a sequence anymore as we're going to add to to a different
10596 gsi_replace (gsi_p
, new_stmt
, true);
10598 /* Move declaration of temporaries in the loop body before we make
10600 omp_for_body
= gimple_omp_body (stmt
);
10601 if (!gimple_seq_empty_p (omp_for_body
)
10602 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
10605 = as_a
<gbind
*> (gimple_seq_first_stmt (omp_for_body
));
10606 tree vars
= gimple_bind_vars (inner_bind
);
10607 gimple_bind_append_vars (new_stmt
, vars
);
10608 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10609 keep them on the inner_bind and it's block. */
10610 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
10611 if (gimple_bind_block (inner_bind
))
10612 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
10615 if (gimple_omp_for_combined_into_p (stmt
))
10617 extract_omp_for_data (stmt
, &fd
, NULL
);
10620 /* We need two temporaries with fd.loop.v type (istart/iend)
10621 and then (fd.collapse - 1) temporaries with the same
10622 type for count2 ... countN-1 vars if not constant. */
10624 tree type
= fd
.iter_type
;
10625 if (fd
.collapse
> 1
10626 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
10627 count
+= fd
.collapse
- 1;
10628 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
10629 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
10630 tree clauses
= *pc
;
10633 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
10634 OMP_CLAUSE__LOOPTEMP_
);
10635 for (i
= 0; i
< count
; i
++)
10640 gcc_assert (outerc
);
10641 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
10642 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
10643 OMP_CLAUSE__LOOPTEMP_
);
10647 temp
= create_tmp_var (type
);
10648 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
10650 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
10651 OMP_CLAUSE_DECL (*pc
) = temp
;
10652 pc
= &OMP_CLAUSE_CHAIN (*pc
);
10657 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10660 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
10662 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
10664 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10666 /* Lower the header expressions. At this point, we can assume that
10667 the header is of the form:
10669 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10671 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10672 using the .omp_data_s mapping, if needed. */
10673 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
10675 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
10676 if (!is_gimple_min_invariant (*rhs_p
))
10677 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10679 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
10680 if (!is_gimple_min_invariant (*rhs_p
))
10681 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10683 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
10684 if (!is_gimple_min_invariant (*rhs_p
))
10685 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10688 /* Once lowered, extract the bounds and clauses. */
10689 extract_omp_for_data (stmt
, &fd
, NULL
);
10691 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
10693 gimple_seq_add_stmt (&body
, stmt
);
10694 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
10696 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
10699 /* After the loop, add exit clauses. */
10700 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
10702 if (ctx
->cancellable
)
10703 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
10705 gimple_seq_add_seq (&body
, dlist
);
10707 body
= maybe_catch_exception (body
);
10709 /* Region exit marker goes at the end of the loop body. */
10710 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
10711 maybe_add_implicit_barrier_cancel (ctx
, &body
);
10712 pop_gimplify_context (new_stmt
);
10714 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10715 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
10716 if (BLOCK_VARS (block
))
10717 TREE_USED (block
) = 1;
10719 gimple_bind_set_body (new_stmt
, body
);
10720 gimple_omp_set_body (stmt
, NULL
);
10721 gimple_omp_for_set_pre_body (stmt
, NULL
);
10724 /* Callback for walk_stmts. Check if the current statement only contains
10725 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10728 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
10729 bool *handled_ops_p
,
10730 struct walk_stmt_info
*wi
)
10732 int *info
= (int *) wi
->info
;
10733 gimple stmt
= gsi_stmt (*gsi_p
);
10735 *handled_ops_p
= true;
10736 switch (gimple_code (stmt
))
10740 case GIMPLE_OMP_FOR
:
10741 case GIMPLE_OMP_SECTIONS
:
10742 *info
= *info
== 0 ? 1 : -1;
10751 struct omp_taskcopy_context
10753 /* This field must be at the beginning, as we do "inheritance": Some
10754 callback functions for tree-inline.c (e.g., omp_copy_decl)
10755 receive a copy_body_data pointer that is up-casted to an
10756 omp_context pointer. */
10762 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
10764 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
10766 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
10767 return create_tmp_var (TREE_TYPE (var
));
10773 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
10775 tree name
, new_fields
= NULL
, type
, f
;
10777 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
10778 name
= DECL_NAME (TYPE_NAME (orig_type
));
10779 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
10780 TYPE_DECL
, name
, type
);
10781 TYPE_NAME (type
) = name
;
10783 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
10785 tree new_f
= copy_node (f
);
10786 DECL_CONTEXT (new_f
) = type
;
10787 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
10788 TREE_CHAIN (new_f
) = new_fields
;
10789 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10790 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10791 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
10793 new_fields
= new_f
;
10794 tcctx
->cb
.decl_map
->put (f
, new_f
);
10796 TYPE_FIELDS (type
) = nreverse (new_fields
);
10797 layout_type (type
);
10801 /* Create task copyfn. */
10804 create_task_copyfn (gomp_task
*task_stmt
, omp_context
*ctx
)
10806 struct function
*child_cfun
;
10807 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
10808 tree record_type
, srecord_type
, bind
, list
;
10809 bool record_needs_remap
= false, srecord_needs_remap
= false;
10811 struct omp_taskcopy_context tcctx
;
10812 location_t loc
= gimple_location (task_stmt
);
10814 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
10815 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
10816 gcc_assert (child_cfun
->cfg
== NULL
);
10817 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
10819 /* Reset DECL_CONTEXT on function arguments. */
10820 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
10821 DECL_CONTEXT (t
) = child_fn
;
10823 /* Populate the function. */
10824 push_gimplify_context ();
10825 push_cfun (child_cfun
);
10827 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
10828 TREE_SIDE_EFFECTS (bind
) = 1;
10830 DECL_SAVED_TREE (child_fn
) = bind
;
10831 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
10833 /* Remap src and dst argument types if needed. */
10834 record_type
= ctx
->record_type
;
10835 srecord_type
= ctx
->srecord_type
;
10836 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
10837 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10839 record_needs_remap
= true;
10842 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
10843 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10845 srecord_needs_remap
= true;
10849 if (record_needs_remap
|| srecord_needs_remap
)
10851 memset (&tcctx
, '\0', sizeof (tcctx
));
10852 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
10853 tcctx
.cb
.dst_fn
= child_fn
;
10854 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
10855 gcc_checking_assert (tcctx
.cb
.src_node
);
10856 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
10857 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
10858 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
10859 tcctx
.cb
.eh_lp_nr
= 0;
10860 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
10861 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
10864 if (record_needs_remap
)
10865 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
10866 if (srecord_needs_remap
)
10867 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
10870 tcctx
.cb
.decl_map
= NULL
;
10872 arg
= DECL_ARGUMENTS (child_fn
);
10873 TREE_TYPE (arg
) = build_pointer_type (record_type
);
10874 sarg
= DECL_CHAIN (arg
);
10875 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
10877 /* First pass: initialize temporaries used in record_type and srecord_type
10878 sizes and field offsets. */
10879 if (tcctx
.cb
.decl_map
)
10880 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10881 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
10885 decl
= OMP_CLAUSE_DECL (c
);
10886 p
= tcctx
.cb
.decl_map
->get (decl
);
10889 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10890 sf
= (tree
) n
->value
;
10891 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10892 src
= build_simple_mem_ref_loc (loc
, sarg
);
10893 src
= omp_build_component_ref (src
, sf
);
10894 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
10895 append_to_statement_list (t
, &list
);
10898 /* Second pass: copy shared var pointers and copy construct non-VLA
10899 firstprivate vars. */
10900 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10901 switch (OMP_CLAUSE_CODE (c
))
10903 case OMP_CLAUSE_SHARED
:
10904 decl
= OMP_CLAUSE_DECL (c
);
10905 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10908 f
= (tree
) n
->value
;
10909 if (tcctx
.cb
.decl_map
)
10910 f
= *tcctx
.cb
.decl_map
->get (f
);
10911 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10912 sf
= (tree
) n
->value
;
10913 if (tcctx
.cb
.decl_map
)
10914 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10915 src
= build_simple_mem_ref_loc (loc
, sarg
);
10916 src
= omp_build_component_ref (src
, sf
);
10917 dst
= build_simple_mem_ref_loc (loc
, arg
);
10918 dst
= omp_build_component_ref (dst
, f
);
10919 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
10920 append_to_statement_list (t
, &list
);
10922 case OMP_CLAUSE_FIRSTPRIVATE
:
10923 decl
= OMP_CLAUSE_DECL (c
);
10924 if (is_variable_sized (decl
))
10926 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10929 f
= (tree
) n
->value
;
10930 if (tcctx
.cb
.decl_map
)
10931 f
= *tcctx
.cb
.decl_map
->get (f
);
10932 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10935 sf
= (tree
) n
->value
;
10936 if (tcctx
.cb
.decl_map
)
10937 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10938 src
= build_simple_mem_ref_loc (loc
, sarg
);
10939 src
= omp_build_component_ref (src
, sf
);
10940 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
10941 src
= build_simple_mem_ref_loc (loc
, src
);
10945 dst
= build_simple_mem_ref_loc (loc
, arg
);
10946 dst
= omp_build_component_ref (dst
, f
);
10947 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
10948 append_to_statement_list (t
, &list
);
10950 case OMP_CLAUSE_PRIVATE
:
10951 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
10953 decl
= OMP_CLAUSE_DECL (c
);
10954 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10955 f
= (tree
) n
->value
;
10956 if (tcctx
.cb
.decl_map
)
10957 f
= *tcctx
.cb
.decl_map
->get (f
);
10958 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10961 sf
= (tree
) n
->value
;
10962 if (tcctx
.cb
.decl_map
)
10963 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10964 src
= build_simple_mem_ref_loc (loc
, sarg
);
10965 src
= omp_build_component_ref (src
, sf
);
10966 if (use_pointer_for_field (decl
, NULL
))
10967 src
= build_simple_mem_ref_loc (loc
, src
);
10971 dst
= build_simple_mem_ref_loc (loc
, arg
);
10972 dst
= omp_build_component_ref (dst
, f
);
10973 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
10974 append_to_statement_list (t
, &list
);
10980 /* Last pass: handle VLA firstprivates. */
10981 if (tcctx
.cb
.decl_map
)
10982 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10983 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
10987 decl
= OMP_CLAUSE_DECL (c
);
10988 if (!is_variable_sized (decl
))
10990 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10993 f
= (tree
) n
->value
;
10994 f
= *tcctx
.cb
.decl_map
->get (f
);
10995 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
10996 ind
= DECL_VALUE_EXPR (decl
);
10997 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
10998 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
10999 n
= splay_tree_lookup (ctx
->sfield_map
,
11000 (splay_tree_key
) TREE_OPERAND (ind
, 0));
11001 sf
= (tree
) n
->value
;
11002 sf
= *tcctx
.cb
.decl_map
->get (sf
);
11003 src
= build_simple_mem_ref_loc (loc
, sarg
);
11004 src
= omp_build_component_ref (src
, sf
);
11005 src
= build_simple_mem_ref_loc (loc
, src
);
11006 dst
= build_simple_mem_ref_loc (loc
, arg
);
11007 dst
= omp_build_component_ref (dst
, f
);
11008 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
11009 append_to_statement_list (t
, &list
);
11010 n
= splay_tree_lookup (ctx
->field_map
,
11011 (splay_tree_key
) TREE_OPERAND (ind
, 0));
11012 df
= (tree
) n
->value
;
11013 df
= *tcctx
.cb
.decl_map
->get (df
);
11014 ptr
= build_simple_mem_ref_loc (loc
, arg
);
11015 ptr
= omp_build_component_ref (ptr
, df
);
11016 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
11017 build_fold_addr_expr_loc (loc
, dst
));
11018 append_to_statement_list (t
, &list
);
11021 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
11022 append_to_statement_list (t
, &list
);
11024 if (tcctx
.cb
.decl_map
)
11025 delete tcctx
.cb
.decl_map
;
11026 pop_gimplify_context (NULL
);
11027 BIND_EXPR_BODY (bind
) = list
;
11032 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
11036 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
11038 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
11039 OMP_CLAUSE_DEPEND
);
11040 gcc_assert (clauses
);
11041 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11042 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
11043 switch (OMP_CLAUSE_DEPEND_KIND (c
))
11045 case OMP_CLAUSE_DEPEND_IN
:
11048 case OMP_CLAUSE_DEPEND_OUT
:
11049 case OMP_CLAUSE_DEPEND_INOUT
:
11053 gcc_unreachable ();
11055 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
11056 tree array
= create_tmp_var (type
);
11057 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
11059 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
11060 gimple_seq_add_stmt (iseq
, g
);
11061 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
11063 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
11064 gimple_seq_add_stmt (iseq
, g
);
11065 for (i
= 0; i
< 2; i
++)
11067 if ((i
? n_in
: n_out
) == 0)
11069 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11070 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
11071 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
11073 tree t
= OMP_CLAUSE_DECL (c
);
11074 t
= fold_convert (ptr_type_node
, t
);
11075 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
11076 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
11077 NULL_TREE
, NULL_TREE
);
11078 g
= gimple_build_assign (r
, t
);
11079 gimple_seq_add_stmt (iseq
, g
);
11082 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
11083 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
11084 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
11085 OMP_CLAUSE_CHAIN (c
) = *p
;
11087 tree clobber
= build_constructor (type
, NULL
);
11088 TREE_THIS_VOLATILE (clobber
) = 1;
11089 g
= gimple_build_assign (array
, clobber
);
11090 gimple_seq_add_stmt (oseq
, g
);
11093 /* Lower the OpenMP parallel or task directive in the current statement
11094 in GSI_P. CTX holds context information for the directive. */
11097 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11101 gimple stmt
= gsi_stmt (*gsi_p
);
11102 gbind
*par_bind
, *bind
, *dep_bind
= NULL
;
11103 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
11104 location_t loc
= gimple_location (stmt
);
11106 clauses
= gimple_omp_taskreg_clauses (stmt
);
11108 = as_a
<gbind
*> (gimple_seq_first_stmt (gimple_omp_body (stmt
)));
11109 par_body
= gimple_bind_body (par_bind
);
11110 child_fn
= ctx
->cb
.dst_fn
;
11111 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
11112 && !gimple_omp_parallel_combined_p (stmt
))
11114 struct walk_stmt_info wi
;
11117 memset (&wi
, 0, sizeof (wi
));
11119 wi
.val_only
= true;
11120 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
11122 gimple_omp_parallel_set_combined_p (stmt
, true);
11124 gimple_seq dep_ilist
= NULL
;
11125 gimple_seq dep_olist
= NULL
;
11126 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
11127 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
11129 push_gimplify_context ();
11130 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
11131 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
11134 if (ctx
->srecord_type
)
11135 create_task_copyfn (as_a
<gomp_task
*> (stmt
), ctx
);
11137 push_gimplify_context ();
11142 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
11143 lower_omp (&par_body
, ctx
);
11144 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
11145 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
11147 /* Declare all the variables created by mapping and the variables
11148 declared in the scope of the parallel body. */
11149 record_vars_into (ctx
->block_vars
, child_fn
);
11150 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
11152 if (ctx
->record_type
)
11155 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
11156 : ctx
->record_type
, ".omp_data_o");
11157 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11158 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11159 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
11164 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
11165 lower_send_shared_vars (&ilist
, &olist
, ctx
);
11167 if (ctx
->record_type
)
11169 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
11170 TREE_THIS_VOLATILE (clobber
) = 1;
11171 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11175 /* Once all the expansions are done, sequence all the different
11176 fragments inside gimple_omp_body. */
11180 if (ctx
->record_type
)
11182 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11183 /* fixup_child_record_type might have changed receiver_decl's type. */
11184 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11185 gimple_seq_add_stmt (&new_body
,
11186 gimple_build_assign (ctx
->receiver_decl
, t
));
11189 gimple_seq_add_seq (&new_body
, par_ilist
);
11190 gimple_seq_add_seq (&new_body
, par_body
);
11191 gimple_seq_add_seq (&new_body
, par_rlist
);
11192 if (ctx
->cancellable
)
11193 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
11194 gimple_seq_add_seq (&new_body
, par_olist
);
11195 new_body
= maybe_catch_exception (new_body
);
11196 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
)
11197 gimple_seq_add_stmt (&new_body
,
11198 gimple_build_omp_continue (integer_zero_node
,
11199 integer_zero_node
));
11200 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11201 gimple_omp_set_body (stmt
, new_body
);
11203 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
11204 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
11205 gimple_bind_add_seq (bind
, ilist
);
11206 gimple_bind_add_stmt (bind
, stmt
);
11207 gimple_bind_add_seq (bind
, olist
);
11209 pop_gimplify_context (NULL
);
11213 gimple_bind_add_seq (dep_bind
, dep_ilist
);
11214 gimple_bind_add_stmt (dep_bind
, bind
);
11215 gimple_bind_add_seq (dep_bind
, dep_olist
);
11216 pop_gimplify_context (dep_bind
);
11220 /* Lower the GIMPLE_OMP_TARGET in the current statement
11221 in GSI_P. CTX holds context information for the directive. */
11224 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11227 tree child_fn
, t
, c
;
11228 gomp_target
*stmt
= as_a
<gomp_target
*> (gsi_stmt (*gsi_p
));
11229 gbind
*tgt_bind
, *bind
;
11230 gimple_seq tgt_body
, olist
, ilist
, orlist
, irlist
, new_body
;
11231 location_t loc
= gimple_location (stmt
);
11232 bool offloaded
, data_region
;
11233 unsigned int map_cnt
= 0;
11235 offloaded
= is_gimple_omp_offloaded (stmt
);
11236 switch (gimple_omp_target_kind (stmt
))
11238 case GF_OMP_TARGET_KIND_REGION
:
11239 case GF_OMP_TARGET_KIND_UPDATE
:
11240 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
11241 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
11242 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
11243 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
11244 data_region
= false;
11246 case GF_OMP_TARGET_KIND_DATA
:
11247 case GF_OMP_TARGET_KIND_OACC_DATA
:
11248 data_region
= true;
11251 gcc_unreachable ();
11254 clauses
= gimple_omp_target_clauses (stmt
);
11260 tgt_bind
= gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt
));
11261 tgt_body
= gimple_bind_body (tgt_bind
);
11263 else if (data_region
)
11264 tgt_body
= gimple_omp_body (stmt
);
11265 child_fn
= ctx
->cb
.dst_fn
;
11267 push_gimplify_context ();
11272 && is_gimple_omp_oacc (stmt
))
11273 oacc_process_reduction_data (&tgt_body
, &irlist
, &orlist
, ctx
);
11275 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11276 switch (OMP_CLAUSE_CODE (c
))
11282 case OMP_CLAUSE_MAP
:
11283 #ifdef ENABLE_CHECKING
11284 /* First check what we're prepared to handle in the following. */
11285 switch (OMP_CLAUSE_MAP_KIND (c
))
11287 case GOMP_MAP_ALLOC
:
11289 case GOMP_MAP_FROM
:
11290 case GOMP_MAP_TOFROM
:
11291 case GOMP_MAP_POINTER
:
11292 case GOMP_MAP_TO_PSET
:
11294 case GOMP_MAP_FORCE_ALLOC
:
11295 case GOMP_MAP_FORCE_TO
:
11296 case GOMP_MAP_FORCE_FROM
:
11297 case GOMP_MAP_FORCE_TOFROM
:
11298 case GOMP_MAP_FORCE_PRESENT
:
11299 case GOMP_MAP_FORCE_DEALLOC
:
11300 case GOMP_MAP_FORCE_DEVICEPTR
:
11301 gcc_assert (is_gimple_omp_oacc (stmt
));
11304 gcc_unreachable ();
11308 case OMP_CLAUSE_TO
:
11309 case OMP_CLAUSE_FROM
:
11310 var
= OMP_CLAUSE_DECL (c
);
11313 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
11314 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11319 if (DECL_SIZE (var
)
11320 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
11322 tree var2
= DECL_VALUE_EXPR (var
);
11323 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
11324 var2
= TREE_OPERAND (var2
, 0);
11325 gcc_assert (DECL_P (var2
));
11329 if (!maybe_lookup_field (var
, ctx
))
11334 x
= build_receiver_ref (var
, true, ctx
);
11335 tree new_var
= lookup_decl (var
, ctx
);
11336 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11337 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11338 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
11339 x
= build_simple_mem_ref (x
);
11340 SET_DECL_VALUE_EXPR (new_var
, x
);
11341 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
11348 target_nesting_level
++;
11349 lower_omp (&tgt_body
, ctx
);
11350 target_nesting_level
--;
11352 else if (data_region
)
11353 lower_omp (&tgt_body
, ctx
);
11357 /* Declare all the variables created by mapping and the variables
11358 declared in the scope of the target body. */
11359 record_vars_into (ctx
->block_vars
, child_fn
);
11360 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
11365 if (ctx
->record_type
)
11368 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
11369 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11370 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11371 t
= make_tree_vec (3);
11372 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
11373 TREE_VEC_ELT (t
, 1)
11374 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
11375 ".omp_data_sizes");
11376 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
11377 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
11378 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
11381 if (is_gimple_omp_oacc (stmt
))
11383 tkind_type
= short_unsigned_type_node
;
11388 tkind_type
= unsigned_char_type_node
;
11391 TREE_VEC_ELT (t
, 2)
11392 = create_tmp_var (build_array_type_nelts (tkind_type
, map_cnt
),
11393 ".omp_data_kinds");
11394 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
11395 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
11396 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
11397 gimple_omp_target_set_data_arg (stmt
, t
);
11399 vec
<constructor_elt
, va_gc
> *vsize
;
11400 vec
<constructor_elt
, va_gc
> *vkind
;
11401 vec_alloc (vsize
, map_cnt
);
11402 vec_alloc (vkind
, map_cnt
);
11403 unsigned int map_idx
= 0;
11405 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11406 switch (OMP_CLAUSE_CODE (c
))
11412 case OMP_CLAUSE_MAP
:
11413 case OMP_CLAUSE_TO
:
11414 case OMP_CLAUSE_FROM
:
11416 ovar
= OMP_CLAUSE_DECL (c
);
11417 if (!DECL_P (ovar
))
11419 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11420 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11422 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
11423 == get_base_address (ovar
));
11424 nc
= OMP_CLAUSE_CHAIN (c
);
11425 ovar
= OMP_CLAUSE_DECL (nc
);
11429 tree x
= build_sender_ref (ovar
, ctx
);
11431 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
11432 gimplify_assign (x
, v
, &ilist
);
11438 if (DECL_SIZE (ovar
)
11439 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
11441 tree ovar2
= DECL_VALUE_EXPR (ovar
);
11442 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
11443 ovar2
= TREE_OPERAND (ovar2
, 0);
11444 gcc_assert (DECL_P (ovar2
));
11447 if (!maybe_lookup_field (ovar
, ctx
))
11451 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
11452 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
11453 talign
= DECL_ALIGN_UNIT (ovar
);
11456 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
11457 tree x
= build_sender_ref (ovar
, ctx
);
11458 if (maybe_lookup_oacc_reduction (var
, ctx
))
11460 gcc_checking_assert (offloaded
11461 && is_gimple_omp_oacc (stmt
));
11462 gimplify_assign (x
, var
, &ilist
);
11464 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11465 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11466 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11467 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
11469 gcc_assert (offloaded
);
11471 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)));
11472 mark_addressable (avar
);
11473 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
11474 talign
= DECL_ALIGN_UNIT (avar
);
11475 avar
= build_fold_addr_expr (avar
);
11476 gimplify_assign (x
, avar
, &ilist
);
11478 else if (is_gimple_reg (var
))
11480 gcc_assert (offloaded
);
11481 tree avar
= create_tmp_var (TREE_TYPE (var
));
11482 mark_addressable (avar
);
11483 enum gomp_map_kind map_kind
= OMP_CLAUSE_MAP_KIND (c
);
11484 if (GOMP_MAP_COPY_TO_P (map_kind
)
11485 || map_kind
== GOMP_MAP_POINTER
11486 || map_kind
== GOMP_MAP_TO_PSET
11487 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11488 gimplify_assign (avar
, var
, &ilist
);
11489 avar
= build_fold_addr_expr (avar
);
11490 gimplify_assign (x
, avar
, &ilist
);
11491 if ((GOMP_MAP_COPY_FROM_P (map_kind
)
11492 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11493 && !TYPE_READONLY (TREE_TYPE (var
)))
11495 x
= build_sender_ref (ovar
, ctx
);
11496 x
= build_simple_mem_ref (x
);
11497 gimplify_assign (var
, x
, &olist
);
11502 var
= build_fold_addr_expr (var
);
11503 gimplify_assign (x
, var
, &ilist
);
11506 tree s
= OMP_CLAUSE_SIZE (c
);
11507 if (s
== NULL_TREE
)
11508 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
11509 s
= fold_convert (size_type_node
, s
);
11510 tree purpose
= size_int (map_idx
++);
11511 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
11512 if (TREE_CODE (s
) != INTEGER_CST
)
11513 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
11515 unsigned HOST_WIDE_INT tkind
;
11516 switch (OMP_CLAUSE_CODE (c
))
11518 case OMP_CLAUSE_MAP
:
11519 tkind
= OMP_CLAUSE_MAP_KIND (c
);
11521 case OMP_CLAUSE_TO
:
11522 tkind
= GOMP_MAP_TO
;
11524 case OMP_CLAUSE_FROM
:
11525 tkind
= GOMP_MAP_FROM
;
11528 gcc_unreachable ();
11530 gcc_checking_assert (tkind
11531 < (HOST_WIDE_INT_C (1U) << talign_shift
));
11532 talign
= ceil_log2 (talign
);
11533 tkind
|= talign
<< talign_shift
;
11534 gcc_checking_assert (tkind
11535 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
11536 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
11537 build_int_cstu (tkind_type
, tkind
));
11542 gcc_assert (map_idx
== map_cnt
);
11544 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
11545 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
11546 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
11547 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
11548 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
11550 gimple_seq initlist
= NULL
;
11551 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
11552 TREE_VEC_ELT (t
, 1)),
11553 &initlist
, true, NULL_TREE
);
11554 gimple_seq_add_seq (&ilist
, initlist
);
11556 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
11558 TREE_THIS_VOLATILE (clobber
) = 1;
11559 gimple_seq_add_stmt (&olist
,
11560 gimple_build_assign (TREE_VEC_ELT (t
, 1),
11564 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
11565 TREE_THIS_VOLATILE (clobber
) = 1;
11566 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11570 /* Once all the expansions are done, sequence all the different
11571 fragments inside gimple_omp_body. */
11576 && ctx
->record_type
)
11578 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11579 /* fixup_child_record_type might have changed receiver_decl's type. */
11580 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11581 gimple_seq_add_stmt (&new_body
,
11582 gimple_build_assign (ctx
->receiver_decl
, t
));
11587 gimple_seq_add_seq (&new_body
, tgt_body
);
11588 new_body
= maybe_catch_exception (new_body
);
11590 else if (data_region
)
11591 new_body
= tgt_body
;
11592 if (offloaded
|| data_region
)
11594 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11595 gimple_omp_set_body (stmt
, new_body
);
11598 bind
= gimple_build_bind (NULL
, NULL
,
11599 tgt_bind
? gimple_bind_block (tgt_bind
)
11601 gsi_replace (gsi_p
, bind
, true);
11602 gimple_bind_add_seq (bind
, irlist
);
11603 gimple_bind_add_seq (bind
, ilist
);
11604 gimple_bind_add_stmt (bind
, stmt
);
11605 gimple_bind_add_seq (bind
, olist
);
11606 gimple_bind_add_seq (bind
, orlist
);
11608 pop_gimplify_context (NULL
);
11611 /* Expand code for an OpenMP teams directive. */
11614 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11616 gomp_teams
*teams_stmt
= as_a
<gomp_teams
*> (gsi_stmt (*gsi_p
));
11617 push_gimplify_context ();
11619 tree block
= make_node (BLOCK
);
11620 gbind
*bind
= gimple_build_bind (NULL
, NULL
, block
);
11621 gsi_replace (gsi_p
, bind
, true);
11622 gimple_seq bind_body
= NULL
;
11623 gimple_seq dlist
= NULL
;
11624 gimple_seq olist
= NULL
;
11626 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11627 OMP_CLAUSE_NUM_TEAMS
);
11628 if (num_teams
== NULL_TREE
)
11629 num_teams
= build_int_cst (unsigned_type_node
, 0);
11632 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
11633 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
11634 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
11636 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11637 OMP_CLAUSE_THREAD_LIMIT
);
11638 if (thread_limit
== NULL_TREE
)
11639 thread_limit
= build_int_cst (unsigned_type_node
, 0);
11642 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
11643 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
11644 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
11648 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
11649 &bind_body
, &dlist
, ctx
, NULL
);
11650 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
11651 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
11652 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
11654 location_t loc
= gimple_location (teams_stmt
);
11655 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
11656 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
11657 gimple_set_location (call
, loc
);
11658 gimple_seq_add_stmt (&bind_body
, call
);
11660 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
11661 gimple_omp_set_body (teams_stmt
, NULL
);
11662 gimple_seq_add_seq (&bind_body
, olist
);
11663 gimple_seq_add_seq (&bind_body
, dlist
);
11664 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
11665 gimple_bind_set_body (bind
, bind_body
);
11667 pop_gimplify_context (bind
);
11669 gimple_bind_append_vars (bind
, ctx
->block_vars
);
11670 BLOCK_VARS (block
) = ctx
->block_vars
;
11671 if (BLOCK_VARS (block
))
11672 TREE_USED (block
) = 1;
11676 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11677 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11678 of OMP context, but with task_shared_vars set. */
11681 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
11686 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11687 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
11690 if (task_shared_vars
11692 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
11695 /* If a global variable has been privatized, TREE_CONSTANT on
11696 ADDR_EXPR might be wrong. */
11697 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
11698 recompute_tree_invariant_for_addr_expr (t
);
11700 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
11705 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11707 gimple stmt
= gsi_stmt (*gsi_p
);
11708 struct walk_stmt_info wi
;
11711 if (gimple_has_location (stmt
))
11712 input_location
= gimple_location (stmt
);
11714 if (task_shared_vars
)
11715 memset (&wi
, '\0', sizeof (wi
));
11717 /* If we have issued syntax errors, avoid doing any heavy lifting.
11718 Just replace the OMP directives with a NOP to avoid
11719 confusing RTL expansion. */
11720 if (seen_error () && is_gimple_omp (stmt
))
11722 gsi_replace (gsi_p
, gimple_build_nop (), true);
11726 switch (gimple_code (stmt
))
11730 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
11731 if ((ctx
|| task_shared_vars
)
11732 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
11733 lower_omp_regimplify_p
,
11734 ctx
? NULL
: &wi
, NULL
)
11735 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
11736 lower_omp_regimplify_p
,
11737 ctx
? NULL
: &wi
, NULL
)))
11738 gimple_regimplify_operands (cond_stmt
, gsi_p
);
11742 lower_omp (gimple_catch_handler_ptr (as_a
<gcatch
*> (stmt
)), ctx
);
11744 case GIMPLE_EH_FILTER
:
11745 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
11748 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
11749 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
11751 case GIMPLE_TRANSACTION
:
11752 lower_omp (gimple_transaction_body_ptr (
11753 as_a
<gtransaction
*> (stmt
)),
11757 lower_omp (gimple_bind_body_ptr (as_a
<gbind
*> (stmt
)), ctx
);
11759 case GIMPLE_OMP_PARALLEL
:
11760 case GIMPLE_OMP_TASK
:
11761 ctx
= maybe_lookup_ctx (stmt
);
11763 if (ctx
->cancellable
)
11764 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11765 lower_omp_taskreg (gsi_p
, ctx
);
11767 case GIMPLE_OMP_FOR
:
11768 ctx
= maybe_lookup_ctx (stmt
);
11770 if (ctx
->cancellable
)
11771 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11772 lower_omp_for (gsi_p
, ctx
);
11774 case GIMPLE_OMP_SECTIONS
:
11775 ctx
= maybe_lookup_ctx (stmt
);
11777 if (ctx
->cancellable
)
11778 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11779 lower_omp_sections (gsi_p
, ctx
);
11781 case GIMPLE_OMP_SINGLE
:
11782 ctx
= maybe_lookup_ctx (stmt
);
11784 lower_omp_single (gsi_p
, ctx
);
11786 case GIMPLE_OMP_MASTER
:
11787 ctx
= maybe_lookup_ctx (stmt
);
11789 lower_omp_master (gsi_p
, ctx
);
11791 case GIMPLE_OMP_TASKGROUP
:
11792 ctx
= maybe_lookup_ctx (stmt
);
11794 lower_omp_taskgroup (gsi_p
, ctx
);
11796 case GIMPLE_OMP_ORDERED
:
11797 ctx
= maybe_lookup_ctx (stmt
);
11799 lower_omp_ordered (gsi_p
, ctx
);
11801 case GIMPLE_OMP_CRITICAL
:
11802 ctx
= maybe_lookup_ctx (stmt
);
11804 lower_omp_critical (gsi_p
, ctx
);
11806 case GIMPLE_OMP_ATOMIC_LOAD
:
11807 if ((ctx
|| task_shared_vars
)
11808 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11809 as_a
<gomp_atomic_load
*> (stmt
)),
11810 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
11811 gimple_regimplify_operands (stmt
, gsi_p
);
11813 case GIMPLE_OMP_TARGET
:
11814 ctx
= maybe_lookup_ctx (stmt
);
11816 lower_omp_target (gsi_p
, ctx
);
11818 case GIMPLE_OMP_TEAMS
:
11819 ctx
= maybe_lookup_ctx (stmt
);
11821 lower_omp_teams (gsi_p
, ctx
);
11825 call_stmt
= as_a
<gcall
*> (stmt
);
11826 fndecl
= gimple_call_fndecl (call_stmt
);
11828 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
11829 switch (DECL_FUNCTION_CODE (fndecl
))
11831 case BUILT_IN_GOMP_BARRIER
:
11835 case BUILT_IN_GOMP_CANCEL
:
11836 case BUILT_IN_GOMP_CANCELLATION_POINT
:
11839 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
11840 cctx
= cctx
->outer
;
11841 gcc_assert (gimple_call_lhs (call_stmt
) == NULL_TREE
);
11842 if (!cctx
->cancellable
)
11844 if (DECL_FUNCTION_CODE (fndecl
)
11845 == BUILT_IN_GOMP_CANCELLATION_POINT
)
11847 stmt
= gimple_build_nop ();
11848 gsi_replace (gsi_p
, stmt
, false);
11852 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
11854 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
11855 gimple_call_set_fndecl (call_stmt
, fndecl
);
11856 gimple_call_set_fntype (call_stmt
, TREE_TYPE (fndecl
));
11859 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)));
11860 gimple_call_set_lhs (call_stmt
, lhs
);
11861 tree fallthru_label
;
11862 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
11864 g
= gimple_build_label (fallthru_label
);
11865 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11866 g
= gimple_build_cond (NE_EXPR
, lhs
,
11867 fold_convert (TREE_TYPE (lhs
),
11868 boolean_false_node
),
11869 cctx
->cancel_label
, fallthru_label
);
11870 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11877 if ((ctx
|| task_shared_vars
)
11878 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
11881 /* Just remove clobbers, this should happen only if we have
11882 "privatized" local addressable variables in SIMD regions,
11883 the clobber isn't needed in that case and gimplifying address
11884 of the ARRAY_REF into a pointer and creating MEM_REF based
11885 clobber would create worse code than we get with the clobber
11887 if (gimple_clobber_p (stmt
))
11889 gsi_replace (gsi_p
, gimple_build_nop (), true);
11892 gimple_regimplify_operands (stmt
, gsi_p
);
11899 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
11901 location_t saved_location
= input_location
;
11902 gimple_stmt_iterator gsi
;
11903 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11904 lower_omp_1 (&gsi
, ctx
);
11905 /* During gimplification, we haven't folded statments inside offloading
11906 regions (gimplify.c:maybe_fold_stmt); do that now. */
11907 if (target_nesting_level
)
11908 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11910 input_location
= saved_location
;
11913 /* Main entry point. */
11915 static unsigned int
11916 execute_lower_omp (void)
11922 /* This pass always runs, to provide PROP_gimple_lomp.
11923 But often, there is nothing to do. */
11924 if (flag_cilkplus
== 0 && flag_openacc
== 0 && flag_openmp
== 0
11925 && flag_openmp_simd
== 0)
11928 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
11929 delete_omp_context
);
11931 body
= gimple_body (current_function_decl
);
11932 scan_omp (&body
, NULL
);
11933 gcc_assert (taskreg_nesting_level
== 0);
11934 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
11935 finish_taskreg_scan (ctx
);
11936 taskreg_contexts
.release ();
11938 if (all_contexts
->root
)
11940 if (task_shared_vars
)
11941 push_gimplify_context ();
11942 lower_omp (&body
, NULL
);
11943 if (task_shared_vars
)
11944 pop_gimplify_context (NULL
);
11949 splay_tree_delete (all_contexts
);
11950 all_contexts
= NULL
;
11952 BITMAP_FREE (task_shared_vars
);
11958 const pass_data pass_data_lower_omp
=
11960 GIMPLE_PASS
, /* type */
11961 "omplower", /* name */
11962 OPTGROUP_NONE
, /* optinfo_flags */
11963 TV_NONE
, /* tv_id */
11964 PROP_gimple_any
, /* properties_required */
11965 PROP_gimple_lomp
, /* properties_provided */
11966 0, /* properties_destroyed */
11967 0, /* todo_flags_start */
11968 0, /* todo_flags_finish */
11971 class pass_lower_omp
: public gimple_opt_pass
11974 pass_lower_omp (gcc::context
*ctxt
)
11975 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
11978 /* opt_pass methods: */
11979 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
11981 }; // class pass_lower_omp
11983 } // anon namespace
11986 make_pass_lower_omp (gcc::context
*ctxt
)
11988 return new pass_lower_omp (ctxt
);
11991 /* The following is a utility to diagnose structured block violations.
11992 It is not part of the "omplower" pass, as that's invoked too late. It
11993 should be invoked by the respective front ends after gimplification. */
11995 static splay_tree all_labels
;
11997 /* Check for mismatched contexts and generate an error if needed. Return
11998 true if an error is detected. */
12001 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
12002 gimple branch_ctx
, gimple label_ctx
)
12004 gcc_checking_assert (!branch_ctx
|| is_gimple_omp (branch_ctx
));
12005 gcc_checking_assert (!label_ctx
|| is_gimple_omp (label_ctx
));
12007 if (label_ctx
== branch_ctx
)
12010 const char* kind
= NULL
;
12015 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
12016 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
12018 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
12019 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
12020 kind
= "Cilk Plus";
12024 if ((branch_ctx
&& is_gimple_omp_oacc (branch_ctx
))
12025 || (label_ctx
&& is_gimple_omp_oacc (label_ctx
)))
12027 gcc_checking_assert (kind
== NULL
);
12033 gcc_checking_assert (flag_openmp
);
12038 Previously we kept track of the label's entire context in diagnose_sb_[12]
12039 so we could traverse it and issue a correct "exit" or "enter" error
12040 message upon a structured block violation.
12042 We built the context by building a list with tree_cons'ing, but there is
12043 no easy counterpart in gimple tuples. It seems like far too much work
12044 for issuing exit/enter error messages. If someone really misses the
12045 distinct error message... patches welcome.
12049 /* Try to avoid confusing the user by producing and error message
12050 with correct "exit" or "enter" verbiage. We prefer "exit"
12051 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12052 if (branch_ctx
== NULL
)
12058 if (TREE_VALUE (label_ctx
) == branch_ctx
)
12063 label_ctx
= TREE_CHAIN (label_ctx
);
12068 error ("invalid exit from %s structured block", kind
);
12070 error ("invalid entry to %s structured block", kind
);
12073 /* If it's obvious we have an invalid entry, be specific about the error. */
12074 if (branch_ctx
== NULL
)
12075 error ("invalid entry to %s structured block", kind
);
12078 /* Otherwise, be vague and lazy, but efficient. */
12079 error ("invalid branch to/from %s structured block", kind
);
12082 gsi_replace (gsi_p
, gimple_build_nop (), false);
12086 /* Pass 1: Create a minimal tree of structured blocks, and record
12087 where each label is found. */
12090 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12091 struct walk_stmt_info
*wi
)
12093 gimple context
= (gimple
) wi
->info
;
12094 gimple inner_context
;
12095 gimple stmt
= gsi_stmt (*gsi_p
);
12097 *handled_ops_p
= true;
12099 switch (gimple_code (stmt
))
12103 case GIMPLE_OMP_PARALLEL
:
12104 case GIMPLE_OMP_TASK
:
12105 case GIMPLE_OMP_SECTIONS
:
12106 case GIMPLE_OMP_SINGLE
:
12107 case GIMPLE_OMP_SECTION
:
12108 case GIMPLE_OMP_MASTER
:
12109 case GIMPLE_OMP_ORDERED
:
12110 case GIMPLE_OMP_CRITICAL
:
12111 case GIMPLE_OMP_TARGET
:
12112 case GIMPLE_OMP_TEAMS
:
12113 case GIMPLE_OMP_TASKGROUP
:
12114 /* The minimal context here is just the current OMP construct. */
12115 inner_context
= stmt
;
12116 wi
->info
= inner_context
;
12117 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12118 wi
->info
= context
;
12121 case GIMPLE_OMP_FOR
:
12122 inner_context
= stmt
;
12123 wi
->info
= inner_context
;
12124 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12126 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
12127 diagnose_sb_1
, NULL
, wi
);
12128 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12129 wi
->info
= context
;
12133 splay_tree_insert (all_labels
,
12134 (splay_tree_key
) gimple_label_label (
12135 as_a
<glabel
*> (stmt
)),
12136 (splay_tree_value
) context
);
12146 /* Pass 2: Check each branch and see if its context differs from that of
12147 the destination label's context. */
12150 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12151 struct walk_stmt_info
*wi
)
12153 gimple context
= (gimple
) wi
->info
;
12155 gimple stmt
= gsi_stmt (*gsi_p
);
12157 *handled_ops_p
= true;
12159 switch (gimple_code (stmt
))
12163 case GIMPLE_OMP_PARALLEL
:
12164 case GIMPLE_OMP_TASK
:
12165 case GIMPLE_OMP_SECTIONS
:
12166 case GIMPLE_OMP_SINGLE
:
12167 case GIMPLE_OMP_SECTION
:
12168 case GIMPLE_OMP_MASTER
:
12169 case GIMPLE_OMP_ORDERED
:
12170 case GIMPLE_OMP_CRITICAL
:
12171 case GIMPLE_OMP_TARGET
:
12172 case GIMPLE_OMP_TEAMS
:
12173 case GIMPLE_OMP_TASKGROUP
:
12175 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12176 wi
->info
= context
;
12179 case GIMPLE_OMP_FOR
:
12181 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12183 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
12184 diagnose_sb_2
, NULL
, wi
);
12185 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12186 wi
->info
= context
;
12191 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
12192 tree lab
= gimple_cond_true_label (cond_stmt
);
12195 n
= splay_tree_lookup (all_labels
,
12196 (splay_tree_key
) lab
);
12197 diagnose_sb_0 (gsi_p
, context
,
12198 n
? (gimple
) n
->value
: NULL
);
12200 lab
= gimple_cond_false_label (cond_stmt
);
12203 n
= splay_tree_lookup (all_labels
,
12204 (splay_tree_key
) lab
);
12205 diagnose_sb_0 (gsi_p
, context
,
12206 n
? (gimple
) n
->value
: NULL
);
12213 tree lab
= gimple_goto_dest (stmt
);
12214 if (TREE_CODE (lab
) != LABEL_DECL
)
12217 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12218 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
12222 case GIMPLE_SWITCH
:
12224 gswitch
*switch_stmt
= as_a
<gswitch
*> (stmt
);
12226 for (i
= 0; i
< gimple_switch_num_labels (switch_stmt
); ++i
)
12228 tree lab
= CASE_LABEL (gimple_switch_label (switch_stmt
, i
));
12229 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12230 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
12236 case GIMPLE_RETURN
:
12237 diagnose_sb_0 (gsi_p
, context
, NULL
);
12247 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12250 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
12253 gimple last
= last_stmt (bb
);
12254 enum gimple_code code
= gimple_code (last
);
12255 struct omp_region
*cur_region
= *region
;
12256 bool fallthru
= false;
12260 case GIMPLE_OMP_PARALLEL
:
12261 case GIMPLE_OMP_TASK
:
12262 case GIMPLE_OMP_FOR
:
12263 case GIMPLE_OMP_SINGLE
:
12264 case GIMPLE_OMP_TEAMS
:
12265 case GIMPLE_OMP_MASTER
:
12266 case GIMPLE_OMP_TASKGROUP
:
12267 case GIMPLE_OMP_ORDERED
:
12268 case GIMPLE_OMP_CRITICAL
:
12269 case GIMPLE_OMP_SECTION
:
12270 cur_region
= new_omp_region (bb
, code
, cur_region
);
12274 case GIMPLE_OMP_TARGET
:
12275 cur_region
= new_omp_region (bb
, code
, cur_region
);
12277 switch (gimple_omp_target_kind (last
))
12279 case GF_OMP_TARGET_KIND_REGION
:
12280 case GF_OMP_TARGET_KIND_DATA
:
12281 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
12282 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
12283 case GF_OMP_TARGET_KIND_OACC_DATA
:
12285 case GF_OMP_TARGET_KIND_UPDATE
:
12286 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
12287 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
12288 cur_region
= cur_region
->outer
;
12291 gcc_unreachable ();
12295 case GIMPLE_OMP_SECTIONS
:
12296 cur_region
= new_omp_region (bb
, code
, cur_region
);
12300 case GIMPLE_OMP_SECTIONS_SWITCH
:
12304 case GIMPLE_OMP_ATOMIC_LOAD
:
12305 case GIMPLE_OMP_ATOMIC_STORE
:
12309 case GIMPLE_OMP_RETURN
:
12310 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12311 somewhere other than the next block. This will be
12313 cur_region
->exit
= bb
;
12314 if (cur_region
->type
== GIMPLE_OMP_TASK
)
12315 /* Add an edge corresponding to not scheduling the task
12317 make_edge (cur_region
->entry
, bb
, EDGE_ABNORMAL
);
12318 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
12319 cur_region
= cur_region
->outer
;
12322 case GIMPLE_OMP_CONTINUE
:
12323 cur_region
->cont
= bb
;
12324 switch (cur_region
->type
)
12326 case GIMPLE_OMP_FOR
:
12327 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12328 succs edges as abnormal to prevent splitting
12330 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
12331 /* Make the loopback edge. */
12332 make_edge (bb
, single_succ (cur_region
->entry
),
12335 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12336 corresponds to the case that the body of the loop
12337 is not executed at all. */
12338 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
12339 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
12343 case GIMPLE_OMP_SECTIONS
:
12344 /* Wire up the edges into and out of the nested sections. */
12346 basic_block switch_bb
= single_succ (cur_region
->entry
);
12348 struct omp_region
*i
;
12349 for (i
= cur_region
->inner
; i
; i
= i
->next
)
12351 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
12352 make_edge (switch_bb
, i
->entry
, 0);
12353 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
12356 /* Make the loopback edge to the block with
12357 GIMPLE_OMP_SECTIONS_SWITCH. */
12358 make_edge (bb
, switch_bb
, 0);
12360 /* Make the edge from the switch to exit. */
12361 make_edge (switch_bb
, bb
->next_bb
, 0);
12366 case GIMPLE_OMP_TASK
:
12371 gcc_unreachable ();
12376 gcc_unreachable ();
12379 if (*region
!= cur_region
)
12381 *region
= cur_region
;
12383 *region_idx
= cur_region
->entry
->index
;
12391 static unsigned int
12392 diagnose_omp_structured_block_errors (void)
12394 struct walk_stmt_info wi
;
12395 gimple_seq body
= gimple_body (current_function_decl
);
12397 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
12399 memset (&wi
, 0, sizeof (wi
));
12400 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
12402 memset (&wi
, 0, sizeof (wi
));
12403 wi
.want_locations
= true;
12404 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
12406 gimple_set_body (current_function_decl
, body
);
12408 splay_tree_delete (all_labels
);
12416 const pass_data pass_data_diagnose_omp_blocks
=
12418 GIMPLE_PASS
, /* type */
12419 "*diagnose_omp_blocks", /* name */
12420 OPTGROUP_NONE
, /* optinfo_flags */
12421 TV_NONE
, /* tv_id */
12422 PROP_gimple_any
, /* properties_required */
12423 0, /* properties_provided */
12424 0, /* properties_destroyed */
12425 0, /* todo_flags_start */
12426 0, /* todo_flags_finish */
12429 class pass_diagnose_omp_blocks
: public gimple_opt_pass
12432 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12433 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
12436 /* opt_pass methods: */
12437 virtual bool gate (function
*)
12439 return flag_cilkplus
|| flag_openacc
|| flag_openmp
;
12441 virtual unsigned int execute (function
*)
12443 return diagnose_omp_structured_block_errors ();
12446 }; // class pass_diagnose_omp_blocks
12448 } // anon namespace
12451 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12453 return new pass_diagnose_omp_blocks (ctxt
);
12456 /* SIMD clone supporting code. */
12458 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12459 of arguments to reserve space for. */
12461 static struct cgraph_simd_clone
*
12462 simd_clone_struct_alloc (int nargs
)
12464 struct cgraph_simd_clone
*clone_info
;
12465 size_t len
= (sizeof (struct cgraph_simd_clone
)
12466 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
12467 clone_info
= (struct cgraph_simd_clone
*)
12468 ggc_internal_cleared_alloc (len
);
12472 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12475 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
12476 struct cgraph_simd_clone
*from
)
12478 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
12479 + ((from
->nargs
- from
->inbranch
)
12480 * sizeof (struct cgraph_simd_clone_arg
))));
12483 /* Return vector of parameter types of function FNDECL. This uses
12484 TYPE_ARG_TYPES if available, otherwise falls back to types of
12485 DECL_ARGUMENTS types. */
12488 simd_clone_vector_of_formal_parm_types (tree fndecl
)
12490 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
12491 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
12492 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
12495 FOR_EACH_VEC_ELT (args
, i
, arg
)
12496 args
[i
] = TREE_TYPE (args
[i
]);
12500 /* Given a simd function in NODE, extract the simd specific
12501 information from the OMP clauses passed in CLAUSES, and return
12502 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12503 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12504 otherwise set to FALSE. */
12506 static struct cgraph_simd_clone
*
12507 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
12508 bool *inbranch_specified
)
12510 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12513 *inbranch_specified
= false;
12515 n
= args
.length ();
12516 if (n
> 0 && args
.last () == void_type_node
)
12519 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12520 be cloned have a distinctive artificial label in addition to "omp
12524 && lookup_attribute ("cilk simd function",
12525 DECL_ATTRIBUTES (node
->decl
)));
12527 /* Allocate one more than needed just in case this is an in-branch
12528 clone which will require a mask argument. */
12529 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
12530 clone_info
->nargs
= n
;
12531 clone_info
->cilk_elemental
= cilk_clone
;
12538 clauses
= TREE_VALUE (clauses
);
12539 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
12542 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
12544 switch (OMP_CLAUSE_CODE (t
))
12546 case OMP_CLAUSE_INBRANCH
:
12547 clone_info
->inbranch
= 1;
12548 *inbranch_specified
= true;
12550 case OMP_CLAUSE_NOTINBRANCH
:
12551 clone_info
->inbranch
= 0;
12552 *inbranch_specified
= true;
12554 case OMP_CLAUSE_SIMDLEN
:
12555 clone_info
->simdlen
12556 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
12558 case OMP_CLAUSE_LINEAR
:
12560 tree decl
= OMP_CLAUSE_DECL (t
);
12561 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
12562 int argno
= TREE_INT_CST_LOW (decl
);
12563 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
12565 clone_info
->args
[argno
].arg_type
12566 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
12567 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12568 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
12569 && clone_info
->args
[argno
].linear_step
< n
);
12573 if (POINTER_TYPE_P (args
[argno
]))
12574 step
= fold_convert (ssizetype
, step
);
12575 if (!tree_fits_shwi_p (step
))
12577 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12578 "ignoring large linear step");
12582 else if (integer_zerop (step
))
12584 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12585 "ignoring zero linear step");
12591 clone_info
->args
[argno
].arg_type
12592 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
12593 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12598 case OMP_CLAUSE_UNIFORM
:
12600 tree decl
= OMP_CLAUSE_DECL (t
);
12601 int argno
= tree_to_uhwi (decl
);
12602 clone_info
->args
[argno
].arg_type
12603 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
12606 case OMP_CLAUSE_ALIGNED
:
12608 tree decl
= OMP_CLAUSE_DECL (t
);
12609 int argno
= tree_to_uhwi (decl
);
12610 clone_info
->args
[argno
].alignment
12611 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
12622 /* Given a SIMD clone in NODE, calculate the characteristic data
12623 type and return the coresponding type. The characteristic data
12624 type is computed as described in the Intel Vector ABI. */
12627 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
12628 struct cgraph_simd_clone
*clone_info
)
12630 tree type
= integer_type_node
;
12631 tree fndecl
= node
->decl
;
12633 /* a) For non-void function, the characteristic data type is the
12635 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
12636 type
= TREE_TYPE (TREE_TYPE (fndecl
));
12638 /* b) If the function has any non-uniform, non-linear parameters,
12639 then the characteristic data type is the type of the first
12643 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
12644 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
12645 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
12653 /* c) If the characteristic data type determined by a) or b) above
12654 is struct, union, or class type which is pass-by-value (except
12655 for the type that maps to the built-in complex data type), the
12656 characteristic data type is int. */
12657 if (RECORD_OR_UNION_TYPE_P (type
)
12658 && !aggregate_value_p (type
, NULL
)
12659 && TREE_CODE (type
) != COMPLEX_TYPE
)
12660 return integer_type_node
;
12662 /* d) If none of the above three classes is applicable, the
12663 characteristic data type is int. */
12667 /* e) For Intel Xeon Phi native and offload compilation, if the
12668 resulting characteristic data type is 8-bit or 16-bit integer
12669 data type, the characteristic data type is int. */
12670 /* Well, we don't handle Xeon Phi yet. */
12674 simd_clone_mangle (struct cgraph_node
*node
,
12675 struct cgraph_simd_clone
*clone_info
)
12677 char vecsize_mangle
= clone_info
->vecsize_mangle
;
12678 char mask
= clone_info
->inbranch
? 'M' : 'N';
12679 unsigned int simdlen
= clone_info
->simdlen
;
12683 gcc_assert (vecsize_mangle
&& simdlen
);
12685 pp_string (&pp
, "_ZGV");
12686 pp_character (&pp
, vecsize_mangle
);
12687 pp_character (&pp
, mask
);
12688 pp_decimal_int (&pp
, simdlen
);
12690 for (n
= 0; n
< clone_info
->nargs
; ++n
)
12692 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
12694 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
12695 pp_character (&pp
, 'u');
12696 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
12698 gcc_assert (arg
.linear_step
!= 0);
12699 pp_character (&pp
, 'l');
12700 if (arg
.linear_step
> 1)
12701 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12702 else if (arg
.linear_step
< 0)
12704 pp_character (&pp
, 'n');
12705 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
12709 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
12711 pp_character (&pp
, 's');
12712 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12715 pp_character (&pp
, 'v');
12718 pp_character (&pp
, 'a');
12719 pp_decimal_int (&pp
, arg
.alignment
);
12723 pp_underscore (&pp
);
12724 const char *str
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
));
12727 pp_string (&pp
, str
);
12728 str
= pp_formatted_text (&pp
);
12730 /* If there already is a SIMD clone with the same mangled name, don't
12731 add another one. This can happen e.g. for
12732 #pragma omp declare simd
12733 #pragma omp declare simd simdlen(8)
12734 int foo (int, int);
12735 if the simdlen is assumed to be 8 for the first one, etc. */
12736 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
12737 clone
= clone
->simdclone
->next_clone
)
12738 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
12742 return get_identifier (str
);
12745 /* Create a simd clone of OLD_NODE and return it. */
12747 static struct cgraph_node
*
12748 simd_clone_create (struct cgraph_node
*old_node
)
12750 struct cgraph_node
*new_node
;
12751 if (old_node
->definition
)
12753 if (!old_node
->has_gimple_body_p ())
12755 old_node
->get_body ();
12756 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
12762 tree old_decl
= old_node
->decl
;
12763 tree new_decl
= copy_node (old_node
->decl
);
12764 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
12765 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
12766 SET_DECL_RTL (new_decl
, NULL
);
12767 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
12768 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
12769 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
12770 symtab
->call_cgraph_insertion_hooks (new_node
);
12772 if (new_node
== NULL
)
12775 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
12777 /* The function cgraph_function_versioning () will force the new
12778 symbol local. Undo this, and inherit external visability from
12780 new_node
->local
.local
= old_node
->local
.local
;
12781 new_node
->externally_visible
= old_node
->externally_visible
;
12786 /* Adjust the return type of the given function to its appropriate
12787 vector counterpart. Returns a simd array to be used throughout the
12788 function as a return value. */
12791 simd_clone_adjust_return_type (struct cgraph_node
*node
)
12793 tree fndecl
= node
->decl
;
12794 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
12795 unsigned int veclen
;
12798 /* Adjust the function return type. */
12799 if (orig_rettype
== void_type_node
)
12801 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
12802 t
= TREE_TYPE (TREE_TYPE (fndecl
));
12803 if (INTEGRAL_TYPE_P (t
) || POINTER_TYPE_P (t
))
12804 veclen
= node
->simdclone
->vecsize_int
;
12806 veclen
= node
->simdclone
->vecsize_float
;
12807 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (t
));
12808 if (veclen
> node
->simdclone
->simdlen
)
12809 veclen
= node
->simdclone
->simdlen
;
12810 if (POINTER_TYPE_P (t
))
12811 t
= pointer_sized_int_node
;
12812 if (veclen
== node
->simdclone
->simdlen
)
12813 t
= build_vector_type (t
, node
->simdclone
->simdlen
);
12816 t
= build_vector_type (t
, veclen
);
12817 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
12819 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
12820 if (!node
->definition
)
12823 t
= DECL_RESULT (fndecl
);
12824 /* Adjust the DECL_RESULT. */
12825 gcc_assert (TREE_TYPE (t
) != void_type_node
);
12826 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
12829 tree atype
= build_array_type_nelts (orig_rettype
,
12830 node
->simdclone
->simdlen
);
12831 if (veclen
!= node
->simdclone
->simdlen
)
12832 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
12834 /* Set up a SIMD array to use as the return value. */
12835 tree retval
= create_tmp_var_raw (atype
, "retval");
12836 gimple_add_tmp_var (retval
);
12840 /* Each vector argument has a corresponding array to be used locally
12841 as part of the eventual loop. Create such temporary array and
12844 PREFIX is the prefix to be used for the temporary.
12846 TYPE is the inner element type.
12848 SIMDLEN is the number of elements. */
12851 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
12853 tree atype
= build_array_type_nelts (type
, simdlen
);
12854 tree avar
= create_tmp_var_raw (atype
, prefix
);
12855 gimple_add_tmp_var (avar
);
12859 /* Modify the function argument types to their corresponding vector
12860 counterparts if appropriate. Also, create one array for each simd
12861 argument to be used locally when using the function arguments as
12864 NODE is the function whose arguments are to be adjusted.
12866 Returns an adjustment vector that will be filled describing how the
12867 argument types will be adjusted. */
12869 static ipa_parm_adjustment_vec
12870 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
12873 ipa_parm_adjustment_vec adjustments
;
12875 if (node
->definition
)
12876 args
= ipa_get_vector_of_formal_parms (node
->decl
);
12878 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12879 adjustments
.create (args
.length ());
12880 unsigned i
, j
, veclen
;
12881 struct ipa_parm_adjustment adj
;
12882 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
12884 memset (&adj
, 0, sizeof (adj
));
12885 tree parm
= args
[i
];
12886 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
12887 adj
.base_index
= i
;
12890 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
12891 node
->simdclone
->args
[i
].orig_type
= parm_type
;
12893 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
12895 /* No adjustment necessary for scalar arguments. */
12896 adj
.op
= IPA_PARM_OP_COPY
;
12900 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
12901 veclen
= node
->simdclone
->vecsize_int
;
12903 veclen
= node
->simdclone
->vecsize_float
;
12904 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
12905 if (veclen
> node
->simdclone
->simdlen
)
12906 veclen
= node
->simdclone
->simdlen
;
12907 adj
.arg_prefix
= "simd";
12908 if (POINTER_TYPE_P (parm_type
))
12909 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
12911 adj
.type
= build_vector_type (parm_type
, veclen
);
12912 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
12913 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
12915 adjustments
.safe_push (adj
);
12918 memset (&adj
, 0, sizeof (adj
));
12919 adj
.op
= IPA_PARM_OP_NEW
;
12920 adj
.arg_prefix
= "simd";
12921 adj
.base_index
= i
;
12922 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
12926 if (node
->definition
)
12927 node
->simdclone
->args
[i
].simd_array
12928 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
12929 parm_type
, node
->simdclone
->simdlen
);
12931 adjustments
.safe_push (adj
);
12934 if (node
->simdclone
->inbranch
)
12937 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
12940 memset (&adj
, 0, sizeof (adj
));
12941 adj
.op
= IPA_PARM_OP_NEW
;
12942 adj
.arg_prefix
= "mask";
12944 adj
.base_index
= i
;
12945 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
12946 veclen
= node
->simdclone
->vecsize_int
;
12948 veclen
= node
->simdclone
->vecsize_float
;
12949 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
12950 if (veclen
> node
->simdclone
->simdlen
)
12951 veclen
= node
->simdclone
->simdlen
;
12952 if (POINTER_TYPE_P (base_type
))
12953 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
12955 adj
.type
= build_vector_type (base_type
, veclen
);
12956 adjustments
.safe_push (adj
);
12958 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
12959 adjustments
.safe_push (adj
);
12961 /* We have previously allocated one extra entry for the mask. Use
12963 struct cgraph_simd_clone
*sc
= node
->simdclone
;
12965 if (node
->definition
)
12967 sc
->args
[i
].orig_arg
12968 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
12969 sc
->args
[i
].simd_array
12970 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
12972 sc
->args
[i
].orig_type
= base_type
;
12973 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
12976 if (node
->definition
)
12977 ipa_modify_formal_parameters (node
->decl
, adjustments
);
12980 tree new_arg_types
= NULL_TREE
, new_reversed
;
12981 bool last_parm_void
= false;
12982 if (args
.length () > 0 && args
.last () == void_type_node
)
12983 last_parm_void
= true;
12985 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
12986 j
= adjustments
.length ();
12987 for (i
= 0; i
< j
; i
++)
12989 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
12991 if (adj
->op
== IPA_PARM_OP_COPY
)
12992 ptype
= args
[adj
->base_index
];
12995 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
12997 new_reversed
= nreverse (new_arg_types
);
12998 if (last_parm_void
)
13001 TREE_CHAIN (new_arg_types
) = void_list_node
;
13003 new_reversed
= void_list_node
;
13006 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
13007 TYPE_ARG_TYPES (new_type
) = new_reversed
;
13008 TREE_TYPE (node
->decl
) = new_type
;
13010 adjustments
.release ();
13013 return adjustments
;
13016 /* Initialize and copy the function arguments in NODE to their
13017 corresponding local simd arrays. Returns a fresh gimple_seq with
13018 the instruction sequence generated. */
13021 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
13022 ipa_parm_adjustment_vec adjustments
)
13024 gimple_seq seq
= NULL
;
13025 unsigned i
= 0, j
= 0, k
;
13027 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
13029 arg
= DECL_CHAIN (arg
), i
++, j
++)
13031 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
13034 node
->simdclone
->args
[i
].vector_arg
= arg
;
13036 tree array
= node
->simdclone
->args
[i
].simd_array
;
13037 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
13039 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
13040 tree ptr
= build_fold_addr_expr (array
);
13041 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
13042 build_int_cst (ptype
, 0));
13043 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
13044 gimplify_and_add (t
, &seq
);
13048 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
13049 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
13050 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
13052 tree ptr
= build_fold_addr_expr (array
);
13056 arg
= DECL_CHAIN (arg
);
13060 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
13061 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
13062 build_int_cst (ptype
, k
* elemsize
));
13063 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
13064 gimplify_and_add (t
, &seq
);
13071 /* Callback info for ipa_simd_modify_stmt_ops below. */
13073 struct modify_stmt_info
{
13074 ipa_parm_adjustment_vec adjustments
;
13076 /* True if the parent statement was modified by
13077 ipa_simd_modify_stmt_ops. */
13081 /* Callback for walk_gimple_op.
13083 Adjust operands from a given statement as specified in the
13084 adjustments vector in the callback data. */
13087 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
13089 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
13090 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
13091 tree
*orig_tp
= tp
;
13092 if (TREE_CODE (*tp
) == ADDR_EXPR
)
13093 tp
= &TREE_OPERAND (*tp
, 0);
13094 struct ipa_parm_adjustment
*cand
= NULL
;
13095 if (TREE_CODE (*tp
) == PARM_DECL
)
13096 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
13100 *walk_subtrees
= 0;
13103 tree repl
= NULL_TREE
;
13105 repl
= unshare_expr (cand
->new_decl
);
13110 *walk_subtrees
= 0;
13111 bool modified
= info
->modified
;
13112 info
->modified
= false;
13113 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
13114 if (!info
->modified
)
13116 info
->modified
= modified
;
13119 info
->modified
= modified
;
13128 repl
= build_fold_addr_expr (repl
);
13130 if (is_gimple_debug (info
->stmt
))
13132 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
13133 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
13134 DECL_ARTIFICIAL (vexpr
) = 1;
13135 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
13136 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
13141 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
)), repl
);
13142 repl
= gimple_assign_lhs (stmt
);
13144 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
13145 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13148 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
13150 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
13156 info
->modified
= true;
13160 /* Traverse the function body and perform all modifications as
13161 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13162 modified such that the replacement/reduction value will now be an
13163 offset into the corresponding simd_array.
13165 This function will replace all function argument uses with their
13166 corresponding simd array elements, and ajust the return values
13170 ipa_simd_modify_function_body (struct cgraph_node
*node
,
13171 ipa_parm_adjustment_vec adjustments
,
13172 tree retval_array
, tree iter
)
13175 unsigned int i
, j
, l
;
13177 /* Re-use the adjustments array, but this time use it to replace
13178 every function argument use to an offset into the corresponding
13180 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
13182 if (!node
->simdclone
->args
[i
].vector_arg
)
13185 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
13186 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
13187 adjustments
[j
].new_decl
13188 = build4 (ARRAY_REF
,
13190 node
->simdclone
->args
[i
].simd_array
,
13192 NULL_TREE
, NULL_TREE
);
13193 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
13194 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
13195 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
13198 l
= adjustments
.length ();
13199 for (i
= 1; i
< num_ssa_names
; i
++)
13201 tree name
= ssa_name (i
);
13203 && SSA_NAME_VAR (name
)
13204 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
13206 for (j
= 0; j
< l
; j
++)
13207 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
13208 && adjustments
[j
].new_decl
)
13211 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
13214 = copy_var_decl (adjustments
[j
].base
,
13215 DECL_NAME (adjustments
[j
].base
),
13216 TREE_TYPE (adjustments
[j
].base
));
13217 adjustments
[j
].new_ssa_base
= base_var
;
13220 base_var
= adjustments
[j
].new_ssa_base
;
13221 if (SSA_NAME_IS_DEFAULT_DEF (name
))
13223 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13224 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
13225 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
13226 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
13227 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13228 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
13229 gimple stmt
= gimple_build_assign (name
, new_decl
);
13230 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13233 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13238 struct modify_stmt_info info
;
13239 info
.adjustments
= adjustments
;
13241 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
13243 gimple_stmt_iterator gsi
;
13245 gsi
= gsi_start_bb (bb
);
13246 while (!gsi_end_p (gsi
))
13248 gimple stmt
= gsi_stmt (gsi
);
13250 struct walk_stmt_info wi
;
13252 memset (&wi
, 0, sizeof (wi
));
13253 info
.modified
= false;
13255 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
13257 if (greturn
*return_stmt
= dyn_cast
<greturn
*> (stmt
))
13259 tree retval
= gimple_return_retval (return_stmt
);
13262 gsi_remove (&gsi
, true);
13266 /* Replace `return foo' with `retval_array[iter] = foo'. */
13267 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
13268 retval_array
, iter
, NULL
, NULL
);
13269 stmt
= gimple_build_assign (ref
, retval
);
13270 gsi_replace (&gsi
, stmt
, true);
13271 info
.modified
= true;
13276 update_stmt (stmt
);
13277 if (maybe_clean_eh_stmt (stmt
))
13278 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
13285 /* Adjust the argument types in NODE to their appropriate vector
13289 simd_clone_adjust (struct cgraph_node
*node
)
13291 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
13293 targetm
.simd_clone
.adjust (node
);
13295 tree retval
= simd_clone_adjust_return_type (node
);
13296 ipa_parm_adjustment_vec adjustments
13297 = simd_clone_adjust_argument_types (node
);
13299 push_gimplify_context ();
13301 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
13303 /* Adjust all uses of vector arguments accordingly. Adjust all
13304 return values accordingly. */
13305 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
13306 tree iter1
= make_ssa_name (iter
);
13307 tree iter2
= make_ssa_name (iter
);
13308 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
13310 /* Initialize the iteration variable. */
13311 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13312 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
13313 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
13314 /* Insert the SIMD array and iv initialization at function
13316 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
13318 pop_gimplify_context (NULL
);
13320 /* Create a new BB right before the original exit BB, to hold the
13321 iteration increment and the condition/branch. */
13322 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
13323 basic_block incr_bb
= create_empty_bb (orig_exit
);
13324 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
13325 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13326 flag. Set it now to be a FALLTHRU_EDGE. */
13327 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
13328 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
13329 for (unsigned i
= 0;
13330 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
13332 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
13333 redirect_edge_succ (e
, incr_bb
);
13335 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
13336 e
->probability
= REG_BR_PROB_BASE
;
13337 gsi
= gsi_last_bb (incr_bb
);
13338 gimple g
= gimple_build_assign (iter2
, PLUS_EXPR
, iter1
,
13339 build_int_cst (unsigned_type_node
, 1));
13340 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13342 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13343 struct loop
*loop
= alloc_loop ();
13344 cfun
->has_force_vectorize_loops
= true;
13345 loop
->safelen
= node
->simdclone
->simdlen
;
13346 loop
->force_vectorize
= true;
13347 loop
->header
= body_bb
;
13349 /* Branch around the body if the mask applies. */
13350 if (node
->simdclone
->inbranch
)
13352 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
13354 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
13355 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)));
13356 tree aref
= build4 (ARRAY_REF
,
13357 TREE_TYPE (TREE_TYPE (mask_array
)),
13360 g
= gimple_build_assign (mask
, aref
);
13361 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13362 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
13363 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
13365 aref
= build1 (VIEW_CONVERT_EXPR
,
13366 build_nonstandard_integer_type (bitsize
, 0), mask
);
13367 mask
= make_ssa_name (TREE_TYPE (aref
));
13368 g
= gimple_build_assign (mask
, aref
);
13369 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13372 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
13374 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13375 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
13376 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
13379 /* Generate the condition. */
13380 g
= gimple_build_cond (LT_EXPR
,
13382 build_int_cst (unsigned_type_node
,
13383 node
->simdclone
->simdlen
),
13385 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13386 e
= split_block (incr_bb
, gsi_stmt (gsi
));
13387 basic_block latch_bb
= e
->dest
;
13388 basic_block new_exit_bb
;
13389 new_exit_bb
= split_block_after_labels (latch_bb
)->dest
;
13390 loop
->latch
= latch_bb
;
13392 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
13394 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
13395 /* The successor of incr_bb is already pointing to latch_bb; just
13397 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13398 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
13400 gphi
*phi
= create_phi_node (iter1
, body_bb
);
13401 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
13402 edge latch_edge
= single_succ_edge (latch_bb
);
13403 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
13405 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13407 /* Generate the new return. */
13408 gsi
= gsi_last_bb (new_exit_bb
);
13410 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
13411 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
13412 retval
= TREE_OPERAND (retval
, 0);
13415 retval
= build1 (VIEW_CONVERT_EXPR
,
13416 TREE_TYPE (TREE_TYPE (node
->decl
)),
13418 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
13419 false, GSI_CONTINUE_LINKING
);
13421 g
= gimple_build_return (retval
);
13422 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13424 /* Handle aligned clauses by replacing default defs of the aligned
13425 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13426 lhs. Handle linear by adding PHIs. */
13427 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
13428 if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
13429 && (TREE_ADDRESSABLE (node
->simdclone
->args
[i
].orig_arg
)
13430 || !is_gimple_reg_type
13431 (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
13433 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13434 if (is_gimple_reg_type (TREE_TYPE (orig_arg
)))
13435 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
13438 iter1
= create_tmp_var_raw (TREE_TYPE (orig_arg
));
13439 gimple_add_tmp_var (iter1
);
13441 gsi
= gsi_after_labels (entry_bb
);
13442 g
= gimple_build_assign (iter1
, orig_arg
);
13443 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13444 gsi
= gsi_after_labels (body_bb
);
13445 g
= gimple_build_assign (orig_arg
, iter1
);
13446 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13448 else if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
13449 && DECL_BY_REFERENCE (node
->simdclone
->args
[i
].orig_arg
)
13450 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
13452 && TREE_ADDRESSABLE
13453 (TREE_TYPE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
13455 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13456 tree def
= ssa_default_def (cfun
, orig_arg
);
13457 if (def
&& !has_zero_uses (def
))
13459 iter1
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg
)));
13460 gimple_add_tmp_var (iter1
);
13461 gsi
= gsi_after_labels (entry_bb
);
13462 g
= gimple_build_assign (iter1
, build_simple_mem_ref (def
));
13463 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13464 gsi
= gsi_after_labels (body_bb
);
13465 g
= gimple_build_assign (build_simple_mem_ref (def
), iter1
);
13466 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13469 else if (node
->simdclone
->args
[i
].alignment
13470 && node
->simdclone
->args
[i
].arg_type
13471 == SIMD_CLONE_ARG_TYPE_UNIFORM
13472 && (node
->simdclone
->args
[i
].alignment
13473 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
13474 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
13477 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
13478 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13479 tree def
= ssa_default_def (cfun
, orig_arg
);
13480 if (def
&& !has_zero_uses (def
))
13482 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
13483 gimple_seq seq
= NULL
;
13484 bool need_cvt
= false;
13486 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
13488 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
13491 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
);
13492 gimple_call_set_lhs (g
, t
);
13493 gimple_seq_add_stmt_without_update (&seq
, g
);
13496 t
= make_ssa_name (orig_arg
);
13497 g
= gimple_build_assign (t
, NOP_EXPR
, gimple_call_lhs (g
));
13498 gimple_seq_add_stmt_without_update (&seq
, g
);
13500 gsi_insert_seq_on_edge_immediate
13501 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
13503 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13504 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
13506 node
->create_edge (cgraph_node::get_create (fn
),
13507 call
, entry_bb
->count
, freq
);
13509 imm_use_iterator iter
;
13510 use_operand_p use_p
;
13512 tree repl
= gimple_get_lhs (g
);
13513 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13514 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
13517 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13518 SET_USE (use_p
, repl
);
13521 else if (node
->simdclone
->args
[i
].arg_type
13522 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
13524 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13525 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13526 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
13527 tree def
= NULL_TREE
;
13528 if (TREE_ADDRESSABLE (orig_arg
))
13530 def
= make_ssa_name (TREE_TYPE (orig_arg
));
13531 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
13532 iter2
= make_ssa_name (TREE_TYPE (orig_arg
));
13533 gsi
= gsi_after_labels (entry_bb
);
13534 g
= gimple_build_assign (def
, orig_arg
);
13535 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13539 def
= ssa_default_def (cfun
, orig_arg
);
13540 if (!def
|| has_zero_uses (def
))
13544 iter1
= make_ssa_name (orig_arg
);
13545 iter2
= make_ssa_name (orig_arg
);
13550 phi
= create_phi_node (iter1
, body_bb
);
13551 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
13552 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13553 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13554 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
13555 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13556 ? TREE_TYPE (orig_arg
) : sizetype
;
13558 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
13559 g
= gimple_build_assign (iter2
, code
, iter1
, addcst
);
13560 gsi
= gsi_last_bb (incr_bb
);
13561 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
13563 imm_use_iterator iter
;
13564 use_operand_p use_p
;
13566 if (TREE_ADDRESSABLE (orig_arg
))
13568 gsi
= gsi_after_labels (body_bb
);
13569 g
= gimple_build_assign (orig_arg
, iter1
);
13570 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13573 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13574 if (use_stmt
== phi
)
13577 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13578 SET_USE (use_p
, iter1
);
13582 calculate_dominance_info (CDI_DOMINATORS
);
13583 add_loop (loop
, loop
->header
->loop_father
);
13584 update_ssa (TODO_update_ssa
);
13589 /* If the function in NODE is tagged as an elemental SIMD function,
13590 create the appropriate SIMD clones. */
13593 expand_simd_clones (struct cgraph_node
*node
)
13595 tree attr
= lookup_attribute ("omp declare simd",
13596 DECL_ATTRIBUTES (node
->decl
));
13597 if (attr
== NULL_TREE
13598 || node
->global
.inlined_to
13599 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
13603 #pragma omp declare simd
13605 in C, there we don't know the argument types at all. */
13606 if (!node
->definition
13607 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
13612 /* Start with parsing the "omp declare simd" attribute(s). */
13613 bool inbranch_clause_specified
;
13614 struct cgraph_simd_clone
*clone_info
13615 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
13616 &inbranch_clause_specified
);
13617 if (clone_info
== NULL
)
13620 int orig_simdlen
= clone_info
->simdlen
;
13621 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
13622 /* The target can return 0 (no simd clones should be created),
13623 1 (just one ISA of simd clones should be created) or higher
13624 count of ISA variants. In that case, clone_info is initialized
13625 for the first ISA variant. */
13627 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
13632 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13633 also create one inbranch and one !inbranch clone of it. */
13634 for (int i
= 0; i
< count
* 2; i
++)
13636 struct cgraph_simd_clone
*clone
= clone_info
;
13637 if (inbranch_clause_specified
&& (i
& 1) != 0)
13642 clone
= simd_clone_struct_alloc (clone_info
->nargs
13644 simd_clone_struct_copy (clone
, clone_info
);
13645 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13646 and simd_clone_adjust_argument_types did to the first
13648 clone
->nargs
-= clone_info
->inbranch
;
13649 clone
->simdlen
= orig_simdlen
;
13650 /* And call the target hook again to get the right ISA. */
13651 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
13655 clone
->inbranch
= 1;
13658 /* simd_clone_mangle might fail if such a clone has been created
13660 tree id
= simd_clone_mangle (node
, clone
);
13661 if (id
== NULL_TREE
)
13664 /* Only when we are sure we want to create the clone actually
13665 clone the function (or definitions) or create another
13666 extern FUNCTION_DECL (for prototypes without definitions). */
13667 struct cgraph_node
*n
= simd_clone_create (node
);
13671 n
->simdclone
= clone
;
13672 clone
->origin
= node
;
13673 clone
->next_clone
= NULL
;
13674 if (node
->simd_clones
== NULL
)
13676 clone
->prev_clone
= n
;
13677 node
->simd_clones
= n
;
13681 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
13682 clone
->prev_clone
->simdclone
->next_clone
= n
;
13683 node
->simd_clones
->simdclone
->prev_clone
= n
;
13685 symtab
->change_decl_assembler_name (n
->decl
, id
);
13686 /* And finally adjust the return type, parameters and for
13687 definitions also function body. */
13688 if (node
->definition
)
13689 simd_clone_adjust (n
);
13692 simd_clone_adjust_return_type (n
);
13693 simd_clone_adjust_argument_types (n
);
13697 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
13700 /* Entry point for IPA simd clone creation pass. */
13702 static unsigned int
13703 ipa_omp_simd_clone (void)
13705 struct cgraph_node
*node
;
13706 FOR_EACH_FUNCTION (node
)
13707 expand_simd_clones (node
);
13713 const pass_data pass_data_omp_simd_clone
=
13715 SIMPLE_IPA_PASS
, /* type */
13716 "simdclone", /* name */
13717 OPTGROUP_NONE
, /* optinfo_flags */
13718 TV_NONE
, /* tv_id */
13719 ( PROP_ssa
| PROP_cfg
), /* properties_required */
13720 0, /* properties_provided */
13721 0, /* properties_destroyed */
13722 0, /* todo_flags_start */
13723 0, /* todo_flags_finish */
13726 class pass_omp_simd_clone
: public simple_ipa_opt_pass
13729 pass_omp_simd_clone(gcc::context
*ctxt
)
13730 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
13733 /* opt_pass methods: */
13734 virtual bool gate (function
*);
13735 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
13739 pass_omp_simd_clone::gate (function
*)
13741 return ((flag_openmp
|| flag_openmp_simd
13743 || (in_lto_p
&& !flag_wpa
))
13744 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
13747 } // anon namespace
13749 simple_ipa_opt_pass
*
13750 make_pass_omp_simd_clone (gcc::context
*ctxt
)
13752 return new pass_omp_simd_clone (ctxt
);
13755 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13756 adds their addresses and sizes to constructor-vector V_CTOR. */
13758 add_decls_addresses_to_decl_constructor (vec
<tree
, va_gc
> *v_decls
,
13759 vec
<constructor_elt
, va_gc
> *v_ctor
)
13761 unsigned len
= vec_safe_length (v_decls
);
13762 for (unsigned i
= 0; i
< len
; i
++)
13764 tree it
= (*v_decls
)[i
];
13765 bool is_function
= TREE_CODE (it
) != VAR_DECL
;
13767 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, build_fold_addr_expr (it
));
13769 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
,
13770 fold_convert (const_ptr_type_node
,
13771 DECL_SIZE_UNIT (it
)));
13775 /* Create new symbols containing (address, size) pairs for global variables,
13776 marked with "omp declare target" attribute, as well as addresses for the
13777 functions, which are outlined offloading regions. */
13779 omp_finish_file (void)
13781 unsigned num_funcs
= vec_safe_length (offload_funcs
);
13782 unsigned num_vars
= vec_safe_length (offload_vars
);
13784 if (num_funcs
== 0 && num_vars
== 0)
13787 if (targetm_common
.have_named_sections
)
13789 vec
<constructor_elt
, va_gc
> *v_f
, *v_v
;
13790 vec_alloc (v_f
, num_funcs
);
13791 vec_alloc (v_v
, num_vars
* 2);
13793 add_decls_addresses_to_decl_constructor (offload_funcs
, v_f
);
13794 add_decls_addresses_to_decl_constructor (offload_vars
, v_v
);
13796 tree vars_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13798 tree funcs_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13800 TYPE_ALIGN (vars_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13801 TYPE_ALIGN (funcs_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13802 tree ctor_v
= build_constructor (vars_decl_type
, v_v
);
13803 tree ctor_f
= build_constructor (funcs_decl_type
, v_f
);
13804 TREE_CONSTANT (ctor_v
) = TREE_CONSTANT (ctor_f
) = 1;
13805 TREE_STATIC (ctor_v
) = TREE_STATIC (ctor_f
) = 1;
13806 tree funcs_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13807 get_identifier (".offload_func_table"),
13809 tree vars_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13810 get_identifier (".offload_var_table"),
13812 TREE_STATIC (funcs_decl
) = TREE_STATIC (vars_decl
) = 1;
13813 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13814 otherwise a joint table in a binary will contain padding between
13815 tables from multiple object files. */
13816 DECL_USER_ALIGN (funcs_decl
) = DECL_USER_ALIGN (vars_decl
) = 1;
13817 DECL_ALIGN (funcs_decl
) = TYPE_ALIGN (funcs_decl_type
);
13818 DECL_ALIGN (vars_decl
) = TYPE_ALIGN (vars_decl_type
);
13819 DECL_INITIAL (funcs_decl
) = ctor_f
;
13820 DECL_INITIAL (vars_decl
) = ctor_v
;
13821 set_decl_section_name (funcs_decl
, OFFLOAD_FUNC_TABLE_SECTION_NAME
);
13822 set_decl_section_name (vars_decl
, OFFLOAD_VAR_TABLE_SECTION_NAME
);
13824 varpool_node::finalize_decl (vars_decl
);
13825 varpool_node::finalize_decl (funcs_decl
);
13829 for (unsigned i
= 0; i
< num_funcs
; i
++)
13831 tree it
= (*offload_funcs
)[i
];
13832 targetm
.record_offload_symbol (it
);
13834 for (unsigned i
= 0; i
< num_vars
; i
++)
13836 tree it
= (*offload_vars
)[i
];
13837 targetm
.record_offload_symbol (it
);
13842 #include "gt-omp-low.h"