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-2016 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"
34 #include "alloc-pool.h"
35 #include "tree-pass.h"
41 #include "pretty-print.h"
42 #include "diagnostic-core.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
47 #include "internal-fn.h"
48 #include "gimple-fold.h"
50 #include "gimple-iterator.h"
51 #include "gimplify-me.h"
52 #include "gimple-walk.h"
53 #include "tree-iterator.h"
54 #include "tree-inline.h"
55 #include "langhooks.h"
57 #include "tree-into-ssa.h"
68 #include "splay-tree.h"
70 #include "common/common-target.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "symbol-summary.h"
76 #include "tree-nested.h"
80 #include "lto-section-names.h"
81 #include "gomp-constants.h"
82 #include "gimple-pretty-print.h"
83 #include "symbol-summary.h"
87 /* Lowering of OMP parallel and workshare constructs proceeds in two
88 phases. The first phase scans the function looking for OMP statements
89 and then for variables that must be replaced to satisfy data sharing
90 clauses. The second phase expands code for the constructs, as well as
91 re-gimplifying things when variables have been replaced with complex
94 Final code generation is done by pass_expand_omp. The flowgraph is
95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
98 /* OMP region information. Every parallel and workshare
99 directive is enclosed between two markers, the OMP_* directive
100 and a corresponding GIMPLE_OMP_RETURN statement. */
104 /* The enclosing region. */
105 struct omp_region
*outer
;
107 /* First child region. */
108 struct omp_region
*inner
;
110 /* Next peer region. */
111 struct omp_region
*next
;
113 /* Block containing the omp directive as its last stmt. */
116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
122 /* If this is a combined parallel+workshare region, this is a list
123 of additional arguments needed by the combined parallel+workshare
125 vec
<tree
, va_gc
> *ws_args
;
127 /* The code for the omp directive of this region. */
128 enum gimple_code type
;
130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
131 enum omp_clause_schedule_kind sched_kind
;
133 /* Schedule modifiers. */
134 unsigned char sched_modifiers
;
136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel
;
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
141 gomp_ordered
*ord_stmt
;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context
*outer
;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map
;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map
;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
182 /* What to do with variables with implicitly determined sharing
184 enum omp_clause_default_kind default_kind
;
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
191 /* True if this parallel directive is nested within another. */
194 /* True if this construct can be cancelled. */
198 /* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
201 struct omp_for_data_loop
203 tree v
, n1
, n2
, step
;
204 enum tree_code cond_code
;
207 /* A structure describing the main elements of a parallel loop. */
211 struct omp_for_data_loop loop
;
217 bool have_nowait
, have_ordered
, simd_schedule
;
218 unsigned char sched_modifiers
;
219 enum omp_clause_schedule_kind sched_kind
;
220 struct omp_for_data_loop
*loops
;
223 /* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
228 oacc_loop
*parent
; /* Containing loop. */
230 oacc_loop
*child
; /* First inner loop. */
232 oacc_loop
*sibling
; /* Next loop within same parent. */
234 location_t loc
; /* Location of the loop start. */
236 gcall
*marker
; /* Initial head marker. */
238 gcall
*heads
[GOMP_DIM_MAX
]; /* Head marker functions. */
239 gcall
*tails
[GOMP_DIM_MAX
]; /* Tail marker functions. */
241 tree routine
; /* Pseudo-loop enclosing a routine. */
243 unsigned mask
; /* Partitioning mask. */
244 unsigned inner
; /* Partitioning of inner loops. */
245 unsigned flags
; /* Partitioning flags. */
246 unsigned ifns
; /* Contained loop abstraction functions. */
247 tree chunk_size
; /* Chunk size. */
248 gcall
*head_end
; /* Final marker of head sequence. */
251 /* Flags for an OpenACC loop. */
253 enum oacc_loop_flags
{
254 OLF_SEQ
= 1u << 0, /* Explicitly sequential */
255 OLF_AUTO
= 1u << 1, /* Compiler chooses axes. */
256 OLF_INDEPENDENT
= 1u << 2, /* Iterations are known independent. */
257 OLF_GANG_STATIC
= 1u << 3, /* Gang partitioning is static (has op). */
259 /* Explicitly specified loop axes. */
261 OLF_DIM_GANG
= 1u << (OLF_DIM_BASE
+ GOMP_DIM_GANG
),
262 OLF_DIM_WORKER
= 1u << (OLF_DIM_BASE
+ GOMP_DIM_WORKER
),
263 OLF_DIM_VECTOR
= 1u << (OLF_DIM_BASE
+ GOMP_DIM_VECTOR
),
265 OLF_MAX
= OLF_DIM_BASE
+ GOMP_DIM_MAX
269 static splay_tree all_contexts
;
270 static int taskreg_nesting_level
;
271 static int target_nesting_level
;
272 static struct omp_region
*root_omp_region
;
273 static bitmap task_shared_vars
;
274 static vec
<omp_context
*> taskreg_contexts
;
275 static bool omp_any_child_fn_dumped
;
277 static void scan_omp (gimple_seq
*, omp_context
*);
278 static tree
scan_omp_1_op (tree
*, int *, void *);
279 static gphi
*find_phi_with_arg_on_edge (tree
, edge
);
281 #define WALK_SUBSTMTS \
285 case GIMPLE_EH_FILTER: \
286 case GIMPLE_TRANSACTION: \
287 /* The sub-statements for these should be walked. */ \
288 *handled_ops_p = false; \
291 /* Return true if CTX corresponds to an oacc parallel region. */
294 is_oacc_parallel (omp_context
*ctx
)
296 enum gimple_code outer_type
= gimple_code (ctx
->stmt
);
297 return ((outer_type
== GIMPLE_OMP_TARGET
)
298 && (gimple_omp_target_kind (ctx
->stmt
)
299 == GF_OMP_TARGET_KIND_OACC_PARALLEL
));
302 /* Return true if CTX corresponds to an oacc kernels region. */
305 is_oacc_kernels (omp_context
*ctx
)
307 enum gimple_code outer_type
= gimple_code (ctx
->stmt
);
308 return ((outer_type
== GIMPLE_OMP_TARGET
)
309 && (gimple_omp_target_kind (ctx
->stmt
)
310 == GF_OMP_TARGET_KIND_OACC_KERNELS
));
313 /* If DECL is the artificial dummy VAR_DECL created for non-static
314 data member privatization, return the underlying "this" parameter,
315 otherwise return NULL. */
318 omp_member_access_dummy_var (tree decl
)
321 || !DECL_ARTIFICIAL (decl
)
322 || !DECL_IGNORED_P (decl
)
323 || !DECL_HAS_VALUE_EXPR_P (decl
)
324 || !lang_hooks
.decls
.omp_disregard_value_expr (decl
, false))
327 tree v
= DECL_VALUE_EXPR (decl
);
328 if (TREE_CODE (v
) != COMPONENT_REF
)
332 switch (TREE_CODE (v
))
338 case POINTER_PLUS_EXPR
:
339 v
= TREE_OPERAND (v
, 0);
342 if (DECL_CONTEXT (v
) == current_function_decl
343 && DECL_ARTIFICIAL (v
)
344 && TREE_CODE (TREE_TYPE (v
)) == POINTER_TYPE
)
352 /* Helper for unshare_and_remap, called through walk_tree. */
355 unshare_and_remap_1 (tree
*tp
, int *walk_subtrees
, void *data
)
357 tree
*pair
= (tree
*) data
;
360 *tp
= unshare_expr (pair
[1]);
363 else if (IS_TYPE_OR_DECL_P (*tp
))
368 /* Return unshare_expr (X) with all occurrences of FROM
372 unshare_and_remap (tree x
, tree from
, tree to
)
374 tree pair
[2] = { from
, to
};
375 x
= unshare_expr (x
);
376 walk_tree (&x
, unshare_and_remap_1
, pair
, NULL
);
380 /* Holds offload tables with decls. */
381 vec
<tree
, va_gc
> *offload_funcs
, *offload_vars
;
383 /* Convenience function for calling scan_omp_1_op on tree operands. */
386 scan_omp_op (tree
*tp
, omp_context
*ctx
)
388 struct walk_stmt_info wi
;
390 memset (&wi
, 0, sizeof (wi
));
392 wi
.want_locations
= true;
394 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
397 static void lower_omp (gimple_seq
*, omp_context
*);
398 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
399 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
401 /* Find an OMP clause of type KIND within CLAUSES. */
404 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
406 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
407 if (OMP_CLAUSE_CODE (clauses
) == kind
)
413 /* Return true if CTX is for an omp parallel. */
416 is_parallel_ctx (omp_context
*ctx
)
418 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
422 /* Return true if CTX is for an omp task. */
425 is_task_ctx (omp_context
*ctx
)
427 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
431 /* Return true if CTX is for an omp taskloop. */
434 is_taskloop_ctx (omp_context
*ctx
)
436 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
437 && gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_TASKLOOP
;
441 /* Return true if CTX is for an omp parallel or omp task. */
444 is_taskreg_ctx (omp_context
*ctx
)
446 return is_parallel_ctx (ctx
) || is_task_ctx (ctx
);
450 /* Return true if REGION is a combined parallel+workshare region. */
453 is_combined_parallel (struct omp_region
*region
)
455 return region
->is_combined_parallel
;
458 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
462 adjust_for_condition (location_t loc
, enum tree_code
*cond_code
, tree
*n2
)
471 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
472 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, 1);
474 *n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (*n2
), *n2
,
475 build_int_cst (TREE_TYPE (*n2
), 1));
476 *cond_code
= LT_EXPR
;
479 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
480 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, -1);
482 *n2
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (*n2
), *n2
,
483 build_int_cst (TREE_TYPE (*n2
), 1));
484 *cond_code
= GT_EXPR
;
491 /* Return the looping step from INCR, extracted from the step of a gimple omp
495 get_omp_for_step_from_incr (location_t loc
, tree incr
)
498 switch (TREE_CODE (incr
))
501 step
= TREE_OPERAND (incr
, 1);
503 case POINTER_PLUS_EXPR
:
504 step
= fold_convert (ssizetype
, TREE_OPERAND (incr
, 1));
507 step
= TREE_OPERAND (incr
, 1);
508 step
= fold_build1_loc (loc
, NEGATE_EXPR
, TREE_TYPE (step
), step
);
516 /* Extract the header elements of parallel loop FOR_STMT and store
520 extract_omp_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
521 struct omp_for_data_loop
*loops
)
523 tree t
, var
, *collapse_iter
, *collapse_count
;
524 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
525 struct omp_for_data_loop
*loop
;
527 struct omp_for_data_loop dummy_loop
;
528 location_t loc
= gimple_location (for_stmt
);
529 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
530 bool distribute
= gimple_omp_for_kind (for_stmt
)
531 == GF_OMP_FOR_KIND_DISTRIBUTE
;
532 bool taskloop
= gimple_omp_for_kind (for_stmt
)
533 == GF_OMP_FOR_KIND_TASKLOOP
;
536 fd
->for_stmt
= for_stmt
;
538 if (gimple_omp_for_collapse (for_stmt
) > 1)
541 fd
->loops
= &fd
->loop
;
543 fd
->have_nowait
= distribute
|| simd
;
544 fd
->have_ordered
= false;
547 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
548 fd
->sched_modifiers
= 0;
549 fd
->chunk_size
= NULL_TREE
;
550 fd
->simd_schedule
= false;
551 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
552 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
553 collapse_iter
= NULL
;
554 collapse_count
= NULL
;
556 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
557 switch (OMP_CLAUSE_CODE (t
))
559 case OMP_CLAUSE_NOWAIT
:
560 fd
->have_nowait
= true;
562 case OMP_CLAUSE_ORDERED
:
563 fd
->have_ordered
= true;
564 if (OMP_CLAUSE_ORDERED_EXPR (t
))
565 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
567 case OMP_CLAUSE_SCHEDULE
:
568 gcc_assert (!distribute
&& !taskloop
);
570 = (enum omp_clause_schedule_kind
)
571 (OMP_CLAUSE_SCHEDULE_KIND (t
) & OMP_CLAUSE_SCHEDULE_MASK
);
572 fd
->sched_modifiers
= (OMP_CLAUSE_SCHEDULE_KIND (t
)
573 & ~OMP_CLAUSE_SCHEDULE_MASK
);
574 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
575 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
577 case OMP_CLAUSE_DIST_SCHEDULE
:
578 gcc_assert (distribute
);
579 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
581 case OMP_CLAUSE_COLLAPSE
:
582 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
583 if (fd
->collapse
> 1)
585 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
586 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
592 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
597 collapse_iter
= &iterv
;
598 collapse_count
= &countv
;
601 /* FIXME: for now map schedule(auto) to schedule(static).
602 There should be analysis to determine whether all iterations
603 are approximately the same amount of work (then schedule(static)
604 is best) or if it varies (then schedule(dynamic,N) is better). */
605 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
607 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
608 gcc_assert (fd
->chunk_size
== NULL
);
610 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
612 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
613 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
614 gcc_assert (fd
->chunk_size
== NULL
);
615 else if (fd
->chunk_size
== NULL
)
617 /* We only need to compute a default chunk size for ordered
618 static loops and dynamic loops. */
619 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
621 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
622 ? integer_zero_node
: integer_one_node
;
625 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
626 for (i
= 0; i
< cnt
; i
++)
628 if (i
== 0 && fd
->collapse
== 1 && (fd
->ordered
== 0 || loops
== NULL
))
630 else if (loops
!= NULL
)
635 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
636 gcc_assert (SSA_VAR_P (loop
->v
));
637 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
638 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
639 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
640 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
642 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
643 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
644 gcc_assert (loop
->cond_code
!= NE_EXPR
645 || gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_CILKSIMD
646 || gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
);
647 adjust_for_condition (loc
, &loop
->cond_code
, &loop
->n2
);
649 t
= gimple_omp_for_incr (for_stmt
, i
);
650 gcc_assert (TREE_OPERAND (t
, 0) == var
);
651 loop
->step
= get_omp_for_step_from_incr (loc
, t
);
654 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
655 && !fd
->have_ordered
))
657 if (fd
->collapse
== 1)
658 iter_type
= TREE_TYPE (loop
->v
);
660 || TYPE_PRECISION (iter_type
)
661 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
663 = build_nonstandard_integer_type
664 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
666 else if (iter_type
!= long_long_unsigned_type_node
)
668 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
669 iter_type
= long_long_unsigned_type_node
;
670 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
671 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
672 >= TYPE_PRECISION (iter_type
))
676 if (loop
->cond_code
== LT_EXPR
)
677 n
= fold_build2_loc (loc
,
678 PLUS_EXPR
, TREE_TYPE (loop
->v
),
679 loop
->n2
, loop
->step
);
682 if (TREE_CODE (n
) != INTEGER_CST
683 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
684 iter_type
= long_long_unsigned_type_node
;
686 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
687 > TYPE_PRECISION (iter_type
))
691 if (loop
->cond_code
== LT_EXPR
)
694 n2
= fold_build2_loc (loc
,
695 PLUS_EXPR
, TREE_TYPE (loop
->v
),
696 loop
->n2
, loop
->step
);
700 n1
= fold_build2_loc (loc
,
701 MINUS_EXPR
, TREE_TYPE (loop
->v
),
702 loop
->n2
, loop
->step
);
705 if (TREE_CODE (n1
) != INTEGER_CST
706 || TREE_CODE (n2
) != INTEGER_CST
707 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
708 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
709 iter_type
= long_long_unsigned_type_node
;
713 if (i
>= fd
->collapse
)
716 if (collapse_count
&& *collapse_count
== NULL
)
718 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
719 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
720 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
721 if (t
&& integer_zerop (t
))
722 count
= build_zero_cst (long_long_unsigned_type_node
);
723 else if ((i
== 0 || count
!= NULL_TREE
)
724 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
725 && TREE_CONSTANT (loop
->n1
)
726 && TREE_CONSTANT (loop
->n2
)
727 && TREE_CODE (loop
->step
) == INTEGER_CST
)
729 tree itype
= TREE_TYPE (loop
->v
);
731 if (POINTER_TYPE_P (itype
))
732 itype
= signed_type_for (itype
);
733 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
734 t
= fold_build2_loc (loc
,
736 fold_convert_loc (loc
, itype
, loop
->step
), t
);
737 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
738 fold_convert_loc (loc
, itype
, loop
->n2
));
739 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
740 fold_convert_loc (loc
, itype
, loop
->n1
));
741 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
742 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
743 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
744 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
745 fold_convert_loc (loc
, itype
,
748 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
749 fold_convert_loc (loc
, itype
, loop
->step
));
750 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
751 if (count
!= NULL_TREE
)
752 count
= fold_build2_loc (loc
,
753 MULT_EXPR
, long_long_unsigned_type_node
,
757 if (TREE_CODE (count
) != INTEGER_CST
)
760 else if (count
&& !integer_zerop (count
))
767 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
768 || fd
->have_ordered
))
770 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
771 iter_type
= long_long_unsigned_type_node
;
773 iter_type
= long_integer_type_node
;
775 else if (collapse_iter
&& *collapse_iter
!= NULL
)
776 iter_type
= TREE_TYPE (*collapse_iter
);
777 fd
->iter_type
= iter_type
;
778 if (collapse_iter
&& *collapse_iter
== NULL
)
779 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
780 if (collapse_count
&& *collapse_count
== NULL
)
783 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
785 *collapse_count
= create_tmp_var (iter_type
, ".count");
788 if (fd
->collapse
> 1 || (fd
->ordered
&& loops
))
790 fd
->loop
.v
= *collapse_iter
;
791 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
792 fd
->loop
.n2
= *collapse_count
;
793 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
794 fd
->loop
.cond_code
= LT_EXPR
;
801 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
802 is the immediate dominator of PAR_ENTRY_BB, return true if there
803 are no data dependencies that would prevent expanding the parallel
804 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
806 When expanding a combined parallel+workshare region, the call to
807 the child function may need additional arguments in the case of
808 GIMPLE_OMP_FOR regions. In some cases, these arguments are
809 computed out of variables passed in from the parent to the child
810 via 'struct .omp_data_s'. For instance:
812 #pragma omp parallel for schedule (guided, i * 4)
817 # BLOCK 2 (PAR_ENTRY_BB)
819 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
821 # BLOCK 3 (WS_ENTRY_BB)
822 .omp_data_i = &.omp_data_o;
823 D.1667 = .omp_data_i->i;
825 #pragma omp for schedule (guided, D.1598)
827 When we outline the parallel region, the call to the child function
828 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
829 that value is computed *after* the call site. So, in principle we
830 cannot do the transformation.
832 To see whether the code in WS_ENTRY_BB blocks the combined
833 parallel+workshare call, we collect all the variables used in the
834 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
835 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
838 FIXME. If we had the SSA form built at this point, we could merely
839 hoist the code in block 3 into block 2 and be done with it. But at
840 this point we don't have dataflow information and though we could
841 hack something up here, it is really not worth the aggravation. */
844 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
846 struct omp_for_data fd
;
847 gimple
*ws_stmt
= last_stmt (ws_entry_bb
);
849 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
852 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
854 extract_omp_for_data (as_a
<gomp_for
*> (ws_stmt
), &fd
, NULL
);
856 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
858 if (fd
.iter_type
!= long_integer_type_node
)
861 /* FIXME. We give up too easily here. If any of these arguments
862 are not constants, they will likely involve variables that have
863 been mapped into fields of .omp_data_s for sharing with the child
864 function. With appropriate data flow, it would be possible to
866 if (!is_gimple_min_invariant (fd
.loop
.n1
)
867 || !is_gimple_min_invariant (fd
.loop
.n2
)
868 || !is_gimple_min_invariant (fd
.loop
.step
)
869 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
876 static int omp_max_vf (void);
878 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
879 presence (SIMD_SCHEDULE). */
882 omp_adjust_chunk_size (tree chunk_size
, bool simd_schedule
)
887 int vf
= omp_max_vf ();
891 tree type
= TREE_TYPE (chunk_size
);
892 chunk_size
= fold_build2 (PLUS_EXPR
, type
, chunk_size
,
893 build_int_cst (type
, vf
- 1));
894 return fold_build2 (BIT_AND_EXPR
, type
, chunk_size
,
895 build_int_cst (type
, -vf
));
899 /* Collect additional arguments needed to emit a combined
900 parallel+workshare call. WS_STMT is the workshare directive being
903 static vec
<tree
, va_gc
> *
904 get_ws_args_for (gimple
*par_stmt
, gimple
*ws_stmt
)
907 location_t loc
= gimple_location (ws_stmt
);
908 vec
<tree
, va_gc
> *ws_args
;
910 if (gomp_for
*for_stmt
= dyn_cast
<gomp_for
*> (ws_stmt
))
912 struct omp_for_data fd
;
915 extract_omp_for_data (for_stmt
, &fd
, NULL
);
919 if (gimple_omp_for_combined_into_p (for_stmt
))
922 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
923 OMP_CLAUSE__LOOPTEMP_
);
925 n1
= OMP_CLAUSE_DECL (innerc
);
926 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
927 OMP_CLAUSE__LOOPTEMP_
);
929 n2
= OMP_CLAUSE_DECL (innerc
);
932 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
934 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
935 ws_args
->quick_push (t
);
937 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
938 ws_args
->quick_push (t
);
940 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
941 ws_args
->quick_push (t
);
945 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
946 t
= omp_adjust_chunk_size (t
, fd
.simd_schedule
);
947 ws_args
->quick_push (t
);
952 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
954 /* Number of sections is equal to the number of edges from the
955 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
956 the exit of the sections region. */
957 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
958 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
959 vec_alloc (ws_args
, 1);
960 ws_args
->quick_push (t
);
968 /* Discover whether REGION is a combined parallel+workshare region. */
971 determine_parallel_type (struct omp_region
*region
)
973 basic_block par_entry_bb
, par_exit_bb
;
974 basic_block ws_entry_bb
, ws_exit_bb
;
976 if (region
== NULL
|| region
->inner
== NULL
977 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
978 || region
->inner
->cont
== NULL
)
981 /* We only support parallel+for and parallel+sections. */
982 if (region
->type
!= GIMPLE_OMP_PARALLEL
983 || (region
->inner
->type
!= GIMPLE_OMP_FOR
984 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
987 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
988 WS_EXIT_BB -> PAR_EXIT_BB. */
989 par_entry_bb
= region
->entry
;
990 par_exit_bb
= region
->exit
;
991 ws_entry_bb
= region
->inner
->entry
;
992 ws_exit_bb
= region
->inner
->exit
;
994 if (single_succ (par_entry_bb
) == ws_entry_bb
995 && single_succ (ws_exit_bb
) == par_exit_bb
996 && workshare_safe_to_combine_p (ws_entry_bb
)
997 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
998 || (last_and_only_stmt (ws_entry_bb
)
999 && last_and_only_stmt (par_exit_bb
))))
1001 gimple
*par_stmt
= last_stmt (par_entry_bb
);
1002 gimple
*ws_stmt
= last_stmt (ws_entry_bb
);
1004 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
1006 /* If this is a combined parallel loop, we need to determine
1007 whether or not to use the combined library calls. There
1008 are two cases where we do not apply the transformation:
1009 static loops and any kind of ordered loop. In the first
1010 case, we already open code the loop so there is no need
1011 to do anything else. In the latter case, the combined
1012 parallel loop call would still need extra synchronization
1013 to implement ordered semantics, so there would not be any
1014 gain in using the combined call. */
1015 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
1016 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
1018 || ((OMP_CLAUSE_SCHEDULE_KIND (c
) & OMP_CLAUSE_SCHEDULE_MASK
)
1019 == OMP_CLAUSE_SCHEDULE_STATIC
)
1020 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
1022 region
->is_combined_parallel
= false;
1023 region
->inner
->is_combined_parallel
= false;
1028 region
->is_combined_parallel
= true;
1029 region
->inner
->is_combined_parallel
= true;
1030 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
1035 /* Return true if EXPR is variable sized. */
1038 is_variable_sized (const_tree expr
)
1040 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
1043 /* Return true if DECL is a reference type. */
1046 is_reference (tree decl
)
1048 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
1051 /* Return the type of a decl. If the decl is reference type,
1052 return its base type. */
1054 get_base_type (tree decl
)
1056 tree type
= TREE_TYPE (decl
);
1057 if (is_reference (decl
))
1058 type
= TREE_TYPE (type
);
1062 /* Lookup variables. The "maybe" form
1063 allows for the variable form to not have been entered, otherwise we
1064 assert that the variable must have been entered. */
1067 lookup_decl (tree var
, omp_context
*ctx
)
1069 tree
*n
= ctx
->cb
.decl_map
->get (var
);
1074 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
1076 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
1077 return n
? *n
: NULL_TREE
;
1081 lookup_field (tree var
, omp_context
*ctx
)
1084 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
1085 return (tree
) n
->value
;
1089 lookup_sfield (splay_tree_key key
, omp_context
*ctx
)
1092 n
= splay_tree_lookup (ctx
->sfield_map
1093 ? ctx
->sfield_map
: ctx
->field_map
, key
);
1094 return (tree
) n
->value
;
1098 lookup_sfield (tree var
, omp_context
*ctx
)
1100 return lookup_sfield ((splay_tree_key
) var
, ctx
);
1104 maybe_lookup_field (splay_tree_key key
, omp_context
*ctx
)
1107 n
= splay_tree_lookup (ctx
->field_map
, key
);
1108 return n
? (tree
) n
->value
: NULL_TREE
;
1112 maybe_lookup_field (tree var
, omp_context
*ctx
)
1114 return maybe_lookup_field ((splay_tree_key
) var
, ctx
);
1117 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1118 the parallel context if DECL is to be shared. */
1121 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
1123 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
1126 /* We can only use copy-in/copy-out semantics for shared variables
1127 when we know the value is not accessible from an outer scope. */
1130 gcc_assert (!is_gimple_omp_oacc (shared_ctx
->stmt
));
1132 /* ??? Trivially accessible from anywhere. But why would we even
1133 be passing an address in this case? Should we simply assert
1134 this to be false, or should we have a cleanup pass that removes
1135 these from the list of mappings? */
1136 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
1139 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1140 without analyzing the expression whether or not its location
1141 is accessible to anyone else. In the case of nested parallel
1142 regions it certainly may be. */
1143 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
1146 /* Do not use copy-in/copy-out for variables that have their
1148 if (TREE_ADDRESSABLE (decl
))
1151 /* lower_send_shared_vars only uses copy-in, but not copy-out
1153 if (TREE_READONLY (decl
)
1154 || ((TREE_CODE (decl
) == RESULT_DECL
1155 || TREE_CODE (decl
) == PARM_DECL
)
1156 && DECL_BY_REFERENCE (decl
)))
1159 /* Disallow copy-in/out in nested parallel if
1160 decl is shared in outer parallel, otherwise
1161 each thread could store the shared variable
1162 in its own copy-in location, making the
1163 variable no longer really shared. */
1164 if (shared_ctx
->is_nested
)
1168 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
1169 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
1176 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
1177 c
; c
= OMP_CLAUSE_CHAIN (c
))
1178 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1179 && OMP_CLAUSE_DECL (c
) == decl
)
1183 goto maybe_mark_addressable_and_ret
;
1187 /* For tasks avoid using copy-in/out. As tasks can be
1188 deferred or executed in different thread, when GOMP_task
1189 returns, the task hasn't necessarily terminated. */
1190 if (is_task_ctx (shared_ctx
))
1193 maybe_mark_addressable_and_ret
:
1194 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
1195 if (is_gimple_reg (outer
) && !omp_member_access_dummy_var (outer
))
1197 /* Taking address of OUTER in lower_send_shared_vars
1198 might need regimplification of everything that uses the
1200 if (!task_shared_vars
)
1201 task_shared_vars
= BITMAP_ALLOC (NULL
);
1202 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
1203 TREE_ADDRESSABLE (outer
) = 1;
1212 /* Construct a new automatic decl similar to VAR. */
1215 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
1217 tree copy
= copy_var_decl (var
, name
, type
);
1219 DECL_CONTEXT (copy
) = current_function_decl
;
1220 DECL_CHAIN (copy
) = ctx
->block_vars
;
1221 /* If VAR is listed in task_shared_vars, it means it wasn't
1222 originally addressable and is just because task needs to take
1223 it's address. But we don't need to take address of privatizations
1225 if (TREE_ADDRESSABLE (var
)
1227 && bitmap_bit_p (task_shared_vars
, DECL_UID (var
)))
1228 TREE_ADDRESSABLE (copy
) = 0;
1229 ctx
->block_vars
= copy
;
1235 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
1237 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
1240 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1243 omp_build_component_ref (tree obj
, tree field
)
1245 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
1246 if (TREE_THIS_VOLATILE (field
))
1247 TREE_THIS_VOLATILE (ret
) |= 1;
1248 if (TREE_READONLY (field
))
1249 TREE_READONLY (ret
) |= 1;
1253 /* Build tree nodes to access the field for VAR on the receiver side. */
1256 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1258 tree x
, field
= lookup_field (var
, ctx
);
1260 /* If the receiver record type was remapped in the child function,
1261 remap the field into the new record type. */
1262 x
= maybe_lookup_field (field
, ctx
);
1266 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1267 TREE_THIS_NOTRAP (x
) = 1;
1268 x
= omp_build_component_ref (x
, field
);
1271 x
= build_simple_mem_ref (x
);
1272 TREE_THIS_NOTRAP (x
) = 1;
1278 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1279 of a parallel, this is a component reference; for workshare constructs
1280 this is some variable. */
1283 build_outer_var_ref (tree var
, omp_context
*ctx
, bool lastprivate
= false)
1287 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1289 else if (is_variable_sized (var
))
1291 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1292 x
= build_outer_var_ref (x
, ctx
, lastprivate
);
1293 x
= build_simple_mem_ref (x
);
1295 else if (is_taskreg_ctx (ctx
))
1297 bool by_ref
= use_pointer_for_field (var
, NULL
);
1298 x
= build_receiver_ref (var
, by_ref
, ctx
);
1300 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1301 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1303 /* #pragma omp simd isn't a worksharing construct, and can reference even
1304 private vars in its linear etc. clauses. */
1306 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1307 x
= lookup_decl (var
, ctx
->outer
);
1308 else if (ctx
->outer
)
1309 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1313 else if (lastprivate
&& is_taskloop_ctx (ctx
))
1315 gcc_assert (ctx
->outer
);
1317 = splay_tree_lookup (ctx
->outer
->field_map
,
1318 (splay_tree_key
) &DECL_UID (var
));
1321 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
->outer
)))
1324 x
= lookup_decl (var
, ctx
->outer
);
1328 tree field
= (tree
) n
->value
;
1329 /* If the receiver record type was remapped in the child function,
1330 remap the field into the new record type. */
1331 x
= maybe_lookup_field (field
, ctx
->outer
);
1335 x
= build_simple_mem_ref (ctx
->outer
->receiver_decl
);
1336 x
= omp_build_component_ref (x
, field
);
1337 if (use_pointer_for_field (var
, ctx
->outer
))
1338 x
= build_simple_mem_ref (x
);
1341 else if (ctx
->outer
)
1343 omp_context
*outer
= ctx
->outer
;
1344 if (gimple_code (outer
->stmt
) == GIMPLE_OMP_GRID_BODY
)
1346 outer
= outer
->outer
;
1348 && gimple_code (outer
->stmt
) != GIMPLE_OMP_GRID_BODY
);
1350 x
= lookup_decl (var
, outer
);
1352 else if (is_reference (var
))
1353 /* This can happen with orphaned constructs. If var is reference, it is
1354 possible it is shared and as such valid. */
1356 else if (omp_member_access_dummy_var (var
))
1363 tree t
= omp_member_access_dummy_var (var
);
1366 x
= DECL_VALUE_EXPR (var
);
1367 tree o
= maybe_lookup_decl_in_outer_ctx (t
, ctx
);
1369 x
= unshare_and_remap (x
, t
, o
);
1371 x
= unshare_expr (x
);
1375 if (is_reference (var
))
1376 x
= build_simple_mem_ref (x
);
1381 /* Build tree nodes to access the field for VAR on the sender side. */
1384 build_sender_ref (splay_tree_key key
, omp_context
*ctx
)
1386 tree field
= lookup_sfield (key
, ctx
);
1387 return omp_build_component_ref (ctx
->sender_decl
, field
);
1391 build_sender_ref (tree var
, omp_context
*ctx
)
1393 return build_sender_ref ((splay_tree_key
) var
, ctx
);
1396 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1397 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1400 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
,
1401 bool base_pointers_restrict
= false)
1403 tree field
, type
, sfield
= NULL_TREE
;
1404 splay_tree_key key
= (splay_tree_key
) var
;
1406 if ((mask
& 8) != 0)
1408 key
= (splay_tree_key
) &DECL_UID (var
);
1409 gcc_checking_assert (key
!= (splay_tree_key
) var
);
1411 gcc_assert ((mask
& 1) == 0
1412 || !splay_tree_lookup (ctx
->field_map
, key
));
1413 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1414 || !splay_tree_lookup (ctx
->sfield_map
, key
));
1415 gcc_assert ((mask
& 3) == 3
1416 || !is_gimple_omp_oacc (ctx
->stmt
));
1418 type
= TREE_TYPE (var
);
1419 /* Prevent redeclaring the var in the split-off function with a restrict
1420 pointer type. Note that we only clear type itself, restrict qualifiers in
1421 the pointed-to type will be ignored by points-to analysis. */
1422 if (POINTER_TYPE_P (type
)
1423 && TYPE_RESTRICT (type
))
1424 type
= build_qualified_type (type
, TYPE_QUALS (type
) & ~TYPE_QUAL_RESTRICT
);
1428 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1429 type
= build_pointer_type (build_pointer_type (type
));
1433 type
= build_pointer_type (type
);
1434 if (base_pointers_restrict
)
1435 type
= build_qualified_type (type
, TYPE_QUAL_RESTRICT
);
1437 else if ((mask
& 3) == 1 && is_reference (var
))
1438 type
= TREE_TYPE (type
);
1440 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1441 FIELD_DECL
, DECL_NAME (var
), type
);
1443 /* Remember what variable this field was created for. This does have a
1444 side effect of making dwarf2out ignore this member, so for helpful
1445 debugging we clear it later in delete_omp_context. */
1446 DECL_ABSTRACT_ORIGIN (field
) = var
;
1447 if (type
== TREE_TYPE (var
))
1449 SET_DECL_ALIGN (field
, DECL_ALIGN (var
));
1450 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1451 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1454 SET_DECL_ALIGN (field
, TYPE_ALIGN (type
));
1456 if ((mask
& 3) == 3)
1458 insert_field_into_struct (ctx
->record_type
, field
);
1459 if (ctx
->srecord_type
)
1461 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1462 FIELD_DECL
, DECL_NAME (var
), type
);
1463 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1464 SET_DECL_ALIGN (sfield
, DECL_ALIGN (field
));
1465 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1466 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1467 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1472 if (ctx
->srecord_type
== NULL_TREE
)
1476 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1477 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1478 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1480 sfield
= build_decl (DECL_SOURCE_LOCATION (t
),
1481 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1482 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1483 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1484 splay_tree_insert (ctx
->sfield_map
,
1485 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1486 (splay_tree_value
) sfield
);
1490 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1491 : ctx
->srecord_type
, field
);
1495 splay_tree_insert (ctx
->field_map
, key
, (splay_tree_value
) field
);
1496 if ((mask
& 2) && ctx
->sfield_map
)
1497 splay_tree_insert (ctx
->sfield_map
, key
, (splay_tree_value
) sfield
);
1501 install_var_local (tree var
, omp_context
*ctx
)
1503 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1504 insert_decl_map (&ctx
->cb
, var
, new_var
);
1508 /* Adjust the replacement for DECL in CTX for the new context. This means
1509 copying the DECL_VALUE_EXPR, and fixing up the type. */
1512 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1514 tree new_decl
, size
;
1516 new_decl
= lookup_decl (decl
, ctx
);
1518 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1520 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1521 && DECL_HAS_VALUE_EXPR_P (decl
))
1523 tree ve
= DECL_VALUE_EXPR (decl
);
1524 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1525 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1526 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1529 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1531 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1532 if (size
== error_mark_node
)
1533 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1534 DECL_SIZE (new_decl
) = size
;
1536 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1537 if (size
== error_mark_node
)
1538 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1539 DECL_SIZE_UNIT (new_decl
) = size
;
1543 /* The callback for remap_decl. Search all containing contexts for a
1544 mapping of the variable; this avoids having to duplicate the splay
1545 tree ahead of time. We know a mapping doesn't already exist in the
1546 given context. Create new mappings to implement default semantics. */
1549 omp_copy_decl (tree var
, copy_body_data
*cb
)
1551 omp_context
*ctx
= (omp_context
*) cb
;
1554 if (TREE_CODE (var
) == LABEL_DECL
)
1556 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1557 DECL_CONTEXT (new_var
) = current_function_decl
;
1558 insert_decl_map (&ctx
->cb
, var
, new_var
);
1562 while (!is_taskreg_ctx (ctx
))
1567 new_var
= maybe_lookup_decl (var
, ctx
);
1572 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1575 return error_mark_node
;
1579 /* Debugging dumps for parallel regions. */
1580 void dump_omp_region (FILE *, struct omp_region
*, int);
1581 void debug_omp_region (struct omp_region
*);
1582 void debug_all_omp_regions (void);
1584 /* Dump the parallel region tree rooted at REGION. */
1587 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1589 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1590 gimple_code_name
[region
->type
]);
1593 dump_omp_region (file
, region
->inner
, indent
+ 4);
1597 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1598 region
->cont
->index
);
1602 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1603 region
->exit
->index
);
1605 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1608 dump_omp_region (file
, region
->next
, indent
);
1612 debug_omp_region (struct omp_region
*region
)
1614 dump_omp_region (stderr
, region
, 0);
1618 debug_all_omp_regions (void)
1620 dump_omp_region (stderr
, root_omp_region
, 0);
1624 /* Create a new parallel region starting at STMT inside region PARENT. */
1626 static struct omp_region
*
1627 new_omp_region (basic_block bb
, enum gimple_code type
,
1628 struct omp_region
*parent
)
1630 struct omp_region
*region
= XCNEW (struct omp_region
);
1632 region
->outer
= parent
;
1634 region
->type
= type
;
1638 /* This is a nested region. Add it to the list of inner
1639 regions in PARENT. */
1640 region
->next
= parent
->inner
;
1641 parent
->inner
= region
;
1645 /* This is a toplevel region. Add it to the list of toplevel
1646 regions in ROOT_OMP_REGION. */
1647 region
->next
= root_omp_region
;
1648 root_omp_region
= region
;
1654 /* Release the memory associated with the region tree rooted at REGION. */
1657 free_omp_region_1 (struct omp_region
*region
)
1659 struct omp_region
*i
, *n
;
1661 for (i
= region
->inner
; i
; i
= n
)
1664 free_omp_region_1 (i
);
1670 /* Release the memory for the entire omp region tree. */
1673 free_omp_regions (void)
1675 struct omp_region
*r
, *n
;
1676 for (r
= root_omp_region
; r
; r
= n
)
1679 free_omp_region_1 (r
);
1681 root_omp_region
= NULL
;
1685 /* Create a new context, with OUTER_CTX being the surrounding context. */
1687 static omp_context
*
1688 new_omp_context (gimple
*stmt
, omp_context
*outer_ctx
)
1690 omp_context
*ctx
= XCNEW (omp_context
);
1692 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1693 (splay_tree_value
) ctx
);
1698 ctx
->outer
= outer_ctx
;
1699 ctx
->cb
= outer_ctx
->cb
;
1700 ctx
->cb
.block
= NULL
;
1701 ctx
->depth
= outer_ctx
->depth
+ 1;
1705 ctx
->cb
.src_fn
= current_function_decl
;
1706 ctx
->cb
.dst_fn
= current_function_decl
;
1707 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1708 gcc_checking_assert (ctx
->cb
.src_node
);
1709 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1710 ctx
->cb
.src_cfun
= cfun
;
1711 ctx
->cb
.copy_decl
= omp_copy_decl
;
1712 ctx
->cb
.eh_lp_nr
= 0;
1713 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1717 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1722 static gimple_seq
maybe_catch_exception (gimple_seq
);
1724 /* Finalize task copyfn. */
1727 finalize_task_copyfn (gomp_task
*task_stmt
)
1729 struct function
*child_cfun
;
1731 gimple_seq seq
= NULL
, new_seq
;
1734 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1735 if (child_fn
== NULL_TREE
)
1738 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1739 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1741 push_cfun (child_cfun
);
1742 bind
= gimplify_body (child_fn
, false);
1743 gimple_seq_add_stmt (&seq
, bind
);
1744 new_seq
= maybe_catch_exception (seq
);
1747 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1749 gimple_seq_add_stmt (&seq
, bind
);
1751 gimple_set_body (child_fn
, seq
);
1754 /* Inform the callgraph about the new function. */
1755 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
1756 node
->parallelized_function
= 1;
1757 cgraph_node::add_new_function (child_fn
, false);
1760 /* Destroy a omp_context data structures. Called through the splay tree
1761 value delete callback. */
1764 delete_omp_context (splay_tree_value value
)
1766 omp_context
*ctx
= (omp_context
*) value
;
1768 delete ctx
->cb
.decl_map
;
1771 splay_tree_delete (ctx
->field_map
);
1772 if (ctx
->sfield_map
)
1773 splay_tree_delete (ctx
->sfield_map
);
1775 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1776 it produces corrupt debug information. */
1777 if (ctx
->record_type
)
1780 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1781 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1783 if (ctx
->srecord_type
)
1786 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1787 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1790 if (is_task_ctx (ctx
))
1791 finalize_task_copyfn (as_a
<gomp_task
*> (ctx
->stmt
));
1796 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1800 fixup_child_record_type (omp_context
*ctx
)
1802 tree f
, type
= ctx
->record_type
;
1804 if (!ctx
->receiver_decl
)
1806 /* ??? It isn't sufficient to just call remap_type here, because
1807 variably_modified_type_p doesn't work the way we expect for
1808 record types. Testing each field for whether it needs remapping
1809 and creating a new record by hand works, however. */
1810 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1811 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1815 tree name
, new_fields
= NULL
;
1817 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1818 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1819 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1820 TYPE_DECL
, name
, type
);
1821 TYPE_NAME (type
) = name
;
1823 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1825 tree new_f
= copy_node (f
);
1826 DECL_CONTEXT (new_f
) = type
;
1827 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1828 DECL_CHAIN (new_f
) = new_fields
;
1829 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1830 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1832 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1836 /* Arrange to be able to look up the receiver field
1837 given the sender field. */
1838 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1839 (splay_tree_value
) new_f
);
1841 TYPE_FIELDS (type
) = nreverse (new_fields
);
1845 /* In a target region we never modify any of the pointers in *.omp_data_i,
1846 so attempt to help the optimizers. */
1847 if (is_gimple_omp_offloaded (ctx
->stmt
))
1848 type
= build_qualified_type (type
, TYPE_QUAL_CONST
);
1850 TREE_TYPE (ctx
->receiver_decl
)
1851 = build_qualified_type (build_reference_type (type
), TYPE_QUAL_RESTRICT
);
1854 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1855 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1859 scan_sharing_clauses (tree clauses
, omp_context
*ctx
,
1860 bool base_pointers_restrict
= false)
1863 bool scan_array_reductions
= false;
1865 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1869 switch (OMP_CLAUSE_CODE (c
))
1871 case OMP_CLAUSE_PRIVATE
:
1872 decl
= OMP_CLAUSE_DECL (c
);
1873 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1875 else if (!is_variable_sized (decl
))
1876 install_var_local (decl
, ctx
);
1879 case OMP_CLAUSE_SHARED
:
1880 decl
= OMP_CLAUSE_DECL (c
);
1881 /* Ignore shared directives in teams construct. */
1882 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1884 /* Global variables don't need to be copied,
1885 the receiver side will use them directly. */
1886 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1887 if (is_global_var (odecl
))
1889 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1892 gcc_assert (is_taskreg_ctx (ctx
));
1893 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1894 || !is_variable_sized (decl
));
1895 /* Global variables don't need to be copied,
1896 the receiver side will use them directly. */
1897 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1899 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
1901 use_pointer_for_field (decl
, ctx
);
1904 by_ref
= use_pointer_for_field (decl
, NULL
);
1905 if ((! TREE_READONLY (decl
) && !OMP_CLAUSE_SHARED_READONLY (c
))
1906 || TREE_ADDRESSABLE (decl
)
1908 || is_reference (decl
))
1910 by_ref
= use_pointer_for_field (decl
, ctx
);
1911 install_var_field (decl
, by_ref
, 3, ctx
);
1912 install_var_local (decl
, ctx
);
1915 /* We don't need to copy const scalar vars back. */
1916 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1919 case OMP_CLAUSE_REDUCTION
:
1920 decl
= OMP_CLAUSE_DECL (c
);
1921 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1922 && TREE_CODE (decl
) == MEM_REF
)
1924 tree t
= TREE_OPERAND (decl
, 0);
1925 if (TREE_CODE (t
) == POINTER_PLUS_EXPR
)
1926 t
= TREE_OPERAND (t
, 0);
1927 if (TREE_CODE (t
) == INDIRECT_REF
1928 || TREE_CODE (t
) == ADDR_EXPR
)
1929 t
= TREE_OPERAND (t
, 0);
1930 install_var_local (t
, ctx
);
1931 if (is_taskreg_ctx (ctx
)
1932 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t
, ctx
))
1933 && !is_variable_sized (t
))
1935 by_ref
= use_pointer_for_field (t
, ctx
);
1936 install_var_field (t
, by_ref
, 3, ctx
);
1942 case OMP_CLAUSE_LASTPRIVATE
:
1943 /* Let the corresponding firstprivate clause create
1945 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1949 case OMP_CLAUSE_FIRSTPRIVATE
:
1950 case OMP_CLAUSE_LINEAR
:
1951 decl
= OMP_CLAUSE_DECL (c
);
1953 if ((OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
1954 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_IS_DEVICE_PTR
)
1955 && is_gimple_omp_offloaded (ctx
->stmt
))
1957 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
1958 install_var_field (decl
, !is_reference (decl
), 3, ctx
);
1959 else if (TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1960 install_var_field (decl
, true, 3, ctx
);
1962 install_var_field (decl
, false, 3, ctx
);
1964 if (is_variable_sized (decl
))
1966 if (is_task_ctx (ctx
))
1967 install_var_field (decl
, false, 1, ctx
);
1970 else if (is_taskreg_ctx (ctx
))
1973 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1974 by_ref
= use_pointer_for_field (decl
, NULL
);
1976 if (is_task_ctx (ctx
)
1977 && (global
|| by_ref
|| is_reference (decl
)))
1979 install_var_field (decl
, false, 1, ctx
);
1981 install_var_field (decl
, by_ref
, 2, ctx
);
1984 install_var_field (decl
, by_ref
, 3, ctx
);
1986 install_var_local (decl
, ctx
);
1989 case OMP_CLAUSE_USE_DEVICE_PTR
:
1990 decl
= OMP_CLAUSE_DECL (c
);
1991 if (TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1992 install_var_field (decl
, true, 3, ctx
);
1994 install_var_field (decl
, false, 3, ctx
);
1995 if (DECL_SIZE (decl
)
1996 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1998 tree decl2
= DECL_VALUE_EXPR (decl
);
1999 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2000 decl2
= TREE_OPERAND (decl2
, 0);
2001 gcc_assert (DECL_P (decl2
));
2002 install_var_local (decl2
, ctx
);
2004 install_var_local (decl
, ctx
);
2007 case OMP_CLAUSE_IS_DEVICE_PTR
:
2008 decl
= OMP_CLAUSE_DECL (c
);
2011 case OMP_CLAUSE__LOOPTEMP_
:
2012 gcc_assert (is_taskreg_ctx (ctx
));
2013 decl
= OMP_CLAUSE_DECL (c
);
2014 install_var_field (decl
, false, 3, ctx
);
2015 install_var_local (decl
, ctx
);
2018 case OMP_CLAUSE_COPYPRIVATE
:
2019 case OMP_CLAUSE_COPYIN
:
2020 decl
= OMP_CLAUSE_DECL (c
);
2021 by_ref
= use_pointer_for_field (decl
, NULL
);
2022 install_var_field (decl
, by_ref
, 3, ctx
);
2025 case OMP_CLAUSE_DEFAULT
:
2026 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
2029 case OMP_CLAUSE_FINAL
:
2031 case OMP_CLAUSE_NUM_THREADS
:
2032 case OMP_CLAUSE_NUM_TEAMS
:
2033 case OMP_CLAUSE_THREAD_LIMIT
:
2034 case OMP_CLAUSE_DEVICE
:
2035 case OMP_CLAUSE_SCHEDULE
:
2036 case OMP_CLAUSE_DIST_SCHEDULE
:
2037 case OMP_CLAUSE_DEPEND
:
2038 case OMP_CLAUSE_PRIORITY
:
2039 case OMP_CLAUSE_GRAINSIZE
:
2040 case OMP_CLAUSE_NUM_TASKS
:
2041 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2042 case OMP_CLAUSE_NUM_GANGS
:
2043 case OMP_CLAUSE_NUM_WORKERS
:
2044 case OMP_CLAUSE_VECTOR_LENGTH
:
2046 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
2050 case OMP_CLAUSE_FROM
:
2051 case OMP_CLAUSE_MAP
:
2053 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
2054 decl
= OMP_CLAUSE_DECL (c
);
2055 /* Global variables with "omp declare target" attribute
2056 don't need to be copied, the receiver side will use them
2057 directly. However, global variables with "omp declare target link"
2058 attribute need to be copied. */
2059 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2061 && ((OMP_CLAUSE_MAP_KIND (c
) != GOMP_MAP_FIRSTPRIVATE_POINTER
2062 && (OMP_CLAUSE_MAP_KIND (c
)
2063 != GOMP_MAP_FIRSTPRIVATE_REFERENCE
))
2064 || TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2065 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
2066 && varpool_node::get_create (decl
)->offloadable
2067 && !lookup_attribute ("omp declare target link",
2068 DECL_ATTRIBUTES (decl
)))
2070 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2071 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
)
2073 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2074 not offloaded; there is nothing to map for those. */
2075 if (!is_gimple_omp_offloaded (ctx
->stmt
)
2076 && !POINTER_TYPE_P (TREE_TYPE (decl
))
2077 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
2080 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2081 && (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
2082 || (OMP_CLAUSE_MAP_KIND (c
)
2083 == GOMP_MAP_FIRSTPRIVATE_REFERENCE
)))
2085 if (TREE_CODE (decl
) == COMPONENT_REF
2086 || (TREE_CODE (decl
) == INDIRECT_REF
2087 && TREE_CODE (TREE_OPERAND (decl
, 0)) == COMPONENT_REF
2088 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl
, 0)))
2089 == REFERENCE_TYPE
)))
2091 if (DECL_SIZE (decl
)
2092 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2094 tree decl2
= DECL_VALUE_EXPR (decl
);
2095 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2096 decl2
= TREE_OPERAND (decl2
, 0);
2097 gcc_assert (DECL_P (decl2
));
2098 install_var_local (decl2
, ctx
);
2100 install_var_local (decl
, ctx
);
2105 if (DECL_SIZE (decl
)
2106 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2108 tree decl2
= DECL_VALUE_EXPR (decl
);
2109 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2110 decl2
= TREE_OPERAND (decl2
, 0);
2111 gcc_assert (DECL_P (decl2
));
2112 install_var_field (decl2
, true, 3, ctx
);
2113 install_var_local (decl2
, ctx
);
2114 install_var_local (decl
, ctx
);
2118 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
2119 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
2120 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
2121 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2122 install_var_field (decl
, true, 7, ctx
);
2124 install_var_field (decl
, true, 3, ctx
,
2125 base_pointers_restrict
);
2126 if (is_gimple_omp_offloaded (ctx
->stmt
)
2127 && !OMP_CLAUSE_MAP_IN_REDUCTION (c
))
2128 install_var_local (decl
, ctx
);
2133 tree base
= get_base_address (decl
);
2134 tree nc
= OMP_CLAUSE_CHAIN (c
);
2137 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
2138 && OMP_CLAUSE_DECL (nc
) == base
2139 && OMP_CLAUSE_MAP_KIND (nc
) == GOMP_MAP_POINTER
2140 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
2142 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
2143 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
2149 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
2150 decl
= OMP_CLAUSE_DECL (c
);
2152 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
2153 (splay_tree_key
) decl
));
2155 = build_decl (OMP_CLAUSE_LOCATION (c
),
2156 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
2157 SET_DECL_ALIGN (field
, TYPE_ALIGN (ptr_type_node
));
2158 insert_field_into_struct (ctx
->record_type
, field
);
2159 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
2160 (splay_tree_value
) field
);
2165 case OMP_CLAUSE__GRIDDIM_
:
2168 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c
), ctx
->outer
);
2169 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c
), ctx
->outer
);
2173 case OMP_CLAUSE_NOWAIT
:
2174 case OMP_CLAUSE_ORDERED
:
2175 case OMP_CLAUSE_COLLAPSE
:
2176 case OMP_CLAUSE_UNTIED
:
2177 case OMP_CLAUSE_MERGEABLE
:
2178 case OMP_CLAUSE_PROC_BIND
:
2179 case OMP_CLAUSE_SAFELEN
:
2180 case OMP_CLAUSE_SIMDLEN
:
2181 case OMP_CLAUSE_THREADS
:
2182 case OMP_CLAUSE_SIMD
:
2183 case OMP_CLAUSE_NOGROUP
:
2184 case OMP_CLAUSE_DEFAULTMAP
:
2185 case OMP_CLAUSE_ASYNC
:
2186 case OMP_CLAUSE_WAIT
:
2187 case OMP_CLAUSE_GANG
:
2188 case OMP_CLAUSE_WORKER
:
2189 case OMP_CLAUSE_VECTOR
:
2190 case OMP_CLAUSE_INDEPENDENT
:
2191 case OMP_CLAUSE_AUTO
:
2192 case OMP_CLAUSE_SEQ
:
2195 case OMP_CLAUSE_ALIGNED
:
2196 decl
= OMP_CLAUSE_DECL (c
);
2197 if (is_global_var (decl
)
2198 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2199 install_var_local (decl
, ctx
);
2202 case OMP_CLAUSE_TILE
:
2203 case OMP_CLAUSE__CACHE_
:
2209 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2211 switch (OMP_CLAUSE_CODE (c
))
2213 case OMP_CLAUSE_LASTPRIVATE
:
2214 /* Let the corresponding firstprivate clause create
2216 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2217 scan_array_reductions
= true;
2218 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
2222 case OMP_CLAUSE_FIRSTPRIVATE
:
2223 case OMP_CLAUSE_PRIVATE
:
2224 case OMP_CLAUSE_LINEAR
:
2225 case OMP_CLAUSE_IS_DEVICE_PTR
:
2226 decl
= OMP_CLAUSE_DECL (c
);
2227 if (is_variable_sized (decl
))
2229 if ((OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
2230 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_IS_DEVICE_PTR
)
2231 && is_gimple_omp_offloaded (ctx
->stmt
))
2233 tree decl2
= DECL_VALUE_EXPR (decl
);
2234 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2235 decl2
= TREE_OPERAND (decl2
, 0);
2236 gcc_assert (DECL_P (decl2
));
2237 install_var_local (decl2
, ctx
);
2238 fixup_remapped_decl (decl2
, ctx
, false);
2240 install_var_local (decl
, ctx
);
2242 fixup_remapped_decl (decl
, ctx
,
2243 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
2244 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
2245 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2246 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2247 scan_array_reductions
= true;
2250 case OMP_CLAUSE_REDUCTION
:
2251 decl
= OMP_CLAUSE_DECL (c
);
2252 if (TREE_CODE (decl
) != MEM_REF
)
2254 if (is_variable_sized (decl
))
2255 install_var_local (decl
, ctx
);
2256 fixup_remapped_decl (decl
, ctx
, false);
2258 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2259 scan_array_reductions
= true;
2262 case OMP_CLAUSE_SHARED
:
2263 /* Ignore shared directives in teams construct. */
2264 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2266 decl
= OMP_CLAUSE_DECL (c
);
2267 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2269 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
2271 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
,
2274 bool by_ref
= use_pointer_for_field (decl
, ctx
);
2275 install_var_field (decl
, by_ref
, 11, ctx
);
2278 fixup_remapped_decl (decl
, ctx
, false);
2281 case OMP_CLAUSE_MAP
:
2282 if (!is_gimple_omp_offloaded (ctx
->stmt
))
2284 decl
= OMP_CLAUSE_DECL (c
);
2286 && ((OMP_CLAUSE_MAP_KIND (c
) != GOMP_MAP_FIRSTPRIVATE_POINTER
2287 && (OMP_CLAUSE_MAP_KIND (c
)
2288 != GOMP_MAP_FIRSTPRIVATE_REFERENCE
))
2289 || TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
2290 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
2291 && varpool_node::get_create (decl
)->offloadable
)
2295 if ((OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
2296 || OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
)
2297 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
2298 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
2300 tree new_decl
= lookup_decl (decl
, ctx
);
2301 TREE_TYPE (new_decl
)
2302 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
2304 else if (DECL_SIZE (decl
)
2305 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2307 tree decl2
= DECL_VALUE_EXPR (decl
);
2308 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2309 decl2
= TREE_OPERAND (decl2
, 0);
2310 gcc_assert (DECL_P (decl2
));
2311 fixup_remapped_decl (decl2
, ctx
, false);
2312 fixup_remapped_decl (decl
, ctx
, true);
2315 fixup_remapped_decl (decl
, ctx
, false);
2319 case OMP_CLAUSE_COPYPRIVATE
:
2320 case OMP_CLAUSE_COPYIN
:
2321 case OMP_CLAUSE_DEFAULT
:
2323 case OMP_CLAUSE_NUM_THREADS
:
2324 case OMP_CLAUSE_NUM_TEAMS
:
2325 case OMP_CLAUSE_THREAD_LIMIT
:
2326 case OMP_CLAUSE_DEVICE
:
2327 case OMP_CLAUSE_SCHEDULE
:
2328 case OMP_CLAUSE_DIST_SCHEDULE
:
2329 case OMP_CLAUSE_NOWAIT
:
2330 case OMP_CLAUSE_ORDERED
:
2331 case OMP_CLAUSE_COLLAPSE
:
2332 case OMP_CLAUSE_UNTIED
:
2333 case OMP_CLAUSE_FINAL
:
2334 case OMP_CLAUSE_MERGEABLE
:
2335 case OMP_CLAUSE_PROC_BIND
:
2336 case OMP_CLAUSE_SAFELEN
:
2337 case OMP_CLAUSE_SIMDLEN
:
2338 case OMP_CLAUSE_ALIGNED
:
2339 case OMP_CLAUSE_DEPEND
:
2340 case OMP_CLAUSE__LOOPTEMP_
:
2342 case OMP_CLAUSE_FROM
:
2343 case OMP_CLAUSE_PRIORITY
:
2344 case OMP_CLAUSE_GRAINSIZE
:
2345 case OMP_CLAUSE_NUM_TASKS
:
2346 case OMP_CLAUSE_THREADS
:
2347 case OMP_CLAUSE_SIMD
:
2348 case OMP_CLAUSE_NOGROUP
:
2349 case OMP_CLAUSE_DEFAULTMAP
:
2350 case OMP_CLAUSE_USE_DEVICE_PTR
:
2351 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2352 case OMP_CLAUSE_ASYNC
:
2353 case OMP_CLAUSE_WAIT
:
2354 case OMP_CLAUSE_NUM_GANGS
:
2355 case OMP_CLAUSE_NUM_WORKERS
:
2356 case OMP_CLAUSE_VECTOR_LENGTH
:
2357 case OMP_CLAUSE_GANG
:
2358 case OMP_CLAUSE_WORKER
:
2359 case OMP_CLAUSE_VECTOR
:
2360 case OMP_CLAUSE_INDEPENDENT
:
2361 case OMP_CLAUSE_AUTO
:
2362 case OMP_CLAUSE_SEQ
:
2363 case OMP_CLAUSE__GRIDDIM_
:
2366 case OMP_CLAUSE_TILE
:
2367 case OMP_CLAUSE__CACHE_
:
2373 gcc_checking_assert (!scan_array_reductions
2374 || !is_gimple_omp_oacc (ctx
->stmt
));
2375 if (scan_array_reductions
)
2377 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2378 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
2379 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2381 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
2382 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
2384 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2385 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2386 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
2387 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2388 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2389 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
2393 /* Create a new name for omp child function. Returns an identifier. If
2394 IS_CILK_FOR is true then the suffix for the child function is
2398 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
2401 return clone_function_name (current_function_decl
, "_cilk_for_fn");
2402 return clone_function_name (current_function_decl
,
2403 task_copy
? "_omp_cpyfn" : "_omp_fn");
2406 /* Returns the type of the induction variable for the child function for
2407 _Cilk_for and the types for _high and _low variables based on TYPE. */
2410 cilk_for_check_loop_diff_type (tree type
)
2412 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
2414 if (TYPE_UNSIGNED (type
))
2415 return uint32_type_node
;
2417 return integer_type_node
;
2421 if (TYPE_UNSIGNED (type
))
2422 return uint64_type_node
;
2424 return long_long_integer_type_node
;
2428 /* Build a decl for the omp child function. It'll not contain a body
2429 yet, just the bare decl. */
2432 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
2434 tree decl
, type
, name
, t
;
2437 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2438 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2439 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
2440 tree cilk_var_type
= NULL_TREE
;
2442 name
= create_omp_child_function_name (task_copy
,
2443 cilk_for_count
!= NULL_TREE
);
2445 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2446 ptr_type_node
, NULL_TREE
);
2447 else if (cilk_for_count
)
2449 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
2450 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
2451 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2452 cilk_var_type
, cilk_var_type
, NULL_TREE
);
2455 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
2457 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
2459 gcc_checking_assert (!is_gimple_omp_oacc (ctx
->stmt
)
2462 ctx
->cb
.dst_fn
= decl
;
2464 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
2466 TREE_STATIC (decl
) = 1;
2467 TREE_USED (decl
) = 1;
2468 DECL_ARTIFICIAL (decl
) = 1;
2469 DECL_IGNORED_P (decl
) = 0;
2470 TREE_PUBLIC (decl
) = 0;
2471 DECL_UNINLINABLE (decl
) = 1;
2472 DECL_EXTERNAL (decl
) = 0;
2473 DECL_CONTEXT (decl
) = NULL_TREE
;
2474 DECL_INITIAL (decl
) = make_node (BLOCK
);
2475 if (cgraph_node::get (current_function_decl
)->offloadable
)
2476 cgraph_node::get_create (decl
)->offloadable
= 1;
2480 for (octx
= ctx
; octx
; octx
= octx
->outer
)
2481 if (is_gimple_omp_offloaded (octx
->stmt
))
2483 cgraph_node::get_create (decl
)->offloadable
= 1;
2484 if (ENABLE_OFFLOADING
)
2485 g
->have_offload
= true;
2491 if (cgraph_node::get_create (decl
)->offloadable
2492 && !lookup_attribute ("omp declare target",
2493 DECL_ATTRIBUTES (current_function_decl
)))
2494 DECL_ATTRIBUTES (decl
)
2495 = tree_cons (get_identifier ("omp target entrypoint"),
2496 NULL_TREE
, DECL_ATTRIBUTES (decl
));
2498 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2499 RESULT_DECL
, NULL_TREE
, void_type_node
);
2500 DECL_ARTIFICIAL (t
) = 1;
2501 DECL_IGNORED_P (t
) = 1;
2502 DECL_CONTEXT (t
) = decl
;
2503 DECL_RESULT (decl
) = t
;
2505 /* _Cilk_for's child function requires two extra parameters called
2506 __low and __high that are set the by Cilk runtime when it calls this
2510 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2511 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
2512 DECL_ARTIFICIAL (t
) = 1;
2513 DECL_NAMELESS (t
) = 1;
2514 DECL_ARG_TYPE (t
) = ptr_type_node
;
2515 DECL_CONTEXT (t
) = current_function_decl
;
2517 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2518 DECL_ARGUMENTS (decl
) = t
;
2520 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2521 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
2522 DECL_ARTIFICIAL (t
) = 1;
2523 DECL_NAMELESS (t
) = 1;
2524 DECL_ARG_TYPE (t
) = ptr_type_node
;
2525 DECL_CONTEXT (t
) = current_function_decl
;
2527 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2528 DECL_ARGUMENTS (decl
) = t
;
2531 tree data_name
= get_identifier (".omp_data_i");
2532 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
2534 DECL_ARTIFICIAL (t
) = 1;
2535 DECL_NAMELESS (t
) = 1;
2536 DECL_ARG_TYPE (t
) = ptr_type_node
;
2537 DECL_CONTEXT (t
) = current_function_decl
;
2539 TREE_READONLY (t
) = 1;
2541 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2542 DECL_ARGUMENTS (decl
) = t
;
2544 ctx
->receiver_decl
= t
;
2547 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2548 PARM_DECL
, get_identifier (".omp_data_o"),
2550 DECL_ARTIFICIAL (t
) = 1;
2551 DECL_NAMELESS (t
) = 1;
2552 DECL_ARG_TYPE (t
) = ptr_type_node
;
2553 DECL_CONTEXT (t
) = current_function_decl
;
2555 TREE_ADDRESSABLE (t
) = 1;
2556 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2557 DECL_ARGUMENTS (decl
) = t
;
2560 /* Allocate memory for the function structure. The call to
2561 allocate_struct_function clobbers CFUN, so we need to restore
2563 push_struct_function (decl
);
2564 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2565 init_tree_ssa (cfun
);
2569 /* Callback for walk_gimple_seq. Check if combined parallel
2570 contains gimple_omp_for_combined_into_p OMP_FOR. */
2573 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2574 bool *handled_ops_p
,
2575 struct walk_stmt_info
*wi
)
2577 gimple
*stmt
= gsi_stmt (*gsi_p
);
2579 *handled_ops_p
= true;
2580 switch (gimple_code (stmt
))
2584 case GIMPLE_OMP_FOR
:
2585 if (gimple_omp_for_combined_into_p (stmt
)
2586 && gimple_omp_for_kind (stmt
)
2587 == *(const enum gf_mask
*) (wi
->info
))
2590 return integer_zero_node
;
2599 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2602 add_taskreg_looptemp_clauses (enum gf_mask msk
, gimple
*stmt
,
2603 omp_context
*outer_ctx
)
2605 struct walk_stmt_info wi
;
2607 memset (&wi
, 0, sizeof (wi
));
2609 wi
.info
= (void *) &msk
;
2610 walk_gimple_seq (gimple_omp_body (stmt
), find_combined_for
, NULL
, &wi
);
2611 if (wi
.info
!= (void *) &msk
)
2613 gomp_for
*for_stmt
= as_a
<gomp_for
*> ((gimple
*) wi
.info
);
2614 struct omp_for_data fd
;
2615 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2616 /* We need two temporaries with fd.loop.v type (istart/iend)
2617 and then (fd.collapse - 1) temporaries with the same
2618 type for count2 ... countN-1 vars if not constant. */
2619 size_t count
= 2, i
;
2620 tree type
= fd
.iter_type
;
2622 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2624 count
+= fd
.collapse
- 1;
2625 /* If there are lastprivate clauses on the inner
2626 GIMPLE_OMP_FOR, add one more temporaries for the total number
2627 of iterations (product of count1 ... countN-1). */
2628 if (find_omp_clause (gimple_omp_for_clauses (for_stmt
),
2629 OMP_CLAUSE_LASTPRIVATE
))
2631 else if (msk
== GF_OMP_FOR_KIND_FOR
2632 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2633 OMP_CLAUSE_LASTPRIVATE
))
2636 for (i
= 0; i
< count
; i
++)
2638 tree temp
= create_tmp_var (type
);
2639 tree c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
2640 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2641 OMP_CLAUSE_DECL (c
) = temp
;
2642 OMP_CLAUSE_CHAIN (c
) = gimple_omp_taskreg_clauses (stmt
);
2643 gimple_omp_taskreg_set_clauses (stmt
, c
);
2648 /* Scan an OpenMP parallel directive. */
2651 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2655 gomp_parallel
*stmt
= as_a
<gomp_parallel
*> (gsi_stmt (*gsi
));
2657 /* Ignore parallel directives with empty bodies, unless there
2658 are copyin clauses. */
2660 && empty_body_p (gimple_omp_body (stmt
))
2661 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2662 OMP_CLAUSE_COPYIN
) == NULL
)
2664 gsi_replace (gsi
, gimple_build_nop (), false);
2668 if (gimple_omp_parallel_combined_p (stmt
))
2669 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR
, stmt
, outer_ctx
);
2671 ctx
= new_omp_context (stmt
, outer_ctx
);
2672 taskreg_contexts
.safe_push (ctx
);
2673 if (taskreg_nesting_level
> 1)
2674 ctx
->is_nested
= true;
2675 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2676 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2677 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2678 name
= create_tmp_var_name (".omp_data_s");
2679 name
= build_decl (gimple_location (stmt
),
2680 TYPE_DECL
, name
, ctx
->record_type
);
2681 DECL_ARTIFICIAL (name
) = 1;
2682 DECL_NAMELESS (name
) = 1;
2683 TYPE_NAME (ctx
->record_type
) = name
;
2684 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2685 if (!gimple_omp_parallel_grid_phony (stmt
))
2687 create_omp_child_function (ctx
, false);
2688 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2691 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2692 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2694 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2695 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2698 /* Scan an OpenMP task directive. */
2701 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2705 gomp_task
*stmt
= as_a
<gomp_task
*> (gsi_stmt (*gsi
));
2707 /* Ignore task directives with empty bodies. */
2709 && empty_body_p (gimple_omp_body (stmt
)))
2711 gsi_replace (gsi
, gimple_build_nop (), false);
2715 if (gimple_omp_task_taskloop_p (stmt
))
2716 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP
, stmt
, outer_ctx
);
2718 ctx
= new_omp_context (stmt
, outer_ctx
);
2719 taskreg_contexts
.safe_push (ctx
);
2720 if (taskreg_nesting_level
> 1)
2721 ctx
->is_nested
= true;
2722 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2723 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2724 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2725 name
= create_tmp_var_name (".omp_data_s");
2726 name
= build_decl (gimple_location (stmt
),
2727 TYPE_DECL
, name
, ctx
->record_type
);
2728 DECL_ARTIFICIAL (name
) = 1;
2729 DECL_NAMELESS (name
) = 1;
2730 TYPE_NAME (ctx
->record_type
) = name
;
2731 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2732 create_omp_child_function (ctx
, false);
2733 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2735 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2737 if (ctx
->srecord_type
)
2739 name
= create_tmp_var_name (".omp_data_a");
2740 name
= build_decl (gimple_location (stmt
),
2741 TYPE_DECL
, name
, ctx
->srecord_type
);
2742 DECL_ARTIFICIAL (name
) = 1;
2743 DECL_NAMELESS (name
) = 1;
2744 TYPE_NAME (ctx
->srecord_type
) = name
;
2745 TYPE_ARTIFICIAL (ctx
->srecord_type
) = 1;
2746 create_omp_child_function (ctx
, true);
2749 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2751 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2753 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2754 t
= build_int_cst (long_integer_type_node
, 0);
2755 gimple_omp_task_set_arg_size (stmt
, t
);
2756 t
= build_int_cst (long_integer_type_node
, 1);
2757 gimple_omp_task_set_arg_align (stmt
, t
);
2762 /* If any decls have been made addressable during scan_omp,
2763 adjust their fields if needed, and layout record types
2764 of parallel/task constructs. */
2767 finish_taskreg_scan (omp_context
*ctx
)
2769 if (ctx
->record_type
== NULL_TREE
)
2772 /* If any task_shared_vars were needed, verify all
2773 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2774 statements if use_pointer_for_field hasn't changed
2775 because of that. If it did, update field types now. */
2776 if (task_shared_vars
)
2780 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2781 c
; c
= OMP_CLAUSE_CHAIN (c
))
2782 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
2783 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
2785 tree decl
= OMP_CLAUSE_DECL (c
);
2787 /* Global variables don't need to be copied,
2788 the receiver side will use them directly. */
2789 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2791 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2792 || !use_pointer_for_field (decl
, ctx
))
2794 tree field
= lookup_field (decl
, ctx
);
2795 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2796 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2798 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2799 TREE_THIS_VOLATILE (field
) = 0;
2800 DECL_USER_ALIGN (field
) = 0;
2801 SET_DECL_ALIGN (field
, TYPE_ALIGN (TREE_TYPE (field
)));
2802 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2803 SET_TYPE_ALIGN (ctx
->record_type
, DECL_ALIGN (field
));
2804 if (ctx
->srecord_type
)
2806 tree sfield
= lookup_sfield (decl
, ctx
);
2807 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2808 TREE_THIS_VOLATILE (sfield
) = 0;
2809 DECL_USER_ALIGN (sfield
) = 0;
2810 SET_DECL_ALIGN (sfield
, DECL_ALIGN (field
));
2811 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2812 SET_TYPE_ALIGN (ctx
->srecord_type
, DECL_ALIGN (sfield
));
2817 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2819 layout_type (ctx
->record_type
);
2820 fixup_child_record_type (ctx
);
2824 location_t loc
= gimple_location (ctx
->stmt
);
2825 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2826 /* Move VLA fields to the end. */
2827 p
= &TYPE_FIELDS (ctx
->record_type
);
2829 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2830 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2833 *p
= TREE_CHAIN (*p
);
2834 TREE_CHAIN (*q
) = NULL_TREE
;
2835 q
= &TREE_CHAIN (*q
);
2838 p
= &DECL_CHAIN (*p
);
2840 if (gimple_omp_task_taskloop_p (ctx
->stmt
))
2842 /* Move fields corresponding to first and second _looptemp_
2843 clause first. There are filled by GOMP_taskloop
2844 and thus need to be in specific positions. */
2845 tree c1
= gimple_omp_task_clauses (ctx
->stmt
);
2846 c1
= find_omp_clause (c1
, OMP_CLAUSE__LOOPTEMP_
);
2847 tree c2
= find_omp_clause (OMP_CLAUSE_CHAIN (c1
),
2848 OMP_CLAUSE__LOOPTEMP_
);
2849 tree f1
= lookup_field (OMP_CLAUSE_DECL (c1
), ctx
);
2850 tree f2
= lookup_field (OMP_CLAUSE_DECL (c2
), ctx
);
2851 p
= &TYPE_FIELDS (ctx
->record_type
);
2853 if (*p
== f1
|| *p
== f2
)
2854 *p
= DECL_CHAIN (*p
);
2856 p
= &DECL_CHAIN (*p
);
2857 DECL_CHAIN (f1
) = f2
;
2858 DECL_CHAIN (f2
) = TYPE_FIELDS (ctx
->record_type
);
2859 TYPE_FIELDS (ctx
->record_type
) = f1
;
2860 if (ctx
->srecord_type
)
2862 f1
= lookup_sfield (OMP_CLAUSE_DECL (c1
), ctx
);
2863 f2
= lookup_sfield (OMP_CLAUSE_DECL (c2
), ctx
);
2864 p
= &TYPE_FIELDS (ctx
->srecord_type
);
2866 if (*p
== f1
|| *p
== f2
)
2867 *p
= DECL_CHAIN (*p
);
2869 p
= &DECL_CHAIN (*p
);
2870 DECL_CHAIN (f1
) = f2
;
2871 DECL_CHAIN (f2
) = TYPE_FIELDS (ctx
->srecord_type
);
2872 TYPE_FIELDS (ctx
->srecord_type
) = f1
;
2875 layout_type (ctx
->record_type
);
2876 fixup_child_record_type (ctx
);
2877 if (ctx
->srecord_type
)
2878 layout_type (ctx
->srecord_type
);
2879 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2880 TYPE_SIZE_UNIT (ctx
->record_type
));
2881 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2882 t
= build_int_cst (long_integer_type_node
,
2883 TYPE_ALIGN_UNIT (ctx
->record_type
));
2884 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2888 /* Find the enclosing offload context. */
2890 static omp_context
*
2891 enclosing_target_ctx (omp_context
*ctx
)
2893 for (; ctx
; ctx
= ctx
->outer
)
2894 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
)
2900 /* Return true if ctx is part of an oacc kernels region. */
2903 ctx_in_oacc_kernels_region (omp_context
*ctx
)
2905 for (;ctx
!= NULL
; ctx
= ctx
->outer
)
2907 gimple
*stmt
= ctx
->stmt
;
2908 if (gimple_code (stmt
) == GIMPLE_OMP_TARGET
2909 && gimple_omp_target_kind (stmt
) == GF_OMP_TARGET_KIND_OACC_KERNELS
)
2916 /* Check the parallelism clauses inside a kernels regions.
2917 Until kernels handling moves to use the same loop indirection
2918 scheme as parallel, we need to do this checking early. */
2921 check_oacc_kernel_gwv (gomp_for
*stmt
, omp_context
*ctx
)
2923 bool checking
= true;
2924 unsigned outer_mask
= 0;
2925 unsigned this_mask
= 0;
2926 bool has_seq
= false, has_auto
= false;
2929 outer_mask
= check_oacc_kernel_gwv (NULL
, ctx
->outer
);
2933 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
)
2935 stmt
= as_a
<gomp_for
*> (ctx
->stmt
);
2938 for (tree c
= gimple_omp_for_clauses (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
2940 switch (OMP_CLAUSE_CODE (c
))
2942 case OMP_CLAUSE_GANG
:
2943 this_mask
|= GOMP_DIM_MASK (GOMP_DIM_GANG
);
2945 case OMP_CLAUSE_WORKER
:
2946 this_mask
|= GOMP_DIM_MASK (GOMP_DIM_WORKER
);
2948 case OMP_CLAUSE_VECTOR
:
2949 this_mask
|= GOMP_DIM_MASK (GOMP_DIM_VECTOR
);
2951 case OMP_CLAUSE_SEQ
:
2954 case OMP_CLAUSE_AUTO
:
2964 if (has_seq
&& (this_mask
|| has_auto
))
2965 error_at (gimple_location (stmt
), "%<seq%> overrides other"
2966 " OpenACC loop specifiers");
2967 else if (has_auto
&& this_mask
)
2968 error_at (gimple_location (stmt
), "%<auto%> conflicts with other"
2969 " OpenACC loop specifiers");
2971 if (this_mask
& outer_mask
)
2972 error_at (gimple_location (stmt
), "inner loop uses same"
2973 " OpenACC parallelism as containing loop");
2976 return outer_mask
| this_mask
;
2979 /* Scan a GIMPLE_OMP_FOR. */
2982 scan_omp_for (gomp_for
*stmt
, omp_context
*outer_ctx
)
2986 tree clauses
= gimple_omp_for_clauses (stmt
);
2988 ctx
= new_omp_context (stmt
, outer_ctx
);
2990 if (is_gimple_omp_oacc (stmt
))
2992 omp_context
*tgt
= enclosing_target_ctx (outer_ctx
);
2994 if (!tgt
|| is_oacc_parallel (tgt
))
2995 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2997 char const *check
= NULL
;
2999 switch (OMP_CLAUSE_CODE (c
))
3001 case OMP_CLAUSE_GANG
:
3005 case OMP_CLAUSE_WORKER
:
3009 case OMP_CLAUSE_VECTOR
:
3017 if (check
&& OMP_CLAUSE_OPERAND (c
, 0))
3018 error_at (gimple_location (stmt
),
3019 "argument not permitted on %qs clause in"
3020 " OpenACC %<parallel%>", check
);
3023 if (tgt
&& is_oacc_kernels (tgt
))
3025 /* Strip out reductions, as they are not handled yet. */
3026 tree
*prev_ptr
= &clauses
;
3028 while (tree probe
= *prev_ptr
)
3030 tree
*next_ptr
= &OMP_CLAUSE_CHAIN (probe
);
3032 if (OMP_CLAUSE_CODE (probe
) == OMP_CLAUSE_REDUCTION
)
3033 *prev_ptr
= *next_ptr
;
3035 prev_ptr
= next_ptr
;
3038 gimple_omp_for_set_clauses (stmt
, clauses
);
3039 check_oacc_kernel_gwv (stmt
, ctx
);
3043 scan_sharing_clauses (clauses
, ctx
);
3045 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
3046 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
3048 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
3049 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
3050 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
3051 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
3053 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3056 /* Scan an OpenMP sections directive. */
3059 scan_omp_sections (gomp_sections
*stmt
, omp_context
*outer_ctx
)
3063 ctx
= new_omp_context (stmt
, outer_ctx
);
3064 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
3065 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3068 /* Scan an OpenMP single directive. */
3071 scan_omp_single (gomp_single
*stmt
, omp_context
*outer_ctx
)
3076 ctx
= new_omp_context (stmt
, outer_ctx
);
3077 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
3078 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
3079 name
= create_tmp_var_name (".omp_copy_s");
3080 name
= build_decl (gimple_location (stmt
),
3081 TYPE_DECL
, name
, ctx
->record_type
);
3082 TYPE_NAME (ctx
->record_type
) = name
;
3084 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
3085 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3087 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
3088 ctx
->record_type
= NULL
;
3090 layout_type (ctx
->record_type
);
3093 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3094 used in the corresponding offloaded function are restrict. */
3097 omp_target_base_pointers_restrict_p (tree clauses
)
3099 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3101 if (flag_openacc
== 0)
3104 /* I. Basic example:
3108 unsigned int a[2], b[2];
3110 #pragma acc kernels \
3119 After gimplification, we have:
3121 #pragma omp target oacc_kernels \
3122 map(force_from:a [len: 8]) \
3123 map(force_from:b [len: 8])
3129 Because both mappings have the force prefix, we know that they will be
3130 allocated when calling the corresponding offloaded function, which means we
3131 can mark the base pointers for a and b in the offloaded function as
3135 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3137 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
)
3140 switch (OMP_CLAUSE_MAP_KIND (c
))
3142 case GOMP_MAP_FORCE_ALLOC
:
3143 case GOMP_MAP_FORCE_TO
:
3144 case GOMP_MAP_FORCE_FROM
:
3145 case GOMP_MAP_FORCE_TOFROM
:
3155 /* Scan a GIMPLE_OMP_TARGET. */
3158 scan_omp_target (gomp_target
*stmt
, omp_context
*outer_ctx
)
3162 bool offloaded
= is_gimple_omp_offloaded (stmt
);
3163 tree clauses
= gimple_omp_target_clauses (stmt
);
3165 ctx
= new_omp_context (stmt
, outer_ctx
);
3166 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
3167 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
3168 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
3169 name
= create_tmp_var_name (".omp_data_t");
3170 name
= build_decl (gimple_location (stmt
),
3171 TYPE_DECL
, name
, ctx
->record_type
);
3172 DECL_ARTIFICIAL (name
) = 1;
3173 DECL_NAMELESS (name
) = 1;
3174 TYPE_NAME (ctx
->record_type
) = name
;
3175 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
3177 bool base_pointers_restrict
= false;
3180 create_omp_child_function (ctx
, false);
3181 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
3183 base_pointers_restrict
= omp_target_base_pointers_restrict_p (clauses
);
3184 if (base_pointers_restrict
3185 && dump_file
&& (dump_flags
& TDF_DETAILS
))
3187 "Base pointers in offloaded function are restrict\n");
3190 scan_sharing_clauses (clauses
, ctx
, base_pointers_restrict
);
3191 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3193 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
3194 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
3197 TYPE_FIELDS (ctx
->record_type
)
3198 = nreverse (TYPE_FIELDS (ctx
->record_type
));
3201 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
3202 for (tree field
= TYPE_FIELDS (ctx
->record_type
);
3204 field
= DECL_CHAIN (field
))
3205 gcc_assert (DECL_ALIGN (field
) == align
);
3207 layout_type (ctx
->record_type
);
3209 fixup_child_record_type (ctx
);
3213 /* Scan an OpenMP teams directive. */
3216 scan_omp_teams (gomp_teams
*stmt
, omp_context
*outer_ctx
)
3218 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
3219 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
3220 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3223 /* Check nesting restrictions. */
3225 check_omp_nesting_restrictions (gimple
*stmt
, omp_context
*ctx
)
3229 if (ctx
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_GRID_BODY
)
3230 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3231 the original copy of its contents. */
3234 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3235 inside an OpenACC CTX. */
3236 if (!(is_gimple_omp (stmt
)
3237 && is_gimple_omp_oacc (stmt
))
3238 /* Except for atomic codes that we share with OpenMP. */
3239 && !(gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
3240 || gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
))
3242 if (get_oacc_fn_attrib (cfun
->decl
) != NULL
)
3244 error_at (gimple_location (stmt
),
3245 "non-OpenACC construct inside of OpenACC routine");
3249 for (omp_context
*octx
= ctx
; octx
!= NULL
; octx
= octx
->outer
)
3250 if (is_gimple_omp (octx
->stmt
)
3251 && is_gimple_omp_oacc (octx
->stmt
))
3253 error_at (gimple_location (stmt
),
3254 "non-OpenACC construct inside of OpenACC region");
3261 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3262 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3265 if (gimple_code (stmt
) == GIMPLE_OMP_ORDERED
)
3267 c
= gimple_omp_ordered_clauses (as_a
<gomp_ordered
*> (stmt
));
3268 if (find_omp_clause (c
, OMP_CLAUSE_SIMD
))
3270 if (find_omp_clause (c
, OMP_CLAUSE_THREADS
)
3271 && (ctx
->outer
== NULL
3272 || !gimple_omp_for_combined_into_p (ctx
->stmt
)
3273 || gimple_code (ctx
->outer
->stmt
) != GIMPLE_OMP_FOR
3274 || (gimple_omp_for_kind (ctx
->outer
->stmt
)
3275 != GF_OMP_FOR_KIND_FOR
)
3276 || !gimple_omp_for_combined_p (ctx
->outer
->stmt
)))
3278 error_at (gimple_location (stmt
),
3279 "%<ordered simd threads%> must be closely "
3280 "nested inside of %<for simd%> region");
3286 error_at (gimple_location (stmt
),
3287 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3288 " may not be nested inside %<simd%> region");
3291 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3293 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
3294 || (gimple_omp_for_kind (stmt
)
3295 != GF_OMP_FOR_KIND_DISTRIBUTE
))
3296 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
3298 error_at (gimple_location (stmt
),
3299 "only %<distribute%> or %<parallel%> regions are "
3300 "allowed to be strictly nested inside %<teams%> "
3306 switch (gimple_code (stmt
))
3308 case GIMPLE_OMP_FOR
:
3309 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
3311 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
3313 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
3315 error_at (gimple_location (stmt
),
3316 "%<distribute%> region must be strictly nested "
3317 "inside %<teams%> construct");
3322 /* We split taskloop into task and nested taskloop in it. */
3323 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_TASKLOOP
)
3325 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
3330 switch (gimple_code (ctx
->stmt
))
3332 case GIMPLE_OMP_FOR
:
3333 ok
= (gimple_omp_for_kind (ctx
->stmt
)
3334 == GF_OMP_FOR_KIND_OACC_LOOP
);
3337 case GIMPLE_OMP_TARGET
:
3338 switch (gimple_omp_target_kind (ctx
->stmt
))
3340 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
3341 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
3352 else if (get_oacc_fn_attrib (current_function_decl
))
3356 error_at (gimple_location (stmt
),
3357 "OpenACC loop directive must be associated with"
3358 " an OpenACC compute region");
3364 if (is_gimple_call (stmt
)
3365 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3366 == BUILT_IN_GOMP_CANCEL
3367 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3368 == BUILT_IN_GOMP_CANCELLATION_POINT
))
3370 const char *bad
= NULL
;
3371 const char *kind
= NULL
;
3372 const char *construct
3373 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3374 == BUILT_IN_GOMP_CANCEL
)
3375 ? "#pragma omp cancel"
3376 : "#pragma omp cancellation point";
3379 error_at (gimple_location (stmt
), "orphaned %qs construct",
3383 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
3384 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
3388 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
3389 bad
= "#pragma omp parallel";
3390 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3391 == BUILT_IN_GOMP_CANCEL
3392 && !integer_zerop (gimple_call_arg (stmt
, 1)))
3393 ctx
->cancellable
= true;
3397 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3398 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
3399 bad
= "#pragma omp for";
3400 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3401 == BUILT_IN_GOMP_CANCEL
3402 && !integer_zerop (gimple_call_arg (stmt
, 1)))
3404 ctx
->cancellable
= true;
3405 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3407 warning_at (gimple_location (stmt
), 0,
3408 "%<#pragma omp cancel for%> inside "
3409 "%<nowait%> for construct");
3410 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3411 OMP_CLAUSE_ORDERED
))
3412 warning_at (gimple_location (stmt
), 0,
3413 "%<#pragma omp cancel for%> inside "
3414 "%<ordered%> for construct");
3419 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
3420 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
3421 bad
= "#pragma omp sections";
3422 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3423 == BUILT_IN_GOMP_CANCEL
3424 && !integer_zerop (gimple_call_arg (stmt
, 1)))
3426 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
3428 ctx
->cancellable
= true;
3429 if (find_omp_clause (gimple_omp_sections_clauses
3432 warning_at (gimple_location (stmt
), 0,
3433 "%<#pragma omp cancel sections%> inside "
3434 "%<nowait%> sections construct");
3438 gcc_assert (ctx
->outer
3439 && gimple_code (ctx
->outer
->stmt
)
3440 == GIMPLE_OMP_SECTIONS
);
3441 ctx
->outer
->cancellable
= true;
3442 if (find_omp_clause (gimple_omp_sections_clauses
3445 warning_at (gimple_location (stmt
), 0,
3446 "%<#pragma omp cancel sections%> inside "
3447 "%<nowait%> sections construct");
3453 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
3454 bad
= "#pragma omp task";
3457 for (omp_context
*octx
= ctx
->outer
;
3458 octx
; octx
= octx
->outer
)
3460 switch (gimple_code (octx
->stmt
))
3462 case GIMPLE_OMP_TASKGROUP
:
3464 case GIMPLE_OMP_TARGET
:
3465 if (gimple_omp_target_kind (octx
->stmt
)
3466 != GF_OMP_TARGET_KIND_REGION
)
3469 case GIMPLE_OMP_PARALLEL
:
3470 case GIMPLE_OMP_TEAMS
:
3471 error_at (gimple_location (stmt
),
3472 "%<%s taskgroup%> construct not closely "
3473 "nested inside of %<taskgroup%> region",
3481 ctx
->cancellable
= true;
3486 error_at (gimple_location (stmt
), "invalid arguments");
3491 error_at (gimple_location (stmt
),
3492 "%<%s %s%> construct not closely nested inside of %qs",
3493 construct
, kind
, bad
);
3498 case GIMPLE_OMP_SECTIONS
:
3499 case GIMPLE_OMP_SINGLE
:
3500 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3501 switch (gimple_code (ctx
->stmt
))
3503 case GIMPLE_OMP_FOR
:
3504 if (gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
3505 && gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_TASKLOOP
)
3508 case GIMPLE_OMP_SECTIONS
:
3509 case GIMPLE_OMP_SINGLE
:
3510 case GIMPLE_OMP_ORDERED
:
3511 case GIMPLE_OMP_MASTER
:
3512 case GIMPLE_OMP_TASK
:
3513 case GIMPLE_OMP_CRITICAL
:
3514 if (is_gimple_call (stmt
))
3516 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
3517 != BUILT_IN_GOMP_BARRIER
)
3519 error_at (gimple_location (stmt
),
3520 "barrier region may not be closely nested inside "
3521 "of work-sharing, %<critical%>, %<ordered%>, "
3522 "%<master%>, explicit %<task%> or %<taskloop%> "
3526 error_at (gimple_location (stmt
),
3527 "work-sharing region may not be closely nested inside "
3528 "of work-sharing, %<critical%>, %<ordered%>, "
3529 "%<master%>, explicit %<task%> or %<taskloop%> region");
3531 case GIMPLE_OMP_PARALLEL
:
3532 case GIMPLE_OMP_TEAMS
:
3534 case GIMPLE_OMP_TARGET
:
3535 if (gimple_omp_target_kind (ctx
->stmt
)
3536 == GF_OMP_TARGET_KIND_REGION
)
3543 case GIMPLE_OMP_MASTER
:
3544 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3545 switch (gimple_code (ctx
->stmt
))
3547 case GIMPLE_OMP_FOR
:
3548 if (gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
3549 && gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_TASKLOOP
)
3552 case GIMPLE_OMP_SECTIONS
:
3553 case GIMPLE_OMP_SINGLE
:
3554 case GIMPLE_OMP_TASK
:
3555 error_at (gimple_location (stmt
),
3556 "%<master%> region may not be closely nested inside "
3557 "of work-sharing, explicit %<task%> or %<taskloop%> "
3560 case GIMPLE_OMP_PARALLEL
:
3561 case GIMPLE_OMP_TEAMS
:
3563 case GIMPLE_OMP_TARGET
:
3564 if (gimple_omp_target_kind (ctx
->stmt
)
3565 == GF_OMP_TARGET_KIND_REGION
)
3572 case GIMPLE_OMP_TASK
:
3573 for (c
= gimple_omp_task_clauses (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
3574 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
3575 && (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SOURCE
3576 || OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
))
3578 enum omp_clause_depend_kind kind
= OMP_CLAUSE_DEPEND_KIND (c
);
3579 error_at (OMP_CLAUSE_LOCATION (c
),
3580 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3581 kind
== OMP_CLAUSE_DEPEND_SOURCE
? "source" : "sink");
3585 case GIMPLE_OMP_ORDERED
:
3586 for (c
= gimple_omp_ordered_clauses (as_a
<gomp_ordered
*> (stmt
));
3587 c
; c
= OMP_CLAUSE_CHAIN (c
))
3589 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_DEPEND
)
3591 gcc_assert (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_THREADS
3592 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SIMD
);
3595 enum omp_clause_depend_kind kind
= OMP_CLAUSE_DEPEND_KIND (c
);
3596 if (kind
== OMP_CLAUSE_DEPEND_SOURCE
3597 || kind
== OMP_CLAUSE_DEPEND_SINK
)
3600 /* Look for containing ordered(N) loop. */
3602 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
3604 = find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3605 OMP_CLAUSE_ORDERED
)) == NULL_TREE
)
3607 error_at (OMP_CLAUSE_LOCATION (c
),
3608 "%<ordered%> construct with %<depend%> clause "
3609 "must be closely nested inside an %<ordered%> "
3613 else if (OMP_CLAUSE_ORDERED_EXPR (oclause
) == NULL_TREE
)
3615 error_at (OMP_CLAUSE_LOCATION (c
),
3616 "%<ordered%> construct with %<depend%> clause "
3617 "must be closely nested inside a loop with "
3618 "%<ordered%> clause with a parameter");
3624 error_at (OMP_CLAUSE_LOCATION (c
),
3625 "invalid depend kind in omp %<ordered%> %<depend%>");
3629 c
= gimple_omp_ordered_clauses (as_a
<gomp_ordered
*> (stmt
));
3630 if (find_omp_clause (c
, OMP_CLAUSE_SIMD
))
3632 /* ordered simd must be closely nested inside of simd region,
3633 and simd region must not encounter constructs other than
3634 ordered simd, therefore ordered simd may be either orphaned,
3635 or ctx->stmt must be simd. The latter case is handled already
3639 error_at (gimple_location (stmt
),
3640 "%<ordered%> %<simd%> must be closely nested inside "
3645 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3646 switch (gimple_code (ctx
->stmt
))
3648 case GIMPLE_OMP_CRITICAL
:
3649 case GIMPLE_OMP_TASK
:
3650 case GIMPLE_OMP_ORDERED
:
3651 ordered_in_taskloop
:
3652 error_at (gimple_location (stmt
),
3653 "%<ordered%> region may not be closely nested inside "
3654 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3655 "%<taskloop%> region");
3657 case GIMPLE_OMP_FOR
:
3658 if (gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_TASKLOOP
)
3659 goto ordered_in_taskloop
;
3660 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3661 OMP_CLAUSE_ORDERED
) == NULL
)
3663 error_at (gimple_location (stmt
),
3664 "%<ordered%> region must be closely nested inside "
3665 "a loop region with an %<ordered%> clause");
3669 case GIMPLE_OMP_TARGET
:
3670 if (gimple_omp_target_kind (ctx
->stmt
)
3671 != GF_OMP_TARGET_KIND_REGION
)
3674 case GIMPLE_OMP_PARALLEL
:
3675 case GIMPLE_OMP_TEAMS
:
3676 error_at (gimple_location (stmt
),
3677 "%<ordered%> region must be closely nested inside "
3678 "a loop region with an %<ordered%> clause");
3684 case GIMPLE_OMP_CRITICAL
:
3687 = gimple_omp_critical_name (as_a
<gomp_critical
*> (stmt
));
3688 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3689 if (gomp_critical
*other_crit
3690 = dyn_cast
<gomp_critical
*> (ctx
->stmt
))
3691 if (this_stmt_name
== gimple_omp_critical_name (other_crit
))
3693 error_at (gimple_location (stmt
),
3694 "%<critical%> region may not be nested inside "
3695 "a %<critical%> region with the same name");
3700 case GIMPLE_OMP_TEAMS
:
3702 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
3703 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
3705 error_at (gimple_location (stmt
),
3706 "%<teams%> construct not closely nested inside of "
3707 "%<target%> construct");
3711 case GIMPLE_OMP_TARGET
:
3712 for (c
= gimple_omp_target_clauses (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
3713 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
3714 && (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SOURCE
3715 || OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
))
3717 enum omp_clause_depend_kind kind
= OMP_CLAUSE_DEPEND_KIND (c
);
3718 error_at (OMP_CLAUSE_LOCATION (c
),
3719 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3720 kind
== OMP_CLAUSE_DEPEND_SOURCE
? "source" : "sink");
3723 if (is_gimple_omp_offloaded (stmt
)
3724 && get_oacc_fn_attrib (cfun
->decl
) != NULL
)
3726 error_at (gimple_location (stmt
),
3727 "OpenACC region inside of OpenACC routine, nested "
3728 "parallelism not supported yet");
3731 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3733 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
3735 if (is_gimple_omp (stmt
)
3736 && is_gimple_omp_oacc (stmt
)
3737 && is_gimple_omp (ctx
->stmt
))
3739 error_at (gimple_location (stmt
),
3740 "OpenACC construct inside of non-OpenACC region");
3746 const char *stmt_name
, *ctx_stmt_name
;
3747 switch (gimple_omp_target_kind (stmt
))
3749 case GF_OMP_TARGET_KIND_REGION
: stmt_name
= "target"; break;
3750 case GF_OMP_TARGET_KIND_DATA
: stmt_name
= "target data"; break;
3751 case GF_OMP_TARGET_KIND_UPDATE
: stmt_name
= "target update"; break;
3752 case GF_OMP_TARGET_KIND_ENTER_DATA
:
3753 stmt_name
= "target enter data"; break;
3754 case GF_OMP_TARGET_KIND_EXIT_DATA
:
3755 stmt_name
= "target exit data"; break;
3756 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: stmt_name
= "parallel"; break;
3757 case GF_OMP_TARGET_KIND_OACC_KERNELS
: stmt_name
= "kernels"; break;
3758 case GF_OMP_TARGET_KIND_OACC_DATA
: stmt_name
= "data"; break;
3759 case GF_OMP_TARGET_KIND_OACC_UPDATE
: stmt_name
= "update"; break;
3760 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
3761 stmt_name
= "enter/exit data"; break;
3762 case GF_OMP_TARGET_KIND_OACC_HOST_DATA
: stmt_name
= "host_data";
3764 default: gcc_unreachable ();
3766 switch (gimple_omp_target_kind (ctx
->stmt
))
3768 case GF_OMP_TARGET_KIND_REGION
: ctx_stmt_name
= "target"; break;
3769 case GF_OMP_TARGET_KIND_DATA
: ctx_stmt_name
= "target data"; break;
3770 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
3771 ctx_stmt_name
= "parallel"; break;
3772 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
3773 ctx_stmt_name
= "kernels"; break;
3774 case GF_OMP_TARGET_KIND_OACC_DATA
: ctx_stmt_name
= "data"; break;
3775 case GF_OMP_TARGET_KIND_OACC_HOST_DATA
:
3776 ctx_stmt_name
= "host_data"; break;
3777 default: gcc_unreachable ();
3780 /* OpenACC/OpenMP mismatch? */
3781 if (is_gimple_omp_oacc (stmt
)
3782 != is_gimple_omp_oacc (ctx
->stmt
))
3784 error_at (gimple_location (stmt
),
3785 "%s %qs construct inside of %s %qs region",
3786 (is_gimple_omp_oacc (stmt
)
3787 ? "OpenACC" : "OpenMP"), stmt_name
,
3788 (is_gimple_omp_oacc (ctx
->stmt
)
3789 ? "OpenACC" : "OpenMP"), ctx_stmt_name
);
3792 if (is_gimple_omp_offloaded (ctx
->stmt
))
3794 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3795 if (is_gimple_omp_oacc (ctx
->stmt
))
3797 error_at (gimple_location (stmt
),
3798 "%qs construct inside of %qs region",
3799 stmt_name
, ctx_stmt_name
);
3804 warning_at (gimple_location (stmt
), 0,
3805 "%qs construct inside of %qs region",
3806 stmt_name
, ctx_stmt_name
);
3818 /* Helper function scan_omp.
3820 Callback for walk_tree or operators in walk_gimple_stmt used to
3821 scan for OMP directives in TP. */
3824 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
3826 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
3827 omp_context
*ctx
= (omp_context
*) wi
->info
;
3830 switch (TREE_CODE (t
))
3838 tree repl
= remap_decl (t
, &ctx
->cb
);
3839 gcc_checking_assert (TREE_CODE (repl
) != ERROR_MARK
);
3845 if (ctx
&& TYPE_P (t
))
3846 *tp
= remap_type (t
, &ctx
->cb
);
3847 else if (!DECL_P (t
))
3852 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
3853 if (tem
!= TREE_TYPE (t
))
3855 if (TREE_CODE (t
) == INTEGER_CST
)
3856 *tp
= wide_int_to_tree (tem
, t
);
3858 TREE_TYPE (t
) = tem
;
3868 /* Return true if FNDECL is a setjmp or a longjmp. */
3871 setjmp_or_longjmp_p (const_tree fndecl
)
3873 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
3874 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
3875 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
3878 tree declname
= DECL_NAME (fndecl
);
3881 const char *name
= IDENTIFIER_POINTER (declname
);
3882 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
3886 /* Helper function for scan_omp.
3888 Callback for walk_gimple_stmt used to scan for OMP directives in
3889 the current statement in GSI. */
3892 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
3893 struct walk_stmt_info
*wi
)
3895 gimple
*stmt
= gsi_stmt (*gsi
);
3896 omp_context
*ctx
= (omp_context
*) wi
->info
;
3898 if (gimple_has_location (stmt
))
3899 input_location
= gimple_location (stmt
);
3901 /* Check the nesting restrictions. */
3902 bool remove
= false;
3903 if (is_gimple_omp (stmt
))
3904 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3905 else if (is_gimple_call (stmt
))
3907 tree fndecl
= gimple_call_fndecl (stmt
);
3910 if (setjmp_or_longjmp_p (fndecl
)
3912 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3913 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3916 error_at (gimple_location (stmt
),
3917 "setjmp/longjmp inside simd construct");
3919 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
3920 switch (DECL_FUNCTION_CODE (fndecl
))
3922 case BUILT_IN_GOMP_BARRIER
:
3923 case BUILT_IN_GOMP_CANCEL
:
3924 case BUILT_IN_GOMP_CANCELLATION_POINT
:
3925 case BUILT_IN_GOMP_TASKYIELD
:
3926 case BUILT_IN_GOMP_TASKWAIT
:
3927 case BUILT_IN_GOMP_TASKGROUP_START
:
3928 case BUILT_IN_GOMP_TASKGROUP_END
:
3929 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3938 stmt
= gimple_build_nop ();
3939 gsi_replace (gsi
, stmt
, false);
3942 *handled_ops_p
= true;
3944 switch (gimple_code (stmt
))
3946 case GIMPLE_OMP_PARALLEL
:
3947 taskreg_nesting_level
++;
3948 scan_omp_parallel (gsi
, ctx
);
3949 taskreg_nesting_level
--;
3952 case GIMPLE_OMP_TASK
:
3953 taskreg_nesting_level
++;
3954 scan_omp_task (gsi
, ctx
);
3955 taskreg_nesting_level
--;
3958 case GIMPLE_OMP_FOR
:
3959 scan_omp_for (as_a
<gomp_for
*> (stmt
), ctx
);
3962 case GIMPLE_OMP_SECTIONS
:
3963 scan_omp_sections (as_a
<gomp_sections
*> (stmt
), ctx
);
3966 case GIMPLE_OMP_SINGLE
:
3967 scan_omp_single (as_a
<gomp_single
*> (stmt
), ctx
);
3970 case GIMPLE_OMP_SECTION
:
3971 case GIMPLE_OMP_MASTER
:
3972 case GIMPLE_OMP_TASKGROUP
:
3973 case GIMPLE_OMP_ORDERED
:
3974 case GIMPLE_OMP_CRITICAL
:
3975 case GIMPLE_OMP_GRID_BODY
:
3976 ctx
= new_omp_context (stmt
, ctx
);
3977 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3980 case GIMPLE_OMP_TARGET
:
3981 scan_omp_target (as_a
<gomp_target
*> (stmt
), ctx
);
3984 case GIMPLE_OMP_TEAMS
:
3985 scan_omp_teams (as_a
<gomp_teams
*> (stmt
), ctx
);
3992 *handled_ops_p
= false;
3994 for (var
= gimple_bind_vars (as_a
<gbind
*> (stmt
));
3996 var
= DECL_CHAIN (var
))
3997 insert_decl_map (&ctx
->cb
, var
, var
);
4001 *handled_ops_p
= false;
4009 /* Scan all the statements starting at the current statement. CTX
4010 contains context information about the OMP directives and
4011 clauses found during the scan. */
4014 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
4016 location_t saved_location
;
4017 struct walk_stmt_info wi
;
4019 memset (&wi
, 0, sizeof (wi
));
4021 wi
.want_locations
= true;
4023 saved_location
= input_location
;
4024 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
4025 input_location
= saved_location
;
4028 /* Re-gimplification and code generation routines. */
4030 /* Build a call to GOMP_barrier. */
4033 build_omp_barrier (tree lhs
)
4035 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
4036 : BUILT_IN_GOMP_BARRIER
);
4037 gcall
*g
= gimple_build_call (fndecl
, 0);
4039 gimple_call_set_lhs (g
, lhs
);
4043 /* If a context was created for STMT when it was scanned, return it. */
4045 static omp_context
*
4046 maybe_lookup_ctx (gimple
*stmt
)
4049 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
4050 return n
? (omp_context
*) n
->value
: NULL
;
4054 /* Find the mapping for DECL in CTX or the immediately enclosing
4055 context that has a mapping for DECL.
4057 If CTX is a nested parallel directive, we may have to use the decl
4058 mappings created in CTX's parent context. Suppose that we have the
4059 following parallel nesting (variable UIDs showed for clarity):
4062 #omp parallel shared(iD.1562) -> outer parallel
4063 iD.1562 = iD.1562 + 1;
4065 #omp parallel shared (iD.1562) -> inner parallel
4066 iD.1562 = iD.1562 - 1;
4068 Each parallel structure will create a distinct .omp_data_s structure
4069 for copying iD.1562 in/out of the directive:
4071 outer parallel .omp_data_s.1.i -> iD.1562
4072 inner parallel .omp_data_s.2.i -> iD.1562
4074 A shared variable mapping will produce a copy-out operation before
4075 the parallel directive and a copy-in operation after it. So, in
4076 this case we would have:
4079 .omp_data_o.1.i = iD.1562;
4080 #omp parallel shared(iD.1562) -> outer parallel
4081 .omp_data_i.1 = &.omp_data_o.1
4082 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4084 .omp_data_o.2.i = iD.1562; -> **
4085 #omp parallel shared(iD.1562) -> inner parallel
4086 .omp_data_i.2 = &.omp_data_o.2
4087 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4090 ** This is a problem. The symbol iD.1562 cannot be referenced
4091 inside the body of the outer parallel region. But since we are
4092 emitting this copy operation while expanding the inner parallel
4093 directive, we need to access the CTX structure of the outer
4094 parallel directive to get the correct mapping:
4096 .omp_data_o.2.i = .omp_data_i.1->i
4098 Since there may be other workshare or parallel directives enclosing
4099 the parallel directive, it may be necessary to walk up the context
4100 parent chain. This is not a problem in general because nested
4101 parallelism happens only rarely. */
4104 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
4109 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
4110 t
= maybe_lookup_decl (decl
, up
);
4112 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
4114 return t
? t
: decl
;
4118 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4119 in outer contexts. */
4122 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
4127 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
4128 t
= maybe_lookup_decl (decl
, up
);
4130 return t
? t
: decl
;
4134 /* Construct the initialization value for reduction operation OP. */
4137 omp_reduction_init_op (location_t loc
, enum tree_code op
, tree type
)
4146 case TRUTH_ORIF_EXPR
:
4147 case TRUTH_XOR_EXPR
:
4149 return build_zero_cst (type
);
4152 case TRUTH_AND_EXPR
:
4153 case TRUTH_ANDIF_EXPR
:
4155 return fold_convert_loc (loc
, type
, integer_one_node
);
4158 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
4161 if (SCALAR_FLOAT_TYPE_P (type
))
4163 REAL_VALUE_TYPE max
, min
;
4164 if (HONOR_INFINITIES (type
))
4167 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
4170 real_maxval (&min
, 1, TYPE_MODE (type
));
4171 return build_real (type
, min
);
4173 else if (POINTER_TYPE_P (type
))
4176 = wi::min_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
4177 return wide_int_to_tree (type
, min
);
4181 gcc_assert (INTEGRAL_TYPE_P (type
));
4182 return TYPE_MIN_VALUE (type
);
4186 if (SCALAR_FLOAT_TYPE_P (type
))
4188 REAL_VALUE_TYPE max
;
4189 if (HONOR_INFINITIES (type
))
4192 real_maxval (&max
, 0, TYPE_MODE (type
));
4193 return build_real (type
, max
);
4195 else if (POINTER_TYPE_P (type
))
4198 = wi::max_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
4199 return wide_int_to_tree (type
, max
);
4203 gcc_assert (INTEGRAL_TYPE_P (type
));
4204 return TYPE_MAX_VALUE (type
);
4212 /* Construct the initialization value for reduction CLAUSE. */
4215 omp_reduction_init (tree clause
, tree type
)
4217 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause
),
4218 OMP_CLAUSE_REDUCTION_CODE (clause
), type
);
4221 /* Return alignment to be assumed for var in CLAUSE, which should be
4222 OMP_CLAUSE_ALIGNED. */
4225 omp_clause_aligned_alignment (tree clause
)
4227 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
4228 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
4230 /* Otherwise return implementation defined alignment. */
4231 unsigned int al
= 1;
4232 machine_mode mode
, vmode
;
4233 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
4235 vs
= 1 << floor_log2 (vs
);
4236 static enum mode_class classes
[]
4237 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
4238 for (int i
= 0; i
< 4; i
+= 2)
4239 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
4241 mode
= GET_MODE_WIDER_MODE (mode
))
4243 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
4244 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
4247 && GET_MODE_SIZE (vmode
) < vs
4248 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
4249 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
4251 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
4252 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
4254 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
4255 / GET_MODE_SIZE (mode
));
4256 if (TYPE_MODE (type
) != vmode
)
4258 if (TYPE_ALIGN_UNIT (type
) > al
)
4259 al
= TYPE_ALIGN_UNIT (type
);
4261 return build_int_cst (integer_type_node
, al
);
4264 /* Return maximum possible vectorization factor for the target. */
4271 || !flag_tree_loop_optimize
4272 || (!flag_tree_loop_vectorize
4273 && (global_options_set
.x_flag_tree_loop_vectorize
4274 || global_options_set
.x_flag_tree_vectorize
)))
4277 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
4280 vs
= 1 << floor_log2 (vs
);
4283 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
4284 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
4285 return GET_MODE_NUNITS (vqimode
);
4289 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4293 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
4294 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
4298 max_vf
= omp_max_vf ();
4301 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
4302 OMP_CLAUSE_SAFELEN
);
4303 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
4305 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
4307 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
4311 idx
= create_tmp_var (unsigned_type_node
);
4312 lane
= create_tmp_var (unsigned_type_node
);
4318 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
4319 tree avar
= create_tmp_var_raw (atype
);
4320 if (TREE_ADDRESSABLE (new_var
))
4321 TREE_ADDRESSABLE (avar
) = 1;
4322 DECL_ATTRIBUTES (avar
)
4323 = tree_cons (get_identifier ("omp simd array"), NULL
,
4324 DECL_ATTRIBUTES (avar
));
4325 gimple_add_tmp_var (avar
);
4326 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
4327 NULL_TREE
, NULL_TREE
);
4328 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
4329 NULL_TREE
, NULL_TREE
);
4330 if (DECL_P (new_var
))
4332 SET_DECL_VALUE_EXPR (new_var
, lvar
);
4333 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4338 /* Helper function of lower_rec_input_clauses. For a reference
4339 in simd reduction, add an underlying variable it will reference. */
4342 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
4344 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
4345 if (TREE_CONSTANT (z
))
4347 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)),
4348 get_name (new_vard
));
4349 gimple_add_tmp_var (z
);
4350 TREE_ADDRESSABLE (z
) = 1;
4351 z
= build_fold_addr_expr_loc (loc
, z
);
4352 gimplify_assign (new_vard
, z
, ilist
);
4356 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4357 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4358 private variables. Initialization statements go in ILIST, while calls
4359 to destructors go in DLIST. */
4362 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
4363 omp_context
*ctx
, struct omp_for_data
*fd
)
4365 tree c
, dtor
, copyin_seq
, x
, ptr
;
4366 bool copyin_by_ref
= false;
4367 bool lastprivate_firstprivate
= false;
4368 bool reduction_omp_orig_ref
= false;
4370 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4371 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
4373 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
4374 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
4375 gimple_seq llist
[2] = { NULL
, NULL
};
4379 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4380 with data sharing clauses referencing variable sized vars. That
4381 is unnecessarily hard to support and very unlikely to result in
4382 vectorized code anyway. */
4384 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4385 switch (OMP_CLAUSE_CODE (c
))
4387 case OMP_CLAUSE_LINEAR
:
4388 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
4391 case OMP_CLAUSE_PRIVATE
:
4392 case OMP_CLAUSE_FIRSTPRIVATE
:
4393 case OMP_CLAUSE_LASTPRIVATE
:
4394 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
4397 case OMP_CLAUSE_REDUCTION
:
4398 if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == MEM_REF
4399 || is_variable_sized (OMP_CLAUSE_DECL (c
)))
4406 /* Do all the fixed sized types in the first pass, and the variable sized
4407 types in the second pass. This makes sure that the scalar arguments to
4408 the variable sized types are processed before we use them in the
4409 variable sized operations. */
4410 for (pass
= 0; pass
< 2; ++pass
)
4412 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4414 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
4417 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4421 case OMP_CLAUSE_PRIVATE
:
4422 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
4425 case OMP_CLAUSE_SHARED
:
4426 /* Ignore shared directives in teams construct. */
4427 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
4429 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
4431 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
)
4432 || is_global_var (OMP_CLAUSE_DECL (c
)));
4435 case OMP_CLAUSE_FIRSTPRIVATE
:
4436 case OMP_CLAUSE_COPYIN
:
4438 case OMP_CLAUSE_LINEAR
:
4439 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
)
4440 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
4441 lastprivate_firstprivate
= true;
4443 case OMP_CLAUSE_REDUCTION
:
4444 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
4445 reduction_omp_orig_ref
= true;
4447 case OMP_CLAUSE__LOOPTEMP_
:
4448 /* Handle _looptemp_ clauses only on parallel/task. */
4452 case OMP_CLAUSE_LASTPRIVATE
:
4453 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4455 lastprivate_firstprivate
= true;
4456 if (pass
!= 0 || is_taskloop_ctx (ctx
))
4459 /* Even without corresponding firstprivate, if
4460 decl is Fortran allocatable, it needs outer var
4463 && lang_hooks
.decls
.omp_private_outer_ref
4464 (OMP_CLAUSE_DECL (c
)))
4465 lastprivate_firstprivate
= true;
4467 case OMP_CLAUSE_ALIGNED
:
4470 var
= OMP_CLAUSE_DECL (c
);
4471 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
4472 && !is_global_var (var
))
4474 new_var
= maybe_lookup_decl (var
, ctx
);
4475 if (new_var
== NULL_TREE
)
4476 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
4477 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
4478 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
4479 omp_clause_aligned_alignment (c
));
4480 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
4481 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
4482 gimplify_and_add (x
, ilist
);
4484 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
4485 && is_global_var (var
))
4487 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
4488 new_var
= lookup_decl (var
, ctx
);
4489 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
4490 t
= build_fold_addr_expr_loc (clause_loc
, t
);
4491 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
4492 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
4493 omp_clause_aligned_alignment (c
));
4494 t
= fold_convert_loc (clause_loc
, ptype
, t
);
4495 x
= create_tmp_var (ptype
);
4496 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
4497 gimplify_and_add (t
, ilist
);
4498 t
= build_simple_mem_ref_loc (clause_loc
, x
);
4499 SET_DECL_VALUE_EXPR (new_var
, t
);
4500 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4507 new_var
= var
= OMP_CLAUSE_DECL (c
);
4508 if (c_kind
== OMP_CLAUSE_REDUCTION
&& TREE_CODE (var
) == MEM_REF
)
4510 var
= TREE_OPERAND (var
, 0);
4511 if (TREE_CODE (var
) == POINTER_PLUS_EXPR
)
4512 var
= TREE_OPERAND (var
, 0);
4513 if (TREE_CODE (var
) == INDIRECT_REF
4514 || TREE_CODE (var
) == ADDR_EXPR
)
4515 var
= TREE_OPERAND (var
, 0);
4516 if (is_variable_sized (var
))
4518 gcc_assert (DECL_HAS_VALUE_EXPR_P (var
));
4519 var
= DECL_VALUE_EXPR (var
);
4520 gcc_assert (TREE_CODE (var
) == INDIRECT_REF
);
4521 var
= TREE_OPERAND (var
, 0);
4522 gcc_assert (DECL_P (var
));
4526 if (c_kind
!= OMP_CLAUSE_COPYIN
)
4527 new_var
= lookup_decl (var
, ctx
);
4529 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
4534 /* C/C++ array section reductions. */
4535 else if (c_kind
== OMP_CLAUSE_REDUCTION
4536 && var
!= OMP_CLAUSE_DECL (c
))
4541 tree bias
= TREE_OPERAND (OMP_CLAUSE_DECL (c
), 1);
4542 tree orig_var
= TREE_OPERAND (OMP_CLAUSE_DECL (c
), 0);
4543 if (TREE_CODE (orig_var
) == POINTER_PLUS_EXPR
)
4545 tree b
= TREE_OPERAND (orig_var
, 1);
4546 b
= maybe_lookup_decl (b
, ctx
);
4549 b
= TREE_OPERAND (orig_var
, 1);
4550 b
= maybe_lookup_decl_in_outer_ctx (b
, ctx
);
4552 if (integer_zerop (bias
))
4556 bias
= fold_convert_loc (clause_loc
,
4557 TREE_TYPE (b
), bias
);
4558 bias
= fold_build2_loc (clause_loc
, PLUS_EXPR
,
4559 TREE_TYPE (b
), b
, bias
);
4561 orig_var
= TREE_OPERAND (orig_var
, 0);
4563 if (TREE_CODE (orig_var
) == INDIRECT_REF
4564 || TREE_CODE (orig_var
) == ADDR_EXPR
)
4565 orig_var
= TREE_OPERAND (orig_var
, 0);
4566 tree d
= OMP_CLAUSE_DECL (c
);
4567 tree type
= TREE_TYPE (d
);
4568 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
4569 tree v
= TYPE_MAX_VALUE (TYPE_DOMAIN (type
));
4570 const char *name
= get_name (orig_var
);
4571 if (TREE_CONSTANT (v
))
4573 x
= create_tmp_var_raw (type
, name
);
4574 gimple_add_tmp_var (x
);
4575 TREE_ADDRESSABLE (x
) = 1;
4576 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4581 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
4582 tree t
= maybe_lookup_decl (v
, ctx
);
4586 v
= maybe_lookup_decl_in_outer_ctx (v
, ctx
);
4587 gimplify_expr (&v
, ilist
, NULL
, is_gimple_val
, fb_rvalue
);
4588 t
= fold_build2_loc (clause_loc
, PLUS_EXPR
,
4590 build_int_cst (TREE_TYPE (v
), 1));
4591 t
= fold_build2_loc (clause_loc
, MULT_EXPR
,
4593 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4594 tree al
= size_int (TYPE_ALIGN (TREE_TYPE (type
)));
4595 x
= build_call_expr_loc (clause_loc
, atmp
, 2, t
, al
);
4598 tree ptype
= build_pointer_type (TREE_TYPE (type
));
4599 x
= fold_convert_loc (clause_loc
, ptype
, x
);
4600 tree y
= create_tmp_var (ptype
, name
);
4601 gimplify_assign (y
, x
, ilist
);
4605 if (!integer_zerop (bias
))
4607 bias
= fold_convert_loc (clause_loc
, pointer_sized_int_node
,
4609 yb
= fold_convert_loc (clause_loc
, pointer_sized_int_node
,
4611 yb
= fold_build2_loc (clause_loc
, MINUS_EXPR
,
4612 pointer_sized_int_node
, yb
, bias
);
4613 x
= fold_convert_loc (clause_loc
, TREE_TYPE (x
), yb
);
4614 yb
= create_tmp_var (ptype
, name
);
4615 gimplify_assign (yb
, x
, ilist
);
4619 d
= TREE_OPERAND (d
, 0);
4620 if (TREE_CODE (d
) == POINTER_PLUS_EXPR
)
4621 d
= TREE_OPERAND (d
, 0);
4622 if (TREE_CODE (d
) == ADDR_EXPR
)
4624 if (orig_var
!= var
)
4626 gcc_assert (is_variable_sized (orig_var
));
4627 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
),
4629 gimplify_assign (new_var
, x
, ilist
);
4630 tree new_orig_var
= lookup_decl (orig_var
, ctx
);
4631 tree t
= build_fold_indirect_ref (new_var
);
4632 DECL_IGNORED_P (new_var
) = 0;
4633 TREE_THIS_NOTRAP (t
);
4634 SET_DECL_VALUE_EXPR (new_orig_var
, t
);
4635 DECL_HAS_VALUE_EXPR_P (new_orig_var
) = 1;
4639 x
= build2 (MEM_REF
, TREE_TYPE (new_var
), x
,
4640 build_int_cst (ptype
, 0));
4641 SET_DECL_VALUE_EXPR (new_var
, x
);
4642 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4647 gcc_assert (orig_var
== var
);
4648 if (TREE_CODE (d
) == INDIRECT_REF
)
4650 x
= create_tmp_var (ptype
, name
);
4651 TREE_ADDRESSABLE (x
) = 1;
4652 gimplify_assign (x
, yb
, ilist
);
4653 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4655 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
4656 gimplify_assign (new_var
, x
, ilist
);
4658 tree y1
= create_tmp_var (ptype
, NULL
);
4659 gimplify_assign (y1
, y
, ilist
);
4660 tree i2
= NULL_TREE
, y2
= NULL_TREE
;
4661 tree body2
= NULL_TREE
, end2
= NULL_TREE
;
4662 tree y3
= NULL_TREE
, y4
= NULL_TREE
;
4663 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) || is_simd
)
4665 y2
= create_tmp_var (ptype
, NULL
);
4666 gimplify_assign (y2
, y
, ilist
);
4667 tree ref
= build_outer_var_ref (var
, ctx
);
4668 /* For ref build_outer_var_ref already performs this. */
4669 if (TREE_CODE (d
) == INDIRECT_REF
)
4670 gcc_assert (is_reference (var
));
4671 else if (TREE_CODE (d
) == ADDR_EXPR
)
4672 ref
= build_fold_addr_expr (ref
);
4673 else if (is_reference (var
))
4674 ref
= build_fold_addr_expr (ref
);
4675 ref
= fold_convert_loc (clause_loc
, ptype
, ref
);
4676 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
)
4677 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
4679 y3
= create_tmp_var (ptype
, NULL
);
4680 gimplify_assign (y3
, unshare_expr (ref
), ilist
);
4684 y4
= create_tmp_var (ptype
, NULL
);
4685 gimplify_assign (y4
, ref
, dlist
);
4688 tree i
= create_tmp_var (TREE_TYPE (v
), NULL
);
4689 gimplify_assign (i
, build_int_cst (TREE_TYPE (v
), 0), ilist
);
4690 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
4691 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
4692 gimple_seq_add_stmt (ilist
, gimple_build_label (body
));
4695 i2
= create_tmp_var (TREE_TYPE (v
), NULL
);
4696 gimplify_assign (i2
, build_int_cst (TREE_TYPE (v
), 0), dlist
);
4697 body2
= create_artificial_label (UNKNOWN_LOCATION
);
4698 end2
= create_artificial_label (UNKNOWN_LOCATION
);
4699 gimple_seq_add_stmt (dlist
, gimple_build_label (body2
));
4701 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4703 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4704 tree decl_placeholder
4705 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c
);
4706 SET_DECL_VALUE_EXPR (decl_placeholder
,
4707 build_simple_mem_ref (y1
));
4708 DECL_HAS_VALUE_EXPR_P (decl_placeholder
) = 1;
4709 SET_DECL_VALUE_EXPR (placeholder
,
4710 y3
? build_simple_mem_ref (y3
)
4712 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4713 x
= lang_hooks
.decls
.omp_clause_default_ctor
4714 (c
, build_simple_mem_ref (y1
),
4715 y3
? build_simple_mem_ref (y3
) : NULL_TREE
);
4717 gimplify_and_add (x
, ilist
);
4718 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4720 gimple_seq tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4721 lower_omp (&tseq
, ctx
);
4722 gimple_seq_add_seq (ilist
, tseq
);
4724 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4727 SET_DECL_VALUE_EXPR (decl_placeholder
,
4728 build_simple_mem_ref (y2
));
4729 SET_DECL_VALUE_EXPR (placeholder
,
4730 build_simple_mem_ref (y4
));
4731 gimple_seq tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4732 lower_omp (&tseq
, ctx
);
4733 gimple_seq_add_seq (dlist
, tseq
);
4734 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4736 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4737 DECL_HAS_VALUE_EXPR_P (decl_placeholder
) = 0;
4738 x
= lang_hooks
.decls
.omp_clause_dtor
4739 (c
, build_simple_mem_ref (y2
));
4742 gimple_seq tseq
= NULL
;
4744 gimplify_stmt (&dtor
, &tseq
);
4745 gimple_seq_add_seq (dlist
, tseq
);
4750 x
= omp_reduction_init (c
, TREE_TYPE (type
));
4751 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4753 /* reduction(-:var) sums up the partial results, so it
4754 acts identically to reduction(+:var). */
4755 if (code
== MINUS_EXPR
)
4758 gimplify_assign (build_simple_mem_ref (y1
), x
, ilist
);
4761 x
= build2 (code
, TREE_TYPE (type
),
4762 build_simple_mem_ref (y4
),
4763 build_simple_mem_ref (y2
));
4764 gimplify_assign (build_simple_mem_ref (y4
), x
, dlist
);
4768 = gimple_build_assign (y1
, POINTER_PLUS_EXPR
, y1
,
4769 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4770 gimple_seq_add_stmt (ilist
, g
);
4773 g
= gimple_build_assign (y3
, POINTER_PLUS_EXPR
, y3
,
4774 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4775 gimple_seq_add_stmt (ilist
, g
);
4777 g
= gimple_build_assign (i
, PLUS_EXPR
, i
,
4778 build_int_cst (TREE_TYPE (i
), 1));
4779 gimple_seq_add_stmt (ilist
, g
);
4780 g
= gimple_build_cond (LE_EXPR
, i
, v
, body
, end
);
4781 gimple_seq_add_stmt (ilist
, g
);
4782 gimple_seq_add_stmt (ilist
, gimple_build_label (end
));
4785 g
= gimple_build_assign (y2
, POINTER_PLUS_EXPR
, y2
,
4786 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4787 gimple_seq_add_stmt (dlist
, g
);
4790 g
= gimple_build_assign
4791 (y4
, POINTER_PLUS_EXPR
, y4
,
4792 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
4793 gimple_seq_add_stmt (dlist
, g
);
4795 g
= gimple_build_assign (i2
, PLUS_EXPR
, i2
,
4796 build_int_cst (TREE_TYPE (i2
), 1));
4797 gimple_seq_add_stmt (dlist
, g
);
4798 g
= gimple_build_cond (LE_EXPR
, i2
, v
, body2
, end2
);
4799 gimple_seq_add_stmt (dlist
, g
);
4800 gimple_seq_add_stmt (dlist
, gimple_build_label (end2
));
4804 else if (is_variable_sized (var
))
4806 /* For variable sized types, we need to allocate the
4807 actual storage here. Call alloca and store the
4808 result in the pointer decl that we created elsewhere. */
4812 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
4817 ptr
= DECL_VALUE_EXPR (new_var
);
4818 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
4819 ptr
= TREE_OPERAND (ptr
, 0);
4820 gcc_assert (DECL_P (ptr
));
4821 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
4823 /* void *tmp = __builtin_alloca */
4824 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
4825 stmt
= gimple_build_call (atmp
, 2, x
,
4826 size_int (DECL_ALIGN (var
)));
4827 tmp
= create_tmp_var_raw (ptr_type_node
);
4828 gimple_add_tmp_var (tmp
);
4829 gimple_call_set_lhs (stmt
, tmp
);
4831 gimple_seq_add_stmt (ilist
, stmt
);
4833 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
4834 gimplify_assign (ptr
, x
, ilist
);
4837 else if (is_reference (var
))
4839 /* For references that are being privatized for Fortran,
4840 allocate new backing storage for the new pointer
4841 variable. This allows us to avoid changing all the
4842 code that expects a pointer to something that expects
4843 a direct variable. */
4847 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
4848 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
4850 x
= build_receiver_ref (var
, false, ctx
);
4851 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4853 else if (TREE_CONSTANT (x
))
4855 /* For reduction in SIMD loop, defer adding the
4856 initialization of the reference, because if we decide
4857 to use SIMD array for it, the initilization could cause
4859 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
4863 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
4865 gimple_add_tmp_var (x
);
4866 TREE_ADDRESSABLE (x
) = 1;
4867 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4873 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
4874 tree rtype
= TREE_TYPE (TREE_TYPE (new_var
));
4875 tree al
= size_int (TYPE_ALIGN (rtype
));
4876 x
= build_call_expr_loc (clause_loc
, atmp
, 2, x
, al
);
4881 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
4882 gimplify_assign (new_var
, x
, ilist
);
4885 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4887 else if (c_kind
== OMP_CLAUSE_REDUCTION
4888 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4896 switch (OMP_CLAUSE_CODE (c
))
4898 case OMP_CLAUSE_SHARED
:
4899 /* Ignore shared directives in teams construct. */
4900 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
4902 /* Shared global vars are just accessed directly. */
4903 if (is_global_var (new_var
))
4905 /* For taskloop firstprivate/lastprivate, represented
4906 as firstprivate and shared clause on the task, new_var
4907 is the firstprivate var. */
4908 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
4910 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4911 needs to be delayed until after fixup_child_record_type so
4912 that we get the correct type during the dereference. */
4913 by_ref
= use_pointer_for_field (var
, ctx
);
4914 x
= build_receiver_ref (var
, by_ref
, ctx
);
4915 SET_DECL_VALUE_EXPR (new_var
, x
);
4916 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
4918 /* ??? If VAR is not passed by reference, and the variable
4919 hasn't been initialized yet, then we'll get a warning for
4920 the store into the omp_data_s structure. Ideally, we'd be
4921 able to notice this and not store anything at all, but
4922 we're generating code too early. Suppress the warning. */
4924 TREE_NO_WARNING (var
) = 1;
4927 case OMP_CLAUSE_LASTPRIVATE
:
4928 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4932 case OMP_CLAUSE_PRIVATE
:
4933 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
4934 x
= build_outer_var_ref (var
, ctx
);
4935 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4937 if (is_task_ctx (ctx
))
4938 x
= build_receiver_ref (var
, false, ctx
);
4940 x
= build_outer_var_ref (var
, ctx
);
4946 nx
= lang_hooks
.decls
.omp_clause_default_ctor
4947 (c
, unshare_expr (new_var
), x
);
4950 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
4951 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
4952 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
4953 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4954 idx
, lane
, ivar
, lvar
))
4957 x
= lang_hooks
.decls
.omp_clause_default_ctor
4958 (c
, unshare_expr (ivar
), x
);
4960 gimplify_and_add (x
, &llist
[0]);
4963 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4966 gimple_seq tseq
= NULL
;
4969 gimplify_stmt (&dtor
, &tseq
);
4970 gimple_seq_add_seq (&llist
[1], tseq
);
4977 gimplify_and_add (nx
, ilist
);
4981 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
4984 gimple_seq tseq
= NULL
;
4987 gimplify_stmt (&dtor
, &tseq
);
4988 gimple_seq_add_seq (dlist
, tseq
);
4992 case OMP_CLAUSE_LINEAR
:
4993 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
4994 goto do_firstprivate
;
4995 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
4998 x
= build_outer_var_ref (var
, ctx
);
5001 case OMP_CLAUSE_FIRSTPRIVATE
:
5002 if (is_task_ctx (ctx
))
5004 if (is_reference (var
) || is_variable_sized (var
))
5006 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
5008 || use_pointer_for_field (var
, NULL
))
5010 x
= build_receiver_ref (var
, false, ctx
);
5011 SET_DECL_VALUE_EXPR (new_var
, x
);
5012 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
5017 x
= build_outer_var_ref (var
, ctx
);
5020 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
5021 && gimple_omp_for_combined_into_p (ctx
->stmt
))
5023 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
5024 tree stept
= TREE_TYPE (t
);
5025 tree ct
= find_omp_clause (clauses
,
5026 OMP_CLAUSE__LOOPTEMP_
);
5028 tree l
= OMP_CLAUSE_DECL (ct
);
5029 tree n1
= fd
->loop
.n1
;
5030 tree step
= fd
->loop
.step
;
5031 tree itype
= TREE_TYPE (l
);
5032 if (POINTER_TYPE_P (itype
))
5033 itype
= signed_type_for (itype
);
5034 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
5035 if (TYPE_UNSIGNED (itype
)
5036 && fd
->loop
.cond_code
== GT_EXPR
)
5037 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5038 fold_build1 (NEGATE_EXPR
, itype
, l
),
5039 fold_build1 (NEGATE_EXPR
,
5042 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
5043 t
= fold_build2 (MULT_EXPR
, stept
,
5044 fold_convert (stept
, l
), t
);
5046 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
5048 x
= lang_hooks
.decls
.omp_clause_linear_ctor
5050 gimplify_and_add (x
, ilist
);
5054 if (POINTER_TYPE_P (TREE_TYPE (x
)))
5055 x
= fold_build2 (POINTER_PLUS_EXPR
,
5056 TREE_TYPE (x
), x
, t
);
5058 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
5061 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
5062 || TREE_ADDRESSABLE (new_var
))
5063 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
5064 idx
, lane
, ivar
, lvar
))
5066 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
5068 tree iv
= create_tmp_var (TREE_TYPE (new_var
));
5069 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
5070 gimplify_and_add (x
, ilist
);
5071 gimple_stmt_iterator gsi
5072 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
5074 = gimple_build_assign (unshare_expr (lvar
), iv
);
5075 gsi_insert_before_without_update (&gsi
, g
,
5077 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
5078 enum tree_code code
= PLUS_EXPR
;
5079 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
5080 code
= POINTER_PLUS_EXPR
;
5081 g
= gimple_build_assign (iv
, code
, iv
, t
);
5082 gsi_insert_before_without_update (&gsi
, g
,
5086 x
= lang_hooks
.decls
.omp_clause_copy_ctor
5087 (c
, unshare_expr (ivar
), x
);
5088 gimplify_and_add (x
, &llist
[0]);
5089 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
5092 gimple_seq tseq
= NULL
;
5095 gimplify_stmt (&dtor
, &tseq
);
5096 gimple_seq_add_seq (&llist
[1], tseq
);
5101 x
= lang_hooks
.decls
.omp_clause_copy_ctor
5102 (c
, unshare_expr (new_var
), x
);
5103 gimplify_and_add (x
, ilist
);
5106 case OMP_CLAUSE__LOOPTEMP_
:
5107 gcc_assert (is_taskreg_ctx (ctx
));
5108 x
= build_outer_var_ref (var
, ctx
);
5109 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
5110 gimplify_and_add (x
, ilist
);
5113 case OMP_CLAUSE_COPYIN
:
5114 by_ref
= use_pointer_for_field (var
, NULL
);
5115 x
= build_receiver_ref (var
, by_ref
, ctx
);
5116 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
5117 append_to_statement_list (x
, ©in_seq
);
5118 copyin_by_ref
|= by_ref
;
5121 case OMP_CLAUSE_REDUCTION
:
5122 /* OpenACC reductions are initialized using the
5123 GOACC_REDUCTION internal function. */
5124 if (is_gimple_omp_oacc (ctx
->stmt
))
5126 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
5128 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
5130 x
= build_outer_var_ref (var
, ctx
);
5132 if (is_reference (var
)
5133 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
5135 x
= build_fold_addr_expr_loc (clause_loc
, x
);
5136 SET_DECL_VALUE_EXPR (placeholder
, x
);
5137 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
5138 tree new_vard
= new_var
;
5139 if (is_reference (var
))
5141 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
5142 new_vard
= TREE_OPERAND (new_var
, 0);
5143 gcc_assert (DECL_P (new_vard
));
5146 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
5147 idx
, lane
, ivar
, lvar
))
5149 if (new_vard
== new_var
)
5151 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
5152 SET_DECL_VALUE_EXPR (new_var
, ivar
);
5156 SET_DECL_VALUE_EXPR (new_vard
,
5157 build_fold_addr_expr (ivar
));
5158 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
5160 x
= lang_hooks
.decls
.omp_clause_default_ctor
5161 (c
, unshare_expr (ivar
),
5162 build_outer_var_ref (var
, ctx
));
5164 gimplify_and_add (x
, &llist
[0]);
5165 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
5167 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
5168 lower_omp (&tseq
, ctx
);
5169 gimple_seq_add_seq (&llist
[0], tseq
);
5171 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
5172 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
5173 lower_omp (&tseq
, ctx
);
5174 gimple_seq_add_seq (&llist
[1], tseq
);
5175 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
5176 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
5177 if (new_vard
== new_var
)
5178 SET_DECL_VALUE_EXPR (new_var
, lvar
);
5180 SET_DECL_VALUE_EXPR (new_vard
,
5181 build_fold_addr_expr (lvar
));
5182 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
5187 gimplify_stmt (&dtor
, &tseq
);
5188 gimple_seq_add_seq (&llist
[1], tseq
);
5192 /* If this is a reference to constant size reduction var
5193 with placeholder, we haven't emitted the initializer
5194 for it because it is undesirable if SIMD arrays are used.
5195 But if they aren't used, we need to emit the deferred
5196 initialization now. */
5197 else if (is_reference (var
) && is_simd
)
5198 handle_simd_reference (clause_loc
, new_vard
, ilist
);
5199 x
= lang_hooks
.decls
.omp_clause_default_ctor
5200 (c
, unshare_expr (new_var
),
5201 build_outer_var_ref (var
, ctx
));
5203 gimplify_and_add (x
, ilist
);
5204 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
5206 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
5207 lower_omp (&tseq
, ctx
);
5208 gimple_seq_add_seq (ilist
, tseq
);
5210 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
5213 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
5214 lower_omp (&tseq
, ctx
);
5215 gimple_seq_add_seq (dlist
, tseq
);
5216 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
5218 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
5223 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
5224 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
5225 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
5227 /* reduction(-:var) sums up the partial results, so it
5228 acts identically to reduction(+:var). */
5229 if (code
== MINUS_EXPR
)
5232 tree new_vard
= new_var
;
5233 if (is_simd
&& is_reference (var
))
5235 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
5236 new_vard
= TREE_OPERAND (new_var
, 0);
5237 gcc_assert (DECL_P (new_vard
));
5240 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
5241 idx
, lane
, ivar
, lvar
))
5243 tree ref
= build_outer_var_ref (var
, ctx
);
5245 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
5247 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
5248 ref
= build_outer_var_ref (var
, ctx
);
5249 gimplify_assign (ref
, x
, &llist
[1]);
5251 if (new_vard
!= new_var
)
5253 SET_DECL_VALUE_EXPR (new_vard
,
5254 build_fold_addr_expr (lvar
));
5255 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
5260 if (is_reference (var
) && is_simd
)
5261 handle_simd_reference (clause_loc
, new_vard
, ilist
);
5262 gimplify_assign (new_var
, x
, ilist
);
5265 tree ref
= build_outer_var_ref (var
, ctx
);
5267 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
5268 ref
= build_outer_var_ref (var
, ctx
);
5269 gimplify_assign (ref
, x
, dlist
);
5283 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
5284 /* Don't want uninit warnings on simduid, it is always uninitialized,
5285 but we use it not for the value, but for the DECL_UID only. */
5286 TREE_NO_WARNING (uid
) = 1;
5288 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
5289 gimple_call_set_lhs (g
, lane
);
5290 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
5291 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
5292 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
5293 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
5294 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
5295 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
5296 g
= gimple_build_assign (lane
, INTEGER_CST
,
5297 build_int_cst (unsigned_type_node
, 0));
5298 gimple_seq_add_stmt (ilist
, g
);
5299 for (int i
= 0; i
< 2; i
++)
5302 tree vf
= create_tmp_var (unsigned_type_node
);
5303 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
5304 gimple_call_set_lhs (g
, vf
);
5305 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
5306 gimple_seq_add_stmt (seq
, g
);
5307 tree t
= build_int_cst (unsigned_type_node
, 0);
5308 g
= gimple_build_assign (idx
, INTEGER_CST
, t
);
5309 gimple_seq_add_stmt (seq
, g
);
5310 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
5311 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
5312 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
5313 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
5314 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
5315 gimple_seq_add_seq (seq
, llist
[i
]);
5316 t
= build_int_cst (unsigned_type_node
, 1);
5317 g
= gimple_build_assign (idx
, PLUS_EXPR
, idx
, t
);
5318 gimple_seq_add_stmt (seq
, g
);
5319 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
5320 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
5321 gimple_seq_add_stmt (seq
, g
);
5322 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
5326 /* The copyin sequence is not to be executed by the main thread, since
5327 that would result in self-copies. Perhaps not visible to scalars,
5328 but it certainly is to C++ operator=. */
5331 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
5333 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
5334 build_int_cst (TREE_TYPE (x
), 0));
5335 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
5336 gimplify_and_add (x
, ilist
);
5339 /* If any copyin variable is passed by reference, we must ensure the
5340 master thread doesn't modify it before it is copied over in all
5341 threads. Similarly for variables in both firstprivate and
5342 lastprivate clauses we need to ensure the lastprivate copying
5343 happens after firstprivate copying in all threads. And similarly
5344 for UDRs if initializer expression refers to omp_orig. */
5345 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
5347 /* Don't add any barrier for #pragma omp simd or
5348 #pragma omp distribute. */
5349 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
5350 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
5351 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
5354 /* If max_vf is non-zero, then we can use only a vectorization factor
5355 up to the max_vf we chose. So stick it into the safelen clause. */
5358 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
5359 OMP_CLAUSE_SAFELEN
);
5361 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
5362 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
5365 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
5366 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
5368 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
5369 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
5375 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5376 both parallel and workshare constructs. PREDICATE may be NULL if it's
5380 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
5383 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
5384 bool par_clauses
= false;
5385 tree simduid
= NULL
, lastlane
= NULL
;
5387 /* Early exit if there are no lastprivate or linear clauses. */
5388 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
5389 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
5390 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
5391 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
5393 if (clauses
== NULL
)
5395 /* If this was a workshare clause, see if it had been combined
5396 with its parallel. In that case, look for the clauses on the
5397 parallel statement itself. */
5398 if (is_parallel_ctx (ctx
))
5402 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
5405 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
5406 OMP_CLAUSE_LASTPRIVATE
);
5407 if (clauses
== NULL
)
5415 tree label_true
, arm1
, arm2
;
5417 label
= create_artificial_label (UNKNOWN_LOCATION
);
5418 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
5419 arm1
= TREE_OPERAND (predicate
, 0);
5420 arm2
= TREE_OPERAND (predicate
, 1);
5421 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
5422 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
5423 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
5425 gimple_seq_add_stmt (stmt_list
, stmt
);
5426 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
5429 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
5430 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
5432 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
5434 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
5437 for (c
= clauses
; c
;)
5440 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
5442 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5443 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
5444 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
5446 var
= OMP_CLAUSE_DECL (c
);
5447 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5448 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
)
5449 && is_taskloop_ctx (ctx
))
5451 gcc_checking_assert (ctx
->outer
&& is_task_ctx (ctx
->outer
));
5452 new_var
= lookup_decl (var
, ctx
->outer
);
5455 new_var
= lookup_decl (var
, ctx
);
5457 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
5459 tree val
= DECL_VALUE_EXPR (new_var
);
5460 if (TREE_CODE (val
) == ARRAY_REF
5461 && VAR_P (TREE_OPERAND (val
, 0))
5462 && lookup_attribute ("omp simd array",
5463 DECL_ATTRIBUTES (TREE_OPERAND (val
,
5466 if (lastlane
== NULL
)
5468 lastlane
= create_tmp_var (unsigned_type_node
);
5470 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
5472 TREE_OPERAND (val
, 1));
5473 gimple_call_set_lhs (g
, lastlane
);
5474 gimple_seq_add_stmt (stmt_list
, g
);
5476 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
5477 TREE_OPERAND (val
, 0), lastlane
,
5478 NULL_TREE
, NULL_TREE
);
5482 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5483 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
5485 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
5486 gimple_seq_add_seq (stmt_list
,
5487 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
5488 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
5490 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
5491 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
5493 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
5494 gimple_seq_add_seq (stmt_list
,
5495 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
5496 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
5500 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
5501 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c
))
5503 gcc_checking_assert (is_taskloop_ctx (ctx
));
5504 tree ovar
= maybe_lookup_decl_in_outer_ctx (var
,
5506 if (is_global_var (ovar
))
5510 x
= build_outer_var_ref (var
, ctx
, true);
5511 if (is_reference (var
))
5512 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5513 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
5514 gimplify_and_add (x
, stmt_list
);
5516 c
= OMP_CLAUSE_CHAIN (c
);
5517 if (c
== NULL
&& !par_clauses
)
5519 /* If this was a workshare clause, see if it had been combined
5520 with its parallel. In that case, continue looking for the
5521 clauses also on the parallel statement itself. */
5522 if (is_parallel_ctx (ctx
))
5526 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
5529 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
5530 OMP_CLAUSE_LASTPRIVATE
);
5536 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
5539 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5540 (which might be a placeholder). INNER is true if this is an inner
5541 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5542 join markers. Generate the before-loop forking sequence in
5543 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5544 general form of these sequences is
5546 GOACC_REDUCTION_SETUP
5548 GOACC_REDUCTION_INIT
5550 GOACC_REDUCTION_FINI
5552 GOACC_REDUCTION_TEARDOWN. */
5555 lower_oacc_reductions (location_t loc
, tree clauses
, tree level
, bool inner
,
5556 gcall
*fork
, gcall
*join
, gimple_seq
*fork_seq
,
5557 gimple_seq
*join_seq
, omp_context
*ctx
)
5559 gimple_seq before_fork
= NULL
;
5560 gimple_seq after_fork
= NULL
;
5561 gimple_seq before_join
= NULL
;
5562 gimple_seq after_join
= NULL
;
5563 tree init_code
= NULL_TREE
, fini_code
= NULL_TREE
,
5564 setup_code
= NULL_TREE
, teardown_code
= NULL_TREE
;
5565 unsigned offset
= 0;
5567 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
5568 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
5570 tree orig
= OMP_CLAUSE_DECL (c
);
5571 tree var
= maybe_lookup_decl (orig
, ctx
);
5572 tree ref_to_res
= NULL_TREE
;
5573 tree incoming
, outgoing
, v1
, v2
, v3
;
5574 bool is_private
= false;
5576 enum tree_code rcode
= OMP_CLAUSE_REDUCTION_CODE (c
);
5577 if (rcode
== MINUS_EXPR
)
5579 else if (rcode
== TRUTH_ANDIF_EXPR
)
5580 rcode
= BIT_AND_EXPR
;
5581 else if (rcode
== TRUTH_ORIF_EXPR
)
5582 rcode
= BIT_IOR_EXPR
;
5583 tree op
= build_int_cst (unsigned_type_node
, rcode
);
5588 incoming
= outgoing
= var
;
5592 /* See if an outer construct also reduces this variable. */
5593 omp_context
*outer
= ctx
;
5595 while (omp_context
*probe
= outer
->outer
)
5597 enum gimple_code type
= gimple_code (probe
->stmt
);
5602 case GIMPLE_OMP_FOR
:
5603 cls
= gimple_omp_for_clauses (probe
->stmt
);
5606 case GIMPLE_OMP_TARGET
:
5607 if (gimple_omp_target_kind (probe
->stmt
)
5608 != GF_OMP_TARGET_KIND_OACC_PARALLEL
)
5611 cls
= gimple_omp_target_clauses (probe
->stmt
);
5619 for (; cls
; cls
= OMP_CLAUSE_CHAIN (cls
))
5620 if (OMP_CLAUSE_CODE (cls
) == OMP_CLAUSE_REDUCTION
5621 && orig
== OMP_CLAUSE_DECL (cls
))
5623 incoming
= outgoing
= lookup_decl (orig
, probe
);
5624 goto has_outer_reduction
;
5626 else if ((OMP_CLAUSE_CODE (cls
) == OMP_CLAUSE_FIRSTPRIVATE
5627 || OMP_CLAUSE_CODE (cls
) == OMP_CLAUSE_PRIVATE
)
5628 && orig
== OMP_CLAUSE_DECL (cls
))
5636 /* This is the outermost construct with this reduction,
5637 see if there's a mapping for it. */
5638 if (gimple_code (outer
->stmt
) == GIMPLE_OMP_TARGET
5639 && maybe_lookup_field (orig
, outer
) && !is_private
)
5641 ref_to_res
= build_receiver_ref (orig
, false, outer
);
5642 if (is_reference (orig
))
5643 ref_to_res
= build_simple_mem_ref (ref_to_res
);
5645 tree type
= TREE_TYPE (var
);
5646 if (POINTER_TYPE_P (type
))
5647 type
= TREE_TYPE (type
);
5650 incoming
= omp_reduction_init_op (loc
, rcode
, type
);
5652 else if (ctx
->outer
)
5653 incoming
= outgoing
= lookup_decl (orig
, ctx
->outer
);
5655 incoming
= outgoing
= orig
;
5657 has_outer_reduction
:;
5661 ref_to_res
= integer_zero_node
;
5663 if (is_reference (orig
))
5665 tree type
= TREE_TYPE (var
);
5666 const char *id
= IDENTIFIER_POINTER (DECL_NAME (var
));
5670 tree x
= create_tmp_var (TREE_TYPE (type
), id
);
5671 gimplify_assign (var
, build_fold_addr_expr (x
), fork_seq
);
5674 v1
= create_tmp_var (type
, id
);
5675 v2
= create_tmp_var (type
, id
);
5676 v3
= create_tmp_var (type
, id
);
5678 gimplify_assign (v1
, var
, fork_seq
);
5679 gimplify_assign (v2
, var
, fork_seq
);
5680 gimplify_assign (v3
, var
, fork_seq
);
5682 var
= build_simple_mem_ref (var
);
5683 v1
= build_simple_mem_ref (v1
);
5684 v2
= build_simple_mem_ref (v2
);
5685 v3
= build_simple_mem_ref (v3
);
5686 outgoing
= build_simple_mem_ref (outgoing
);
5688 if (!TREE_CONSTANT (incoming
))
5689 incoming
= build_simple_mem_ref (incoming
);
5694 /* Determine position in reduction buffer, which may be used
5696 enum machine_mode mode
= TYPE_MODE (TREE_TYPE (var
));
5697 unsigned align
= GET_MODE_ALIGNMENT (mode
) / BITS_PER_UNIT
;
5698 offset
= (offset
+ align
- 1) & ~(align
- 1);
5699 tree off
= build_int_cst (sizetype
, offset
);
5700 offset
+= GET_MODE_SIZE (mode
);
5704 init_code
= build_int_cst (integer_type_node
,
5705 IFN_GOACC_REDUCTION_INIT
);
5706 fini_code
= build_int_cst (integer_type_node
,
5707 IFN_GOACC_REDUCTION_FINI
);
5708 setup_code
= build_int_cst (integer_type_node
,
5709 IFN_GOACC_REDUCTION_SETUP
);
5710 teardown_code
= build_int_cst (integer_type_node
,
5711 IFN_GOACC_REDUCTION_TEARDOWN
);
5715 = build_call_expr_internal_loc (loc
, IFN_GOACC_REDUCTION
,
5716 TREE_TYPE (var
), 6, setup_code
,
5717 unshare_expr (ref_to_res
),
5718 incoming
, level
, op
, off
);
5720 = build_call_expr_internal_loc (loc
, IFN_GOACC_REDUCTION
,
5721 TREE_TYPE (var
), 6, init_code
,
5722 unshare_expr (ref_to_res
),
5723 v1
, level
, op
, off
);
5725 = build_call_expr_internal_loc (loc
, IFN_GOACC_REDUCTION
,
5726 TREE_TYPE (var
), 6, fini_code
,
5727 unshare_expr (ref_to_res
),
5728 v2
, level
, op
, off
);
5730 = build_call_expr_internal_loc (loc
, IFN_GOACC_REDUCTION
,
5731 TREE_TYPE (var
), 6, teardown_code
,
5732 ref_to_res
, v3
, level
, op
, off
);
5734 gimplify_assign (v1
, setup_call
, &before_fork
);
5735 gimplify_assign (v2
, init_call
, &after_fork
);
5736 gimplify_assign (v3
, fini_call
, &before_join
);
5737 gimplify_assign (outgoing
, teardown_call
, &after_join
);
5740 /* Now stitch things together. */
5741 gimple_seq_add_seq (fork_seq
, before_fork
);
5743 gimple_seq_add_stmt (fork_seq
, fork
);
5744 gimple_seq_add_seq (fork_seq
, after_fork
);
5746 gimple_seq_add_seq (join_seq
, before_join
);
5748 gimple_seq_add_stmt (join_seq
, join
);
5749 gimple_seq_add_seq (join_seq
, after_join
);
5752 /* Generate code to implement the REDUCTION clauses. */
5755 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
5757 gimple_seq sub_seq
= NULL
;
5762 /* OpenACC loop reductions are handled elsewhere. */
5763 if (is_gimple_omp_oacc (ctx
->stmt
))
5766 /* SIMD reductions are handled in lower_rec_input_clauses. */
5767 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
5768 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
5771 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5772 update in that case, otherwise use a lock. */
5773 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
5774 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
5776 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
)
5777 || TREE_CODE (OMP_CLAUSE_DECL (c
)) == MEM_REF
)
5779 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5789 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
5791 tree var
, ref
, new_var
, orig_var
;
5792 enum tree_code code
;
5793 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
5795 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
5798 orig_var
= var
= OMP_CLAUSE_DECL (c
);
5799 if (TREE_CODE (var
) == MEM_REF
)
5801 var
= TREE_OPERAND (var
, 0);
5802 if (TREE_CODE (var
) == POINTER_PLUS_EXPR
)
5803 var
= TREE_OPERAND (var
, 0);
5804 if (TREE_CODE (var
) == INDIRECT_REF
5805 || TREE_CODE (var
) == ADDR_EXPR
)
5806 var
= TREE_OPERAND (var
, 0);
5808 if (is_variable_sized (var
))
5810 gcc_assert (DECL_HAS_VALUE_EXPR_P (var
));
5811 var
= DECL_VALUE_EXPR (var
);
5812 gcc_assert (TREE_CODE (var
) == INDIRECT_REF
);
5813 var
= TREE_OPERAND (var
, 0);
5814 gcc_assert (DECL_P (var
));
5817 new_var
= lookup_decl (var
, ctx
);
5818 if (var
== OMP_CLAUSE_DECL (c
) && is_reference (var
))
5819 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5820 ref
= build_outer_var_ref (var
, ctx
);
5821 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
5823 /* reduction(-:var) sums up the partial results, so it acts
5824 identically to reduction(+:var). */
5825 if (code
== MINUS_EXPR
)
5830 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
5832 addr
= save_expr (addr
);
5833 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
5834 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
5835 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
5836 gimplify_and_add (x
, stmt_seqp
);
5839 else if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == MEM_REF
)
5841 tree d
= OMP_CLAUSE_DECL (c
);
5842 tree type
= TREE_TYPE (d
);
5843 tree v
= TYPE_MAX_VALUE (TYPE_DOMAIN (type
));
5844 tree i
= create_tmp_var (TREE_TYPE (v
), NULL
);
5845 tree ptype
= build_pointer_type (TREE_TYPE (type
));
5846 tree bias
= TREE_OPERAND (d
, 1);
5847 d
= TREE_OPERAND (d
, 0);
5848 if (TREE_CODE (d
) == POINTER_PLUS_EXPR
)
5850 tree b
= TREE_OPERAND (d
, 1);
5851 b
= maybe_lookup_decl (b
, ctx
);
5854 b
= TREE_OPERAND (d
, 1);
5855 b
= maybe_lookup_decl_in_outer_ctx (b
, ctx
);
5857 if (integer_zerop (bias
))
5861 bias
= fold_convert_loc (clause_loc
, TREE_TYPE (b
), bias
);
5862 bias
= fold_build2_loc (clause_loc
, PLUS_EXPR
,
5863 TREE_TYPE (b
), b
, bias
);
5865 d
= TREE_OPERAND (d
, 0);
5867 /* For ref build_outer_var_ref already performs this, so
5868 only new_var needs a dereference. */
5869 if (TREE_CODE (d
) == INDIRECT_REF
)
5871 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5872 gcc_assert (is_reference (var
) && var
== orig_var
);
5874 else if (TREE_CODE (d
) == ADDR_EXPR
)
5876 if (orig_var
== var
)
5878 new_var
= build_fold_addr_expr (new_var
);
5879 ref
= build_fold_addr_expr (ref
);
5884 gcc_assert (orig_var
== var
);
5885 if (is_reference (var
))
5886 ref
= build_fold_addr_expr (ref
);
5890 tree t
= maybe_lookup_decl (v
, ctx
);
5894 v
= maybe_lookup_decl_in_outer_ctx (v
, ctx
);
5895 gimplify_expr (&v
, stmt_seqp
, NULL
, is_gimple_val
, fb_rvalue
);
5897 if (!integer_zerop (bias
))
5899 bias
= fold_convert_loc (clause_loc
, sizetype
, bias
);
5900 new_var
= fold_build2_loc (clause_loc
, POINTER_PLUS_EXPR
,
5901 TREE_TYPE (new_var
), new_var
,
5902 unshare_expr (bias
));
5903 ref
= fold_build2_loc (clause_loc
, POINTER_PLUS_EXPR
,
5904 TREE_TYPE (ref
), ref
, bias
);
5906 new_var
= fold_convert_loc (clause_loc
, ptype
, new_var
);
5907 ref
= fold_convert_loc (clause_loc
, ptype
, ref
);
5908 tree m
= create_tmp_var (ptype
, NULL
);
5909 gimplify_assign (m
, new_var
, stmt_seqp
);
5911 m
= create_tmp_var (ptype
, NULL
);
5912 gimplify_assign (m
, ref
, stmt_seqp
);
5914 gimplify_assign (i
, build_int_cst (TREE_TYPE (v
), 0), stmt_seqp
);
5915 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
5916 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
5917 gimple_seq_add_stmt (&sub_seq
, gimple_build_label (body
));
5918 tree priv
= build_simple_mem_ref_loc (clause_loc
, new_var
);
5919 tree out
= build_simple_mem_ref_loc (clause_loc
, ref
);
5920 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
5922 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
5923 tree decl_placeholder
5924 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c
);
5925 SET_DECL_VALUE_EXPR (placeholder
, out
);
5926 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
5927 SET_DECL_VALUE_EXPR (decl_placeholder
, priv
);
5928 DECL_HAS_VALUE_EXPR_P (decl_placeholder
) = 1;
5929 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
5930 gimple_seq_add_seq (&sub_seq
,
5931 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
5932 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
5933 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
5934 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c
) = NULL
;
5938 x
= build2 (code
, TREE_TYPE (out
), out
, priv
);
5939 out
= unshare_expr (out
);
5940 gimplify_assign (out
, x
, &sub_seq
);
5942 gimple
*g
= gimple_build_assign (new_var
, POINTER_PLUS_EXPR
, new_var
,
5943 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
5944 gimple_seq_add_stmt (&sub_seq
, g
);
5945 g
= gimple_build_assign (ref
, POINTER_PLUS_EXPR
, ref
,
5946 TYPE_SIZE_UNIT (TREE_TYPE (type
)));
5947 gimple_seq_add_stmt (&sub_seq
, g
);
5948 g
= gimple_build_assign (i
, PLUS_EXPR
, i
,
5949 build_int_cst (TREE_TYPE (i
), 1));
5950 gimple_seq_add_stmt (&sub_seq
, g
);
5951 g
= gimple_build_cond (LE_EXPR
, i
, v
, body
, end
);
5952 gimple_seq_add_stmt (&sub_seq
, g
);
5953 gimple_seq_add_stmt (&sub_seq
, gimple_build_label (end
));
5955 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
5957 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
5959 if (is_reference (var
)
5960 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
5962 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
5963 SET_DECL_VALUE_EXPR (placeholder
, ref
);
5964 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
5965 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
5966 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
5967 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
5968 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
5972 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
5973 ref
= build_outer_var_ref (var
, ctx
);
5974 gimplify_assign (ref
, x
, &sub_seq
);
5978 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
5980 gimple_seq_add_stmt (stmt_seqp
, stmt
);
5982 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
5984 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
5986 gimple_seq_add_stmt (stmt_seqp
, stmt
);
5990 /* Generate code to implement the COPYPRIVATE clauses. */
5993 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
5998 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
6000 tree var
, new_var
, ref
, x
;
6002 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
6004 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
6007 var
= OMP_CLAUSE_DECL (c
);
6008 by_ref
= use_pointer_for_field (var
, NULL
);
6010 ref
= build_sender_ref (var
, ctx
);
6011 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
6014 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
6015 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
6017 gimplify_assign (ref
, x
, slist
);
6019 ref
= build_receiver_ref (var
, false, ctx
);
6022 ref
= fold_convert_loc (clause_loc
,
6023 build_pointer_type (TREE_TYPE (new_var
)),
6025 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
6027 if (is_reference (var
))
6029 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
6030 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
6031 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
6033 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
6034 gimplify_and_add (x
, rlist
);
6039 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6040 and REDUCTION from the sender (aka parent) side. */
6043 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
6047 int ignored_looptemp
= 0;
6048 bool is_taskloop
= false;
6050 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6051 by GOMP_taskloop. */
6052 if (is_task_ctx (ctx
) && gimple_omp_task_taskloop_p (ctx
->stmt
))
6054 ignored_looptemp
= 2;
6058 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
6060 tree val
, ref
, x
, var
;
6061 bool by_ref
, do_in
= false, do_out
= false;
6062 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
6064 switch (OMP_CLAUSE_CODE (c
))
6066 case OMP_CLAUSE_PRIVATE
:
6067 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
6070 case OMP_CLAUSE_FIRSTPRIVATE
:
6071 case OMP_CLAUSE_COPYIN
:
6072 case OMP_CLAUSE_LASTPRIVATE
:
6073 case OMP_CLAUSE_REDUCTION
:
6075 case OMP_CLAUSE_SHARED
:
6076 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
6079 case OMP_CLAUSE__LOOPTEMP_
:
6080 if (ignored_looptemp
)
6090 val
= OMP_CLAUSE_DECL (c
);
6091 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
6092 && TREE_CODE (val
) == MEM_REF
)
6094 val
= TREE_OPERAND (val
, 0);
6095 if (TREE_CODE (val
) == POINTER_PLUS_EXPR
)
6096 val
= TREE_OPERAND (val
, 0);
6097 if (TREE_CODE (val
) == INDIRECT_REF
6098 || TREE_CODE (val
) == ADDR_EXPR
)
6099 val
= TREE_OPERAND (val
, 0);
6100 if (is_variable_sized (val
))
6104 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6105 outer taskloop region. */
6106 omp_context
*ctx_for_o
= ctx
;
6108 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
6109 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
6110 ctx_for_o
= ctx
->outer
;
6112 var
= lookup_decl_in_outer_ctx (val
, ctx_for_o
);
6114 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
6115 && is_global_var (var
))
6118 t
= omp_member_access_dummy_var (var
);
6121 var
= DECL_VALUE_EXPR (var
);
6122 tree o
= maybe_lookup_decl_in_outer_ctx (t
, ctx_for_o
);
6124 var
= unshare_and_remap (var
, t
, o
);
6126 var
= unshare_expr (var
);
6129 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
6131 /* Handle taskloop firstprivate/lastprivate, where the
6132 lastprivate on GIMPLE_OMP_TASK is represented as
6133 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6134 tree f
= lookup_sfield ((splay_tree_key
) &DECL_UID (val
), ctx
);
6135 x
= omp_build_component_ref (ctx
->sender_decl
, f
);
6136 if (use_pointer_for_field (val
, ctx
))
6137 var
= build_fold_addr_expr (var
);
6138 gimplify_assign (x
, var
, ilist
);
6139 DECL_ABSTRACT_ORIGIN (f
) = NULL
;
6143 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
6144 || val
== OMP_CLAUSE_DECL (c
))
6145 && is_variable_sized (val
))
6147 by_ref
= use_pointer_for_field (val
, NULL
);
6149 switch (OMP_CLAUSE_CODE (c
))
6151 case OMP_CLAUSE_FIRSTPRIVATE
:
6152 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c
)
6154 && is_task_ctx (ctx
))
6155 TREE_NO_WARNING (var
) = 1;
6159 case OMP_CLAUSE_PRIVATE
:
6160 case OMP_CLAUSE_COPYIN
:
6161 case OMP_CLAUSE__LOOPTEMP_
:
6165 case OMP_CLAUSE_LASTPRIVATE
:
6166 if (by_ref
|| is_reference (val
))
6168 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
6175 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
6180 case OMP_CLAUSE_REDUCTION
:
6182 if (val
== OMP_CLAUSE_DECL (c
))
6183 do_out
= !(by_ref
|| is_reference (val
));
6185 by_ref
= TREE_CODE (TREE_TYPE (val
)) == ARRAY_TYPE
;
6194 ref
= build_sender_ref (val
, ctx
);
6195 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
6196 gimplify_assign (ref
, x
, ilist
);
6197 if (is_task_ctx (ctx
))
6198 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
6203 ref
= build_sender_ref (val
, ctx
);
6204 gimplify_assign (var
, ref
, olist
);
6209 /* Generate code to implement SHARED from the sender (aka parent)
6210 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6211 list things that got automatically shared. */
6214 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
6216 tree var
, ovar
, nvar
, t
, f
, x
, record_type
;
6218 if (ctx
->record_type
== NULL
)
6221 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
6222 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
6224 ovar
= DECL_ABSTRACT_ORIGIN (f
);
6225 if (!ovar
|| TREE_CODE (ovar
) == FIELD_DECL
)
6228 nvar
= maybe_lookup_decl (ovar
, ctx
);
6229 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
6232 /* If CTX is a nested parallel directive. Find the immediately
6233 enclosing parallel or workshare construct that contains a
6234 mapping for OVAR. */
6235 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
6237 t
= omp_member_access_dummy_var (var
);
6240 var
= DECL_VALUE_EXPR (var
);
6241 tree o
= maybe_lookup_decl_in_outer_ctx (t
, ctx
);
6243 var
= unshare_and_remap (var
, t
, o
);
6245 var
= unshare_expr (var
);
6248 if (use_pointer_for_field (ovar
, ctx
))
6250 x
= build_sender_ref (ovar
, ctx
);
6251 var
= build_fold_addr_expr (var
);
6252 gimplify_assign (x
, var
, ilist
);
6256 x
= build_sender_ref (ovar
, ctx
);
6257 gimplify_assign (x
, var
, ilist
);
6259 if (!TREE_READONLY (var
)
6260 /* We don't need to receive a new reference to a result
6261 or parm decl. In fact we may not store to it as we will
6262 invalidate any pending RSO and generate wrong gimple
6264 && !((TREE_CODE (var
) == RESULT_DECL
6265 || TREE_CODE (var
) == PARM_DECL
)
6266 && DECL_BY_REFERENCE (var
)))
6268 x
= build_sender_ref (ovar
, ctx
);
6269 gimplify_assign (var
, x
, olist
);
6275 /* Emit an OpenACC head marker call, encapulating the partitioning and
6276 other information that must be processed by the target compiler.
6277 Return the maximum number of dimensions the associated loop might
6278 be partitioned over. */
6281 lower_oacc_head_mark (location_t loc
, tree ddvar
, tree clauses
,
6282 gimple_seq
*seq
, omp_context
*ctx
)
6284 unsigned levels
= 0;
6286 tree gang_static
= NULL_TREE
;
6287 auto_vec
<tree
, 5> args
;
6289 args
.quick_push (build_int_cst
6290 (integer_type_node
, IFN_UNIQUE_OACC_HEAD_MARK
));
6291 args
.quick_push (ddvar
);
6292 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
6294 switch (OMP_CLAUSE_CODE (c
))
6296 case OMP_CLAUSE_GANG
:
6297 tag
|= OLF_DIM_GANG
;
6298 gang_static
= OMP_CLAUSE_GANG_STATIC_EXPR (c
);
6299 /* static:* is represented by -1, and we can ignore it, as
6300 scheduling is always static. */
6301 if (gang_static
&& integer_minus_onep (gang_static
))
6302 gang_static
= NULL_TREE
;
6306 case OMP_CLAUSE_WORKER
:
6307 tag
|= OLF_DIM_WORKER
;
6311 case OMP_CLAUSE_VECTOR
:
6312 tag
|= OLF_DIM_VECTOR
;
6316 case OMP_CLAUSE_SEQ
:
6320 case OMP_CLAUSE_AUTO
:
6324 case OMP_CLAUSE_INDEPENDENT
:
6325 tag
|= OLF_INDEPENDENT
;
6335 if (DECL_P (gang_static
))
6336 gang_static
= build_outer_var_ref (gang_static
, ctx
);
6337 tag
|= OLF_GANG_STATIC
;
6340 /* In a parallel region, loops are implicitly INDEPENDENT. */
6341 omp_context
*tgt
= enclosing_target_ctx (ctx
);
6342 if (!tgt
|| is_oacc_parallel (tgt
))
6343 tag
|= OLF_INDEPENDENT
;
6345 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6346 if (!(tag
& (((GOMP_DIM_MASK (GOMP_DIM_MAX
) - 1) << OLF_DIM_BASE
)
6350 /* Ensure at least one level. */
6354 args
.quick_push (build_int_cst (integer_type_node
, levels
));
6355 args
.quick_push (build_int_cst (integer_type_node
, tag
));
6357 args
.quick_push (gang_static
);
6359 gcall
*call
= gimple_build_call_internal_vec (IFN_UNIQUE
, args
);
6360 gimple_set_location (call
, loc
);
6361 gimple_set_lhs (call
, ddvar
);
6362 gimple_seq_add_stmt (seq
, call
);
6367 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6368 partitioning level of the enclosed region. */
6371 lower_oacc_loop_marker (location_t loc
, tree ddvar
, bool head
,
6372 tree tofollow
, gimple_seq
*seq
)
6374 int marker_kind
= (head
? IFN_UNIQUE_OACC_HEAD_MARK
6375 : IFN_UNIQUE_OACC_TAIL_MARK
);
6376 tree marker
= build_int_cst (integer_type_node
, marker_kind
);
6377 int nargs
= 2 + (tofollow
!= NULL_TREE
);
6378 gcall
*call
= gimple_build_call_internal (IFN_UNIQUE
, nargs
,
6379 marker
, ddvar
, tofollow
);
6380 gimple_set_location (call
, loc
);
6381 gimple_set_lhs (call
, ddvar
);
6382 gimple_seq_add_stmt (seq
, call
);
6385 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6386 the loop clauses, from which we extract reductions. Initialize
6390 lower_oacc_head_tail (location_t loc
, tree clauses
,
6391 gimple_seq
*head
, gimple_seq
*tail
, omp_context
*ctx
)
6394 tree ddvar
= create_tmp_var (integer_type_node
, ".data_dep");
6395 gimple_seq_add_stmt (head
, gimple_build_assign (ddvar
, integer_zero_node
));
6397 unsigned count
= lower_oacc_head_mark (loc
, ddvar
, clauses
, head
, ctx
);
6398 tree fork_kind
= build_int_cst (unsigned_type_node
, IFN_UNIQUE_OACC_FORK
);
6399 tree join_kind
= build_int_cst (unsigned_type_node
, IFN_UNIQUE_OACC_JOIN
);
6402 for (unsigned done
= 1; count
; count
--, done
++)
6404 gimple_seq fork_seq
= NULL
;
6405 gimple_seq join_seq
= NULL
;
6407 tree place
= build_int_cst (integer_type_node
, -1);
6408 gcall
*fork
= gimple_build_call_internal (IFN_UNIQUE
, 3,
6409 fork_kind
, ddvar
, place
);
6410 gimple_set_location (fork
, loc
);
6411 gimple_set_lhs (fork
, ddvar
);
6413 gcall
*join
= gimple_build_call_internal (IFN_UNIQUE
, 3,
6414 join_kind
, ddvar
, place
);
6415 gimple_set_location (join
, loc
);
6416 gimple_set_lhs (join
, ddvar
);
6418 /* Mark the beginning of this level sequence. */
6420 lower_oacc_loop_marker (loc
, ddvar
, true,
6421 build_int_cst (integer_type_node
, count
),
6423 lower_oacc_loop_marker (loc
, ddvar
, false,
6424 build_int_cst (integer_type_node
, done
),
6427 lower_oacc_reductions (loc
, clauses
, place
, inner
,
6428 fork
, join
, &fork_seq
, &join_seq
, ctx
);
6430 /* Append this level to head. */
6431 gimple_seq_add_seq (head
, fork_seq
);
6432 /* Prepend it to tail. */
6433 gimple_seq_add_seq (&join_seq
, *tail
);
6439 /* Mark the end of the sequence. */
6440 lower_oacc_loop_marker (loc
, ddvar
, true, NULL_TREE
, head
);
6441 lower_oacc_loop_marker (loc
, ddvar
, false, NULL_TREE
, tail
);
6444 /* A convenience function to build an empty GIMPLE_COND with just the
6448 gimple_build_cond_empty (tree cond
)
6450 enum tree_code pred_code
;
6453 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
6454 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
6457 /* Return true if a parallel REGION is within a declare target function or
6458 within a target region and is not a part of a gridified target. */
6461 parallel_needs_hsa_kernel_p (struct omp_region
*region
)
6463 bool indirect
= false;
6464 for (region
= region
->outer
; region
; region
= region
->outer
)
6466 if (region
->type
== GIMPLE_OMP_PARALLEL
)
6468 else if (region
->type
== GIMPLE_OMP_TARGET
)
6470 gomp_target
*tgt_stmt
6471 = as_a
<gomp_target
*> (last_stmt (region
->entry
));
6473 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt
),
6474 OMP_CLAUSE__GRIDDIM_
))
6481 if (lookup_attribute ("omp declare target",
6482 DECL_ATTRIBUTES (current_function_decl
)))
6488 static void expand_omp_build_assign (gimple_stmt_iterator
*, tree
, tree
,
6491 /* Build the function calls to GOMP_parallel_start etc to actually
6492 generate the parallel operation. REGION is the parallel region
6493 being expanded. BB is the block where to insert the code. WS_ARGS
6494 will be set if this is a call to a combined parallel+workshare
6495 construct, it contains the list of additional arguments needed by
6496 the workshare construct. */
6499 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
6500 gomp_parallel
*entry_stmt
,
6501 vec
<tree
, va_gc
> *ws_args
)
6503 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
6504 gimple_stmt_iterator gsi
;
6506 enum built_in_function start_ix
;
6508 location_t clause_loc
;
6509 vec
<tree
, va_gc
> *args
;
6511 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
6513 /* Determine what flavor of GOMP_parallel we will be
6515 start_ix
= BUILT_IN_GOMP_PARALLEL
;
6516 if (is_combined_parallel (region
))
6518 switch (region
->inner
->type
)
6520 case GIMPLE_OMP_FOR
:
6521 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
6522 switch (region
->inner
->sched_kind
)
6524 case OMP_CLAUSE_SCHEDULE_RUNTIME
:
6527 case OMP_CLAUSE_SCHEDULE_DYNAMIC
:
6528 case OMP_CLAUSE_SCHEDULE_GUIDED
:
6529 if (region
->inner
->sched_modifiers
6530 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC
)
6532 start_ix2
= 3 + region
->inner
->sched_kind
;
6537 start_ix2
= region
->inner
->sched_kind
;
6540 start_ix2
+= (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
;
6541 start_ix
= (enum built_in_function
) start_ix2
;
6543 case GIMPLE_OMP_SECTIONS
:
6544 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
6551 /* By default, the value of NUM_THREADS is zero (selected at run time)
6552 and there is no conditional. */
6554 val
= build_int_cst (unsigned_type_node
, 0);
6555 flags
= build_int_cst (unsigned_type_node
, 0);
6557 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
6559 cond
= OMP_CLAUSE_IF_EXPR (c
);
6561 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
6564 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
6565 clause_loc
= OMP_CLAUSE_LOCATION (c
);
6568 clause_loc
= gimple_location (entry_stmt
);
6570 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
6572 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
6574 /* Ensure 'val' is of the correct type. */
6575 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
6577 /* If we found the clause 'if (cond)', build either
6578 (cond != 0) or (cond ? val : 1u). */
6581 cond
= gimple_boolify (cond
);
6583 if (integer_zerop (val
))
6584 val
= fold_build2_loc (clause_loc
,
6585 EQ_EXPR
, unsigned_type_node
, cond
,
6586 build_int_cst (TREE_TYPE (cond
), 0));
6589 basic_block cond_bb
, then_bb
, else_bb
;
6590 edge e
, e_then
, e_else
;
6591 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
6593 tmp_var
= create_tmp_var (TREE_TYPE (val
));
6594 if (gimple_in_ssa_p (cfun
))
6596 tmp_then
= make_ssa_name (tmp_var
);
6597 tmp_else
= make_ssa_name (tmp_var
);
6598 tmp_join
= make_ssa_name (tmp_var
);
6607 e
= split_block_after_labels (bb
);
6612 then_bb
= create_empty_bb (cond_bb
);
6613 else_bb
= create_empty_bb (then_bb
);
6614 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
6615 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
6617 stmt
= gimple_build_cond_empty (cond
);
6618 gsi
= gsi_start_bb (cond_bb
);
6619 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
6621 gsi
= gsi_start_bb (then_bb
);
6622 expand_omp_build_assign (&gsi
, tmp_then
, val
, true);
6624 gsi
= gsi_start_bb (else_bb
);
6625 expand_omp_build_assign (&gsi
, tmp_else
,
6626 build_int_cst (unsigned_type_node
, 1),
6629 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
6630 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
6631 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
6632 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
6633 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
6634 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
6636 if (gimple_in_ssa_p (cfun
))
6638 gphi
*phi
= create_phi_node (tmp_join
, bb
);
6639 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
6640 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
6646 gsi
= gsi_start_bb (bb
);
6647 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
6648 false, GSI_CONTINUE_LINKING
);
6651 gsi
= gsi_last_bb (bb
);
6652 t
= gimple_omp_parallel_data_arg (entry_stmt
);
6654 t1
= null_pointer_node
;
6656 t1
= build_fold_addr_expr (t
);
6657 tree child_fndecl
= gimple_omp_parallel_child_fn (entry_stmt
);
6658 t2
= build_fold_addr_expr (child_fndecl
);
6660 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
6661 args
->quick_push (t2
);
6662 args
->quick_push (t1
);
6663 args
->quick_push (val
);
6665 args
->splice (*ws_args
);
6666 args
->quick_push (flags
);
6668 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
6669 builtin_decl_explicit (start_ix
), args
);
6671 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6672 false, GSI_CONTINUE_LINKING
);
6674 if (hsa_gen_requested_p ()
6675 && parallel_needs_hsa_kernel_p (region
))
6677 cgraph_node
*child_cnode
= cgraph_node::get (child_fndecl
);
6678 hsa_register_kernel (child_cnode
);
6682 /* Insert a function call whose name is FUNC_NAME with the information from
6683 ENTRY_STMT into the basic_block BB. */
6686 expand_cilk_for_call (basic_block bb
, gomp_parallel
*entry_stmt
,
6687 vec
<tree
, va_gc
> *ws_args
)
6690 gimple_stmt_iterator gsi
;
6691 vec
<tree
, va_gc
> *args
;
6693 gcc_assert (vec_safe_length (ws_args
) == 2);
6694 tree func_name
= (*ws_args
)[0];
6695 tree grain
= (*ws_args
)[1];
6697 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
6698 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
6699 gcc_assert (count
!= NULL_TREE
);
6700 count
= OMP_CLAUSE_OPERAND (count
, 0);
6702 gsi
= gsi_last_bb (bb
);
6703 t
= gimple_omp_parallel_data_arg (entry_stmt
);
6705 t1
= null_pointer_node
;
6707 t1
= build_fold_addr_expr (t
);
6708 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
6710 vec_alloc (args
, 4);
6711 args
->quick_push (t2
);
6712 args
->quick_push (t1
);
6713 args
->quick_push (count
);
6714 args
->quick_push (grain
);
6715 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
6717 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
6718 GSI_CONTINUE_LINKING
);
6721 /* Build the function call to GOMP_task to actually
6722 generate the task operation. BB is the block where to insert the code. */
6725 expand_task_call (struct omp_region
*region
, basic_block bb
,
6726 gomp_task
*entry_stmt
)
6729 gimple_stmt_iterator gsi
;
6730 location_t loc
= gimple_location (entry_stmt
);
6732 tree clauses
= gimple_omp_task_clauses (entry_stmt
);
6734 tree ifc
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
6735 tree untied
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
6736 tree mergeable
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
6737 tree depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
6738 tree finalc
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
6739 tree priority
= find_omp_clause (clauses
, OMP_CLAUSE_PRIORITY
);
6742 = (untied
? GOMP_TASK_FLAG_UNTIED
: 0)
6743 | (mergeable
? GOMP_TASK_FLAG_MERGEABLE
: 0)
6744 | (depend
? GOMP_TASK_FLAG_DEPEND
: 0);
6746 bool taskloop_p
= gimple_omp_task_taskloop_p (entry_stmt
);
6747 tree startvar
= NULL_TREE
, endvar
= NULL_TREE
, step
= NULL_TREE
;
6748 tree num_tasks
= NULL_TREE
;
6752 gimple
*g
= last_stmt (region
->outer
->entry
);
6753 gcc_assert (gimple_code (g
) == GIMPLE_OMP_FOR
6754 && gimple_omp_for_kind (g
) == GF_OMP_FOR_KIND_TASKLOOP
);
6755 struct omp_for_data fd
;
6756 extract_omp_for_data (as_a
<gomp_for
*> (g
), &fd
, NULL
);
6757 startvar
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6758 endvar
= find_omp_clause (OMP_CLAUSE_CHAIN (startvar
),
6759 OMP_CLAUSE__LOOPTEMP_
);
6760 startvar
= OMP_CLAUSE_DECL (startvar
);
6761 endvar
= OMP_CLAUSE_DECL (endvar
);
6762 step
= fold_convert_loc (loc
, fd
.iter_type
, fd
.loop
.step
);
6763 if (fd
.loop
.cond_code
== LT_EXPR
)
6764 iflags
|= GOMP_TASK_FLAG_UP
;
6765 tree tclauses
= gimple_omp_for_clauses (g
);
6766 num_tasks
= find_omp_clause (tclauses
, OMP_CLAUSE_NUM_TASKS
);
6768 num_tasks
= OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks
);
6771 num_tasks
= find_omp_clause (tclauses
, OMP_CLAUSE_GRAINSIZE
);
6774 iflags
|= GOMP_TASK_FLAG_GRAINSIZE
;
6775 num_tasks
= OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks
);
6778 num_tasks
= integer_zero_node
;
6780 num_tasks
= fold_convert_loc (loc
, long_integer_type_node
, num_tasks
);
6781 if (ifc
== NULL_TREE
)
6782 iflags
|= GOMP_TASK_FLAG_IF
;
6783 if (find_omp_clause (tclauses
, OMP_CLAUSE_NOGROUP
))
6784 iflags
|= GOMP_TASK_FLAG_NOGROUP
;
6785 ull
= fd
.iter_type
== long_long_unsigned_type_node
;
6788 iflags
|= GOMP_TASK_FLAG_PRIORITY
;
6790 tree flags
= build_int_cst (unsigned_type_node
, iflags
);
6792 tree cond
= boolean_true_node
;
6797 tree t
= gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc
));
6798 t
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, t
,
6799 build_int_cst (unsigned_type_node
,
6801 build_int_cst (unsigned_type_node
, 0));
6802 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
,
6806 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc
));
6811 tree t
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc
));
6812 t
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, t
,
6813 build_int_cst (unsigned_type_node
,
6814 GOMP_TASK_FLAG_FINAL
),
6815 build_int_cst (unsigned_type_node
, 0));
6816 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, t
);
6819 depend
= OMP_CLAUSE_DECL (depend
);
6821 depend
= build_int_cst (ptr_type_node
, 0);
6823 priority
= fold_convert (integer_type_node
,
6824 OMP_CLAUSE_PRIORITY_EXPR (priority
));
6826 priority
= integer_zero_node
;
6828 gsi
= gsi_last_bb (bb
);
6829 tree t
= gimple_omp_task_data_arg (entry_stmt
);
6831 t2
= null_pointer_node
;
6833 t2
= build_fold_addr_expr_loc (loc
, t
);
6834 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
6835 t
= gimple_omp_task_copy_fn (entry_stmt
);
6837 t3
= null_pointer_node
;
6839 t3
= build_fold_addr_expr_loc (loc
, t
);
6842 t
= build_call_expr (ull
6843 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL
)
6844 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP
),
6846 gimple_omp_task_arg_size (entry_stmt
),
6847 gimple_omp_task_arg_align (entry_stmt
), flags
,
6848 num_tasks
, priority
, startvar
, endvar
, step
);
6850 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
6852 gimple_omp_task_arg_size (entry_stmt
),
6853 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
6856 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6857 false, GSI_CONTINUE_LINKING
);
6861 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6862 catch handler and return it. This prevents programs from violating the
6863 structured block semantics with throws. */
6866 maybe_catch_exception (gimple_seq body
)
6871 if (!flag_exceptions
)
6874 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
6875 decl
= lang_hooks
.eh_protect_cleanup_actions ();
6877 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
6879 g
= gimple_build_eh_must_not_throw (decl
);
6880 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
6883 return gimple_seq_alloc_with_stmt (g
);
6886 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6889 vec2chain (vec
<tree
, va_gc
> *v
)
6891 tree chain
= NULL_TREE
, t
;
6894 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
6896 DECL_CHAIN (t
) = chain
;
6904 /* Remove barriers in REGION->EXIT's block. Note that this is only
6905 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6906 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6907 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6911 remove_exit_barrier (struct omp_region
*region
)
6913 gimple_stmt_iterator gsi
;
6914 basic_block exit_bb
;
6918 int any_addressable_vars
= -1;
6920 exit_bb
= region
->exit
;
6922 /* If the parallel region doesn't return, we don't have REGION->EXIT
6927 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6928 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6929 statements that can appear in between are extremely limited -- no
6930 memory operations at all. Here, we allow nothing at all, so the
6931 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6932 gsi
= gsi_last_bb (exit_bb
);
6933 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
6935 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
6938 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
6940 gsi
= gsi_last_bb (e
->src
);
6941 if (gsi_end_p (gsi
))
6943 stmt
= gsi_stmt (gsi
);
6944 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
6945 && !gimple_omp_return_nowait_p (stmt
))
6947 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6948 in many cases. If there could be tasks queued, the barrier
6949 might be needed to let the tasks run before some local
6950 variable of the parallel that the task uses as shared
6951 runs out of scope. The task can be spawned either
6952 from within current function (this would be easy to check)
6953 or from some function it calls and gets passed an address
6954 of such a variable. */
6955 if (any_addressable_vars
< 0)
6957 gomp_parallel
*parallel_stmt
6958 = as_a
<gomp_parallel
*> (last_stmt (region
->entry
));
6959 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
6960 tree local_decls
, block
, decl
;
6963 any_addressable_vars
= 0;
6964 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
6965 if (TREE_ADDRESSABLE (decl
))
6967 any_addressable_vars
= 1;
6970 for (block
= gimple_block (stmt
);
6971 !any_addressable_vars
6973 && TREE_CODE (block
) == BLOCK
;
6974 block
= BLOCK_SUPERCONTEXT (block
))
6976 for (local_decls
= BLOCK_VARS (block
);
6978 local_decls
= DECL_CHAIN (local_decls
))
6979 if (TREE_ADDRESSABLE (local_decls
))
6981 any_addressable_vars
= 1;
6984 if (block
== gimple_block (parallel_stmt
))
6988 if (!any_addressable_vars
)
6989 gimple_omp_return_set_nowait (stmt
);
6995 remove_exit_barriers (struct omp_region
*region
)
6997 if (region
->type
== GIMPLE_OMP_PARALLEL
)
6998 remove_exit_barrier (region
);
7002 region
= region
->inner
;
7003 remove_exit_barriers (region
);
7004 while (region
->next
)
7006 region
= region
->next
;
7007 remove_exit_barriers (region
);
7012 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7013 calls. These can't be declared as const functions, but
7014 within one parallel body they are constant, so they can be
7015 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7016 which are declared const. Similarly for task body, except
7017 that in untied task omp_get_thread_num () can change at any task
7018 scheduling point. */
7021 optimize_omp_library_calls (gimple
*entry_stmt
)
7024 gimple_stmt_iterator gsi
;
7025 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
7026 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
7027 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
7028 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
7029 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
7030 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
7031 OMP_CLAUSE_UNTIED
) != NULL
);
7033 FOR_EACH_BB_FN (bb
, cfun
)
7034 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
7036 gimple
*call
= gsi_stmt (gsi
);
7039 if (is_gimple_call (call
)
7040 && (decl
= gimple_call_fndecl (call
))
7041 && DECL_EXTERNAL (decl
)
7042 && TREE_PUBLIC (decl
)
7043 && DECL_INITIAL (decl
) == NULL
)
7047 if (DECL_NAME (decl
) == thr_num_id
)
7049 /* In #pragma omp task untied omp_get_thread_num () can change
7050 during the execution of the task region. */
7053 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
7055 else if (DECL_NAME (decl
) == num_thr_id
)
7056 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
7060 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
7061 || gimple_call_num_args (call
) != 0)
7064 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
7067 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
7068 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
7069 TREE_TYPE (TREE_TYPE (built_in
))))
7072 gimple_call_set_fndecl (call
, built_in
);
7077 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7081 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
7085 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7086 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
7089 if (TREE_CODE (t
) == ADDR_EXPR
)
7090 recompute_tree_invariant_for_addr_expr (t
);
7092 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
7096 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7099 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
,
7102 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
7103 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
7104 !after
, after
? GSI_CONTINUE_LINKING
7106 gimple
*stmt
= gimple_build_assign (to
, from
);
7108 gsi_insert_after (gsi_p
, stmt
, GSI_CONTINUE_LINKING
);
7110 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
7111 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
7112 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
7114 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
7115 gimple_regimplify_operands (stmt
, &gsi
);
7119 /* Expand the OpenMP parallel or task directive starting at REGION. */
7122 expand_omp_taskreg (struct omp_region
*region
)
7124 basic_block entry_bb
, exit_bb
, new_bb
;
7125 struct function
*child_cfun
;
7126 tree child_fn
, block
, t
;
7127 gimple_stmt_iterator gsi
;
7128 gimple
*entry_stmt
, *stmt
;
7130 vec
<tree
, va_gc
> *ws_args
;
7132 entry_stmt
= last_stmt (region
->entry
);
7133 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
7134 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
7136 entry_bb
= region
->entry
;
7137 if (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
)
7138 exit_bb
= region
->cont
;
7140 exit_bb
= region
->exit
;
7144 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
7145 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
7146 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
7149 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7150 and the inner statement contains the name of the built-in function
7152 ws_args
= region
->inner
->ws_args
;
7153 else if (is_combined_parallel (region
))
7154 ws_args
= region
->ws_args
;
7158 if (child_cfun
->cfg
)
7160 /* Due to inlining, it may happen that we have already outlined
7161 the region, in which case all we need to do is make the
7162 sub-graph unreachable and emit the parallel call. */
7163 edge entry_succ_e
, exit_succ_e
;
7165 entry_succ_e
= single_succ_edge (entry_bb
);
7167 gsi
= gsi_last_bb (entry_bb
);
7168 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
7169 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
7170 gsi_remove (&gsi
, true);
7175 exit_succ_e
= single_succ_edge (exit_bb
);
7176 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
7178 remove_edge_and_dominated_blocks (entry_succ_e
);
7182 unsigned srcidx
, dstidx
, num
;
7184 /* If the parallel region needs data sent from the parent
7185 function, then the very first statement (except possible
7186 tree profile counter updates) of the parallel body
7187 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7188 &.OMP_DATA_O is passed as an argument to the child function,
7189 we need to replace it with the argument as seen by the child
7192 In most cases, this will end up being the identity assignment
7193 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7194 a function call that has been inlined, the original PARM_DECL
7195 .OMP_DATA_I may have been converted into a different local
7196 variable. In which case, we need to keep the assignment. */
7197 if (gimple_omp_taskreg_data_arg (entry_stmt
))
7199 basic_block entry_succ_bb
7200 = single_succ_p (entry_bb
) ? single_succ (entry_bb
)
7201 : FALLTHRU_EDGE (entry_bb
)->dest
;
7203 gimple
*parcopy_stmt
= NULL
;
7205 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
7209 gcc_assert (!gsi_end_p (gsi
));
7210 stmt
= gsi_stmt (gsi
);
7211 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
7214 if (gimple_num_ops (stmt
) == 2)
7216 tree arg
= gimple_assign_rhs1 (stmt
);
7218 /* We're ignore the subcode because we're
7219 effectively doing a STRIP_NOPS. */
7221 if (TREE_CODE (arg
) == ADDR_EXPR
7222 && TREE_OPERAND (arg
, 0)
7223 == gimple_omp_taskreg_data_arg (entry_stmt
))
7225 parcopy_stmt
= stmt
;
7231 gcc_assert (parcopy_stmt
!= NULL
);
7232 arg
= DECL_ARGUMENTS (child_fn
);
7234 if (!gimple_in_ssa_p (cfun
))
7236 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
7237 gsi_remove (&gsi
, true);
7240 /* ?? Is setting the subcode really necessary ?? */
7241 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
7242 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
7247 tree lhs
= gimple_assign_lhs (parcopy_stmt
);
7248 gcc_assert (SSA_NAME_VAR (lhs
) == arg
);
7249 /* We'd like to set the rhs to the default def in the child_fn,
7250 but it's too early to create ssa names in the child_fn.
7251 Instead, we set the rhs to the parm. In
7252 move_sese_region_to_fn, we introduce a default def for the
7253 parm, map the parm to it's default def, and once we encounter
7254 this stmt, replace the parm with the default def. */
7255 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
7256 update_stmt (parcopy_stmt
);
7260 /* Declare local variables needed in CHILD_CFUN. */
7261 block
= DECL_INITIAL (child_fn
);
7262 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
7263 /* The gimplifier could record temporaries in parallel/task block
7264 rather than in containing function's local_decls chain,
7265 which would mean cgraph missed finalizing them. Do it now. */
7266 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
7267 if (TREE_CODE (t
) == VAR_DECL
7269 && !DECL_EXTERNAL (t
))
7270 varpool_node::finalize_decl (t
);
7271 DECL_SAVED_TREE (child_fn
) = NULL
;
7272 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7273 gimple_set_body (child_fn
, NULL
);
7274 TREE_USED (block
) = 1;
7276 /* Reset DECL_CONTEXT on function arguments. */
7277 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
7278 DECL_CONTEXT (t
) = child_fn
;
7280 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7281 so that it can be moved to the child function. */
7282 gsi
= gsi_last_bb (entry_bb
);
7283 stmt
= gsi_stmt (gsi
);
7284 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
7285 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
7286 e
= split_block (entry_bb
, stmt
);
7287 gsi_remove (&gsi
, true);
7290 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
7291 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7294 e2
= make_edge (e
->src
, BRANCH_EDGE (entry_bb
)->dest
, EDGE_ABNORMAL
);
7295 gcc_assert (e2
->dest
== region
->exit
);
7296 remove_edge (BRANCH_EDGE (entry_bb
));
7297 set_immediate_dominator (CDI_DOMINATORS
, e2
->dest
, e
->src
);
7298 gsi
= gsi_last_bb (region
->exit
);
7299 gcc_assert (!gsi_end_p (gsi
)
7300 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
7301 gsi_remove (&gsi
, true);
7304 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7307 gsi
= gsi_last_bb (exit_bb
);
7308 gcc_assert (!gsi_end_p (gsi
)
7309 && (gimple_code (gsi_stmt (gsi
))
7310 == (e2
? GIMPLE_OMP_CONTINUE
: GIMPLE_OMP_RETURN
)));
7311 stmt
= gimple_build_return (NULL
);
7312 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
7313 gsi_remove (&gsi
, true);
7316 /* Move the parallel region into CHILD_CFUN. */
7318 if (gimple_in_ssa_p (cfun
))
7320 init_tree_ssa (child_cfun
);
7321 init_ssa_operands (child_cfun
);
7322 child_cfun
->gimple_df
->in_ssa_p
= true;
7326 block
= gimple_block (entry_stmt
);
7328 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
7330 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
7333 basic_block dest_bb
= e2
->dest
;
7335 make_edge (new_bb
, dest_bb
, EDGE_FALLTHRU
);
7337 set_immediate_dominator (CDI_DOMINATORS
, dest_bb
, new_bb
);
7339 /* When the OMP expansion process cannot guarantee an up-to-date
7340 loop tree arrange for the child function to fixup loops. */
7341 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
7342 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
7344 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7345 num
= vec_safe_length (child_cfun
->local_decls
);
7346 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
7348 t
= (*child_cfun
->local_decls
)[srcidx
];
7349 if (DECL_CONTEXT (t
) == cfun
->decl
)
7351 if (srcidx
!= dstidx
)
7352 (*child_cfun
->local_decls
)[dstidx
] = t
;
7356 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
7358 /* Inform the callgraph about the new function. */
7359 child_cfun
->curr_properties
= cfun
->curr_properties
;
7360 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
7361 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
7362 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
7363 node
->parallelized_function
= 1;
7364 cgraph_node::add_new_function (child_fn
, true);
7366 bool need_asm
= DECL_ASSEMBLER_NAME_SET_P (current_function_decl
)
7367 && !DECL_ASSEMBLER_NAME_SET_P (child_fn
);
7369 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7370 fixed in a following pass. */
7371 push_cfun (child_cfun
);
7373 assign_assembler_name_if_neeeded (child_fn
);
7376 optimize_omp_library_calls (entry_stmt
);
7377 cgraph_edge::rebuild_edges ();
7379 /* Some EH regions might become dead, see PR34608. If
7380 pass_cleanup_cfg isn't the first pass to happen with the
7381 new child, these dead EH edges might cause problems.
7382 Clean them up now. */
7383 if (flag_exceptions
)
7386 bool changed
= false;
7388 FOR_EACH_BB_FN (bb
, cfun
)
7389 changed
|= gimple_purge_dead_eh_edges (bb
);
7391 cleanup_tree_cfg ();
7393 if (gimple_in_ssa_p (cfun
))
7394 update_ssa (TODO_update_ssa
);
7395 if (flag_checking
&& !loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
7396 verify_loop_structure ();
7399 if (dump_file
&& !gimple_in_ssa_p (cfun
))
7401 omp_any_child_fn_dumped
= true;
7402 dump_function_header (dump_file
, child_fn
, dump_flags
);
7403 dump_function_to_file (child_fn
, dump_file
, dump_flags
);
7407 /* Emit a library call to launch the children threads. */
7409 expand_cilk_for_call (new_bb
,
7410 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
7411 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
7412 expand_parallel_call (region
, new_bb
,
7413 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
7415 expand_task_call (region
, new_bb
, as_a
<gomp_task
*> (entry_stmt
));
7416 if (gimple_in_ssa_p (cfun
))
7417 update_ssa (TODO_update_ssa_only_virtuals
);
7420 /* Information about members of an OpenACC collapsed loop nest. */
7422 struct oacc_collapse
7424 tree base
; /* Base value. */
7425 tree iters
; /* Number of steps. */
7426 tree step
; /* step size. */
7429 /* Helper for expand_oacc_for. Determine collapsed loop information.
7430 Fill in COUNTS array. Emit any initialization code before GSI.
7431 Return the calculated outer loop bound of BOUND_TYPE. */
7434 expand_oacc_collapse_init (const struct omp_for_data
*fd
,
7435 gimple_stmt_iterator
*gsi
,
7436 oacc_collapse
*counts
, tree bound_type
)
7438 tree total
= build_int_cst (bound_type
, 1);
7441 gcc_assert (integer_onep (fd
->loop
.step
));
7442 gcc_assert (integer_zerop (fd
->loop
.n1
));
7444 for (ix
= 0; ix
!= fd
->collapse
; ix
++)
7446 const omp_for_data_loop
*loop
= &fd
->loops
[ix
];
7448 tree iter_type
= TREE_TYPE (loop
->v
);
7449 tree diff_type
= iter_type
;
7450 tree plus_type
= iter_type
;
7452 gcc_assert (loop
->cond_code
== fd
->loop
.cond_code
);
7454 if (POINTER_TYPE_P (iter_type
))
7455 plus_type
= sizetype
;
7456 if (POINTER_TYPE_P (diff_type
) || TYPE_UNSIGNED (diff_type
))
7457 diff_type
= signed_type_for (diff_type
);
7461 tree s
= loop
->step
;
7462 bool up
= loop
->cond_code
== LT_EXPR
;
7463 tree dir
= build_int_cst (diff_type
, up
? +1 : -1);
7467 b
= force_gimple_operand_gsi (gsi
, b
, true, NULL_TREE
,
7468 true, GSI_SAME_STMT
);
7469 e
= force_gimple_operand_gsi (gsi
, e
, true, NULL_TREE
,
7470 true, GSI_SAME_STMT
);
7472 /* Convert the step, avoiding possible unsigned->signed overflow. */
7473 negating
= !up
&& TYPE_UNSIGNED (TREE_TYPE (s
));
7475 s
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (s
), s
);
7476 s
= fold_convert (diff_type
, s
);
7478 s
= fold_build1 (NEGATE_EXPR
, diff_type
, s
);
7479 s
= force_gimple_operand_gsi (gsi
, s
, true, NULL_TREE
,
7480 true, GSI_SAME_STMT
);
7482 /* Determine the range, avoiding possible unsigned->signed overflow. */
7483 negating
= !up
&& TYPE_UNSIGNED (iter_type
);
7484 expr
= fold_build2 (MINUS_EXPR
, plus_type
,
7485 fold_convert (plus_type
, negating
? b
: e
),
7486 fold_convert (plus_type
, negating
? e
: b
));
7487 expr
= fold_convert (diff_type
, expr
);
7489 expr
= fold_build1 (NEGATE_EXPR
, diff_type
, expr
);
7490 tree range
= force_gimple_operand_gsi
7491 (gsi
, expr
, true, NULL_TREE
, true, GSI_SAME_STMT
);
7493 /* Determine number of iterations. */
7494 expr
= fold_build2 (MINUS_EXPR
, diff_type
, range
, dir
);
7495 expr
= fold_build2 (PLUS_EXPR
, diff_type
, expr
, s
);
7496 expr
= fold_build2 (TRUNC_DIV_EXPR
, diff_type
, expr
, s
);
7498 tree iters
= force_gimple_operand_gsi (gsi
, expr
, true, NULL_TREE
,
7499 true, GSI_SAME_STMT
);
7501 counts
[ix
].base
= b
;
7502 counts
[ix
].iters
= iters
;
7503 counts
[ix
].step
= s
;
7505 total
= fold_build2 (MULT_EXPR
, bound_type
, total
,
7506 fold_convert (bound_type
, iters
));
7512 /* Emit initializers for collapsed loop members. IVAR is the outer
7513 loop iteration variable, from which collapsed loop iteration values
7514 are calculated. COUNTS array has been initialized by
7515 expand_oacc_collapse_inits. */
7518 expand_oacc_collapse_vars (const struct omp_for_data
*fd
,
7519 gimple_stmt_iterator
*gsi
,
7520 const oacc_collapse
*counts
, tree ivar
)
7522 tree ivar_type
= TREE_TYPE (ivar
);
7524 /* The most rapidly changing iteration variable is the innermost
7526 for (int ix
= fd
->collapse
; ix
--;)
7528 const omp_for_data_loop
*loop
= &fd
->loops
[ix
];
7529 const oacc_collapse
*collapse
= &counts
[ix
];
7530 tree iter_type
= TREE_TYPE (loop
->v
);
7531 tree diff_type
= TREE_TYPE (collapse
->step
);
7532 tree plus_type
= iter_type
;
7533 enum tree_code plus_code
= PLUS_EXPR
;
7536 if (POINTER_TYPE_P (iter_type
))
7538 plus_code
= POINTER_PLUS_EXPR
;
7539 plus_type
= sizetype
;
7542 expr
= fold_build2 (TRUNC_MOD_EXPR
, ivar_type
, ivar
,
7543 fold_convert (ivar_type
, collapse
->iters
));
7544 expr
= fold_build2 (MULT_EXPR
, diff_type
, fold_convert (diff_type
, expr
),
7546 expr
= fold_build2 (plus_code
, iter_type
, collapse
->base
,
7547 fold_convert (plus_type
, expr
));
7548 expr
= force_gimple_operand_gsi (gsi
, expr
, false, NULL_TREE
,
7549 true, GSI_SAME_STMT
);
7550 gassign
*ass
= gimple_build_assign (loop
->v
, expr
);
7551 gsi_insert_before (gsi
, ass
, GSI_SAME_STMT
);
7555 expr
= fold_build2 (TRUNC_DIV_EXPR
, ivar_type
, ivar
,
7556 fold_convert (ivar_type
, collapse
->iters
));
7557 ivar
= force_gimple_operand_gsi (gsi
, expr
, true, NULL_TREE
,
7558 true, GSI_SAME_STMT
);
7564 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7565 of the combined collapse > 1 loop constructs, generate code like:
7566 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7571 count3 = (adj + N32 - N31) / STEP3;
7572 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7577 count2 = (adj + N22 - N21) / STEP2;
7578 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7583 count1 = (adj + N12 - N11) / STEP1;
7584 count = count1 * count2 * count3;
7585 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7587 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7588 of the combined loop constructs, just initialize COUNTS array
7589 from the _looptemp_ clauses. */
7591 /* NOTE: It *could* be better to moosh all of the BBs together,
7592 creating one larger BB with all the computation and the unexpected
7593 jump at the end. I.e.
7595 bool zero3, zero2, zero1, zero;
7598 count3 = (N32 - N31) /[cl] STEP3;
7600 count2 = (N22 - N21) /[cl] STEP2;
7602 count1 = (N12 - N11) /[cl] STEP1;
7603 zero = zero3 || zero2 || zero1;
7604 count = count1 * count2 * count3;
7605 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7607 After all, we expect the zero=false, and thus we expect to have to
7608 evaluate all of the comparison expressions, so short-circuiting
7609 oughtn't be a win. Since the condition isn't protecting a
7610 denominator, we're not concerned about divide-by-zero, so we can
7611 fully evaluate count even if a numerator turned out to be wrong.
7613 It seems like putting this all together would create much better
7614 scheduling opportunities, and less pressure on the chip's branch
7618 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
7619 basic_block
&entry_bb
, tree
*counts
,
7620 basic_block
&zero_iter1_bb
, int &first_zero_iter1
,
7621 basic_block
&zero_iter2_bb
, int &first_zero_iter2
,
7622 basic_block
&l2_dom_bb
)
7624 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
7628 /* Collapsed loops need work for expansion into SSA form. */
7629 gcc_assert (!gimple_in_ssa_p (cfun
));
7631 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
7632 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
7634 gcc_assert (fd
->ordered
== 0);
7635 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7636 isn't supposed to be handled, as the inner loop doesn't
7638 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7639 OMP_CLAUSE__LOOPTEMP_
);
7640 gcc_assert (innerc
);
7641 for (i
= 0; i
< fd
->collapse
; i
++)
7643 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7644 OMP_CLAUSE__LOOPTEMP_
);
7645 gcc_assert (innerc
);
7647 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
7649 counts
[0] = NULL_TREE
;
7654 for (i
= fd
->collapse
; i
< fd
->ordered
; i
++)
7656 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7657 counts
[i
] = NULL_TREE
;
7658 t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
7659 fold_convert (itype
, fd
->loops
[i
].n1
),
7660 fold_convert (itype
, fd
->loops
[i
].n2
));
7661 if (t
&& integer_zerop (t
))
7663 for (i
= fd
->collapse
; i
< fd
->ordered
; i
++)
7664 counts
[i
] = build_int_cst (type
, 0);
7668 for (i
= 0; i
< (fd
->ordered
? fd
->ordered
: fd
->collapse
); i
++)
7670 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7672 if (i
>= fd
->collapse
&& counts
[i
])
7674 if ((SSA_VAR_P (fd
->loop
.n2
) || i
>= fd
->collapse
)
7675 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
7676 fold_convert (itype
, fd
->loops
[i
].n1
),
7677 fold_convert (itype
, fd
->loops
[i
].n2
)))
7678 == NULL_TREE
|| !integer_onep (t
)))
7682 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
7683 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
7684 true, GSI_SAME_STMT
);
7685 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
7686 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
7687 true, GSI_SAME_STMT
);
7688 cond_stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
7689 NULL_TREE
, NULL_TREE
);
7690 gsi_insert_before (gsi
, cond_stmt
, GSI_SAME_STMT
);
7691 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
7692 expand_omp_regimplify_p
, NULL
, NULL
)
7693 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
7694 expand_omp_regimplify_p
, NULL
, NULL
))
7696 *gsi
= gsi_for_stmt (cond_stmt
);
7697 gimple_regimplify_operands (cond_stmt
, gsi
);
7699 e
= split_block (entry_bb
, cond_stmt
);
7700 basic_block
&zero_iter_bb
7701 = i
< fd
->collapse
? zero_iter1_bb
: zero_iter2_bb
;
7702 int &first_zero_iter
7703 = i
< fd
->collapse
? first_zero_iter1
: first_zero_iter2
;
7704 if (zero_iter_bb
== NULL
)
7706 gassign
*assign_stmt
;
7707 first_zero_iter
= i
;
7708 zero_iter_bb
= create_empty_bb (entry_bb
);
7709 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
7710 *gsi
= gsi_after_labels (zero_iter_bb
);
7711 if (i
< fd
->collapse
)
7712 assign_stmt
= gimple_build_assign (fd
->loop
.n2
,
7713 build_zero_cst (type
));
7716 counts
[i
] = create_tmp_reg (type
, ".count");
7718 = gimple_build_assign (counts
[i
], build_zero_cst (type
));
7720 gsi_insert_before (gsi
, assign_stmt
, GSI_SAME_STMT
);
7721 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
7724 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
7725 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
7726 e
->flags
= EDGE_TRUE_VALUE
;
7727 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
7728 if (l2_dom_bb
== NULL
)
7729 l2_dom_bb
= entry_bb
;
7731 *gsi
= gsi_last_bb (entry_bb
);
7734 if (POINTER_TYPE_P (itype
))
7735 itype
= signed_type_for (itype
);
7736 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
7738 t
= fold_build2 (PLUS_EXPR
, itype
,
7739 fold_convert (itype
, fd
->loops
[i
].step
), t
);
7740 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
7741 fold_convert (itype
, fd
->loops
[i
].n2
));
7742 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
7743 fold_convert (itype
, fd
->loops
[i
].n1
));
7744 /* ?? We could probably use CEIL_DIV_EXPR instead of
7745 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7746 generate the same code in the end because generically we
7747 don't know that the values involved must be negative for
7749 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
7750 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
7751 fold_build1 (NEGATE_EXPR
, itype
, t
),
7752 fold_build1 (NEGATE_EXPR
, itype
,
7753 fold_convert (itype
,
7754 fd
->loops
[i
].step
)));
7756 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
7757 fold_convert (itype
, fd
->loops
[i
].step
));
7758 t
= fold_convert (type
, t
);
7759 if (TREE_CODE (t
) == INTEGER_CST
)
7763 if (i
< fd
->collapse
|| i
!= first_zero_iter2
)
7764 counts
[i
] = create_tmp_reg (type
, ".count");
7765 expand_omp_build_assign (gsi
, counts
[i
], t
);
7767 if (SSA_VAR_P (fd
->loop
.n2
) && i
< fd
->collapse
)
7772 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
7773 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
7779 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7781 V3 = N31 + (T % count3) * STEP3;
7783 V2 = N21 + (T % count2) * STEP2;
7785 V1 = N11 + T * STEP1;
7786 if this loop doesn't have an inner loop construct combined with it.
7787 If it does have an inner loop construct combined with it and the
7788 iteration count isn't known constant, store values from counts array
7789 into its _looptemp_ temporaries instead. */
7792 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
7793 tree
*counts
, gimple
*inner_stmt
, tree startvar
)
7796 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7798 /* If fd->loop.n2 is constant, then no propagation of the counts
7799 is needed, they are constant. */
7800 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
7803 tree clauses
= gimple_code (inner_stmt
) != GIMPLE_OMP_FOR
7804 ? gimple_omp_taskreg_clauses (inner_stmt
)
7805 : gimple_omp_for_clauses (inner_stmt
);
7806 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7807 isn't supposed to be handled, as the inner loop doesn't
7809 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
7810 gcc_assert (innerc
);
7811 for (i
= 0; i
< fd
->collapse
; i
++)
7813 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7814 OMP_CLAUSE__LOOPTEMP_
);
7815 gcc_assert (innerc
);
7818 tree tem
= OMP_CLAUSE_DECL (innerc
);
7819 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
7820 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
7821 false, GSI_CONTINUE_LINKING
);
7822 gassign
*stmt
= gimple_build_assign (tem
, t
);
7823 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
7829 tree type
= TREE_TYPE (fd
->loop
.v
);
7830 tree tem
= create_tmp_reg (type
, ".tem");
7831 gassign
*stmt
= gimple_build_assign (tem
, startvar
);
7832 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
7834 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
7836 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
7838 if (POINTER_TYPE_P (vtype
))
7839 itype
= signed_type_for (vtype
);
7841 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
7844 t
= fold_convert (itype
, t
);
7845 t
= fold_build2 (MULT_EXPR
, itype
, t
,
7846 fold_convert (itype
, fd
->loops
[i
].step
));
7847 if (POINTER_TYPE_P (vtype
))
7848 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
7850 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
7851 t
= force_gimple_operand_gsi (gsi
, t
,
7852 DECL_P (fd
->loops
[i
].v
)
7853 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
7855 GSI_CONTINUE_LINKING
);
7856 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
7857 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
7860 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
7861 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
7862 false, GSI_CONTINUE_LINKING
);
7863 stmt
= gimple_build_assign (tem
, t
);
7864 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
7870 /* Helper function for expand_omp_for_*. Generate code like:
7873 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7877 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7884 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
7885 basic_block body_bb
)
7887 basic_block last_bb
, bb
, collapse_bb
= NULL
;
7889 gimple_stmt_iterator gsi
;
7895 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
7897 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
7899 bb
= create_empty_bb (last_bb
);
7900 add_bb_to_loop (bb
, last_bb
->loop_father
);
7901 gsi
= gsi_start_bb (bb
);
7903 if (i
< fd
->collapse
- 1)
7905 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
7906 e
->probability
= REG_BR_PROB_BASE
/ 8;
7908 t
= fd
->loops
[i
+ 1].n1
;
7909 t
= force_gimple_operand_gsi (&gsi
, t
,
7910 DECL_P (fd
->loops
[i
+ 1].v
)
7911 && TREE_ADDRESSABLE (fd
->loops
[i
7914 GSI_CONTINUE_LINKING
);
7915 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
7916 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7921 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
7923 if (POINTER_TYPE_P (vtype
))
7924 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
7926 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
7927 t
= force_gimple_operand_gsi (&gsi
, t
,
7928 DECL_P (fd
->loops
[i
].v
)
7929 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
7930 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
7931 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
7932 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7936 t
= fd
->loops
[i
].n2
;
7937 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7938 false, GSI_CONTINUE_LINKING
);
7939 tree v
= fd
->loops
[i
].v
;
7940 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
7941 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
7942 false, GSI_CONTINUE_LINKING
);
7943 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
7944 stmt
= gimple_build_cond_empty (t
);
7945 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
7946 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
7947 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7950 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
7958 /* Expand #pragma omp ordered depend(source). */
7961 expand_omp_ordered_source (gimple_stmt_iterator
*gsi
, struct omp_for_data
*fd
,
7962 tree
*counts
, location_t loc
)
7964 enum built_in_function source_ix
7965 = fd
->iter_type
== long_integer_type_node
7966 ? BUILT_IN_GOMP_DOACROSS_POST
: BUILT_IN_GOMP_DOACROSS_ULL_POST
;
7968 = gimple_build_call (builtin_decl_explicit (source_ix
), 1,
7969 build_fold_addr_expr (counts
[fd
->ordered
]));
7970 gimple_set_location (g
, loc
);
7971 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
7974 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7977 expand_omp_ordered_sink (gimple_stmt_iterator
*gsi
, struct omp_for_data
*fd
,
7978 tree
*counts
, tree c
, location_t loc
)
7980 auto_vec
<tree
, 10> args
;
7981 enum built_in_function sink_ix
7982 = fd
->iter_type
== long_integer_type_node
7983 ? BUILT_IN_GOMP_DOACROSS_WAIT
: BUILT_IN_GOMP_DOACROSS_ULL_WAIT
;
7984 tree t
, off
, coff
= NULL_TREE
, deps
= OMP_CLAUSE_DECL (c
), cond
= NULL_TREE
;
7986 gimple_stmt_iterator gsi2
= *gsi
;
7987 bool warned_step
= false;
7989 for (i
= 0; i
< fd
->ordered
; i
++)
7991 off
= TREE_PURPOSE (deps
);
7992 if (!integer_zerop (off
))
7994 gcc_assert (fd
->loops
[i
].cond_code
== LT_EXPR
7995 || fd
->loops
[i
].cond_code
== GT_EXPR
);
7996 bool forward
= fd
->loops
[i
].cond_code
== LT_EXPR
;
7997 if (forward
^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
7998 warning_at (loc
, 0, "%<depend(sink)%> clause waiting for "
7999 "lexically later iteration");
8002 deps
= TREE_CHAIN (deps
);
8004 /* If all offsets corresponding to the collapsed loops are zero,
8005 this depend clause can be ignored. FIXME: but there is still a
8006 flush needed. We need to emit one __sync_synchronize () for it
8007 though (perhaps conditionally)? Solve this together with the
8008 conservative dependence folding optimization.
8009 if (i >= fd->collapse)
8012 deps
= OMP_CLAUSE_DECL (c
);
8014 edge e1
= split_block (gsi_bb (gsi2
), gsi_stmt (gsi2
));
8015 edge e2
= split_block_after_labels (e1
->dest
);
8017 *gsi
= gsi_after_labels (e1
->dest
);
8018 for (i
= 0; i
< fd
->ordered
; i
++)
8020 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
8021 if (POINTER_TYPE_P (itype
))
8024 deps
= TREE_CHAIN (deps
);
8025 off
= TREE_PURPOSE (deps
);
8026 tree s
= fold_convert_loc (loc
, itype
, fd
->loops
[i
].step
);
8028 if (integer_zerop (off
))
8029 t
= boolean_true_node
;
8033 tree co
= fold_convert_loc (loc
, itype
, off
);
8034 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
8036 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
8037 co
= fold_build1_loc (loc
, NEGATE_EXPR
, itype
, co
);
8038 a
= fold_build2_loc (loc
, POINTER_PLUS_EXPR
,
8039 TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].v
,
8042 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
8043 a
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
8044 fd
->loops
[i
].v
, co
);
8046 a
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
8047 fd
->loops
[i
].v
, co
);
8048 if (fd
->loops
[i
].cond_code
== LT_EXPR
)
8050 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
8051 t
= fold_build2_loc (loc
, GE_EXPR
, boolean_type_node
, a
,
8054 t
= fold_build2_loc (loc
, LT_EXPR
, boolean_type_node
, a
,
8057 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
8058 t
= fold_build2_loc (loc
, GT_EXPR
, boolean_type_node
, a
,
8061 t
= fold_build2_loc (loc
, LE_EXPR
, boolean_type_node
, a
,
8065 cond
= fold_build2_loc (loc
, BIT_AND_EXPR
, boolean_type_node
, cond
, t
);
8069 off
= fold_convert_loc (loc
, itype
, off
);
8071 if (fd
->loops
[i
].cond_code
== LT_EXPR
8072 ? !integer_onep (fd
->loops
[i
].step
)
8073 : !integer_minus_onep (fd
->loops
[i
].step
))
8075 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
8076 t
= fold_build2_loc (loc
, TRUNC_MOD_EXPR
, itype
, off
,
8077 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
8080 t
= fold_build2_loc (loc
, TRUNC_MOD_EXPR
, itype
, off
, s
);
8081 t
= fold_build2_loc (loc
, EQ_EXPR
, boolean_type_node
, t
,
8082 build_int_cst (itype
, 0));
8083 if (integer_zerop (t
) && !warned_step
)
8085 warning_at (loc
, 0, "%<depend(sink)%> refers to iteration never "
8086 "in the iteration space");
8089 cond
= fold_build2_loc (loc
, BIT_AND_EXPR
, boolean_type_node
,
8093 if (i
<= fd
->collapse
- 1 && fd
->collapse
> 1)
8099 t
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
8100 fd
->loops
[i
].v
, fd
->loops
[i
].n1
);
8101 t
= fold_convert_loc (loc
, fd
->iter_type
, t
);
8103 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
8104 off
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, off
,
8105 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
8108 off
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, off
, s
);
8109 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps
))
8110 off
= fold_build1_loc (loc
, NEGATE_EXPR
, itype
, off
);
8111 off
= fold_convert_loc (loc
, fd
->iter_type
, off
);
8112 if (i
<= fd
->collapse
- 1 && fd
->collapse
> 1)
8115 off
= fold_build2_loc (loc
, PLUS_EXPR
, fd
->iter_type
, coff
,
8117 if (i
< fd
->collapse
- 1)
8119 coff
= fold_build2_loc (loc
, MULT_EXPR
, fd
->iter_type
, off
,
8124 off
= unshare_expr (off
);
8125 t
= fold_build2_loc (loc
, PLUS_EXPR
, fd
->iter_type
, t
, off
);
8126 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
,
8127 true, GSI_SAME_STMT
);
8130 gimple
*g
= gimple_build_call_vec (builtin_decl_explicit (sink_ix
), args
);
8131 gimple_set_location (g
, loc
);
8132 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
8134 *gsi
= gsi_last_bb (e1
->src
);
8135 cond
= unshare_expr (cond
);
8136 cond
= force_gimple_operand_gsi (gsi
, cond
, true, NULL_TREE
, false,
8137 GSI_CONTINUE_LINKING
);
8138 gsi_insert_after (gsi
, gimple_build_cond_empty (cond
), GSI_NEW_STMT
);
8139 edge e3
= make_edge (e1
->src
, e2
->dest
, EDGE_FALSE_VALUE
);
8140 e3
->probability
= REG_BR_PROB_BASE
/ 8;
8141 e1
->probability
= REG_BR_PROB_BASE
- e3
->probability
;
8142 e1
->flags
= EDGE_TRUE_VALUE
;
8143 set_immediate_dominator (CDI_DOMINATORS
, e2
->dest
, e1
->src
);
8145 *gsi
= gsi_after_labels (e2
->dest
);
8148 /* Expand all #pragma omp ordered depend(source) and
8149 #pragma omp ordered depend(sink:...) constructs in the current
8150 #pragma omp for ordered(n) region. */
8153 expand_omp_ordered_source_sink (struct omp_region
*region
,
8154 struct omp_for_data
*fd
, tree
*counts
,
8155 basic_block cont_bb
)
8157 struct omp_region
*inner
;
8159 for (i
= fd
->collapse
- 1; i
< fd
->ordered
; i
++)
8160 if (i
== fd
->collapse
- 1 && fd
->collapse
> 1)
8161 counts
[i
] = NULL_TREE
;
8162 else if (i
>= fd
->collapse
&& !cont_bb
)
8163 counts
[i
] = build_zero_cst (fd
->iter_type
);
8164 else if (!POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
))
8165 && integer_onep (fd
->loops
[i
].step
))
8166 counts
[i
] = NULL_TREE
;
8168 counts
[i
] = create_tmp_var (fd
->iter_type
, ".orditer");
8170 = build_array_type_nelts (fd
->iter_type
, fd
->ordered
- fd
->collapse
+ 1);
8171 counts
[fd
->ordered
] = create_tmp_var (atype
, ".orditera");
8172 TREE_ADDRESSABLE (counts
[fd
->ordered
]) = 1;
8174 for (inner
= region
->inner
; inner
; inner
= inner
->next
)
8175 if (inner
->type
== GIMPLE_OMP_ORDERED
)
8177 gomp_ordered
*ord_stmt
= inner
->ord_stmt
;
8178 gimple_stmt_iterator gsi
= gsi_for_stmt (ord_stmt
);
8179 location_t loc
= gimple_location (ord_stmt
);
8181 for (c
= gimple_omp_ordered_clauses (ord_stmt
);
8182 c
; c
= OMP_CLAUSE_CHAIN (c
))
8183 if (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SOURCE
)
8186 expand_omp_ordered_source (&gsi
, fd
, counts
, loc
);
8187 for (c
= gimple_omp_ordered_clauses (ord_stmt
);
8188 c
; c
= OMP_CLAUSE_CHAIN (c
))
8189 if (OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
)
8190 expand_omp_ordered_sink (&gsi
, fd
, counts
, c
, loc
);
8191 gsi_remove (&gsi
, true);
8195 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8199 expand_omp_for_ordered_loops (struct omp_for_data
*fd
, tree
*counts
,
8200 basic_block cont_bb
, basic_block body_bb
,
8201 bool ordered_lastprivate
)
8203 if (fd
->ordered
== fd
->collapse
)
8208 gimple_stmt_iterator gsi
= gsi_after_labels (body_bb
);
8209 for (int i
= fd
->collapse
; i
< fd
->ordered
; i
++)
8211 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
8212 tree n1
= fold_convert (type
, fd
->loops
[i
].n1
);
8213 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, n1
);
8214 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
8215 size_int (i
- fd
->collapse
+ 1),
8216 NULL_TREE
, NULL_TREE
);
8217 expand_omp_build_assign (&gsi
, aref
, build_zero_cst (fd
->iter_type
));
8222 for (int i
= fd
->ordered
- 1; i
>= fd
->collapse
; i
--)
8224 tree t
, type
= TREE_TYPE (fd
->loops
[i
].v
);
8225 gimple_stmt_iterator gsi
= gsi_after_labels (body_bb
);
8226 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
,
8227 fold_convert (type
, fd
->loops
[i
].n1
));
8229 expand_omp_build_assign (&gsi
, counts
[i
],
8230 build_zero_cst (fd
->iter_type
));
8231 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
8232 size_int (i
- fd
->collapse
+ 1),
8233 NULL_TREE
, NULL_TREE
);
8234 expand_omp_build_assign (&gsi
, aref
, build_zero_cst (fd
->iter_type
));
8235 if (!gsi_end_p (gsi
))
8238 gsi
= gsi_last_bb (body_bb
);
8239 edge e1
= split_block (body_bb
, gsi_stmt (gsi
));
8240 basic_block new_body
= e1
->dest
;
8241 if (body_bb
== cont_bb
)
8244 basic_block new_header
;
8245 if (EDGE_COUNT (cont_bb
->preds
) > 0)
8247 gsi
= gsi_last_bb (cont_bb
);
8248 if (POINTER_TYPE_P (type
))
8249 t
= fold_build_pointer_plus (fd
->loops
[i
].v
,
8250 fold_convert (sizetype
,
8251 fd
->loops
[i
].step
));
8253 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loops
[i
].v
,
8254 fold_convert (type
, fd
->loops
[i
].step
));
8255 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
8258 t
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, counts
[i
],
8259 build_int_cst (fd
->iter_type
, 1));
8260 expand_omp_build_assign (&gsi
, counts
[i
], t
);
8265 t
= fold_build2 (MINUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
8266 fd
->loops
[i
].v
, fd
->loops
[i
].n1
);
8267 t
= fold_convert (fd
->iter_type
, t
);
8268 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8269 true, GSI_SAME_STMT
);
8271 aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
8272 size_int (i
- fd
->collapse
+ 1),
8273 NULL_TREE
, NULL_TREE
);
8274 expand_omp_build_assign (&gsi
, aref
, t
);
8276 e2
= split_block (cont_bb
, gsi_stmt (gsi
));
8277 new_header
= e2
->dest
;
8280 new_header
= cont_bb
;
8281 gsi
= gsi_after_labels (new_header
);
8282 tree v
= force_gimple_operand_gsi (&gsi
, fd
->loops
[i
].v
, true, NULL_TREE
,
8283 true, GSI_SAME_STMT
);
8285 = force_gimple_operand_gsi (&gsi
, fold_convert (type
, fd
->loops
[i
].n2
),
8286 true, NULL_TREE
, true, GSI_SAME_STMT
);
8287 t
= build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, n2
);
8288 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_NEW_STMT
);
8289 edge e3
= split_block (new_header
, gsi_stmt (gsi
));
8292 make_edge (body_bb
, new_header
, EDGE_FALLTHRU
);
8293 e3
->flags
= EDGE_FALSE_VALUE
;
8294 e3
->probability
= REG_BR_PROB_BASE
/ 8;
8295 e1
= make_edge (new_header
, new_body
, EDGE_TRUE_VALUE
);
8296 e1
->probability
= REG_BR_PROB_BASE
- e3
->probability
;
8298 set_immediate_dominator (CDI_DOMINATORS
, new_header
, body_bb
);
8299 set_immediate_dominator (CDI_DOMINATORS
, new_body
, new_header
);
8303 struct loop
*loop
= alloc_loop ();
8304 loop
->header
= new_header
;
8305 loop
->latch
= e2
->src
;
8306 add_loop (loop
, body_bb
->loop_father
);
8310 /* If there are any lastprivate clauses and it is possible some loops
8311 might have zero iterations, ensure all the decls are initialized,
8312 otherwise we could crash evaluating C++ class iterators with lastprivate
8314 bool need_inits
= false;
8315 for (int i
= fd
->collapse
; ordered_lastprivate
&& i
< fd
->ordered
; i
++)
8318 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
8319 gimple_stmt_iterator gsi
= gsi_after_labels (body_bb
);
8320 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
,
8321 fold_convert (type
, fd
->loops
[i
].n1
));
8325 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
8326 tree this_cond
= fold_build2 (fd
->loops
[i
].cond_code
,
8328 fold_convert (type
, fd
->loops
[i
].n1
),
8329 fold_convert (type
, fd
->loops
[i
].n2
));
8330 if (!integer_onep (this_cond
))
8338 /* A subroutine of expand_omp_for. Generate code for a parallel
8339 loop with any schedule. Given parameters:
8341 for (V = N1; V cond N2; V += STEP) BODY;
8343 where COND is "<" or ">", we generate pseudocode
8345 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8346 if (more) goto L0; else goto L3;
8353 if (V cond iend) goto L1; else goto L2;
8355 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8358 If this is a combined omp parallel loop, instead of the call to
8359 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8360 If this is gimple_omp_for_combined_p loop, then instead of assigning
8361 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8362 inner GIMPLE_OMP_FOR and V += STEP; and
8363 if (V cond iend) goto L1; else goto L2; are removed.
8365 For collapsed loops, given parameters:
8367 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8368 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8369 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8372 we generate pseudocode
8374 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8379 count3 = (adj + N32 - N31) / STEP3;
8380 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8385 count2 = (adj + N22 - N21) / STEP2;
8386 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8391 count1 = (adj + N12 - N11) / STEP1;
8392 count = count1 * count2 * count3;
8397 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8398 if (more) goto L0; else goto L3;
8402 V3 = N31 + (T % count3) * STEP3;
8404 V2 = N21 + (T % count2) * STEP2;
8406 V1 = N11 + T * STEP1;
8411 if (V < iend) goto L10; else goto L2;
8414 if (V3 cond3 N32) goto L1; else goto L11;
8418 if (V2 cond2 N22) goto L1; else goto L12;
8424 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8430 expand_omp_for_generic (struct omp_region
*region
,
8431 struct omp_for_data
*fd
,
8432 enum built_in_function start_fn
,
8433 enum built_in_function next_fn
,
8436 tree type
, istart0
, iend0
, iend
;
8437 tree t
, vmain
, vback
, bias
= NULL_TREE
;
8438 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
8439 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
8440 gimple_stmt_iterator gsi
;
8441 gassign
*assign_stmt
;
8442 bool in_combined_parallel
= is_combined_parallel (region
);
8443 bool broken_loop
= region
->cont
== NULL
;
8445 tree
*counts
= NULL
;
8447 bool ordered_lastprivate
= false;
8449 gcc_assert (!broken_loop
|| !in_combined_parallel
);
8450 gcc_assert (fd
->iter_type
== long_integer_type_node
8451 || !in_combined_parallel
);
8453 entry_bb
= region
->entry
;
8454 cont_bb
= region
->cont
;
8456 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
8457 gcc_assert (broken_loop
8458 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
8459 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
8460 l1_bb
= single_succ (l0_bb
);
8463 l2_bb
= create_empty_bb (cont_bb
);
8464 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
8465 || (single_succ_edge (BRANCH_EDGE (cont_bb
)->dest
)->dest
8467 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
8471 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
8472 exit_bb
= region
->exit
;
8474 gsi
= gsi_last_bb (entry_bb
);
8476 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
8478 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi
)),
8479 OMP_CLAUSE_LASTPRIVATE
))
8480 ordered_lastprivate
= false;
8481 if (fd
->collapse
> 1 || fd
->ordered
)
8483 int first_zero_iter1
= -1, first_zero_iter2
= -1;
8484 basic_block zero_iter1_bb
= NULL
, zero_iter2_bb
= NULL
, l2_dom_bb
= NULL
;
8486 counts
= XALLOCAVEC (tree
, fd
->ordered
? fd
->ordered
+ 1 : fd
->collapse
);
8487 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
8488 zero_iter1_bb
, first_zero_iter1
,
8489 zero_iter2_bb
, first_zero_iter2
, l2_dom_bb
);
8493 /* Some counts[i] vars might be uninitialized if
8494 some loop has zero iterations. But the body shouldn't
8495 be executed in that case, so just avoid uninit warnings. */
8496 for (i
= first_zero_iter1
;
8497 i
< (fd
->ordered
? fd
->ordered
: fd
->collapse
); i
++)
8498 if (SSA_VAR_P (counts
[i
]))
8499 TREE_NO_WARNING (counts
[i
]) = 1;
8501 e
= split_block (entry_bb
, gsi_stmt (gsi
));
8503 make_edge (zero_iter1_bb
, entry_bb
, EDGE_FALLTHRU
);
8504 gsi
= gsi_last_bb (entry_bb
);
8505 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
8506 get_immediate_dominator (CDI_DOMINATORS
,
8511 /* Some counts[i] vars might be uninitialized if
8512 some loop has zero iterations. But the body shouldn't
8513 be executed in that case, so just avoid uninit warnings. */
8514 for (i
= first_zero_iter2
; i
< fd
->ordered
; i
++)
8515 if (SSA_VAR_P (counts
[i
]))
8516 TREE_NO_WARNING (counts
[i
]) = 1;
8518 make_edge (zero_iter2_bb
, entry_bb
, EDGE_FALLTHRU
);
8522 e
= split_block (entry_bb
, gsi_stmt (gsi
));
8524 make_edge (zero_iter2_bb
, entry_bb
, EDGE_FALLTHRU
);
8525 gsi
= gsi_last_bb (entry_bb
);
8526 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
8527 get_immediate_dominator
8528 (CDI_DOMINATORS
, zero_iter2_bb
));
8531 if (fd
->collapse
== 1)
8533 counts
[0] = fd
->loop
.n2
;
8534 fd
->loop
= fd
->loops
[0];
8538 type
= TREE_TYPE (fd
->loop
.v
);
8539 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
8540 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
8541 TREE_ADDRESSABLE (istart0
) = 1;
8542 TREE_ADDRESSABLE (iend0
) = 1;
8544 /* See if we need to bias by LLONG_MIN. */
8545 if (fd
->iter_type
== long_long_unsigned_type_node
8546 && TREE_CODE (type
) == INTEGER_TYPE
8547 && !TYPE_UNSIGNED (type
)
8548 && fd
->ordered
== 0)
8552 if (fd
->loop
.cond_code
== LT_EXPR
)
8555 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
8559 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
8562 if (TREE_CODE (n1
) != INTEGER_CST
8563 || TREE_CODE (n2
) != INTEGER_CST
8564 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
8565 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
8568 gimple_stmt_iterator gsif
= gsi
;
8571 tree arr
= NULL_TREE
;
8572 if (in_combined_parallel
)
8574 gcc_assert (fd
->ordered
== 0);
8575 /* In a combined parallel loop, emit a call to
8576 GOMP_loop_foo_next. */
8577 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
8578 build_fold_addr_expr (istart0
),
8579 build_fold_addr_expr (iend0
));
8583 tree t0
, t1
, t2
, t3
, t4
;
8584 /* If this is not a combined parallel loop, emit a call to
8585 GOMP_loop_foo_start in ENTRY_BB. */
8586 t4
= build_fold_addr_expr (iend0
);
8587 t3
= build_fold_addr_expr (istart0
);
8590 t0
= build_int_cst (unsigned_type_node
,
8591 fd
->ordered
- fd
->collapse
+ 1);
8592 arr
= create_tmp_var (build_array_type_nelts (fd
->iter_type
,
8594 - fd
->collapse
+ 1),
8596 DECL_NAMELESS (arr
) = 1;
8597 TREE_ADDRESSABLE (arr
) = 1;
8598 TREE_STATIC (arr
) = 1;
8599 vec
<constructor_elt
, va_gc
> *v
;
8600 vec_alloc (v
, fd
->ordered
- fd
->collapse
+ 1);
8603 for (idx
= 0; idx
< fd
->ordered
- fd
->collapse
+ 1; idx
++)
8606 if (idx
== 0 && fd
->collapse
> 1)
8609 c
= counts
[idx
+ fd
->collapse
- 1];
8610 tree purpose
= size_int (idx
);
8611 CONSTRUCTOR_APPEND_ELT (v
, purpose
, c
);
8612 if (TREE_CODE (c
) != INTEGER_CST
)
8613 TREE_STATIC (arr
) = 0;
8616 DECL_INITIAL (arr
) = build_constructor (TREE_TYPE (arr
), v
);
8617 if (!TREE_STATIC (arr
))
8618 force_gimple_operand_gsi (&gsi
, build1 (DECL_EXPR
,
8619 void_type_node
, arr
),
8620 true, NULL_TREE
, true, GSI_SAME_STMT
);
8621 t1
= build_fold_addr_expr (arr
);
8626 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
8629 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
8632 = find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
8633 OMP_CLAUSE__LOOPTEMP_
);
8634 gcc_assert (innerc
);
8635 t0
= OMP_CLAUSE_DECL (innerc
);
8636 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
8637 OMP_CLAUSE__LOOPTEMP_
);
8638 gcc_assert (innerc
);
8639 t1
= OMP_CLAUSE_DECL (innerc
);
8641 if (POINTER_TYPE_P (TREE_TYPE (t0
))
8642 && TYPE_PRECISION (TREE_TYPE (t0
))
8643 != TYPE_PRECISION (fd
->iter_type
))
8645 /* Avoid casting pointers to integer of a different size. */
8646 tree itype
= signed_type_for (type
);
8647 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
8648 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
8652 t1
= fold_convert (fd
->iter_type
, t1
);
8653 t0
= fold_convert (fd
->iter_type
, t0
);
8657 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
8658 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
8661 if (fd
->iter_type
== long_integer_type_node
|| fd
->ordered
)
8665 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
8666 t
= omp_adjust_chunk_size (t
, fd
->simd_schedule
);
8668 t
= build_call_expr (builtin_decl_explicit (start_fn
),
8669 5, t0
, t1
, t
, t3
, t4
);
8671 t
= build_call_expr (builtin_decl_explicit (start_fn
),
8672 6, t0
, t1
, t2
, t
, t3
, t4
);
8674 else if (fd
->ordered
)
8675 t
= build_call_expr (builtin_decl_explicit (start_fn
),
8678 t
= build_call_expr (builtin_decl_explicit (start_fn
),
8679 5, t0
, t1
, t2
, t3
, t4
);
8687 /* The GOMP_loop_ull_*start functions have additional boolean
8688 argument, true for < loops and false for > loops.
8689 In Fortran, the C bool type can be different from
8690 boolean_type_node. */
8691 bfn_decl
= builtin_decl_explicit (start_fn
);
8692 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
8693 t5
= build_int_cst (c_bool_type
,
8694 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
8697 tree bfn_decl
= builtin_decl_explicit (start_fn
);
8698 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
8699 t
= omp_adjust_chunk_size (t
, fd
->simd_schedule
);
8700 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
8703 t
= build_call_expr (builtin_decl_explicit (start_fn
),
8704 6, t5
, t0
, t1
, t2
, t3
, t4
);
8707 if (TREE_TYPE (t
) != boolean_type_node
)
8708 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
8709 t
, build_int_cst (TREE_TYPE (t
), 0));
8710 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8711 true, GSI_SAME_STMT
);
8712 if (arr
&& !TREE_STATIC (arr
))
8714 tree clobber
= build_constructor (TREE_TYPE (arr
), NULL
);
8715 TREE_THIS_VOLATILE (clobber
) = 1;
8716 gsi_insert_before (&gsi
, gimple_build_assign (arr
, clobber
),
8719 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
8721 /* Remove the GIMPLE_OMP_FOR statement. */
8722 gsi_remove (&gsi
, true);
8724 if (gsi_end_p (gsif
))
8725 gsif
= gsi_after_labels (gsi_bb (gsif
));
8728 /* Iteration setup for sequential loop goes in L0_BB. */
8729 tree startvar
= fd
->loop
.v
;
8730 tree endvar
= NULL_TREE
;
8732 if (gimple_omp_for_combined_p (fd
->for_stmt
))
8734 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
8735 && gimple_omp_for_kind (inner_stmt
)
8736 == GF_OMP_FOR_KIND_SIMD
);
8737 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
8738 OMP_CLAUSE__LOOPTEMP_
);
8739 gcc_assert (innerc
);
8740 startvar
= OMP_CLAUSE_DECL (innerc
);
8741 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
8742 OMP_CLAUSE__LOOPTEMP_
);
8743 gcc_assert (innerc
);
8744 endvar
= OMP_CLAUSE_DECL (innerc
);
8747 gsi
= gsi_start_bb (l0_bb
);
8749 if (fd
->ordered
&& fd
->collapse
== 1)
8750 t
= fold_build2 (MULT_EXPR
, fd
->iter_type
, t
,
8751 fold_convert (fd
->iter_type
, fd
->loop
.step
));
8753 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
8754 if (fd
->ordered
&& fd
->collapse
== 1)
8756 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
8757 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (startvar
),
8758 fd
->loop
.n1
, fold_convert (sizetype
, t
));
8761 t
= fold_convert (TREE_TYPE (startvar
), t
);
8762 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (startvar
),
8768 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
8769 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
8770 t
= fold_convert (TREE_TYPE (startvar
), t
);
8772 t
= force_gimple_operand_gsi (&gsi
, t
,
8774 && TREE_ADDRESSABLE (startvar
),
8775 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
8776 assign_stmt
= gimple_build_assign (startvar
, t
);
8777 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8780 if (fd
->ordered
&& fd
->collapse
== 1)
8781 t
= fold_build2 (MULT_EXPR
, fd
->iter_type
, t
,
8782 fold_convert (fd
->iter_type
, fd
->loop
.step
));
8784 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
8785 if (fd
->ordered
&& fd
->collapse
== 1)
8787 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
8788 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (startvar
),
8789 fd
->loop
.n1
, fold_convert (sizetype
, t
));
8792 t
= fold_convert (TREE_TYPE (startvar
), t
);
8793 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (startvar
),
8799 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
8800 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
8801 t
= fold_convert (TREE_TYPE (startvar
), t
);
8803 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8804 false, GSI_CONTINUE_LINKING
);
8807 assign_stmt
= gimple_build_assign (endvar
, iend
);
8808 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8809 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
8810 assign_stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
8812 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, iend
);
8813 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8815 /* Handle linear clause adjustments. */
8816 tree itercnt
= NULL_TREE
;
8817 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_FOR
)
8818 for (tree c
= gimple_omp_for_clauses (fd
->for_stmt
);
8819 c
; c
= OMP_CLAUSE_CHAIN (c
))
8820 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
8821 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
8823 tree d
= OMP_CLAUSE_DECL (c
);
8824 bool is_ref
= is_reference (d
);
8825 tree t
= d
, a
, dest
;
8827 t
= build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c
), t
);
8828 tree type
= TREE_TYPE (t
);
8829 if (POINTER_TYPE_P (type
))
8831 dest
= unshare_expr (t
);
8832 tree v
= create_tmp_var (TREE_TYPE (t
), NULL
);
8833 expand_omp_build_assign (&gsif
, v
, t
);
8834 if (itercnt
== NULL_TREE
)
8837 tree n1
= fd
->loop
.n1
;
8838 if (POINTER_TYPE_P (TREE_TYPE (itercnt
)))
8841 = fold_convert (signed_type_for (TREE_TYPE (itercnt
)),
8843 n1
= fold_convert (TREE_TYPE (itercnt
), n1
);
8845 itercnt
= fold_build2 (MINUS_EXPR
, TREE_TYPE (itercnt
),
8847 itercnt
= fold_build2 (EXACT_DIV_EXPR
, TREE_TYPE (itercnt
),
8848 itercnt
, fd
->loop
.step
);
8849 itercnt
= force_gimple_operand_gsi (&gsi
, itercnt
, true,
8851 GSI_CONTINUE_LINKING
);
8853 a
= fold_build2 (MULT_EXPR
, type
,
8854 fold_convert (type
, itercnt
),
8855 fold_convert (type
, OMP_CLAUSE_LINEAR_STEP (c
)));
8856 t
= fold_build2 (type
== TREE_TYPE (t
) ? PLUS_EXPR
8857 : POINTER_PLUS_EXPR
, TREE_TYPE (t
), v
, a
);
8858 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8859 false, GSI_CONTINUE_LINKING
);
8860 assign_stmt
= gimple_build_assign (dest
, t
);
8861 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
8863 if (fd
->collapse
> 1)
8864 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
8868 /* Until now, counts array contained number of iterations or
8869 variable containing it for ith loop. From now on, we need
8870 those counts only for collapsed loops, and only for the 2nd
8871 till the last collapsed one. Move those one element earlier,
8872 we'll use counts[fd->collapse - 1] for the first source/sink
8873 iteration counter and so on and counts[fd->ordered]
8874 as the array holding the current counter values for
8876 if (fd
->collapse
> 1)
8877 memmove (counts
, counts
+ 1, (fd
->collapse
- 1) * sizeof (counts
[0]));
8881 for (i
= fd
->collapse
; i
< fd
->ordered
; i
++)
8883 tree type
= TREE_TYPE (fd
->loops
[i
].v
);
8885 = fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
8886 fold_convert (type
, fd
->loops
[i
].n1
),
8887 fold_convert (type
, fd
->loops
[i
].n2
));
8888 if (!integer_onep (this_cond
))
8891 if (i
< fd
->ordered
)
8894 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun
)->prev_bb
);
8895 add_bb_to_loop (cont_bb
, l1_bb
->loop_father
);
8896 gimple_stmt_iterator gsi
= gsi_after_labels (cont_bb
);
8897 gimple
*g
= gimple_build_omp_continue (fd
->loop
.v
, fd
->loop
.v
);
8898 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
8899 make_edge (cont_bb
, l3_bb
, EDGE_FALLTHRU
);
8900 make_edge (cont_bb
, l1_bb
, 0);
8901 l2_bb
= create_empty_bb (cont_bb
);
8902 broken_loop
= false;
8905 expand_omp_ordered_source_sink (region
, fd
, counts
, cont_bb
);
8906 cont_bb
= expand_omp_for_ordered_loops (fd
, counts
, cont_bb
, l1_bb
,
8907 ordered_lastprivate
);
8908 if (counts
[fd
->collapse
- 1])
8910 gcc_assert (fd
->collapse
== 1);
8911 gsi
= gsi_last_bb (l0_bb
);
8912 expand_omp_build_assign (&gsi
, counts
[fd
->collapse
- 1],
8914 gsi
= gsi_last_bb (cont_bb
);
8915 t
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, counts
[fd
->collapse
- 1],
8916 build_int_cst (fd
->iter_type
, 1));
8917 expand_omp_build_assign (&gsi
, counts
[fd
->collapse
- 1], t
);
8918 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
8919 size_zero_node
, NULL_TREE
, NULL_TREE
);
8920 expand_omp_build_assign (&gsi
, aref
, counts
[fd
->collapse
- 1]);
8921 t
= counts
[fd
->collapse
- 1];
8923 else if (fd
->collapse
> 1)
8927 t
= fold_build2 (MINUS_EXPR
, TREE_TYPE (fd
->loops
[0].v
),
8928 fd
->loops
[0].v
, fd
->loops
[0].n1
);
8929 t
= fold_convert (fd
->iter_type
, t
);
8931 gsi
= gsi_last_bb (l0_bb
);
8932 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
, counts
[fd
->ordered
],
8933 size_zero_node
, NULL_TREE
, NULL_TREE
);
8934 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8935 false, GSI_CONTINUE_LINKING
);
8936 expand_omp_build_assign (&gsi
, aref
, t
, true);
8941 /* Code to control the increment and predicate for the sequential
8942 loop goes in the CONT_BB. */
8943 gsi
= gsi_last_bb (cont_bb
);
8944 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
8945 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
8946 vmain
= gimple_omp_continue_control_use (cont_stmt
);
8947 vback
= gimple_omp_continue_control_def (cont_stmt
);
8949 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
8951 if (POINTER_TYPE_P (type
))
8952 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
8954 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
8955 t
= force_gimple_operand_gsi (&gsi
, t
,
8957 && TREE_ADDRESSABLE (vback
),
8958 NULL_TREE
, true, GSI_SAME_STMT
);
8959 assign_stmt
= gimple_build_assign (vback
, t
);
8960 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
8962 if (fd
->ordered
&& counts
[fd
->collapse
- 1] == NULL_TREE
)
8964 if (fd
->collapse
> 1)
8968 t
= fold_build2 (MINUS_EXPR
, TREE_TYPE (fd
->loops
[0].v
),
8969 fd
->loops
[0].v
, fd
->loops
[0].n1
);
8970 t
= fold_convert (fd
->iter_type
, t
);
8972 tree aref
= build4 (ARRAY_REF
, fd
->iter_type
,
8973 counts
[fd
->ordered
], size_zero_node
,
8974 NULL_TREE
, NULL_TREE
);
8975 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
8976 true, GSI_SAME_STMT
);
8977 expand_omp_build_assign (&gsi
, aref
, t
);
8980 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
8981 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
8983 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
8984 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
8987 /* Remove GIMPLE_OMP_CONTINUE. */
8988 gsi_remove (&gsi
, true);
8990 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
8991 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
8993 /* Emit code to get the next parallel iteration in L2_BB. */
8994 gsi
= gsi_start_bb (l2_bb
);
8996 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
8997 build_fold_addr_expr (istart0
),
8998 build_fold_addr_expr (iend0
));
8999 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9000 false, GSI_CONTINUE_LINKING
);
9001 if (TREE_TYPE (t
) != boolean_type_node
)
9002 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
9003 t
, build_int_cst (TREE_TYPE (t
), 0));
9004 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
9005 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
9008 /* Add the loop cleanup function. */
9009 gsi
= gsi_last_bb (exit_bb
);
9010 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
9011 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
9012 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
9013 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
9015 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
9016 gcall
*call_stmt
= gimple_build_call (t
, 0);
9017 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
9018 gimple_call_set_lhs (call_stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
9019 gsi_insert_after (&gsi
, call_stmt
, GSI_SAME_STMT
);
9022 tree arr
= counts
[fd
->ordered
];
9023 tree clobber
= build_constructor (TREE_TYPE (arr
), NULL
);
9024 TREE_THIS_VOLATILE (clobber
) = 1;
9025 gsi_insert_after (&gsi
, gimple_build_assign (arr
, clobber
),
9028 gsi_remove (&gsi
, true);
9030 /* Connect the new blocks. */
9031 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
9032 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
9038 e
= find_edge (cont_bb
, l3_bb
);
9039 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
9041 phis
= phi_nodes (l3_bb
);
9042 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
9044 gimple
*phi
= gsi_stmt (gsi
);
9045 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
9046 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
9050 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
9051 e
= find_edge (cont_bb
, l1_bb
);
9054 e
= BRANCH_EDGE (cont_bb
);
9055 gcc_assert (single_succ (e
->dest
) == l1_bb
);
9057 if (gimple_omp_for_combined_p (fd
->for_stmt
))
9062 else if (fd
->collapse
> 1)
9065 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
9068 e
->flags
= EDGE_TRUE_VALUE
;
9071 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
9072 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
9076 e
= find_edge (cont_bb
, l2_bb
);
9077 e
->flags
= EDGE_FALLTHRU
;
9079 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
9081 if (gimple_in_ssa_p (cfun
))
9083 /* Add phis to the outer loop that connect to the phis in the inner,
9084 original loop, and move the loop entry value of the inner phi to
9085 the loop entry value of the outer phi. */
9087 for (psi
= gsi_start_phis (l3_bb
); !gsi_end_p (psi
); gsi_next (&psi
))
9089 source_location locus
;
9091 gphi
*exit_phi
= psi
.phi ();
9093 edge l2_to_l3
= find_edge (l2_bb
, l3_bb
);
9094 tree exit_res
= PHI_ARG_DEF_FROM_EDGE (exit_phi
, l2_to_l3
);
9096 basic_block latch
= BRANCH_EDGE (cont_bb
)->dest
;
9097 edge latch_to_l1
= find_edge (latch
, l1_bb
);
9099 = find_phi_with_arg_on_edge (exit_res
, latch_to_l1
);
9101 tree t
= gimple_phi_result (exit_phi
);
9102 tree new_res
= copy_ssa_name (t
, NULL
);
9103 nphi
= create_phi_node (new_res
, l0_bb
);
9105 edge l0_to_l1
= find_edge (l0_bb
, l1_bb
);
9106 t
= PHI_ARG_DEF_FROM_EDGE (inner_phi
, l0_to_l1
);
9107 locus
= gimple_phi_arg_location_from_edge (inner_phi
, l0_to_l1
);
9108 edge entry_to_l0
= find_edge (entry_bb
, l0_bb
);
9109 add_phi_arg (nphi
, t
, entry_to_l0
, locus
);
9111 edge l2_to_l0
= find_edge (l2_bb
, l0_bb
);
9112 add_phi_arg (nphi
, exit_res
, l2_to_l0
, UNKNOWN_LOCATION
);
9114 add_phi_arg (inner_phi
, new_res
, l0_to_l1
, UNKNOWN_LOCATION
);
9118 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
9119 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
9120 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
9121 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
9122 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
9123 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
9124 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
9125 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
9127 /* We enter expand_omp_for_generic with a loop. This original loop may
9128 have its own loop struct, or it may be part of an outer loop struct
9129 (which may be the fake loop). */
9130 struct loop
*outer_loop
= entry_bb
->loop_father
;
9131 bool orig_loop_has_loop_struct
= l1_bb
->loop_father
!= outer_loop
;
9133 add_bb_to_loop (l2_bb
, outer_loop
);
9135 /* We've added a new loop around the original loop. Allocate the
9136 corresponding loop struct. */
9137 struct loop
*new_loop
= alloc_loop ();
9138 new_loop
->header
= l0_bb
;
9139 new_loop
->latch
= l2_bb
;
9140 add_loop (new_loop
, outer_loop
);
9142 /* Allocate a loop structure for the original loop unless we already
9144 if (!orig_loop_has_loop_struct
9145 && !gimple_omp_for_combined_p (fd
->for_stmt
))
9147 struct loop
*orig_loop
= alloc_loop ();
9148 orig_loop
->header
= l1_bb
;
9149 /* The loop may have multiple latches. */
9150 add_loop (orig_loop
, new_loop
);
9156 /* A subroutine of expand_omp_for. Generate code for a parallel
9157 loop with static schedule and no specified chunk size. Given
9160 for (V = N1; V cond N2; V += STEP) BODY;
9162 where COND is "<" or ">", we generate pseudocode
9164 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9169 if ((__typeof (V)) -1 > 0 && cond is >)
9170 n = -(adj + N2 - N1) / -STEP;
9172 n = (adj + N2 - N1) / STEP;
9175 if (threadid < tt) goto L3; else goto L4;
9180 s0 = q * threadid + tt;
9183 if (s0 >= e0) goto L2; else goto L0;
9189 if (V cond e) goto L1;
9194 expand_omp_for_static_nochunk (struct omp_region
*region
,
9195 struct omp_for_data
*fd
,
9198 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
9199 tree type
, itype
, vmain
, vback
;
9200 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
9201 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
9203 gimple_stmt_iterator gsi
;
9205 bool broken_loop
= region
->cont
== NULL
;
9206 tree
*counts
= NULL
;
9209 itype
= type
= TREE_TYPE (fd
->loop
.v
);
9210 if (POINTER_TYPE_P (type
))
9211 itype
= signed_type_for (type
);
9213 entry_bb
= region
->entry
;
9214 cont_bb
= region
->cont
;
9215 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
9216 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
9217 gcc_assert (broken_loop
9218 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
9219 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
9220 body_bb
= single_succ (seq_start_bb
);
9223 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
9224 || single_succ (BRANCH_EDGE (cont_bb
)->dest
) == body_bb
);
9225 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
9227 exit_bb
= region
->exit
;
9229 /* Iteration space partitioning goes in ENTRY_BB. */
9230 gsi
= gsi_last_bb (entry_bb
);
9231 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
9233 if (fd
->collapse
> 1)
9235 int first_zero_iter
= -1, dummy
= -1;
9236 basic_block l2_dom_bb
= NULL
, dummy_bb
= NULL
;
9238 counts
= XALLOCAVEC (tree
, fd
->collapse
);
9239 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
9240 fin_bb
, first_zero_iter
,
9241 dummy_bb
, dummy
, l2_dom_bb
);
9244 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9245 t
= integer_one_node
;
9247 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
9248 fold_convert (type
, fd
->loop
.n1
),
9249 fold_convert (type
, fd
->loop
.n2
));
9250 if (fd
->collapse
== 1
9251 && TYPE_UNSIGNED (type
)
9252 && (t
== NULL_TREE
|| !integer_onep (t
)))
9254 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
9255 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
9256 true, GSI_SAME_STMT
);
9257 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
9258 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
9259 true, GSI_SAME_STMT
);
9260 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
9261 NULL_TREE
, NULL_TREE
);
9262 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
9263 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
9264 expand_omp_regimplify_p
, NULL
, NULL
)
9265 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
9266 expand_omp_regimplify_p
, NULL
, NULL
))
9268 gsi
= gsi_for_stmt (cond_stmt
);
9269 gimple_regimplify_operands (cond_stmt
, &gsi
);
9271 ep
= split_block (entry_bb
, cond_stmt
);
9272 ep
->flags
= EDGE_TRUE_VALUE
;
9273 entry_bb
= ep
->dest
;
9274 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
9275 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
9276 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
9277 if (gimple_in_ssa_p (cfun
))
9279 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
9280 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
9281 !gsi_end_p (gpi
); gsi_next (&gpi
))
9283 gphi
*phi
= gpi
.phi ();
9284 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
9285 ep
, UNKNOWN_LOCATION
);
9288 gsi
= gsi_last_bb (entry_bb
);
9291 switch (gimple_omp_for_kind (fd
->for_stmt
))
9293 case GF_OMP_FOR_KIND_FOR
:
9294 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
9295 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
9297 case GF_OMP_FOR_KIND_DISTRIBUTE
:
9298 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
9299 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
9304 nthreads
= build_call_expr (nthreads
, 0);
9305 nthreads
= fold_convert (itype
, nthreads
);
9306 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
9307 true, GSI_SAME_STMT
);
9308 threadid
= build_call_expr (threadid
, 0);
9309 threadid
= fold_convert (itype
, threadid
);
9310 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
9311 true, GSI_SAME_STMT
);
9315 step
= fd
->loop
.step
;
9316 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9318 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
9319 OMP_CLAUSE__LOOPTEMP_
);
9320 gcc_assert (innerc
);
9321 n1
= OMP_CLAUSE_DECL (innerc
);
9322 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9323 OMP_CLAUSE__LOOPTEMP_
);
9324 gcc_assert (innerc
);
9325 n2
= OMP_CLAUSE_DECL (innerc
);
9327 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
9328 true, NULL_TREE
, true, GSI_SAME_STMT
);
9329 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
9330 true, NULL_TREE
, true, GSI_SAME_STMT
);
9331 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
9332 true, NULL_TREE
, true, GSI_SAME_STMT
);
9334 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
9335 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
9336 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
9337 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
9338 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
9339 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
9340 fold_build1 (NEGATE_EXPR
, itype
, t
),
9341 fold_build1 (NEGATE_EXPR
, itype
, step
));
9343 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
9344 t
= fold_convert (itype
, t
);
9345 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
9347 q
= create_tmp_reg (itype
, "q");
9348 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
9349 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
9350 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
9352 tt
= create_tmp_reg (itype
, "tt");
9353 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
9354 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
9355 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
9357 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
9358 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
9359 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
9361 second_bb
= split_block (entry_bb
, cond_stmt
)->dest
;
9362 gsi
= gsi_last_bb (second_bb
);
9363 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
9365 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
9367 gassign
*assign_stmt
9368 = gimple_build_assign (q
, PLUS_EXPR
, q
, build_int_cst (itype
, 1));
9369 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
9371 third_bb
= split_block (second_bb
, assign_stmt
)->dest
;
9372 gsi
= gsi_last_bb (third_bb
);
9373 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
9375 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
9376 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
9377 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
9379 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
9380 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
9382 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
9383 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
9385 /* Remove the GIMPLE_OMP_FOR statement. */
9386 gsi_remove (&gsi
, true);
9388 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9389 gsi
= gsi_start_bb (seq_start_bb
);
9391 tree startvar
= fd
->loop
.v
;
9392 tree endvar
= NULL_TREE
;
9394 if (gimple_omp_for_combined_p (fd
->for_stmt
))
9396 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
9397 ? gimple_omp_parallel_clauses (inner_stmt
)
9398 : gimple_omp_for_clauses (inner_stmt
);
9399 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
9400 gcc_assert (innerc
);
9401 startvar
= OMP_CLAUSE_DECL (innerc
);
9402 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9403 OMP_CLAUSE__LOOPTEMP_
);
9404 gcc_assert (innerc
);
9405 endvar
= OMP_CLAUSE_DECL (innerc
);
9406 if (fd
->collapse
> 1 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
9407 && gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
9410 for (i
= 1; i
< fd
->collapse
; i
++)
9412 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9413 OMP_CLAUSE__LOOPTEMP_
);
9414 gcc_assert (innerc
);
9416 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9417 OMP_CLAUSE__LOOPTEMP_
);
9420 /* If needed (distribute parallel for with lastprivate),
9421 propagate down the total number of iterations. */
9422 tree t
= fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc
)),
9424 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, false,
9425 GSI_CONTINUE_LINKING
);
9426 assign_stmt
= gimple_build_assign (OMP_CLAUSE_DECL (innerc
), t
);
9427 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9431 t
= fold_convert (itype
, s0
);
9432 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
9433 if (POINTER_TYPE_P (type
))
9434 t
= fold_build_pointer_plus (n1
, t
);
9436 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
9437 t
= fold_convert (TREE_TYPE (startvar
), t
);
9438 t
= force_gimple_operand_gsi (&gsi
, t
,
9440 && TREE_ADDRESSABLE (startvar
),
9441 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
9442 assign_stmt
= gimple_build_assign (startvar
, t
);
9443 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9445 t
= fold_convert (itype
, e0
);
9446 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
9447 if (POINTER_TYPE_P (type
))
9448 t
= fold_build_pointer_plus (n1
, t
);
9450 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
9451 t
= fold_convert (TREE_TYPE (startvar
), t
);
9452 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9453 false, GSI_CONTINUE_LINKING
);
9456 assign_stmt
= gimple_build_assign (endvar
, e
);
9457 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9458 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
9459 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
9461 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
9462 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9464 /* Handle linear clause adjustments. */
9465 tree itercnt
= NULL_TREE
;
9466 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_FOR
)
9467 for (tree c
= gimple_omp_for_clauses (fd
->for_stmt
);
9468 c
; c
= OMP_CLAUSE_CHAIN (c
))
9469 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
9470 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
9472 tree d
= OMP_CLAUSE_DECL (c
);
9473 bool is_ref
= is_reference (d
);
9474 tree t
= d
, a
, dest
;
9476 t
= build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c
), t
);
9477 if (itercnt
== NULL_TREE
)
9479 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9481 itercnt
= fold_build2 (MINUS_EXPR
, itype
,
9482 fold_convert (itype
, n1
),
9483 fold_convert (itype
, fd
->loop
.n1
));
9484 itercnt
= fold_build2 (EXACT_DIV_EXPR
, itype
, itercnt
, step
);
9485 itercnt
= fold_build2 (PLUS_EXPR
, itype
, itercnt
, s0
);
9486 itercnt
= force_gimple_operand_gsi (&gsi
, itercnt
, true,
9488 GSI_CONTINUE_LINKING
);
9493 tree type
= TREE_TYPE (t
);
9494 if (POINTER_TYPE_P (type
))
9496 a
= fold_build2 (MULT_EXPR
, type
,
9497 fold_convert (type
, itercnt
),
9498 fold_convert (type
, OMP_CLAUSE_LINEAR_STEP (c
)));
9499 dest
= unshare_expr (t
);
9500 t
= fold_build2 (type
== TREE_TYPE (t
) ? PLUS_EXPR
9501 : POINTER_PLUS_EXPR
, TREE_TYPE (t
), t
, a
);
9502 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9503 false, GSI_CONTINUE_LINKING
);
9504 assign_stmt
= gimple_build_assign (dest
, t
);
9505 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9507 if (fd
->collapse
> 1)
9508 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
9512 /* The code controlling the sequential loop replaces the
9513 GIMPLE_OMP_CONTINUE. */
9514 gsi
= gsi_last_bb (cont_bb
);
9515 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
9516 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
9517 vmain
= gimple_omp_continue_control_use (cont_stmt
);
9518 vback
= gimple_omp_continue_control_def (cont_stmt
);
9520 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
9522 if (POINTER_TYPE_P (type
))
9523 t
= fold_build_pointer_plus (vmain
, step
);
9525 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
9526 t
= force_gimple_operand_gsi (&gsi
, t
,
9528 && TREE_ADDRESSABLE (vback
),
9529 NULL_TREE
, true, GSI_SAME_STMT
);
9530 assign_stmt
= gimple_build_assign (vback
, t
);
9531 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
9533 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
9534 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
9536 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
9539 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9540 gsi_remove (&gsi
, true);
9542 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
9543 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
9546 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9547 gsi
= gsi_last_bb (exit_bb
);
9548 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
9550 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
9551 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
9553 gsi_remove (&gsi
, true);
9555 /* Connect all the blocks. */
9556 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
9557 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
9558 ep
= find_edge (entry_bb
, second_bb
);
9559 ep
->flags
= EDGE_TRUE_VALUE
;
9560 ep
->probability
= REG_BR_PROB_BASE
/ 4;
9561 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
9562 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
9566 ep
= find_edge (cont_bb
, body_bb
);
9569 ep
= BRANCH_EDGE (cont_bb
);
9570 gcc_assert (single_succ (ep
->dest
) == body_bb
);
9572 if (gimple_omp_for_combined_p (fd
->for_stmt
))
9577 else if (fd
->collapse
> 1)
9580 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
9583 ep
->flags
= EDGE_TRUE_VALUE
;
9584 find_edge (cont_bb
, fin_bb
)->flags
9585 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
9588 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
9589 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
9590 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
9592 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
9593 recompute_dominator (CDI_DOMINATORS
, body_bb
));
9594 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
9595 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
9597 struct loop
*loop
= body_bb
->loop_father
;
9598 if (loop
!= entry_bb
->loop_father
)
9600 gcc_assert (loop
->header
== body_bb
);
9601 gcc_assert (broken_loop
9602 || loop
->latch
== region
->cont
9603 || single_pred (loop
->latch
) == region
->cont
);
9607 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
9609 loop
= alloc_loop ();
9610 loop
->header
= body_bb
;
9611 if (collapse_bb
== NULL
)
9612 loop
->latch
= cont_bb
;
9613 add_loop (loop
, body_bb
->loop_father
);
9617 /* Return phi in E->DEST with ARG on edge E. */
9620 find_phi_with_arg_on_edge (tree arg
, edge e
)
9622 basic_block bb
= e
->dest
;
9624 for (gphi_iterator gpi
= gsi_start_phis (bb
);
9628 gphi
*phi
= gpi
.phi ();
9629 if (PHI_ARG_DEF_FROM_EDGE (phi
, e
) == arg
)
9636 /* A subroutine of expand_omp_for. Generate code for a parallel
9637 loop with static schedule and a specified chunk size. Given
9640 for (V = N1; V cond N2; V += STEP) BODY;
9642 where COND is "<" or ">", we generate pseudocode
9644 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9649 if ((__typeof (V)) -1 > 0 && cond is >)
9650 n = -(adj + N2 - N1) / -STEP;
9652 n = (adj + N2 - N1) / STEP;
9654 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9655 here so that V is defined
9656 if the loop is not entered
9658 s0 = (trip * nthreads + threadid) * CHUNK;
9659 e0 = min(s0 + CHUNK, n);
9660 if (s0 < n) goto L1; else goto L4;
9667 if (V cond e) goto L2; else goto L3;
9675 expand_omp_for_static_chunk (struct omp_region
*region
,
9676 struct omp_for_data
*fd
, gimple
*inner_stmt
)
9678 tree n
, s0
, e0
, e
, t
;
9679 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
9680 tree type
, itype
, vmain
, vback
, vextra
;
9681 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
9682 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
9683 gimple_stmt_iterator gsi
;
9685 bool broken_loop
= region
->cont
== NULL
;
9686 tree
*counts
= NULL
;
9689 itype
= type
= TREE_TYPE (fd
->loop
.v
);
9690 if (POINTER_TYPE_P (type
))
9691 itype
= signed_type_for (type
);
9693 entry_bb
= region
->entry
;
9694 se
= split_block (entry_bb
, last_stmt (entry_bb
));
9696 iter_part_bb
= se
->dest
;
9697 cont_bb
= region
->cont
;
9698 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
9699 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
9700 gcc_assert (broken_loop
9701 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
9702 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
9703 body_bb
= single_succ (seq_start_bb
);
9706 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
9707 || single_succ (BRANCH_EDGE (cont_bb
)->dest
) == body_bb
);
9708 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
9709 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
9711 exit_bb
= region
->exit
;
9713 /* Trip and adjustment setup goes in ENTRY_BB. */
9714 gsi
= gsi_last_bb (entry_bb
);
9715 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
9717 if (fd
->collapse
> 1)
9719 int first_zero_iter
= -1, dummy
= -1;
9720 basic_block l2_dom_bb
= NULL
, dummy_bb
= NULL
;
9722 counts
= XALLOCAVEC (tree
, fd
->collapse
);
9723 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
9724 fin_bb
, first_zero_iter
,
9725 dummy_bb
, dummy
, l2_dom_bb
);
9728 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9729 t
= integer_one_node
;
9731 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
9732 fold_convert (type
, fd
->loop
.n1
),
9733 fold_convert (type
, fd
->loop
.n2
));
9734 if (fd
->collapse
== 1
9735 && TYPE_UNSIGNED (type
)
9736 && (t
== NULL_TREE
|| !integer_onep (t
)))
9738 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
9739 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
9740 true, GSI_SAME_STMT
);
9741 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
9742 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
9743 true, GSI_SAME_STMT
);
9744 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
9745 NULL_TREE
, NULL_TREE
);
9746 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
9747 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
9748 expand_omp_regimplify_p
, NULL
, NULL
)
9749 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
9750 expand_omp_regimplify_p
, NULL
, NULL
))
9752 gsi
= gsi_for_stmt (cond_stmt
);
9753 gimple_regimplify_operands (cond_stmt
, &gsi
);
9755 se
= split_block (entry_bb
, cond_stmt
);
9756 se
->flags
= EDGE_TRUE_VALUE
;
9757 entry_bb
= se
->dest
;
9758 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
9759 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
9760 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
9761 if (gimple_in_ssa_p (cfun
))
9763 int dest_idx
= find_edge (iter_part_bb
, fin_bb
)->dest_idx
;
9764 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
9765 !gsi_end_p (gpi
); gsi_next (&gpi
))
9767 gphi
*phi
= gpi
.phi ();
9768 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
9769 se
, UNKNOWN_LOCATION
);
9772 gsi
= gsi_last_bb (entry_bb
);
9775 switch (gimple_omp_for_kind (fd
->for_stmt
))
9777 case GF_OMP_FOR_KIND_FOR
:
9778 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
9779 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
9781 case GF_OMP_FOR_KIND_DISTRIBUTE
:
9782 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
9783 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
9788 nthreads
= build_call_expr (nthreads
, 0);
9789 nthreads
= fold_convert (itype
, nthreads
);
9790 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
9791 true, GSI_SAME_STMT
);
9792 threadid
= build_call_expr (threadid
, 0);
9793 threadid
= fold_convert (itype
, threadid
);
9794 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
9795 true, GSI_SAME_STMT
);
9799 step
= fd
->loop
.step
;
9800 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9802 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
9803 OMP_CLAUSE__LOOPTEMP_
);
9804 gcc_assert (innerc
);
9805 n1
= OMP_CLAUSE_DECL (innerc
);
9806 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9807 OMP_CLAUSE__LOOPTEMP_
);
9808 gcc_assert (innerc
);
9809 n2
= OMP_CLAUSE_DECL (innerc
);
9811 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
9812 true, NULL_TREE
, true, GSI_SAME_STMT
);
9813 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
9814 true, NULL_TREE
, true, GSI_SAME_STMT
);
9815 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
9816 true, NULL_TREE
, true, GSI_SAME_STMT
);
9817 tree chunk_size
= fold_convert (itype
, fd
->chunk_size
);
9818 chunk_size
= omp_adjust_chunk_size (chunk_size
, fd
->simd_schedule
);
9820 = force_gimple_operand_gsi (&gsi
, chunk_size
, true, NULL_TREE
, true,
9823 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
9824 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
9825 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
9826 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
9827 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
9828 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
9829 fold_build1 (NEGATE_EXPR
, itype
, t
),
9830 fold_build1 (NEGATE_EXPR
, itype
, step
));
9832 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
9833 t
= fold_convert (itype
, t
);
9834 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9835 true, GSI_SAME_STMT
);
9837 trip_var
= create_tmp_reg (itype
, ".trip");
9838 if (gimple_in_ssa_p (cfun
))
9840 trip_init
= make_ssa_name (trip_var
);
9841 trip_main
= make_ssa_name (trip_var
);
9842 trip_back
= make_ssa_name (trip_var
);
9846 trip_init
= trip_var
;
9847 trip_main
= trip_var
;
9848 trip_back
= trip_var
;
9851 gassign
*assign_stmt
9852 = gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
9853 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
9855 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, chunk_size
);
9856 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
9857 if (POINTER_TYPE_P (type
))
9858 t
= fold_build_pointer_plus (n1
, t
);
9860 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
9861 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9862 true, GSI_SAME_STMT
);
9864 /* Remove the GIMPLE_OMP_FOR. */
9865 gsi_remove (&gsi
, true);
9867 gimple_stmt_iterator gsif
= gsi
;
9869 /* Iteration space partitioning goes in ITER_PART_BB. */
9870 gsi
= gsi_last_bb (iter_part_bb
);
9872 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
9873 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
9874 t
= fold_build2 (MULT_EXPR
, itype
, t
, chunk_size
);
9875 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9876 false, GSI_CONTINUE_LINKING
);
9878 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, chunk_size
);
9879 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
9880 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9881 false, GSI_CONTINUE_LINKING
);
9883 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
9884 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
9886 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9887 gsi
= gsi_start_bb (seq_start_bb
);
9889 tree startvar
= fd
->loop
.v
;
9890 tree endvar
= NULL_TREE
;
9892 if (gimple_omp_for_combined_p (fd
->for_stmt
))
9894 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
9895 ? gimple_omp_parallel_clauses (inner_stmt
)
9896 : gimple_omp_for_clauses (inner_stmt
);
9897 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
9898 gcc_assert (innerc
);
9899 startvar
= OMP_CLAUSE_DECL (innerc
);
9900 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9901 OMP_CLAUSE__LOOPTEMP_
);
9902 gcc_assert (innerc
);
9903 endvar
= OMP_CLAUSE_DECL (innerc
);
9904 if (fd
->collapse
> 1 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
9905 && gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
9908 for (i
= 1; i
< fd
->collapse
; i
++)
9910 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9911 OMP_CLAUSE__LOOPTEMP_
);
9912 gcc_assert (innerc
);
9914 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
9915 OMP_CLAUSE__LOOPTEMP_
);
9918 /* If needed (distribute parallel for with lastprivate),
9919 propagate down the total number of iterations. */
9920 tree t
= fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc
)),
9922 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, false,
9923 GSI_CONTINUE_LINKING
);
9924 assign_stmt
= gimple_build_assign (OMP_CLAUSE_DECL (innerc
), t
);
9925 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9930 t
= fold_convert (itype
, s0
);
9931 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
9932 if (POINTER_TYPE_P (type
))
9933 t
= fold_build_pointer_plus (n1
, t
);
9935 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
9936 t
= fold_convert (TREE_TYPE (startvar
), t
);
9937 t
= force_gimple_operand_gsi (&gsi
, t
,
9939 && TREE_ADDRESSABLE (startvar
),
9940 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
9941 assign_stmt
= gimple_build_assign (startvar
, t
);
9942 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9944 t
= fold_convert (itype
, e0
);
9945 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
9946 if (POINTER_TYPE_P (type
))
9947 t
= fold_build_pointer_plus (n1
, t
);
9949 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
9950 t
= fold_convert (TREE_TYPE (startvar
), t
);
9951 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
9952 false, GSI_CONTINUE_LINKING
);
9955 assign_stmt
= gimple_build_assign (endvar
, e
);
9956 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9957 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
9958 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
9960 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
9961 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
9963 /* Handle linear clause adjustments. */
9964 tree itercnt
= NULL_TREE
, itercntbias
= NULL_TREE
;
9965 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_FOR
)
9966 for (tree c
= gimple_omp_for_clauses (fd
->for_stmt
);
9967 c
; c
= OMP_CLAUSE_CHAIN (c
))
9968 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
9969 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
9971 tree d
= OMP_CLAUSE_DECL (c
);
9972 bool is_ref
= is_reference (d
);
9973 tree t
= d
, a
, dest
;
9975 t
= build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c
), t
);
9976 tree type
= TREE_TYPE (t
);
9977 if (POINTER_TYPE_P (type
))
9979 dest
= unshare_expr (t
);
9980 tree v
= create_tmp_var (TREE_TYPE (t
), NULL
);
9981 expand_omp_build_assign (&gsif
, v
, t
);
9982 if (itercnt
== NULL_TREE
)
9984 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
9987 = fold_build2 (MINUS_EXPR
, itype
, fold_convert (itype
, n1
),
9988 fold_convert (itype
, fd
->loop
.n1
));
9989 itercntbias
= fold_build2 (EXACT_DIV_EXPR
, itype
,
9992 = force_gimple_operand_gsi (&gsif
, itercntbias
, true,
9995 itercnt
= fold_build2 (PLUS_EXPR
, itype
, itercntbias
, s0
);
9996 itercnt
= force_gimple_operand_gsi (&gsi
, itercnt
, true,
9998 GSI_CONTINUE_LINKING
);
10003 a
= fold_build2 (MULT_EXPR
, type
,
10004 fold_convert (type
, itercnt
),
10005 fold_convert (type
, OMP_CLAUSE_LINEAR_STEP (c
)));
10006 t
= fold_build2 (type
== TREE_TYPE (t
) ? PLUS_EXPR
10007 : POINTER_PLUS_EXPR
, TREE_TYPE (t
), v
, a
);
10008 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
10009 false, GSI_CONTINUE_LINKING
);
10010 assign_stmt
= gimple_build_assign (dest
, t
);
10011 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10013 if (fd
->collapse
> 1)
10014 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
10018 /* The code controlling the sequential loop goes in CONT_BB,
10019 replacing the GIMPLE_OMP_CONTINUE. */
10020 gsi
= gsi_last_bb (cont_bb
);
10021 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
10022 vmain
= gimple_omp_continue_control_use (cont_stmt
);
10023 vback
= gimple_omp_continue_control_def (cont_stmt
);
10025 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
10027 if (POINTER_TYPE_P (type
))
10028 t
= fold_build_pointer_plus (vmain
, step
);
10030 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
10031 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
10032 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
10033 true, GSI_SAME_STMT
);
10034 assign_stmt
= gimple_build_assign (vback
, t
);
10035 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
10037 if (tree_int_cst_equal (fd
->chunk_size
, integer_one_node
))
10038 t
= build2 (EQ_EXPR
, boolean_type_node
,
10039 build_int_cst (itype
, 0),
10040 build_int_cst (itype
, 1));
10042 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
10043 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
10045 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
10048 /* Remove GIMPLE_OMP_CONTINUE. */
10049 gsi_remove (&gsi
, true);
10051 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
10052 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
10054 /* Trip update code goes into TRIP_UPDATE_BB. */
10055 gsi
= gsi_start_bb (trip_update_bb
);
10057 t
= build_int_cst (itype
, 1);
10058 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
10059 assign_stmt
= gimple_build_assign (trip_back
, t
);
10060 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10063 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10064 gsi
= gsi_last_bb (exit_bb
);
10065 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
10067 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
10068 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
10070 gsi_remove (&gsi
, true);
10072 /* Connect the new blocks. */
10073 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
10074 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
10078 se
= find_edge (cont_bb
, body_bb
);
10081 se
= BRANCH_EDGE (cont_bb
);
10082 gcc_assert (single_succ (se
->dest
) == body_bb
);
10084 if (gimple_omp_for_combined_p (fd
->for_stmt
))
10089 else if (fd
->collapse
> 1)
10092 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
10095 se
->flags
= EDGE_TRUE_VALUE
;
10096 find_edge (cont_bb
, trip_update_bb
)->flags
10097 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
10099 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
10102 if (gimple_in_ssa_p (cfun
))
10110 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
10112 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10113 remove arguments of the phi nodes in fin_bb. We need to create
10114 appropriate phi nodes in iter_part_bb instead. */
10115 se
= find_edge (iter_part_bb
, fin_bb
);
10116 re
= single_succ_edge (trip_update_bb
);
10117 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
10118 ene
= single_succ_edge (entry_bb
);
10120 psi
= gsi_start_phis (fin_bb
);
10121 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
10122 gsi_next (&psi
), ++i
)
10125 source_location locus
;
10128 t
= gimple_phi_result (phi
);
10129 gcc_assert (t
== redirect_edge_var_map_result (vm
));
10131 if (!single_pred_p (fin_bb
))
10132 t
= copy_ssa_name (t
, phi
);
10134 nphi
= create_phi_node (t
, iter_part_bb
);
10136 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
10137 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
10139 /* A special case -- fd->loop.v is not yet computed in
10140 iter_part_bb, we need to use vextra instead. */
10141 if (t
== fd
->loop
.v
)
10143 add_phi_arg (nphi
, t
, ene
, locus
);
10144 locus
= redirect_edge_var_map_location (vm
);
10145 tree back_arg
= redirect_edge_var_map_def (vm
);
10146 add_phi_arg (nphi
, back_arg
, re
, locus
);
10147 edge ce
= find_edge (cont_bb
, body_bb
);
10150 ce
= BRANCH_EDGE (cont_bb
);
10151 gcc_assert (single_succ (ce
->dest
) == body_bb
);
10152 ce
= single_succ_edge (ce
->dest
);
10154 gphi
*inner_loop_phi
= find_phi_with_arg_on_edge (back_arg
, ce
);
10155 gcc_assert (inner_loop_phi
!= NULL
);
10156 add_phi_arg (inner_loop_phi
, gimple_phi_result (nphi
),
10157 find_edge (seq_start_bb
, body_bb
), locus
);
10159 if (!single_pred_p (fin_bb
))
10160 add_phi_arg (phi
, gimple_phi_result (nphi
), se
, locus
);
10162 gcc_assert (gsi_end_p (psi
) && (head
== NULL
|| i
== head
->length ()));
10163 redirect_edge_var_map_clear (re
);
10164 if (single_pred_p (fin_bb
))
10167 psi
= gsi_start_phis (fin_bb
);
10168 if (gsi_end_p (psi
))
10170 remove_phi_node (&psi
, false);
10173 /* Make phi node for trip. */
10174 phi
= create_phi_node (trip_main
, iter_part_bb
);
10175 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
10177 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
10182 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
10183 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
10184 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
10185 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
10186 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
10187 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
10188 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
10189 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
10190 recompute_dominator (CDI_DOMINATORS
, body_bb
));
10194 struct loop
*loop
= body_bb
->loop_father
;
10195 struct loop
*trip_loop
= alloc_loop ();
10196 trip_loop
->header
= iter_part_bb
;
10197 trip_loop
->latch
= trip_update_bb
;
10198 add_loop (trip_loop
, iter_part_bb
->loop_father
);
10200 if (loop
!= entry_bb
->loop_father
)
10202 gcc_assert (loop
->header
== body_bb
);
10203 gcc_assert (loop
->latch
== region
->cont
10204 || single_pred (loop
->latch
) == region
->cont
);
10205 trip_loop
->inner
= loop
;
10209 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
10211 loop
= alloc_loop ();
10212 loop
->header
= body_bb
;
10213 if (collapse_bb
== NULL
)
10214 loop
->latch
= cont_bb
;
10215 add_loop (loop
, trip_loop
);
10220 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10222 for (V = N1; V cond N2; V += STEP) BODY;
10224 where COND is "<" or ">" or "!=", we generate pseudocode
10226 for (ind_var = low; ind_var < high; ind_var++)
10228 V = n1 + (ind_var * STEP)
10233 In the above pseudocode, low and high are function parameters of the
10234 child function. In the function below, we are inserting a temp.
10235 variable that will be making a call to two OMP functions that will not be
10236 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10237 with _Cilk_for). These functions are replaced with low and high
10238 by the function that handles taskreg. */
10242 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
10244 bool broken_loop
= region
->cont
== NULL
;
10245 basic_block entry_bb
= region
->entry
;
10246 basic_block cont_bb
= region
->cont
;
10248 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
10249 gcc_assert (broken_loop
10250 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
10251 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
10252 basic_block l1_bb
, l2_bb
;
10256 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
10257 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
10258 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
10259 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
10263 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
10264 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
10265 l2_bb
= single_succ (l1_bb
);
10267 basic_block exit_bb
= region
->exit
;
10268 basic_block l2_dom_bb
= NULL
;
10270 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
10272 /* Below statements until the "tree high_val = ..." are pseudo statements
10273 used to pass information to be used by expand_omp_taskreg.
10274 low_val and high_val will be replaced by the __low and __high
10275 parameter from the child function.
10277 The call_exprs part is a place-holder, it is mainly used
10278 to distinctly identify to the top-level part that this is
10279 where we should put low and high (reasoning given in header
10283 = gimple_omp_parallel_child_fn (
10284 as_a
<gomp_parallel
*> (last_stmt (region
->outer
->entry
)));
10285 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
10286 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
10288 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
10290 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
10293 gcc_assert (low_val
&& high_val
);
10295 tree type
= TREE_TYPE (low_val
);
10296 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
10297 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
10299 /* Not needed in SSA form right now. */
10300 gcc_assert (!gimple_in_ssa_p (cfun
));
10301 if (l2_dom_bb
== NULL
)
10305 tree n2
= high_val
;
10307 gimple
*stmt
= gimple_build_assign (ind_var
, n1
);
10309 /* Replace the GIMPLE_OMP_FOR statement. */
10310 gsi_replace (&gsi
, stmt
, true);
10314 /* Code to control the increment goes in the CONT_BB. */
10315 gsi
= gsi_last_bb (cont_bb
);
10316 stmt
= gsi_stmt (gsi
);
10317 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
10318 stmt
= gimple_build_assign (ind_var
, PLUS_EXPR
, ind_var
,
10319 build_one_cst (type
));
10321 /* Replace GIMPLE_OMP_CONTINUE. */
10322 gsi_replace (&gsi
, stmt
, true);
10325 /* Emit the condition in L1_BB. */
10326 gsi
= gsi_after_labels (l1_bb
);
10327 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
10328 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
10330 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
10331 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
10332 fd
->loop
.n1
, fold_convert (sizetype
, t
));
10334 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
10335 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
10336 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
10337 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
10339 /* The condition is always '<' since the runtime will fill in the low
10340 and high values. */
10341 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
10342 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
10344 /* Remove GIMPLE_OMP_RETURN. */
10345 gsi
= gsi_last_bb (exit_bb
);
10346 gsi_remove (&gsi
, true);
10348 /* Connect the new blocks. */
10349 remove_edge (FALLTHRU_EDGE (entry_bb
));
10354 remove_edge (BRANCH_EDGE (entry_bb
));
10355 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
10357 e
= BRANCH_EDGE (l1_bb
);
10358 ne
= FALLTHRU_EDGE (l1_bb
);
10359 e
->flags
= EDGE_TRUE_VALUE
;
10363 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
10365 ne
= single_succ_edge (l1_bb
);
10366 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
10369 ne
->flags
= EDGE_FALSE_VALUE
;
10370 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
10371 ne
->probability
= REG_BR_PROB_BASE
/ 8;
10373 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
10374 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
10375 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
10379 struct loop
*loop
= alloc_loop ();
10380 loop
->header
= l1_bb
;
10381 loop
->latch
= cont_bb
;
10382 add_loop (loop
, l1_bb
->loop_father
);
10383 loop
->safelen
= INT_MAX
;
10386 /* Pick the correct library function based on the precision of the
10387 induction variable type. */
10388 tree lib_fun
= NULL_TREE
;
10389 if (TYPE_PRECISION (type
) == 32)
10390 lib_fun
= cilk_for_32_fndecl
;
10391 else if (TYPE_PRECISION (type
) == 64)
10392 lib_fun
= cilk_for_64_fndecl
;
10394 gcc_unreachable ();
10396 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
10398 /* WS_ARGS contains the library function flavor to call:
10399 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10400 user-defined grain value. If the user does not define one, then zero
10401 is passed in by the parser. */
10402 vec_alloc (region
->ws_args
, 2);
10403 region
->ws_args
->quick_push (lib_fun
);
10404 region
->ws_args
->quick_push (fd
->chunk_size
);
10407 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10408 loop. Given parameters:
10410 for (V = N1; V cond N2; V += STEP) BODY;
10412 where COND is "<" or ">", we generate pseudocode
10420 if (V cond N2) goto L0; else goto L2;
10423 For collapsed loops, given parameters:
10425 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10426 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10427 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10430 we generate pseudocode
10436 count3 = (adj + N32 - N31) / STEP3;
10441 count2 = (adj + N22 - N21) / STEP2;
10446 count1 = (adj + N12 - N11) / STEP1;
10447 count = count1 * count2 * count3;
10457 V2 += (V3 cond3 N32) ? 0 : STEP2;
10458 V3 = (V3 cond3 N32) ? V3 : N31;
10459 V1 += (V2 cond2 N22) ? 0 : STEP1;
10460 V2 = (V2 cond2 N22) ? V2 : N21;
10462 if (V < count) goto L0; else goto L2;
10468 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
10471 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
10472 gimple_stmt_iterator gsi
;
10475 bool broken_loop
= region
->cont
== NULL
;
10477 tree
*counts
= NULL
;
10479 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
10480 OMP_CLAUSE_SAFELEN
);
10481 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
10482 OMP_CLAUSE__SIMDUID_
);
10485 type
= TREE_TYPE (fd
->loop
.v
);
10486 entry_bb
= region
->entry
;
10487 cont_bb
= region
->cont
;
10488 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
10489 gcc_assert (broken_loop
10490 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
10491 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
10494 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
10495 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
10496 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
10497 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
10501 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
10502 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
10503 l2_bb
= single_succ (l1_bb
);
10505 exit_bb
= region
->exit
;
10508 gsi
= gsi_last_bb (entry_bb
);
10510 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
10511 /* Not needed in SSA form right now. */
10512 gcc_assert (!gimple_in_ssa_p (cfun
));
10513 if (fd
->collapse
> 1)
10515 int first_zero_iter
= -1, dummy
= -1;
10516 basic_block zero_iter_bb
= l2_bb
, dummy_bb
= NULL
;
10518 counts
= XALLOCAVEC (tree
, fd
->collapse
);
10519 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
10520 zero_iter_bb
, first_zero_iter
,
10521 dummy_bb
, dummy
, l2_dom_bb
);
10523 if (l2_dom_bb
== NULL
)
10528 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
10530 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
10531 OMP_CLAUSE__LOOPTEMP_
);
10532 gcc_assert (innerc
);
10533 n1
= OMP_CLAUSE_DECL (innerc
);
10534 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
10535 OMP_CLAUSE__LOOPTEMP_
);
10536 gcc_assert (innerc
);
10537 n2
= OMP_CLAUSE_DECL (innerc
);
10538 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
10539 fold_convert (type
, n1
));
10540 if (fd
->collapse
> 1)
10543 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
10549 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
10550 fold_convert (type
, fd
->loop
.n1
));
10551 if (fd
->collapse
> 1)
10552 for (i
= 0; i
< fd
->collapse
; i
++)
10554 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
10555 if (POINTER_TYPE_P (itype
))
10556 itype
= signed_type_for (itype
);
10557 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
10558 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
10562 /* Remove the GIMPLE_OMP_FOR statement. */
10563 gsi_remove (&gsi
, true);
10567 /* Code to control the increment goes in the CONT_BB. */
10568 gsi
= gsi_last_bb (cont_bb
);
10569 stmt
= gsi_stmt (gsi
);
10570 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
10572 if (POINTER_TYPE_P (type
))
10573 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
10575 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
10576 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
10578 if (fd
->collapse
> 1)
10580 i
= fd
->collapse
- 1;
10581 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
10583 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
10584 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
10588 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
10589 fd
->loops
[i
].step
);
10590 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
10591 fd
->loops
[i
].v
, t
);
10593 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
10595 for (i
= fd
->collapse
- 1; i
> 0; i
--)
10597 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
10598 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
10599 if (POINTER_TYPE_P (itype2
))
10600 itype2
= signed_type_for (itype2
);
10601 t
= build3 (COND_EXPR
, itype2
,
10602 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
10604 fold_convert (itype
, fd
->loops
[i
].n2
)),
10605 build_int_cst (itype2
, 0),
10606 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
10607 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
10608 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
10610 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
10611 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
10613 t
= build3 (COND_EXPR
, itype
,
10614 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
10616 fold_convert (itype
, fd
->loops
[i
].n2
)),
10618 fold_convert (itype
, fd
->loops
[i
].n1
));
10619 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
10623 /* Remove GIMPLE_OMP_CONTINUE. */
10624 gsi_remove (&gsi
, true);
10627 /* Emit the condition in L1_BB. */
10628 gsi
= gsi_start_bb (l1_bb
);
10630 t
= fold_convert (type
, n2
);
10631 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
10632 false, GSI_CONTINUE_LINKING
);
10633 tree v
= fd
->loop
.v
;
10634 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
10635 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
10636 false, GSI_CONTINUE_LINKING
);
10637 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, v
, t
);
10638 cond_stmt
= gimple_build_cond_empty (t
);
10639 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
10640 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
10642 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
10645 gsi
= gsi_for_stmt (cond_stmt
);
10646 gimple_regimplify_operands (cond_stmt
, &gsi
);
10649 /* Remove GIMPLE_OMP_RETURN. */
10650 gsi
= gsi_last_bb (exit_bb
);
10651 gsi_remove (&gsi
, true);
10653 /* Connect the new blocks. */
10654 remove_edge (FALLTHRU_EDGE (entry_bb
));
10658 remove_edge (BRANCH_EDGE (entry_bb
));
10659 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
10661 e
= BRANCH_EDGE (l1_bb
);
10662 ne
= FALLTHRU_EDGE (l1_bb
);
10663 e
->flags
= EDGE_TRUE_VALUE
;
10667 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
10669 ne
= single_succ_edge (l1_bb
);
10670 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
10673 ne
->flags
= EDGE_FALSE_VALUE
;
10674 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
10675 ne
->probability
= REG_BR_PROB_BASE
/ 8;
10677 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
10678 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
10679 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
10683 struct loop
*loop
= alloc_loop ();
10684 loop
->header
= l1_bb
;
10685 loop
->latch
= cont_bb
;
10686 add_loop (loop
, l1_bb
->loop_father
);
10687 if (safelen
== NULL_TREE
)
10688 loop
->safelen
= INT_MAX
;
10691 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
10692 if (TREE_CODE (safelen
) != INTEGER_CST
)
10694 else if (!tree_fits_uhwi_p (safelen
)
10695 || tree_to_uhwi (safelen
) > INT_MAX
)
10696 loop
->safelen
= INT_MAX
;
10698 loop
->safelen
= tree_to_uhwi (safelen
);
10699 if (loop
->safelen
== 1)
10704 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
10705 cfun
->has_simduid_loops
= true;
10707 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10709 if ((flag_tree_loop_vectorize
10710 || (!global_options_set
.x_flag_tree_loop_vectorize
10711 && !global_options_set
.x_flag_tree_vectorize
))
10712 && flag_tree_loop_optimize
10713 && loop
->safelen
> 1)
10715 loop
->force_vectorize
= true;
10716 cfun
->has_force_vectorize_loops
= true;
10720 cfun
->has_simduid_loops
= true;
10723 /* Taskloop construct is represented after gimplification with
10724 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10725 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10726 which should just compute all the needed loop temporaries
10727 for GIMPLE_OMP_TASK. */
10730 expand_omp_taskloop_for_outer (struct omp_region
*region
,
10731 struct omp_for_data
*fd
,
10732 gimple
*inner_stmt
)
10734 tree type
, bias
= NULL_TREE
;
10735 basic_block entry_bb
, cont_bb
, exit_bb
;
10736 gimple_stmt_iterator gsi
;
10737 gassign
*assign_stmt
;
10738 tree
*counts
= NULL
;
10741 gcc_assert (inner_stmt
);
10742 gcc_assert (region
->cont
);
10743 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_TASK
10744 && gimple_omp_task_taskloop_p (inner_stmt
));
10745 type
= TREE_TYPE (fd
->loop
.v
);
10747 /* See if we need to bias by LLONG_MIN. */
10748 if (fd
->iter_type
== long_long_unsigned_type_node
10749 && TREE_CODE (type
) == INTEGER_TYPE
10750 && !TYPE_UNSIGNED (type
))
10754 if (fd
->loop
.cond_code
== LT_EXPR
)
10757 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
10761 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
10764 if (TREE_CODE (n1
) != INTEGER_CST
10765 || TREE_CODE (n2
) != INTEGER_CST
10766 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
10767 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
10770 entry_bb
= region
->entry
;
10771 cont_bb
= region
->cont
;
10772 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
10773 gcc_assert (BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
10774 exit_bb
= region
->exit
;
10776 gsi
= gsi_last_bb (entry_bb
);
10777 gimple
*for_stmt
= gsi_stmt (gsi
);
10778 gcc_assert (gimple_code (for_stmt
) == GIMPLE_OMP_FOR
);
10779 if (fd
->collapse
> 1)
10781 int first_zero_iter
= -1, dummy
= -1;
10782 basic_block zero_iter_bb
= NULL
, dummy_bb
= NULL
, l2_dom_bb
= NULL
;
10784 counts
= XALLOCAVEC (tree
, fd
->collapse
);
10785 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
10786 zero_iter_bb
, first_zero_iter
,
10787 dummy_bb
, dummy
, l2_dom_bb
);
10791 /* Some counts[i] vars might be uninitialized if
10792 some loop has zero iterations. But the body shouldn't
10793 be executed in that case, so just avoid uninit warnings. */
10794 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
10795 if (SSA_VAR_P (counts
[i
]))
10796 TREE_NO_WARNING (counts
[i
]) = 1;
10798 edge e
= split_block (entry_bb
, gsi_stmt (gsi
));
10799 entry_bb
= e
->dest
;
10800 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
10801 gsi
= gsi_last_bb (entry_bb
);
10802 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
10803 get_immediate_dominator (CDI_DOMINATORS
,
10811 if (POINTER_TYPE_P (TREE_TYPE (t0
))
10812 && TYPE_PRECISION (TREE_TYPE (t0
))
10813 != TYPE_PRECISION (fd
->iter_type
))
10815 /* Avoid casting pointers to integer of a different size. */
10816 tree itype
= signed_type_for (type
);
10817 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
10818 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
10822 t1
= fold_convert (fd
->iter_type
, t1
);
10823 t0
= fold_convert (fd
->iter_type
, t0
);
10827 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
10828 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
10831 tree innerc
= find_omp_clause (gimple_omp_task_clauses (inner_stmt
),
10832 OMP_CLAUSE__LOOPTEMP_
);
10833 gcc_assert (innerc
);
10834 tree startvar
= OMP_CLAUSE_DECL (innerc
);
10835 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
), OMP_CLAUSE__LOOPTEMP_
);
10836 gcc_assert (innerc
);
10837 tree endvar
= OMP_CLAUSE_DECL (innerc
);
10838 if (fd
->collapse
> 1 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
10840 gcc_assert (innerc
);
10841 for (i
= 1; i
< fd
->collapse
; i
++)
10843 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
10844 OMP_CLAUSE__LOOPTEMP_
);
10845 gcc_assert (innerc
);
10847 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
10848 OMP_CLAUSE__LOOPTEMP_
);
10851 /* If needed (inner taskloop has lastprivate clause), propagate
10852 down the total number of iterations. */
10853 tree t
= force_gimple_operand_gsi (&gsi
, fd
->loop
.n2
, false,
10855 GSI_CONTINUE_LINKING
);
10856 assign_stmt
= gimple_build_assign (OMP_CLAUSE_DECL (innerc
), t
);
10857 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10861 t0
= force_gimple_operand_gsi (&gsi
, t0
, false, NULL_TREE
, false,
10862 GSI_CONTINUE_LINKING
);
10863 assign_stmt
= gimple_build_assign (startvar
, t0
);
10864 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10866 t1
= force_gimple_operand_gsi (&gsi
, t1
, false, NULL_TREE
, false,
10867 GSI_CONTINUE_LINKING
);
10868 assign_stmt
= gimple_build_assign (endvar
, t1
);
10869 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
10870 if (fd
->collapse
> 1)
10871 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
10873 /* Remove the GIMPLE_OMP_FOR statement. */
10874 gsi
= gsi_for_stmt (for_stmt
);
10875 gsi_remove (&gsi
, true);
10877 gsi
= gsi_last_bb (cont_bb
);
10878 gsi_remove (&gsi
, true);
10880 gsi
= gsi_last_bb (exit_bb
);
10881 gsi_remove (&gsi
, true);
10883 FALLTHRU_EDGE (entry_bb
)->probability
= REG_BR_PROB_BASE
;
10884 remove_edge (BRANCH_EDGE (entry_bb
));
10885 FALLTHRU_EDGE (cont_bb
)->probability
= REG_BR_PROB_BASE
;
10886 remove_edge (BRANCH_EDGE (cont_bb
));
10887 set_immediate_dominator (CDI_DOMINATORS
, exit_bb
, cont_bb
);
10888 set_immediate_dominator (CDI_DOMINATORS
, region
->entry
,
10889 recompute_dominator (CDI_DOMINATORS
, region
->entry
));
10892 /* Taskloop construct is represented after gimplification with
10893 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10894 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10895 GOMP_taskloop{,_ull} function arranges for each task to be given just
10896 a single range of iterations. */
10899 expand_omp_taskloop_for_inner (struct omp_region
*region
,
10900 struct omp_for_data
*fd
,
10901 gimple
*inner_stmt
)
10903 tree e
, t
, type
, itype
, vmain
, vback
, bias
= NULL_TREE
;
10904 basic_block entry_bb
, exit_bb
, body_bb
, cont_bb
, collapse_bb
= NULL
;
10905 basic_block fin_bb
;
10906 gimple_stmt_iterator gsi
;
10908 bool broken_loop
= region
->cont
== NULL
;
10909 tree
*counts
= NULL
;
10912 itype
= type
= TREE_TYPE (fd
->loop
.v
);
10913 if (POINTER_TYPE_P (type
))
10914 itype
= signed_type_for (type
);
10916 /* See if we need to bias by LLONG_MIN. */
10917 if (fd
->iter_type
== long_long_unsigned_type_node
10918 && TREE_CODE (type
) == INTEGER_TYPE
10919 && !TYPE_UNSIGNED (type
))
10923 if (fd
->loop
.cond_code
== LT_EXPR
)
10926 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
10930 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
10933 if (TREE_CODE (n1
) != INTEGER_CST
10934 || TREE_CODE (n2
) != INTEGER_CST
10935 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
10936 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
10939 entry_bb
= region
->entry
;
10940 cont_bb
= region
->cont
;
10941 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
10942 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
10943 gcc_assert (broken_loop
10944 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
10945 body_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
10948 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
10949 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
10951 exit_bb
= region
->exit
;
10953 /* Iteration space partitioning goes in ENTRY_BB. */
10954 gsi
= gsi_last_bb (entry_bb
);
10955 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
10957 if (fd
->collapse
> 1)
10959 int first_zero_iter
= -1, dummy
= -1;
10960 basic_block l2_dom_bb
= NULL
, dummy_bb
= NULL
;
10962 counts
= XALLOCAVEC (tree
, fd
->collapse
);
10963 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
10964 fin_bb
, first_zero_iter
,
10965 dummy_bb
, dummy
, l2_dom_bb
);
10969 t
= integer_one_node
;
10971 step
= fd
->loop
.step
;
10972 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
10973 OMP_CLAUSE__LOOPTEMP_
);
10974 gcc_assert (innerc
);
10975 n1
= OMP_CLAUSE_DECL (innerc
);
10976 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
), OMP_CLAUSE__LOOPTEMP_
);
10977 gcc_assert (innerc
);
10978 n2
= OMP_CLAUSE_DECL (innerc
);
10981 n1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, n1
, bias
);
10982 n2
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, n2
, bias
);
10984 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
10985 true, NULL_TREE
, true, GSI_SAME_STMT
);
10986 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
10987 true, NULL_TREE
, true, GSI_SAME_STMT
);
10988 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
10989 true, NULL_TREE
, true, GSI_SAME_STMT
);
10991 tree startvar
= fd
->loop
.v
;
10992 tree endvar
= NULL_TREE
;
10994 if (gimple_omp_for_combined_p (fd
->for_stmt
))
10996 tree clauses
= gimple_omp_for_clauses (inner_stmt
);
10997 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
10998 gcc_assert (innerc
);
10999 startvar
= OMP_CLAUSE_DECL (innerc
);
11000 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
11001 OMP_CLAUSE__LOOPTEMP_
);
11002 gcc_assert (innerc
);
11003 endvar
= OMP_CLAUSE_DECL (innerc
);
11005 t
= fold_convert (TREE_TYPE (startvar
), n1
);
11006 t
= force_gimple_operand_gsi (&gsi
, t
,
11008 && TREE_ADDRESSABLE (startvar
),
11009 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
11010 gimple
*assign_stmt
= gimple_build_assign (startvar
, t
);
11011 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
11013 t
= fold_convert (TREE_TYPE (startvar
), n2
);
11014 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
11015 false, GSI_CONTINUE_LINKING
);
11018 assign_stmt
= gimple_build_assign (endvar
, e
);
11019 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
11020 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
11021 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
11023 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
11024 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
11026 if (fd
->collapse
> 1)
11027 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
11031 /* The code controlling the sequential loop replaces the
11032 GIMPLE_OMP_CONTINUE. */
11033 gsi
= gsi_last_bb (cont_bb
);
11034 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
11035 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
11036 vmain
= gimple_omp_continue_control_use (cont_stmt
);
11037 vback
= gimple_omp_continue_control_def (cont_stmt
);
11039 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
11041 if (POINTER_TYPE_P (type
))
11042 t
= fold_build_pointer_plus (vmain
, step
);
11044 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
11045 t
= force_gimple_operand_gsi (&gsi
, t
,
11047 && TREE_ADDRESSABLE (vback
),
11048 NULL_TREE
, true, GSI_SAME_STMT
);
11049 assign_stmt
= gimple_build_assign (vback
, t
);
11050 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
11052 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
11053 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
11055 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
11058 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11059 gsi_remove (&gsi
, true);
11061 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
11062 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
11065 /* Remove the GIMPLE_OMP_FOR statement. */
11066 gsi
= gsi_for_stmt (fd
->for_stmt
);
11067 gsi_remove (&gsi
, true);
11069 /* Remove the GIMPLE_OMP_RETURN statement. */
11070 gsi
= gsi_last_bb (exit_bb
);
11071 gsi_remove (&gsi
, true);
11073 FALLTHRU_EDGE (entry_bb
)->probability
= REG_BR_PROB_BASE
;
11075 remove_edge (BRANCH_EDGE (entry_bb
));
11078 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb
));
11079 region
->outer
->cont
= NULL
;
11082 /* Connect all the blocks. */
11085 ep
= find_edge (cont_bb
, body_bb
);
11086 if (gimple_omp_for_combined_p (fd
->for_stmt
))
11091 else if (fd
->collapse
> 1)
11094 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
11097 ep
->flags
= EDGE_TRUE_VALUE
;
11098 find_edge (cont_bb
, fin_bb
)->flags
11099 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
11102 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
11103 recompute_dominator (CDI_DOMINATORS
, body_bb
));
11105 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
11106 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
11108 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
11110 struct loop
*loop
= alloc_loop ();
11111 loop
->header
= body_bb
;
11112 if (collapse_bb
== NULL
)
11113 loop
->latch
= cont_bb
;
11114 add_loop (loop
, body_bb
->loop_father
);
11118 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11119 partitioned loop. The lowering here is abstracted, in that the
11120 loop parameters are passed through internal functions, which are
11121 further lowered by oacc_device_lower, once we get to the target
11122 compiler. The loop is of the form:
11124 for (V = B; V LTGT E; V += S) {BODY}
11126 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11127 (constant 0 for no chunking) and we will have a GWV partitioning
11128 mask, specifying dimensions over which the loop is to be
11129 partitioned (see note below). We generate code that looks like:
11131 <entry_bb> [incoming FALL->body, BRANCH->exit]
11132 typedef signedintify (typeof (V)) T; // underlying signed integral type
11135 T DIR = LTGT == '<' ? +1 : -1;
11136 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11137 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11139 <head_bb> [created by splitting end of entry_bb]
11140 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11141 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11142 if (!(offset LTGT bound)) goto bottom_bb;
11144 <body_bb> [incoming]
11148 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11150 if (offset LTGT bound) goto body_bb; [*]
11152 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11154 if (chunk < chunk_max) goto head_bb;
11156 <exit_bb> [incoming]
11157 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11159 [*] Needed if V live at end of loop
11161 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11162 transition, and will be specified by a more general mechanism shortly.
11166 expand_oacc_for (struct omp_region
*region
, struct omp_for_data
*fd
)
11168 tree v
= fd
->loop
.v
;
11169 enum tree_code cond_code
= fd
->loop
.cond_code
;
11170 enum tree_code plus_code
= PLUS_EXPR
;
11172 tree chunk_size
= integer_minus_one_node
;
11173 tree gwv
= integer_zero_node
;
11174 tree iter_type
= TREE_TYPE (v
);
11175 tree diff_type
= iter_type
;
11176 tree plus_type
= iter_type
;
11177 struct oacc_collapse
*counts
= NULL
;
11179 gcc_checking_assert (gimple_omp_for_kind (fd
->for_stmt
)
11180 == GF_OMP_FOR_KIND_OACC_LOOP
);
11181 gcc_assert (!gimple_omp_for_combined_into_p (fd
->for_stmt
));
11182 gcc_assert (cond_code
== LT_EXPR
|| cond_code
== GT_EXPR
);
11184 if (POINTER_TYPE_P (iter_type
))
11186 plus_code
= POINTER_PLUS_EXPR
;
11187 plus_type
= sizetype
;
11189 if (POINTER_TYPE_P (diff_type
) || TYPE_UNSIGNED (diff_type
))
11190 diff_type
= signed_type_for (diff_type
);
11192 basic_block entry_bb
= region
->entry
; /* BB ending in OMP_FOR */
11193 basic_block exit_bb
= region
->exit
; /* BB ending in OMP_RETURN */
11194 basic_block cont_bb
= region
->cont
; /* BB ending in OMP_CONTINUE */
11195 basic_block bottom_bb
= NULL
;
11197 /* entry_bb has two sucessors; the branch edge is to the exit
11198 block, fallthrough edge to body. */
11199 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2
11200 && BRANCH_EDGE (entry_bb
)->dest
== exit_bb
);
11202 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11203 body_bb, or to a block whose only successor is the body_bb. Its
11204 fallthrough successor is the final block (same as the branch
11205 successor of the entry_bb). */
11208 basic_block body_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
11209 basic_block bed
= BRANCH_EDGE (cont_bb
)->dest
;
11211 gcc_assert (FALLTHRU_EDGE (cont_bb
)->dest
== exit_bb
);
11212 gcc_assert (bed
== body_bb
|| single_succ_edge (bed
)->dest
== body_bb
);
11215 gcc_assert (!gimple_in_ssa_p (cfun
));
11217 /* The exit block only has entry_bb and cont_bb as predecessors. */
11218 gcc_assert (EDGE_COUNT (exit_bb
->preds
) == 1 + (cont_bb
!= NULL
));
11221 tree chunk_max
= NULL_TREE
;
11222 tree bound
, offset
;
11223 tree step
= create_tmp_var (diff_type
, ".step");
11224 bool up
= cond_code
== LT_EXPR
;
11225 tree dir
= build_int_cst (diff_type
, up
? +1 : -1);
11226 bool chunking
= !gimple_in_ssa_p (cfun
);;
11229 /* SSA instances. */
11230 tree offset_incr
= NULL_TREE
;
11231 tree offset_init
= NULL_TREE
;
11233 gimple_stmt_iterator gsi
;
11239 edge split
, be
, fte
;
11241 /* Split the end of entry_bb to create head_bb. */
11242 split
= split_block (entry_bb
, last_stmt (entry_bb
));
11243 basic_block head_bb
= split
->dest
;
11244 entry_bb
= split
->src
;
11246 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11247 gsi
= gsi_last_bb (entry_bb
);
11248 gomp_for
*for_stmt
= as_a
<gomp_for
*> (gsi_stmt (gsi
));
11249 loc
= gimple_location (for_stmt
);
11251 if (gimple_in_ssa_p (cfun
))
11253 offset_init
= gimple_omp_for_index (for_stmt
, 0);
11254 gcc_assert (integer_zerop (fd
->loop
.n1
));
11255 /* The SSA parallelizer does gang parallelism. */
11256 gwv
= build_int_cst (integer_type_node
, GOMP_DIM_MASK (GOMP_DIM_GANG
));
11259 if (fd
->collapse
> 1)
11261 counts
= XALLOCAVEC (struct oacc_collapse
, fd
->collapse
);
11262 tree total
= expand_oacc_collapse_init (fd
, &gsi
, counts
,
11263 TREE_TYPE (fd
->loop
.n2
));
11265 if (SSA_VAR_P (fd
->loop
.n2
))
11267 total
= force_gimple_operand_gsi (&gsi
, total
, false, NULL_TREE
,
11268 true, GSI_SAME_STMT
);
11269 ass
= gimple_build_assign (fd
->loop
.n2
, total
);
11270 gsi_insert_before (&gsi
, ass
, GSI_SAME_STMT
);
11275 tree b
= fd
->loop
.n1
;
11276 tree e
= fd
->loop
.n2
;
11277 tree s
= fd
->loop
.step
;
11279 b
= force_gimple_operand_gsi (&gsi
, b
, true, NULL_TREE
, true, GSI_SAME_STMT
);
11280 e
= force_gimple_operand_gsi (&gsi
, e
, true, NULL_TREE
, true, GSI_SAME_STMT
);
11282 /* Convert the step, avoiding possible unsigned->signed overflow. */
11283 negating
= !up
&& TYPE_UNSIGNED (TREE_TYPE (s
));
11285 s
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (s
), s
);
11286 s
= fold_convert (diff_type
, s
);
11288 s
= fold_build1 (NEGATE_EXPR
, diff_type
, s
);
11289 s
= force_gimple_operand_gsi (&gsi
, s
, true, NULL_TREE
, true, GSI_SAME_STMT
);
11292 chunk_size
= integer_zero_node
;
11293 expr
= fold_convert (diff_type
, chunk_size
);
11294 chunk_size
= force_gimple_operand_gsi (&gsi
, expr
, true,
11295 NULL_TREE
, true, GSI_SAME_STMT
);
11296 /* Determine the range, avoiding possible unsigned->signed overflow. */
11297 negating
= !up
&& TYPE_UNSIGNED (iter_type
);
11298 expr
= fold_build2 (MINUS_EXPR
, plus_type
,
11299 fold_convert (plus_type
, negating
? b
: e
),
11300 fold_convert (plus_type
, negating
? e
: b
));
11301 expr
= fold_convert (diff_type
, expr
);
11303 expr
= fold_build1 (NEGATE_EXPR
, diff_type
, expr
);
11304 tree range
= force_gimple_operand_gsi (&gsi
, expr
, true,
11305 NULL_TREE
, true, GSI_SAME_STMT
);
11307 chunk_no
= build_int_cst (diff_type
, 0);
11310 gcc_assert (!gimple_in_ssa_p (cfun
));
11313 chunk_max
= create_tmp_var (diff_type
, ".chunk_max");
11314 chunk_no
= create_tmp_var (diff_type
, ".chunk_no");
11316 ass
= gimple_build_assign (chunk_no
, expr
);
11317 gsi_insert_before (&gsi
, ass
, GSI_SAME_STMT
);
11319 call
= gimple_build_call_internal (IFN_GOACC_LOOP
, 6,
11320 build_int_cst (integer_type_node
,
11321 IFN_GOACC_LOOP_CHUNKS
),
11322 dir
, range
, s
, chunk_size
, gwv
);
11323 gimple_call_set_lhs (call
, chunk_max
);
11324 gimple_set_location (call
, loc
);
11325 gsi_insert_before (&gsi
, call
, GSI_SAME_STMT
);
11328 chunk_size
= chunk_no
;
11330 call
= gimple_build_call_internal (IFN_GOACC_LOOP
, 6,
11331 build_int_cst (integer_type_node
,
11332 IFN_GOACC_LOOP_STEP
),
11333 dir
, range
, s
, chunk_size
, gwv
);
11334 gimple_call_set_lhs (call
, step
);
11335 gimple_set_location (call
, loc
);
11336 gsi_insert_before (&gsi
, call
, GSI_SAME_STMT
);
11338 /* Remove the GIMPLE_OMP_FOR. */
11339 gsi_remove (&gsi
, true);
11341 /* Fixup edges from head_bb */
11342 be
= BRANCH_EDGE (head_bb
);
11343 fte
= FALLTHRU_EDGE (head_bb
);
11344 be
->flags
|= EDGE_FALSE_VALUE
;
11345 fte
->flags
^= EDGE_FALLTHRU
| EDGE_TRUE_VALUE
;
11347 basic_block body_bb
= fte
->dest
;
11349 if (gimple_in_ssa_p (cfun
))
11351 gsi
= gsi_last_bb (cont_bb
);
11352 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
11354 offset
= gimple_omp_continue_control_use (cont_stmt
);
11355 offset_incr
= gimple_omp_continue_control_def (cont_stmt
);
11359 offset
= create_tmp_var (diff_type
, ".offset");
11360 offset_init
= offset_incr
= offset
;
11362 bound
= create_tmp_var (TREE_TYPE (offset
), ".bound");
11364 /* Loop offset & bound go into head_bb. */
11365 gsi
= gsi_start_bb (head_bb
);
11367 call
= gimple_build_call_internal (IFN_GOACC_LOOP
, 7,
11368 build_int_cst (integer_type_node
,
11369 IFN_GOACC_LOOP_OFFSET
),
11371 chunk_size
, gwv
, chunk_no
);
11372 gimple_call_set_lhs (call
, offset_init
);
11373 gimple_set_location (call
, loc
);
11374 gsi_insert_after (&gsi
, call
, GSI_CONTINUE_LINKING
);
11376 call
= gimple_build_call_internal (IFN_GOACC_LOOP
, 7,
11377 build_int_cst (integer_type_node
,
11378 IFN_GOACC_LOOP_BOUND
),
11380 chunk_size
, gwv
, offset_init
);
11381 gimple_call_set_lhs (call
, bound
);
11382 gimple_set_location (call
, loc
);
11383 gsi_insert_after (&gsi
, call
, GSI_CONTINUE_LINKING
);
11385 expr
= build2 (cond_code
, boolean_type_node
, offset_init
, bound
);
11386 gsi_insert_after (&gsi
, gimple_build_cond_empty (expr
),
11387 GSI_CONTINUE_LINKING
);
11389 /* V assignment goes into body_bb. */
11390 if (!gimple_in_ssa_p (cfun
))
11392 gsi
= gsi_start_bb (body_bb
);
11394 expr
= build2 (plus_code
, iter_type
, b
,
11395 fold_convert (plus_type
, offset
));
11396 expr
= force_gimple_operand_gsi (&gsi
, expr
, false, NULL_TREE
,
11397 true, GSI_SAME_STMT
);
11398 ass
= gimple_build_assign (v
, expr
);
11399 gsi_insert_before (&gsi
, ass
, GSI_SAME_STMT
);
11400 if (fd
->collapse
> 1)
11401 expand_oacc_collapse_vars (fd
, &gsi
, counts
, v
);
11404 /* Loop increment goes into cont_bb. If this is not a loop, we
11405 will have spawned threads as if it was, and each one will
11406 execute one iteration. The specification is not explicit about
11407 whether such constructs are ill-formed or not, and they can
11408 occur, especially when noreturn routines are involved. */
11411 gsi
= gsi_last_bb (cont_bb
);
11412 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
11413 loc
= gimple_location (cont_stmt
);
11415 /* Increment offset. */
11416 if (gimple_in_ssa_p (cfun
))
11417 expr
= build2 (plus_code
, iter_type
, offset
,
11418 fold_convert (plus_type
, step
));
11420 expr
= build2 (PLUS_EXPR
, diff_type
, offset
, step
);
11421 expr
= force_gimple_operand_gsi (&gsi
, expr
, false, NULL_TREE
,
11422 true, GSI_SAME_STMT
);
11423 ass
= gimple_build_assign (offset_incr
, expr
);
11424 gsi_insert_before (&gsi
, ass
, GSI_SAME_STMT
);
11425 expr
= build2 (cond_code
, boolean_type_node
, offset_incr
, bound
);
11426 gsi_insert_before (&gsi
, gimple_build_cond_empty (expr
), GSI_SAME_STMT
);
11428 /* Remove the GIMPLE_OMP_CONTINUE. */
11429 gsi_remove (&gsi
, true);
11431 /* Fixup edges from cont_bb */
11432 be
= BRANCH_EDGE (cont_bb
);
11433 fte
= FALLTHRU_EDGE (cont_bb
);
11434 be
->flags
|= EDGE_TRUE_VALUE
;
11435 fte
->flags
^= EDGE_FALLTHRU
| EDGE_FALSE_VALUE
;
11439 /* Split the beginning of exit_bb to make bottom_bb. We
11440 need to insert a nop at the start, because splitting is
11441 after a stmt, not before. */
11442 gsi
= gsi_start_bb (exit_bb
);
11443 stmt
= gimple_build_nop ();
11444 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
11445 split
= split_block (exit_bb
, stmt
);
11446 bottom_bb
= split
->src
;
11447 exit_bb
= split
->dest
;
11448 gsi
= gsi_last_bb (bottom_bb
);
11450 /* Chunk increment and test goes into bottom_bb. */
11451 expr
= build2 (PLUS_EXPR
, diff_type
, chunk_no
,
11452 build_int_cst (diff_type
, 1));
11453 ass
= gimple_build_assign (chunk_no
, expr
);
11454 gsi_insert_after (&gsi
, ass
, GSI_CONTINUE_LINKING
);
11456 /* Chunk test at end of bottom_bb. */
11457 expr
= build2 (LT_EXPR
, boolean_type_node
, chunk_no
, chunk_max
);
11458 gsi_insert_after (&gsi
, gimple_build_cond_empty (expr
),
11459 GSI_CONTINUE_LINKING
);
11461 /* Fixup edges from bottom_bb. */
11462 split
->flags
^= EDGE_FALLTHRU
| EDGE_FALSE_VALUE
;
11463 make_edge (bottom_bb
, head_bb
, EDGE_TRUE_VALUE
);
11467 gsi
= gsi_last_bb (exit_bb
);
11468 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
11469 loc
= gimple_location (gsi_stmt (gsi
));
11471 if (!gimple_in_ssa_p (cfun
))
11473 /* Insert the final value of V, in case it is live. This is the
11474 value for the only thread that survives past the join. */
11475 expr
= fold_build2 (MINUS_EXPR
, diff_type
, range
, dir
);
11476 expr
= fold_build2 (PLUS_EXPR
, diff_type
, expr
, s
);
11477 expr
= fold_build2 (TRUNC_DIV_EXPR
, diff_type
, expr
, s
);
11478 expr
= fold_build2 (MULT_EXPR
, diff_type
, expr
, s
);
11479 expr
= build2 (plus_code
, iter_type
, b
, fold_convert (plus_type
, expr
));
11480 expr
= force_gimple_operand_gsi (&gsi
, expr
, false, NULL_TREE
,
11481 true, GSI_SAME_STMT
);
11482 ass
= gimple_build_assign (v
, expr
);
11483 gsi_insert_before (&gsi
, ass
, GSI_SAME_STMT
);
11486 /* Remove the OMP_RETURN. */
11487 gsi_remove (&gsi
, true);
11491 /* We now have one or two nested loops. Update the loop
11493 struct loop
*parent
= entry_bb
->loop_father
;
11494 struct loop
*body
= body_bb
->loop_father
;
11498 struct loop
*chunk_loop
= alloc_loop ();
11499 chunk_loop
->header
= head_bb
;
11500 chunk_loop
->latch
= bottom_bb
;
11501 add_loop (chunk_loop
, parent
);
11502 parent
= chunk_loop
;
11504 else if (parent
!= body
)
11506 gcc_assert (body
->header
== body_bb
);
11507 gcc_assert (body
->latch
== cont_bb
11508 || single_pred (body
->latch
) == cont_bb
);
11514 struct loop
*body_loop
= alloc_loop ();
11515 body_loop
->header
= body_bb
;
11516 body_loop
->latch
= cont_bb
;
11517 add_loop (body_loop
, parent
);
11522 /* Expand the OMP loop defined by REGION. */
11525 expand_omp_for (struct omp_region
*region
, gimple
*inner_stmt
)
11527 struct omp_for_data fd
;
11528 struct omp_for_data_loop
*loops
;
11531 = (struct omp_for_data_loop
*)
11532 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
11533 * sizeof (struct omp_for_data_loop
));
11534 extract_omp_for_data (as_a
<gomp_for
*> (last_stmt (region
->entry
)),
11536 region
->sched_kind
= fd
.sched_kind
;
11537 region
->sched_modifiers
= fd
.sched_modifiers
;
11539 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
11540 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
11541 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
11544 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
11545 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
11546 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
11549 /* If there isn't a continue then this is a degerate case where
11550 the introduction of abnormal edges during lowering will prevent
11551 original loops from being detected. Fix that up. */
11552 loops_state_set (LOOPS_NEED_FIXUP
);
11554 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
11555 expand_omp_simd (region
, &fd
);
11556 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
11557 expand_cilk_for (region
, &fd
);
11558 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
11560 gcc_assert (!inner_stmt
);
11561 expand_oacc_for (region
, &fd
);
11563 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_TASKLOOP
)
11565 if (gimple_omp_for_combined_into_p (fd
.for_stmt
))
11566 expand_omp_taskloop_for_inner (region
, &fd
, inner_stmt
);
11568 expand_omp_taskloop_for_outer (region
, &fd
, inner_stmt
);
11570 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
11571 && !fd
.have_ordered
)
11573 if (fd
.chunk_size
== NULL
)
11574 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
11576 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
11580 int fn_index
, start_ix
, next_ix
;
11582 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
11583 == GF_OMP_FOR_KIND_FOR
);
11584 if (fd
.chunk_size
== NULL
11585 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
11586 fd
.chunk_size
= integer_zero_node
;
11587 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
11588 switch (fd
.sched_kind
)
11590 case OMP_CLAUSE_SCHEDULE_RUNTIME
:
11593 case OMP_CLAUSE_SCHEDULE_DYNAMIC
:
11594 case OMP_CLAUSE_SCHEDULE_GUIDED
:
11595 if ((fd
.sched_modifiers
& OMP_CLAUSE_SCHEDULE_NONMONOTONIC
)
11597 && !fd
.have_ordered
)
11599 fn_index
= 3 + fd
.sched_kind
;
11604 fn_index
= fd
.sched_kind
;
11608 fn_index
+= fd
.have_ordered
* 6;
11610 start_ix
= ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START
) + fn_index
;
11612 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
11613 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
11614 if (fd
.iter_type
== long_long_unsigned_type_node
)
11616 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11617 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
11618 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11619 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
11621 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
11622 (enum built_in_function
) next_ix
, inner_stmt
);
11625 if (gimple_in_ssa_p (cfun
))
11626 update_ssa (TODO_update_ssa_only_virtuals
);
11630 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11632 v = GOMP_sections_start (n);
11649 v = GOMP_sections_next ();
11654 If this is a combined parallel sections, replace the call to
11655 GOMP_sections_start with call to GOMP_sections_next. */
11658 expand_omp_sections (struct omp_region
*region
)
11660 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
11662 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
11663 gimple_stmt_iterator si
, switch_si
;
11664 gomp_sections
*sections_stmt
;
11666 gomp_continue
*cont
;
11669 struct omp_region
*inner
;
11671 bool exit_reachable
= region
->cont
!= NULL
;
11673 gcc_assert (region
->exit
!= NULL
);
11674 entry_bb
= region
->entry
;
11675 l0_bb
= single_succ (entry_bb
);
11676 l1_bb
= region
->cont
;
11677 l2_bb
= region
->exit
;
11678 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
11679 l2
= gimple_block_label (l2_bb
);
11682 /* This can happen if there are reductions. */
11683 len
= EDGE_COUNT (l0_bb
->succs
);
11684 gcc_assert (len
> 0);
11685 e
= EDGE_SUCC (l0_bb
, len
- 1);
11686 si
= gsi_last_bb (e
->dest
);
11689 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
11690 l2
= gimple_block_label (e
->dest
);
11692 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
11694 si
= gsi_last_bb (e
->dest
);
11696 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
11698 l2
= gimple_block_label (e
->dest
);
11703 if (exit_reachable
)
11704 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
11706 default_bb
= create_empty_bb (l0_bb
);
11708 /* We will build a switch() with enough cases for all the
11709 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11710 and a default case to abort if something goes wrong. */
11711 len
= EDGE_COUNT (l0_bb
->succs
);
11713 /* Use vec::quick_push on label_vec throughout, since we know the size
11715 auto_vec
<tree
> label_vec (len
);
11717 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11718 GIMPLE_OMP_SECTIONS statement. */
11719 si
= gsi_last_bb (entry_bb
);
11720 sections_stmt
= as_a
<gomp_sections
*> (gsi_stmt (si
));
11721 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
11722 vin
= gimple_omp_sections_control (sections_stmt
);
11723 if (!is_combined_parallel (region
))
11725 /* If we are not inside a combined parallel+sections region,
11726 call GOMP_sections_start. */
11727 t
= build_int_cst (unsigned_type_node
, len
- 1);
11728 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
11729 stmt
= gimple_build_call (u
, 1, t
);
11733 /* Otherwise, call GOMP_sections_next. */
11734 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
11735 stmt
= gimple_build_call (u
, 0);
11737 gimple_call_set_lhs (stmt
, vin
);
11738 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
11739 gsi_remove (&si
, true);
11741 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11743 switch_si
= gsi_last_bb (l0_bb
);
11744 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
11745 if (exit_reachable
)
11747 cont
= as_a
<gomp_continue
*> (last_stmt (l1_bb
));
11748 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
11749 vmain
= gimple_omp_continue_control_use (cont
);
11750 vnext
= gimple_omp_continue_control_def (cont
);
11758 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
11759 label_vec
.quick_push (t
);
11762 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11763 for (inner
= region
->inner
, casei
= 1;
11765 inner
= inner
->next
, i
++, casei
++)
11767 basic_block s_entry_bb
, s_exit_bb
;
11769 /* Skip optional reduction region. */
11770 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
11777 s_entry_bb
= inner
->entry
;
11778 s_exit_bb
= inner
->exit
;
11780 t
= gimple_block_label (s_entry_bb
);
11781 u
= build_int_cst (unsigned_type_node
, casei
);
11782 u
= build_case_label (u
, NULL
, t
);
11783 label_vec
.quick_push (u
);
11785 si
= gsi_last_bb (s_entry_bb
);
11786 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
11787 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
11788 gsi_remove (&si
, true);
11789 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
11791 if (s_exit_bb
== NULL
)
11794 si
= gsi_last_bb (s_exit_bb
);
11795 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
11796 gsi_remove (&si
, true);
11798 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
11801 /* Error handling code goes in DEFAULT_BB. */
11802 t
= gimple_block_label (default_bb
);
11803 u
= build_case_label (NULL
, NULL
, t
);
11804 make_edge (l0_bb
, default_bb
, 0);
11805 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
11807 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
11808 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
11809 gsi_remove (&switch_si
, true);
11811 si
= gsi_start_bb (default_bb
);
11812 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
11813 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
11815 if (exit_reachable
)
11819 /* Code to get the next section goes in L1_BB. */
11820 si
= gsi_last_bb (l1_bb
);
11821 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
11823 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
11824 stmt
= gimple_build_call (bfn_decl
, 0);
11825 gimple_call_set_lhs (stmt
, vnext
);
11826 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
11827 gsi_remove (&si
, true);
11829 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
11832 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11833 si
= gsi_last_bb (l2_bb
);
11834 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
11835 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
11836 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
11837 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
11839 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
11840 stmt
= gimple_build_call (t
, 0);
11841 if (gimple_omp_return_lhs (gsi_stmt (si
)))
11842 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
11843 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
11844 gsi_remove (&si
, true);
11846 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
11850 /* Expand code for an OpenMP single directive. We've already expanded
11851 much of the code, here we simply place the GOMP_barrier call. */
11854 expand_omp_single (struct omp_region
*region
)
11856 basic_block entry_bb
, exit_bb
;
11857 gimple_stmt_iterator si
;
11859 entry_bb
= region
->entry
;
11860 exit_bb
= region
->exit
;
11862 si
= gsi_last_bb (entry_bb
);
11863 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
11864 gsi_remove (&si
, true);
11865 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
11867 si
= gsi_last_bb (exit_bb
);
11868 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
11870 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
11871 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
11873 gsi_remove (&si
, true);
11874 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
11878 /* Generic expansion for OpenMP synchronization directives: master,
11879 ordered and critical. All we need to do here is remove the entry
11880 and exit markers for REGION. */
11883 expand_omp_synch (struct omp_region
*region
)
11885 basic_block entry_bb
, exit_bb
;
11886 gimple_stmt_iterator si
;
11888 entry_bb
= region
->entry
;
11889 exit_bb
= region
->exit
;
11891 si
= gsi_last_bb (entry_bb
);
11892 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
11893 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
11894 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
11895 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
11896 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
11897 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
11898 gsi_remove (&si
, true);
11899 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
11903 si
= gsi_last_bb (exit_bb
);
11904 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
11905 gsi_remove (&si
, true);
11906 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
11910 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11911 operation as a normal volatile load. */
11914 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
11915 tree loaded_val
, int index
)
11917 enum built_in_function tmpbase
;
11918 gimple_stmt_iterator gsi
;
11919 basic_block store_bb
;
11922 tree decl
, call
, type
, itype
;
11924 gsi
= gsi_last_bb (load_bb
);
11925 stmt
= gsi_stmt (gsi
);
11926 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
11927 loc
= gimple_location (stmt
);
11929 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11930 is smaller than word size, then expand_atomic_load assumes that the load
11931 is atomic. We could avoid the builtin entirely in this case. */
11933 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
11934 decl
= builtin_decl_explicit (tmpbase
);
11935 if (decl
== NULL_TREE
)
11938 type
= TREE_TYPE (loaded_val
);
11939 itype
= TREE_TYPE (TREE_TYPE (decl
));
11941 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
11942 build_int_cst (NULL
,
11943 gimple_omp_atomic_seq_cst_p (stmt
)
11945 : MEMMODEL_RELAXED
));
11946 if (!useless_type_conversion_p (type
, itype
))
11947 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
11948 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
11950 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
11951 gsi_remove (&gsi
, true);
11953 store_bb
= single_succ (load_bb
);
11954 gsi
= gsi_last_bb (store_bb
);
11955 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
11956 gsi_remove (&gsi
, true);
11958 if (gimple_in_ssa_p (cfun
))
11959 update_ssa (TODO_update_ssa_no_phi
);
11964 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11965 operation as a normal volatile store. */
11968 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
11969 tree loaded_val
, tree stored_val
, int index
)
11971 enum built_in_function tmpbase
;
11972 gimple_stmt_iterator gsi
;
11973 basic_block store_bb
= single_succ (load_bb
);
11976 tree decl
, call
, type
, itype
;
11977 machine_mode imode
;
11980 gsi
= gsi_last_bb (load_bb
);
11981 stmt
= gsi_stmt (gsi
);
11982 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
11984 /* If the load value is needed, then this isn't a store but an exchange. */
11985 exchange
= gimple_omp_atomic_need_value_p (stmt
);
11987 gsi
= gsi_last_bb (store_bb
);
11988 stmt
= gsi_stmt (gsi
);
11989 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
11990 loc
= gimple_location (stmt
);
11992 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11993 is smaller than word size, then expand_atomic_store assumes that the store
11994 is atomic. We could avoid the builtin entirely in this case. */
11996 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
11997 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
11998 decl
= builtin_decl_explicit (tmpbase
);
11999 if (decl
== NULL_TREE
)
12002 type
= TREE_TYPE (stored_val
);
12004 /* Dig out the type of the function's second argument. */
12005 itype
= TREE_TYPE (decl
);
12006 itype
= TYPE_ARG_TYPES (itype
);
12007 itype
= TREE_CHAIN (itype
);
12008 itype
= TREE_VALUE (itype
);
12009 imode
= TYPE_MODE (itype
);
12011 if (exchange
&& !can_atomic_exchange_p (imode
, true))
12014 if (!useless_type_conversion_p (itype
, type
))
12015 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
12016 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
12017 build_int_cst (NULL
,
12018 gimple_omp_atomic_seq_cst_p (stmt
)
12020 : MEMMODEL_RELAXED
));
12023 if (!useless_type_conversion_p (type
, itype
))
12024 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
12025 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
12028 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
12029 gsi_remove (&gsi
, true);
12031 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12032 gsi
= gsi_last_bb (load_bb
);
12033 gsi_remove (&gsi
, true);
12035 if (gimple_in_ssa_p (cfun
))
12036 update_ssa (TODO_update_ssa_no_phi
);
12041 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12042 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12043 size of the data type, and thus usable to find the index of the builtin
12044 decl. Returns false if the expression is not of the proper form. */
12047 expand_omp_atomic_fetch_op (basic_block load_bb
,
12048 tree addr
, tree loaded_val
,
12049 tree stored_val
, int index
)
12051 enum built_in_function oldbase
, newbase
, tmpbase
;
12052 tree decl
, itype
, call
;
12054 basic_block store_bb
= single_succ (load_bb
);
12055 gimple_stmt_iterator gsi
;
12058 enum tree_code code
;
12059 bool need_old
, need_new
;
12060 machine_mode imode
;
12063 /* We expect to find the following sequences:
12066 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12069 val = tmp OP something; (or: something OP tmp)
12070 GIMPLE_OMP_STORE (val)
12072 ???FIXME: Allow a more flexible sequence.
12073 Perhaps use data flow to pick the statements.
12077 gsi
= gsi_after_labels (store_bb
);
12078 stmt
= gsi_stmt (gsi
);
12079 loc
= gimple_location (stmt
);
12080 if (!is_gimple_assign (stmt
))
12083 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
12085 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
12086 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
12087 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
12088 gcc_checking_assert (!need_old
|| !need_new
);
12090 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
12093 /* Check for one of the supported fetch-op operations. */
12094 code
= gimple_assign_rhs_code (stmt
);
12098 case POINTER_PLUS_EXPR
:
12099 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
12100 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
12103 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
12104 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
12107 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
12108 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
12111 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
12112 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
12115 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
12116 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
12122 /* Make sure the expression is of the proper form. */
12123 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
12124 rhs
= gimple_assign_rhs2 (stmt
);
12125 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
12126 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
12127 rhs
= gimple_assign_rhs1 (stmt
);
12131 tmpbase
= ((enum built_in_function
)
12132 ((need_new
? newbase
: oldbase
) + index
+ 1));
12133 decl
= builtin_decl_explicit (tmpbase
);
12134 if (decl
== NULL_TREE
)
12136 itype
= TREE_TYPE (TREE_TYPE (decl
));
12137 imode
= TYPE_MODE (itype
);
12139 /* We could test all of the various optabs involved, but the fact of the
12140 matter is that (with the exception of i486 vs i586 and xadd) all targets
12141 that support any atomic operaton optab also implements compare-and-swap.
12142 Let optabs.c take care of expanding any compare-and-swap loop. */
12143 if (!can_compare_and_swap_p (imode
, true))
12146 gsi
= gsi_last_bb (load_bb
);
12147 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
12149 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12150 It only requires that the operation happen atomically. Thus we can
12151 use the RELAXED memory model. */
12152 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
12153 fold_convert_loc (loc
, itype
, rhs
),
12154 build_int_cst (NULL
,
12155 seq_cst
? MEMMODEL_SEQ_CST
12156 : MEMMODEL_RELAXED
));
12158 if (need_old
|| need_new
)
12160 lhs
= need_old
? loaded_val
: stored_val
;
12161 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
12162 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
12165 call
= fold_convert_loc (loc
, void_type_node
, call
);
12166 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
12167 gsi_remove (&gsi
, true);
12169 gsi
= gsi_last_bb (store_bb
);
12170 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
12171 gsi_remove (&gsi
, true);
12172 gsi
= gsi_last_bb (store_bb
);
12173 stmt
= gsi_stmt (gsi
);
12174 gsi_remove (&gsi
, true);
12176 if (gimple_in_ssa_p (cfun
))
12178 release_defs (stmt
);
12179 update_ssa (TODO_update_ssa_no_phi
);
12185 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12189 newval = rhs; // with oldval replacing *addr in rhs
12190 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12191 if (oldval != newval)
12194 INDEX is log2 of the size of the data type, and thus usable to find the
12195 index of the builtin decl. */
12198 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
12199 tree addr
, tree loaded_val
, tree stored_val
,
12202 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
12203 tree type
, itype
, cmpxchg
, iaddr
;
12204 gimple_stmt_iterator si
;
12205 basic_block loop_header
= single_succ (load_bb
);
12206 gimple
*phi
, *stmt
;
12208 enum built_in_function fncode
;
12210 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12211 order to use the RELAXED memory model effectively. */
12212 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12214 cmpxchg
= builtin_decl_explicit (fncode
);
12215 if (cmpxchg
== NULL_TREE
)
12217 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
12218 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
12220 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
12223 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12224 si
= gsi_last_bb (load_bb
);
12225 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
12227 /* For floating-point values, we'll need to view-convert them to integers
12228 so that we can perform the atomic compare and swap. Simplify the
12229 following code by always setting up the "i"ntegral variables. */
12230 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
12234 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
12237 = force_gimple_operand_gsi (&si
,
12238 fold_convert (TREE_TYPE (iaddr
), addr
),
12239 false, NULL_TREE
, true, GSI_SAME_STMT
);
12240 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
12241 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
12242 loadedi
= create_tmp_var (itype
);
12243 if (gimple_in_ssa_p (cfun
))
12244 loadedi
= make_ssa_name (loadedi
);
12249 loadedi
= loaded_val
;
12252 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
12253 tree loaddecl
= builtin_decl_explicit (fncode
);
12256 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
12257 build_call_expr (loaddecl
, 2, iaddr
,
12258 build_int_cst (NULL_TREE
,
12259 MEMMODEL_RELAXED
)));
12261 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
12262 build_int_cst (TREE_TYPE (iaddr
), 0));
12265 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
12268 /* Move the value to the LOADEDI temporary. */
12269 if (gimple_in_ssa_p (cfun
))
12271 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
12272 phi
= create_phi_node (loadedi
, loop_header
);
12273 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
12277 gsi_insert_before (&si
,
12278 gimple_build_assign (loadedi
, initial
),
12280 if (loadedi
!= loaded_val
)
12282 gimple_stmt_iterator gsi2
;
12285 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
12286 gsi2
= gsi_start_bb (loop_header
);
12287 if (gimple_in_ssa_p (cfun
))
12290 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
12291 true, GSI_SAME_STMT
);
12292 stmt
= gimple_build_assign (loaded_val
, x
);
12293 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
12297 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
12298 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
12299 true, GSI_SAME_STMT
);
12302 gsi_remove (&si
, true);
12304 si
= gsi_last_bb (store_bb
);
12305 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
12308 storedi
= stored_val
;
12311 force_gimple_operand_gsi (&si
,
12312 build1 (VIEW_CONVERT_EXPR
, itype
,
12313 stored_val
), true, NULL_TREE
, true,
12316 /* Build the compare&swap statement. */
12317 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
12318 new_storedi
= force_gimple_operand_gsi (&si
,
12319 fold_convert (TREE_TYPE (loadedi
),
12322 true, GSI_SAME_STMT
);
12324 if (gimple_in_ssa_p (cfun
))
12325 old_vali
= loadedi
;
12328 old_vali
= create_tmp_var (TREE_TYPE (loadedi
));
12329 stmt
= gimple_build_assign (old_vali
, loadedi
);
12330 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
12332 stmt
= gimple_build_assign (loadedi
, new_storedi
);
12333 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
12336 /* Note that we always perform the comparison as an integer, even for
12337 floating point. This allows the atomic operation to properly
12338 succeed even with NaNs and -0.0. */
12339 stmt
= gimple_build_cond_empty
12340 (build2 (NE_EXPR
, boolean_type_node
,
12341 new_storedi
, old_vali
));
12342 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
12345 e
= single_succ_edge (store_bb
);
12346 e
->flags
&= ~EDGE_FALLTHRU
;
12347 e
->flags
|= EDGE_FALSE_VALUE
;
12349 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
12351 /* Copy the new value to loadedi (we already did that before the condition
12352 if we are not in SSA). */
12353 if (gimple_in_ssa_p (cfun
))
12355 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
12356 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
12359 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12360 gsi_remove (&si
, true);
12362 struct loop
*loop
= alloc_loop ();
12363 loop
->header
= loop_header
;
12364 loop
->latch
= store_bb
;
12365 add_loop (loop
, loop_header
->loop_father
);
12367 if (gimple_in_ssa_p (cfun
))
12368 update_ssa (TODO_update_ssa_no_phi
);
12373 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12375 GOMP_atomic_start ();
12377 GOMP_atomic_end ();
12379 The result is not globally atomic, but works so long as all parallel
12380 references are within #pragma omp atomic directives. According to
12381 responses received from omp@openmp.org, appears to be within spec.
12382 Which makes sense, since that's how several other compilers handle
12383 this situation as well.
12384 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12385 expanding. STORED_VAL is the operand of the matching
12386 GIMPLE_OMP_ATOMIC_STORE.
12389 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12390 loaded_val = *addr;
12393 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12394 *addr = stored_val;
12398 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
12399 tree addr
, tree loaded_val
, tree stored_val
)
12401 gimple_stmt_iterator si
;
12405 si
= gsi_last_bb (load_bb
);
12406 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
12408 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
12409 t
= build_call_expr (t
, 0);
12410 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
12412 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
12413 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
12414 gsi_remove (&si
, true);
12416 si
= gsi_last_bb (store_bb
);
12417 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
12419 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
12421 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
12423 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
12424 t
= build_call_expr (t
, 0);
12425 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
12426 gsi_remove (&si
, true);
12428 if (gimple_in_ssa_p (cfun
))
12429 update_ssa (TODO_update_ssa_no_phi
);
12433 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12434 using expand_omp_atomic_fetch_op. If it failed, we try to
12435 call expand_omp_atomic_pipeline, and if it fails too, the
12436 ultimate fallback is wrapping the operation in a mutex
12437 (expand_omp_atomic_mutex). REGION is the atomic region built
12438 by build_omp_regions_1(). */
12441 expand_omp_atomic (struct omp_region
*region
)
12443 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
12444 gomp_atomic_load
*load
= as_a
<gomp_atomic_load
*> (last_stmt (load_bb
));
12445 gomp_atomic_store
*store
= as_a
<gomp_atomic_store
*> (last_stmt (store_bb
));
12446 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
12447 tree addr
= gimple_omp_atomic_load_rhs (load
);
12448 tree stored_val
= gimple_omp_atomic_store_val (store
);
12449 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
12450 HOST_WIDE_INT index
;
12452 /* Make sure the type is one of the supported sizes. */
12453 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
12454 index
= exact_log2 (index
);
12455 if (index
>= 0 && index
<= 4)
12457 unsigned int align
= TYPE_ALIGN_UNIT (type
);
12459 /* __sync builtins require strict data alignment. */
12460 if (exact_log2 (align
) >= index
)
12463 if (loaded_val
== stored_val
12464 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
12465 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
12466 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
12467 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
12470 /* Atomic store. */
12471 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
12472 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
12473 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
12474 && store_bb
== single_succ (load_bb
)
12475 && first_stmt (store_bb
) == store
12476 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
12477 stored_val
, index
))
12480 /* When possible, use specialized atomic update functions. */
12481 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
12482 && store_bb
== single_succ (load_bb
)
12483 && expand_omp_atomic_fetch_op (load_bb
, addr
,
12484 loaded_val
, stored_val
, index
))
12487 /* If we don't have specialized __sync builtins, try and implement
12488 as a compare and swap loop. */
12489 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
12490 loaded_val
, stored_val
, index
))
12495 /* The ultimate fallback is wrapping the operation in a mutex. */
12496 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
12500 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12501 macro on gomp-constants.h. We do not check for overflow. */
12504 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
12508 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
12511 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
12512 device
, build_int_cst (unsigned_type_node
,
12513 GOMP_LAUNCH_DEVICE_SHIFT
));
12514 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
12519 /* Look for compute grid dimension clauses and convert to an attribute
12520 attached to FN. This permits the target-side code to (a) massage
12521 the dimensions, (b) emit that data and (c) optimize. Non-constant
12522 dimensions are pushed onto ARGS.
12524 The attribute value is a TREE_LIST. A set of dimensions is
12525 represented as a list of INTEGER_CST. Those that are runtime
12526 exprs are represented as an INTEGER_CST of zero.
12528 TOOO. Normally the attribute will just contain a single such list. If
12529 however it contains a list of lists, this will represent the use of
12530 device_type. Each member of the outer list is an assoc list of
12531 dimensions, keyed by the device type. The first entry will be the
12532 default. Well, that's the plan. */
12534 #define OACC_FN_ATTRIB "oacc function"
12536 /* Replace any existing oacc fn attribute with updated dimensions. */
12539 replace_oacc_fn_attrib (tree fn
, tree dims
)
12541 tree ident
= get_identifier (OACC_FN_ATTRIB
);
12542 tree attribs
= DECL_ATTRIBUTES (fn
);
12544 /* If we happen to be present as the first attrib, drop it. */
12545 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
12546 attribs
= TREE_CHAIN (attribs
);
12547 DECL_ATTRIBUTES (fn
) = tree_cons (ident
, dims
, attribs
);
12550 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12551 function attribute. Push any that are non-constant onto the ARGS
12552 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12553 true, if these are for a kernels region offload function. */
12556 set_oacc_fn_attrib (tree fn
, tree clauses
, bool is_kernel
, vec
<tree
> *args
)
12558 /* Must match GOMP_DIM ordering. */
12559 static const omp_clause_code ids
[]
12560 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
12561 OMP_CLAUSE_VECTOR_LENGTH
};
12563 tree dims
[GOMP_DIM_MAX
];
12564 tree attr
= NULL_TREE
;
12565 unsigned non_const
= 0;
12567 for (ix
= GOMP_DIM_MAX
; ix
--;)
12569 tree clause
= find_omp_clause (clauses
, ids
[ix
]);
12570 tree dim
= NULL_TREE
;
12573 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
12575 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
12577 dim
= integer_zero_node
;
12578 non_const
|= GOMP_DIM_MASK (ix
);
12580 attr
= tree_cons (NULL_TREE
, dim
, attr
);
12581 /* Note kernelness with TREE_PUBLIC. */
12583 TREE_PUBLIC (attr
) = 1;
12586 replace_oacc_fn_attrib (fn
, attr
);
12590 /* Push a dynamic argument set. */
12591 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
12592 NULL_TREE
, non_const
));
12593 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
12594 if (non_const
& GOMP_DIM_MASK (ix
))
12595 args
->safe_push (dims
[ix
]);
12599 /* Process the routine's dimension clauess to generate an attribute
12600 value. Issue diagnostics as appropriate. We default to SEQ
12601 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12602 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12603 can have a loop partitioned on it. non-zero indicates
12604 yes, zero indicates no. By construction once a non-zero has been
12605 reached, further inner dimensions must also be non-zero. We set
12606 TREE_VALUE to zero for the dimensions that may be partitioned and
12607 1 for the other ones -- if a loop is (erroneously) spawned at
12608 an outer level, we don't want to try and partition it. */
12611 build_oacc_routine_dims (tree clauses
)
12613 /* Must match GOMP_DIM ordering. */
12614 static const omp_clause_code ids
[] =
12615 {OMP_CLAUSE_GANG
, OMP_CLAUSE_WORKER
, OMP_CLAUSE_VECTOR
, OMP_CLAUSE_SEQ
};
12619 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
12620 for (ix
= GOMP_DIM_MAX
+ 1; ix
--;)
12621 if (OMP_CLAUSE_CODE (clauses
) == ids
[ix
])
12624 error_at (OMP_CLAUSE_LOCATION (clauses
),
12625 "multiple loop axes specified for routine");
12630 /* Default to SEQ. */
12632 level
= GOMP_DIM_MAX
;
12634 tree dims
= NULL_TREE
;
12636 for (ix
= GOMP_DIM_MAX
; ix
--;)
12637 dims
= tree_cons (build_int_cst (boolean_type_node
, ix
>= level
),
12638 build_int_cst (integer_type_node
, ix
< level
), dims
);
12643 /* Retrieve the oacc function attrib and return it. Non-oacc
12644 functions will return NULL. */
12647 get_oacc_fn_attrib (tree fn
)
12649 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
12652 /* Return true if this oacc fn attrib is for a kernels offload
12653 region. We use the TREE_PUBLIC flag of each dimension -- only
12654 need to check the first one. */
12657 oacc_fn_attrib_kernels_p (tree attr
)
12659 return TREE_PUBLIC (TREE_VALUE (attr
));
12662 /* Return level at which oacc routine may spawn a partitioned loop, or
12663 -1 if it is not a routine (i.e. is an offload fn). */
12666 oacc_fn_attrib_level (tree attr
)
12668 tree pos
= TREE_VALUE (attr
);
12670 if (!TREE_PURPOSE (pos
))
12674 for (ix
= 0; ix
!= GOMP_DIM_MAX
;
12675 ix
++, pos
= TREE_CHAIN (pos
))
12676 if (!integer_zerop (TREE_PURPOSE (pos
)))
12682 /* Extract an oacc execution dimension from FN. FN must be an
12683 offloaded function or routine that has already had its execution
12684 dimensions lowered to the target-specific values. */
12687 get_oacc_fn_dim_size (tree fn
, int axis
)
12689 tree attrs
= get_oacc_fn_attrib (fn
);
12691 gcc_assert (axis
< GOMP_DIM_MAX
);
12693 tree dims
= TREE_VALUE (attrs
);
12695 dims
= TREE_CHAIN (dims
);
12697 int size
= TREE_INT_CST_LOW (TREE_VALUE (dims
));
12702 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12703 IFN_GOACC_DIM_SIZE call. */
12706 get_oacc_ifn_dim_arg (const gimple
*stmt
)
12708 gcc_checking_assert (gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_SIZE
12709 || gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_POS
);
12710 tree arg
= gimple_call_arg (stmt
, 0);
12711 HOST_WIDE_INT axis
= TREE_INT_CST_LOW (arg
);
12713 gcc_checking_assert (axis
>= 0 && axis
< GOMP_DIM_MAX
);
12717 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12721 mark_loops_in_oacc_kernels_region (basic_block region_entry
,
12722 basic_block region_exit
)
12724 struct loop
*outer
= region_entry
->loop_father
;
12725 gcc_assert (region_exit
== NULL
|| outer
== region_exit
->loop_father
);
12727 /* Don't parallelize the kernels region if it contains more than one outer
12729 unsigned int nr_outer_loops
= 0;
12730 struct loop
*single_outer
= NULL
;
12731 for (struct loop
*loop
= outer
->inner
; loop
!= NULL
; loop
= loop
->next
)
12733 gcc_assert (loop_outer (loop
) == outer
);
12735 if (!dominated_by_p (CDI_DOMINATORS
, loop
->header
, region_entry
))
12738 if (region_exit
!= NULL
12739 && dominated_by_p (CDI_DOMINATORS
, loop
->header
, region_exit
))
12743 single_outer
= loop
;
12745 if (nr_outer_loops
!= 1)
12748 for (struct loop
*loop
= single_outer
->inner
; loop
!= NULL
; loop
= loop
->inner
)
12752 /* Mark the loops in the region. */
12753 for (struct loop
*loop
= single_outer
; loop
!= NULL
; loop
= loop
->inner
)
12754 loop
->in_oacc_kernels_region
= true;
12757 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12759 struct GTY(()) grid_launch_attributes_trees
12761 tree kernel_dim_array_type
;
12762 tree kernel_lattrs_dimnum_decl
;
12763 tree kernel_lattrs_grid_decl
;
12764 tree kernel_lattrs_group_decl
;
12765 tree kernel_launch_attributes_type
;
12768 static GTY(()) struct grid_launch_attributes_trees
*grid_attr_trees
;
12770 /* Create types used to pass kernel launch attributes to target. */
12773 grid_create_kernel_launch_attr_types (void)
12775 if (grid_attr_trees
)
12777 grid_attr_trees
= ggc_alloc
<grid_launch_attributes_trees
> ();
12779 tree dim_arr_index_type
12780 = build_index_type (build_int_cst (integer_type_node
, 2));
12781 grid_attr_trees
->kernel_dim_array_type
12782 = build_array_type (uint32_type_node
, dim_arr_index_type
);
12784 grid_attr_trees
->kernel_launch_attributes_type
= make_node (RECORD_TYPE
);
12785 grid_attr_trees
->kernel_lattrs_dimnum_decl
12786 = build_decl (BUILTINS_LOCATION
, FIELD_DECL
, get_identifier ("ndim"),
12788 DECL_CHAIN (grid_attr_trees
->kernel_lattrs_dimnum_decl
) = NULL_TREE
;
12790 grid_attr_trees
->kernel_lattrs_grid_decl
12791 = build_decl (BUILTINS_LOCATION
, FIELD_DECL
, get_identifier ("grid_size"),
12792 grid_attr_trees
->kernel_dim_array_type
);
12793 DECL_CHAIN (grid_attr_trees
->kernel_lattrs_grid_decl
)
12794 = grid_attr_trees
->kernel_lattrs_dimnum_decl
;
12795 grid_attr_trees
->kernel_lattrs_group_decl
12796 = build_decl (BUILTINS_LOCATION
, FIELD_DECL
, get_identifier ("group_size"),
12797 grid_attr_trees
->kernel_dim_array_type
);
12798 DECL_CHAIN (grid_attr_trees
->kernel_lattrs_group_decl
)
12799 = grid_attr_trees
->kernel_lattrs_grid_decl
;
12800 finish_builtin_struct (grid_attr_trees
->kernel_launch_attributes_type
,
12801 "__gomp_kernel_launch_attributes",
12802 grid_attr_trees
->kernel_lattrs_group_decl
, NULL_TREE
);
12805 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12806 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12807 of type uint32_type_node. */
12810 grid_insert_store_range_dim (gimple_stmt_iterator
*gsi
, tree range_var
,
12811 tree fld_decl
, int index
, tree value
)
12813 tree ref
= build4 (ARRAY_REF
, uint32_type_node
,
12814 build3 (COMPONENT_REF
,
12815 grid_attr_trees
->kernel_dim_array_type
,
12816 range_var
, fld_decl
, NULL_TREE
),
12817 build_int_cst (integer_type_node
, index
),
12818 NULL_TREE
, NULL_TREE
);
12819 gsi_insert_before (gsi
, gimple_build_assign (ref
, value
), GSI_SAME_STMT
);
12822 /* Return a tree representation of a pointer to a structure with grid and
12823 work-group size information. Statements filling that information will be
12824 inserted before GSI, TGT_STMT is the target statement which has the
12825 necessary information in it. */
12828 grid_get_kernel_launch_attributes (gimple_stmt_iterator
*gsi
,
12829 gomp_target
*tgt_stmt
)
12831 grid_create_kernel_launch_attr_types ();
12832 tree u32_one
= build_one_cst (uint32_type_node
);
12833 tree lattrs
= create_tmp_var (grid_attr_trees
->kernel_launch_attributes_type
,
12834 "__kernel_launch_attrs");
12836 unsigned max_dim
= 0;
12837 for (tree clause
= gimple_omp_target_clauses (tgt_stmt
);
12839 clause
= OMP_CLAUSE_CHAIN (clause
))
12841 if (OMP_CLAUSE_CODE (clause
) != OMP_CLAUSE__GRIDDIM_
)
12844 unsigned dim
= OMP_CLAUSE__GRIDDIM__DIMENSION (clause
);
12845 max_dim
= MAX (dim
, max_dim
);
12847 grid_insert_store_range_dim (gsi
, lattrs
,
12848 grid_attr_trees
->kernel_lattrs_grid_decl
,
12849 dim
, OMP_CLAUSE__GRIDDIM__SIZE (clause
));
12850 grid_insert_store_range_dim (gsi
, lattrs
,
12851 grid_attr_trees
->kernel_lattrs_group_decl
,
12852 dim
, OMP_CLAUSE__GRIDDIM__GROUP (clause
));
12855 tree dimref
= build3 (COMPONENT_REF
, uint32_type_node
, lattrs
,
12856 grid_attr_trees
->kernel_lattrs_dimnum_decl
, NULL_TREE
);
12857 /* At this moment we cannot gridify a loop with a collapse clause. */
12858 /* TODO: Adjust when we support bigger collapse. */
12859 gcc_assert (max_dim
== 0);
12860 gsi_insert_before (gsi
, gimple_build_assign (dimref
, u32_one
), GSI_SAME_STMT
);
12861 TREE_ADDRESSABLE (lattrs
) = 1;
12862 return build_fold_addr_expr (lattrs
);
12865 /* Build target argument identifier from the DEVICE identifier, value
12866 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12869 get_target_argument_identifier_1 (int device
, bool subseqent_param
, int id
)
12871 tree t
= build_int_cst (integer_type_node
, device
);
12872 if (subseqent_param
)
12873 t
= fold_build2 (BIT_IOR_EXPR
, integer_type_node
, t
,
12874 build_int_cst (integer_type_node
,
12875 GOMP_TARGET_ARG_SUBSEQUENT_PARAM
));
12876 t
= fold_build2 (BIT_IOR_EXPR
, integer_type_node
, t
,
12877 build_int_cst (integer_type_node
, id
));
12881 /* Like above but return it in type that can be directly stored as an element
12882 of the argument array. */
12885 get_target_argument_identifier (int device
, bool subseqent_param
, int id
)
12887 tree t
= get_target_argument_identifier_1 (device
, subseqent_param
, id
);
12888 return fold_convert (ptr_type_node
, t
);
12891 /* Return a target argument consisting of DEVICE identifier, value identifier
12892 ID, and the actual VALUE. */
12895 get_target_argument_value (gimple_stmt_iterator
*gsi
, int device
, int id
,
12898 tree t
= fold_build2 (LSHIFT_EXPR
, integer_type_node
,
12899 fold_convert (integer_type_node
, value
),
12900 build_int_cst (unsigned_type_node
,
12901 GOMP_TARGET_ARG_VALUE_SHIFT
));
12902 t
= fold_build2 (BIT_IOR_EXPR
, integer_type_node
, t
,
12903 get_target_argument_identifier_1 (device
, false, id
));
12904 t
= fold_convert (ptr_type_node
, t
);
12905 return force_gimple_operand_gsi (gsi
, t
, true, NULL
, true, GSI_SAME_STMT
);
12908 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12909 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12910 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12914 push_target_argument_according_to_value (gimple_stmt_iterator
*gsi
, int device
,
12915 int id
, tree value
, vec
<tree
> *args
)
12917 if (tree_fits_shwi_p (value
)
12918 && tree_to_shwi (value
) > -(1 << 15)
12919 && tree_to_shwi (value
) < (1 << 15))
12920 args
->quick_push (get_target_argument_value (gsi
, device
, id
, value
));
12923 args
->quick_push (get_target_argument_identifier (device
, true, id
));
12924 value
= fold_convert (ptr_type_node
, value
);
12925 value
= force_gimple_operand_gsi (gsi
, value
, true, NULL
, true,
12927 args
->quick_push (value
);
12931 /* Create an array of arguments that is then passed to GOMP_target. */
12934 get_target_arguments (gimple_stmt_iterator
*gsi
, gomp_target
*tgt_stmt
)
12936 auto_vec
<tree
, 6> args
;
12937 tree clauses
= gimple_omp_target_clauses (tgt_stmt
);
12938 tree t
, c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_TEAMS
);
12940 t
= OMP_CLAUSE_NUM_TEAMS_EXPR (c
);
12942 t
= integer_minus_one_node
;
12943 push_target_argument_according_to_value (gsi
, GOMP_TARGET_ARG_DEVICE_ALL
,
12944 GOMP_TARGET_ARG_NUM_TEAMS
, t
, &args
);
12946 c
= find_omp_clause (clauses
, OMP_CLAUSE_THREAD_LIMIT
);
12948 t
= OMP_CLAUSE_THREAD_LIMIT_EXPR (c
);
12950 t
= integer_minus_one_node
;
12951 push_target_argument_according_to_value (gsi
, GOMP_TARGET_ARG_DEVICE_ALL
,
12952 GOMP_TARGET_ARG_THREAD_LIMIT
, t
,
12955 /* Add HSA-specific grid sizes, if available. */
12956 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt
),
12957 OMP_CLAUSE__GRIDDIM_
))
12959 t
= get_target_argument_identifier (GOMP_DEVICE_HSA
, true,
12960 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES
);
12961 args
.quick_push (t
);
12962 args
.quick_push (grid_get_kernel_launch_attributes (gsi
, tgt_stmt
));
12965 /* Produce more, perhaps device specific, arguments here. */
12967 tree argarray
= create_tmp_var (build_array_type_nelts (ptr_type_node
,
12968 args
.length () + 1),
12969 ".omp_target_args");
12970 for (unsigned i
= 0; i
< args
.length (); i
++)
12972 tree ref
= build4 (ARRAY_REF
, ptr_type_node
, argarray
,
12973 build_int_cst (integer_type_node
, i
),
12974 NULL_TREE
, NULL_TREE
);
12975 gsi_insert_before (gsi
, gimple_build_assign (ref
, args
[i
]),
12978 tree ref
= build4 (ARRAY_REF
, ptr_type_node
, argarray
,
12979 build_int_cst (integer_type_node
, args
.length ()),
12980 NULL_TREE
, NULL_TREE
);
12981 gsi_insert_before (gsi
, gimple_build_assign (ref
, null_pointer_node
),
12983 TREE_ADDRESSABLE (argarray
) = 1;
12984 return build_fold_addr_expr (argarray
);
12987 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12990 expand_omp_target (struct omp_region
*region
)
12992 basic_block entry_bb
, exit_bb
, new_bb
;
12993 struct function
*child_cfun
;
12994 tree child_fn
, block
, t
;
12995 gimple_stmt_iterator gsi
;
12996 gomp_target
*entry_stmt
;
12999 bool offloaded
, data_region
;
13001 entry_stmt
= as_a
<gomp_target
*> (last_stmt (region
->entry
));
13002 new_bb
= region
->entry
;
13004 offloaded
= is_gimple_omp_offloaded (entry_stmt
);
13005 switch (gimple_omp_target_kind (entry_stmt
))
13007 case GF_OMP_TARGET_KIND_REGION
:
13008 case GF_OMP_TARGET_KIND_UPDATE
:
13009 case GF_OMP_TARGET_KIND_ENTER_DATA
:
13010 case GF_OMP_TARGET_KIND_EXIT_DATA
:
13011 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
13012 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
13013 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
13014 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
13015 case GF_OMP_TARGET_KIND_OACC_DECLARE
:
13016 data_region
= false;
13018 case GF_OMP_TARGET_KIND_DATA
:
13019 case GF_OMP_TARGET_KIND_OACC_DATA
:
13020 case GF_OMP_TARGET_KIND_OACC_HOST_DATA
:
13021 data_region
= true;
13024 gcc_unreachable ();
13027 child_fn
= NULL_TREE
;
13031 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
13032 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
13035 /* Supported by expand_omp_taskreg, but not here. */
13036 if (child_cfun
!= NULL
)
13037 gcc_checking_assert (!child_cfun
->cfg
);
13038 gcc_checking_assert (!gimple_in_ssa_p (cfun
));
13040 entry_bb
= region
->entry
;
13041 exit_bb
= region
->exit
;
13043 if (gimple_omp_target_kind (entry_stmt
) == GF_OMP_TARGET_KIND_OACC_KERNELS
)
13044 mark_loops_in_oacc_kernels_region (region
->entry
, region
->exit
);
13048 unsigned srcidx
, dstidx
, num
;
13050 /* If the offloading region needs data sent from the parent
13051 function, then the very first statement (except possible
13052 tree profile counter updates) of the offloading body
13053 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13054 &.OMP_DATA_O is passed as an argument to the child function,
13055 we need to replace it with the argument as seen by the child
13058 In most cases, this will end up being the identity assignment
13059 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13060 a function call that has been inlined, the original PARM_DECL
13061 .OMP_DATA_I may have been converted into a different local
13062 variable. In which case, we need to keep the assignment. */
13063 tree data_arg
= gimple_omp_target_data_arg (entry_stmt
);
13066 basic_block entry_succ_bb
= single_succ (entry_bb
);
13067 gimple_stmt_iterator gsi
;
13069 gimple
*tgtcopy_stmt
= NULL
;
13070 tree sender
= TREE_VEC_ELT (data_arg
, 0);
13072 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
13074 gcc_assert (!gsi_end_p (gsi
));
13075 stmt
= gsi_stmt (gsi
);
13076 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
13079 if (gimple_num_ops (stmt
) == 2)
13081 tree arg
= gimple_assign_rhs1 (stmt
);
13083 /* We're ignoring the subcode because we're
13084 effectively doing a STRIP_NOPS. */
13086 if (TREE_CODE (arg
) == ADDR_EXPR
13087 && TREE_OPERAND (arg
, 0) == sender
)
13089 tgtcopy_stmt
= stmt
;
13095 gcc_assert (tgtcopy_stmt
!= NULL
);
13096 arg
= DECL_ARGUMENTS (child_fn
);
13098 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
13099 gsi_remove (&gsi
, true);
13102 /* Declare local variables needed in CHILD_CFUN. */
13103 block
= DECL_INITIAL (child_fn
);
13104 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
13105 /* The gimplifier could record temporaries in the offloading block
13106 rather than in containing function's local_decls chain,
13107 which would mean cgraph missed finalizing them. Do it now. */
13108 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
13109 if (TREE_CODE (t
) == VAR_DECL
13111 && !DECL_EXTERNAL (t
))
13112 varpool_node::finalize_decl (t
);
13113 DECL_SAVED_TREE (child_fn
) = NULL
;
13114 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13115 gimple_set_body (child_fn
, NULL
);
13116 TREE_USED (block
) = 1;
13118 /* Reset DECL_CONTEXT on function arguments. */
13119 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
13120 DECL_CONTEXT (t
) = child_fn
;
13122 /* Split ENTRY_BB at GIMPLE_*,
13123 so that it can be moved to the child function. */
13124 gsi
= gsi_last_bb (entry_bb
);
13125 stmt
= gsi_stmt (gsi
);
13127 && gimple_code (stmt
) == gimple_code (entry_stmt
));
13128 e
= split_block (entry_bb
, stmt
);
13129 gsi_remove (&gsi
, true);
13130 entry_bb
= e
->dest
;
13131 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
13133 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13136 gsi
= gsi_last_bb (exit_bb
);
13137 gcc_assert (!gsi_end_p (gsi
)
13138 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
13139 stmt
= gimple_build_return (NULL
);
13140 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
13141 gsi_remove (&gsi
, true);
13144 /* Move the offloading region into CHILD_CFUN. */
13146 block
= gimple_block (entry_stmt
);
13148 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
13150 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
13151 /* When the OMP expansion process cannot guarantee an up-to-date
13152 loop tree arrange for the child function to fixup loops. */
13153 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
13154 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
13156 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13157 num
= vec_safe_length (child_cfun
->local_decls
);
13158 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
13160 t
= (*child_cfun
->local_decls
)[srcidx
];
13161 if (DECL_CONTEXT (t
) == cfun
->decl
)
13163 if (srcidx
!= dstidx
)
13164 (*child_cfun
->local_decls
)[dstidx
] = t
;
13168 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
13170 /* Inform the callgraph about the new function. */
13171 child_cfun
->curr_properties
= cfun
->curr_properties
;
13172 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
13173 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
13174 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
13175 node
->parallelized_function
= 1;
13176 cgraph_node::add_new_function (child_fn
, true);
13178 /* Add the new function to the offload table. */
13179 if (ENABLE_OFFLOADING
)
13180 vec_safe_push (offload_funcs
, child_fn
);
13182 bool need_asm
= DECL_ASSEMBLER_NAME_SET_P (current_function_decl
)
13183 && !DECL_ASSEMBLER_NAME_SET_P (child_fn
);
13185 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13186 fixed in a following pass. */
13187 push_cfun (child_cfun
);
13189 assign_assembler_name_if_neeeded (child_fn
);
13190 cgraph_edge::rebuild_edges ();
13192 /* Some EH regions might become dead, see PR34608. If
13193 pass_cleanup_cfg isn't the first pass to happen with the
13194 new child, these dead EH edges might cause problems.
13195 Clean them up now. */
13196 if (flag_exceptions
)
13199 bool changed
= false;
13201 FOR_EACH_BB_FN (bb
, cfun
)
13202 changed
|= gimple_purge_dead_eh_edges (bb
);
13204 cleanup_tree_cfg ();
13206 if (flag_checking
&& !loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
13207 verify_loop_structure ();
13210 if (dump_file
&& !gimple_in_ssa_p (cfun
))
13212 omp_any_child_fn_dumped
= true;
13213 dump_function_header (dump_file
, child_fn
, dump_flags
);
13214 dump_function_to_file (child_fn
, dump_file
, dump_flags
);
13218 /* Emit a library call to launch the offloading region, or do data
13220 tree t1
, t2
, t3
, t4
, device
, cond
, depend
, c
, clauses
;
13221 enum built_in_function start_ix
;
13222 location_t clause_loc
;
13223 unsigned int flags_i
= 0;
13224 bool oacc_kernels_p
= false;
13226 switch (gimple_omp_target_kind (entry_stmt
))
13228 case GF_OMP_TARGET_KIND_REGION
:
13229 start_ix
= BUILT_IN_GOMP_TARGET
;
13231 case GF_OMP_TARGET_KIND_DATA
:
13232 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
13234 case GF_OMP_TARGET_KIND_UPDATE
:
13235 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
13237 case GF_OMP_TARGET_KIND_ENTER_DATA
:
13238 start_ix
= BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
;
13240 case GF_OMP_TARGET_KIND_EXIT_DATA
:
13241 start_ix
= BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
;
13242 flags_i
|= GOMP_TARGET_FLAG_EXIT_DATA
;
13244 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
13245 oacc_kernels_p
= true;
13247 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
13248 start_ix
= BUILT_IN_GOACC_PARALLEL
;
13250 case GF_OMP_TARGET_KIND_OACC_DATA
:
13251 case GF_OMP_TARGET_KIND_OACC_HOST_DATA
:
13252 start_ix
= BUILT_IN_GOACC_DATA_START
;
13254 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
13255 start_ix
= BUILT_IN_GOACC_UPDATE
;
13257 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
13258 start_ix
= BUILT_IN_GOACC_ENTER_EXIT_DATA
;
13260 case GF_OMP_TARGET_KIND_OACC_DECLARE
:
13261 start_ix
= BUILT_IN_GOACC_DECLARE
;
13264 gcc_unreachable ();
13267 clauses
= gimple_omp_target_clauses (entry_stmt
);
13269 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13270 library choose) and there is no conditional. */
13272 device
= build_int_cst (integer_type_node
, GOMP_DEVICE_ICV
);
13274 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
13276 cond
= OMP_CLAUSE_IF_EXPR (c
);
13278 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
13281 /* Even if we pass it to all library function calls, it is currently only
13282 defined/used for the OpenMP target ones. */
13283 gcc_checking_assert (start_ix
== BUILT_IN_GOMP_TARGET
13284 || start_ix
== BUILT_IN_GOMP_TARGET_DATA
13285 || start_ix
== BUILT_IN_GOMP_TARGET_UPDATE
13286 || start_ix
== BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
);
13288 device
= OMP_CLAUSE_DEVICE_ID (c
);
13289 clause_loc
= OMP_CLAUSE_LOCATION (c
);
13292 clause_loc
= gimple_location (entry_stmt
);
13294 c
= find_omp_clause (clauses
, OMP_CLAUSE_NOWAIT
);
13296 flags_i
|= GOMP_TARGET_FLAG_NOWAIT
;
13298 /* Ensure 'device' is of the correct type. */
13299 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
13301 /* If we found the clause 'if (cond)', build
13302 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13305 cond
= gimple_boolify (cond
);
13307 basic_block cond_bb
, then_bb
, else_bb
;
13311 tmp_var
= create_tmp_var (TREE_TYPE (device
));
13313 e
= split_block_after_labels (new_bb
);
13316 gsi
= gsi_last_bb (new_bb
);
13318 e
= split_block (new_bb
, gsi_stmt (gsi
));
13324 then_bb
= create_empty_bb (cond_bb
);
13325 else_bb
= create_empty_bb (then_bb
);
13326 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
13327 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
13329 stmt
= gimple_build_cond_empty (cond
);
13330 gsi
= gsi_last_bb (cond_bb
);
13331 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
13333 gsi
= gsi_start_bb (then_bb
);
13334 stmt
= gimple_build_assign (tmp_var
, device
);
13335 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
13337 gsi
= gsi_start_bb (else_bb
);
13338 stmt
= gimple_build_assign (tmp_var
,
13339 build_int_cst (integer_type_node
,
13340 GOMP_DEVICE_HOST_FALLBACK
));
13341 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
13343 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
13344 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
13345 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
13346 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
13347 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
13348 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
13353 gsi
= gsi_last_bb (new_bb
);
13354 t
= gimple_omp_target_data_arg (entry_stmt
);
13357 t1
= size_zero_node
;
13358 t2
= build_zero_cst (ptr_type_node
);
13364 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
13365 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
13366 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
13367 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
13368 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
13372 bool tagging
= false;
13373 /* The maximum number used by any start_ix, without varargs. */
13374 auto_vec
<tree
, 11> args
;
13375 args
.quick_push (device
);
13377 args
.quick_push (build_fold_addr_expr (child_fn
));
13378 args
.quick_push (t1
);
13379 args
.quick_push (t2
);
13380 args
.quick_push (t3
);
13381 args
.quick_push (t4
);
13384 case BUILT_IN_GOACC_DATA_START
:
13385 case BUILT_IN_GOACC_DECLARE
:
13386 case BUILT_IN_GOMP_TARGET_DATA
:
13388 case BUILT_IN_GOMP_TARGET
:
13389 case BUILT_IN_GOMP_TARGET_UPDATE
:
13390 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA
:
13391 args
.quick_push (build_int_cst (unsigned_type_node
, flags_i
));
13392 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
13394 depend
= OMP_CLAUSE_DECL (c
);
13396 depend
= build_int_cst (ptr_type_node
, 0);
13397 args
.quick_push (depend
);
13398 if (start_ix
== BUILT_IN_GOMP_TARGET
)
13399 args
.quick_push (get_target_arguments (&gsi
, entry_stmt
));
13401 case BUILT_IN_GOACC_PARALLEL
:
13403 set_oacc_fn_attrib (child_fn
, clauses
, oacc_kernels_p
, &args
);
13407 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
13408 case BUILT_IN_GOACC_UPDATE
:
13410 tree t_async
= NULL_TREE
;
13412 /* If present, use the value specified by the respective
13413 clause, making sure that is of the correct type. */
13414 c
= find_omp_clause (clauses
, OMP_CLAUSE_ASYNC
);
13416 t_async
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
13418 OMP_CLAUSE_ASYNC_EXPR (c
));
13420 /* Default values for t_async. */
13421 t_async
= fold_convert_loc (gimple_location (entry_stmt
),
13423 build_int_cst (integer_type_node
,
13425 if (tagging
&& t_async
)
13427 unsigned HOST_WIDE_INT i_async
= GOMP_LAUNCH_OP_MAX
;
13429 if (TREE_CODE (t_async
) == INTEGER_CST
)
13431 /* See if we can pack the async arg in to the tag's
13433 i_async
= TREE_INT_CST_LOW (t_async
);
13434 if (i_async
< GOMP_LAUNCH_OP_MAX
)
13435 t_async
= NULL_TREE
;
13437 i_async
= GOMP_LAUNCH_OP_MAX
;
13439 args
.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC
, NULL_TREE
,
13443 args
.safe_push (t_async
);
13445 /* Save the argument index, and ... */
13446 unsigned t_wait_idx
= args
.length ();
13447 unsigned num_waits
= 0;
13448 c
= find_omp_clause (clauses
, OMP_CLAUSE_WAIT
);
13450 /* ... push a placeholder. */
13451 args
.safe_push (integer_zero_node
);
13453 for (; c
; c
= OMP_CLAUSE_CHAIN (c
))
13454 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WAIT
)
13456 args
.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
13458 OMP_CLAUSE_WAIT_EXPR (c
)));
13462 if (!tagging
|| num_waits
)
13466 /* Now that we know the number, update the placeholder. */
13468 len
= oacc_launch_pack (GOMP_LAUNCH_WAIT
, NULL_TREE
, num_waits
);
13470 len
= build_int_cst (integer_type_node
, num_waits
);
13471 len
= fold_convert_loc (gimple_location (entry_stmt
),
13472 unsigned_type_node
, len
);
13473 args
[t_wait_idx
] = len
;
13478 gcc_unreachable ();
13481 /* Push terminal marker - zero. */
13482 args
.safe_push (oacc_launch_pack (0, NULL_TREE
, 0));
13484 g
= gimple_build_call_vec (builtin_decl_explicit (start_ix
), args
);
13485 gimple_set_location (g
, gimple_location (entry_stmt
));
13486 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
13489 g
= gsi_stmt (gsi
);
13490 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
13491 gsi_remove (&gsi
, true);
13493 if (data_region
&& region
->exit
)
13495 gsi
= gsi_last_bb (region
->exit
);
13496 g
= gsi_stmt (gsi
);
13497 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
13498 gsi_remove (&gsi
, true);
13502 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13503 variable derived from the thread number. */
13506 grid_expand_omp_for_loop (struct omp_region
*kfor
)
13510 gimple_stmt_iterator gsi
;
13512 struct omp_for_data fd
;
13514 gomp_for
*for_stmt
= as_a
<gomp_for
*> (last_stmt (kfor
->entry
));
13515 gcc_checking_assert (gimple_omp_for_kind (for_stmt
)
13516 == GF_OMP_FOR_KIND_GRID_LOOP
);
13517 basic_block body_bb
= FALLTHRU_EDGE (kfor
->entry
)->dest
;
13519 gcc_assert (gimple_omp_for_collapse (for_stmt
) == 1);
13520 gcc_assert (kfor
->cont
);
13521 extract_omp_for_data (for_stmt
, &fd
, NULL
);
13523 itype
= type
= TREE_TYPE (fd
.loop
.v
);
13524 if (POINTER_TYPE_P (type
))
13525 itype
= signed_type_for (type
);
13527 gsi
= gsi_start_bb (body_bb
);
13530 step
= fd
.loop
.step
;
13531 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
13532 true, NULL_TREE
, true, GSI_SAME_STMT
);
13533 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
13534 true, NULL_TREE
, true, GSI_SAME_STMT
);
13535 threadid
= build_call_expr (builtin_decl_explicit
13536 (BUILT_IN_OMP_GET_THREAD_NUM
), 0);
13537 threadid
= fold_convert (itype
, threadid
);
13538 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
13539 true, GSI_SAME_STMT
);
13541 tree startvar
= fd
.loop
.v
;
13542 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, step
);
13543 if (POINTER_TYPE_P (type
))
13544 t
= fold_build_pointer_plus (n1
, t
);
13546 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
13547 t
= fold_convert (type
, t
);
13548 t
= force_gimple_operand_gsi (&gsi
, t
,
13550 && TREE_ADDRESSABLE (startvar
),
13551 NULL_TREE
, true, GSI_SAME_STMT
);
13552 gassign
*assign_stmt
= gimple_build_assign (startvar
, t
);
13553 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
13555 /* Remove the omp for statement */
13556 gsi
= gsi_last_bb (kfor
->entry
);
13557 gsi_remove (&gsi
, true);
13559 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13560 gsi
= gsi_last_bb (kfor
->cont
);
13561 gcc_assert (!gsi_end_p (gsi
)
13562 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_CONTINUE
);
13563 gsi_remove (&gsi
, true);
13565 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13566 gsi
= gsi_last_bb (kfor
->exit
);
13567 gcc_assert (!gsi_end_p (gsi
)
13568 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
13569 gsi_remove (&gsi
, true);
13571 /* Fixup the much simpler CFG. */
13572 remove_edge (find_edge (kfor
->cont
, body_bb
));
13574 if (kfor
->cont
!= body_bb
)
13575 set_immediate_dominator (CDI_DOMINATORS
, kfor
->cont
, body_bb
);
13576 set_immediate_dominator (CDI_DOMINATORS
, kfor
->exit
, kfor
->cont
);
13579 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13582 struct grid_arg_decl_map
13588 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13589 pertaining to kernel function. */
13592 grid_remap_kernel_arg_accesses (tree
*tp
, int *walk_subtrees
, void *data
)
13594 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
13595 struct grid_arg_decl_map
*adm
= (struct grid_arg_decl_map
*) wi
->info
;
13598 if (t
== adm
->old_arg
)
13599 *tp
= adm
->new_arg
;
13600 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
13604 static void expand_omp (struct omp_region
*region
);
13606 /* If TARGET region contains a kernel body for loop, remove its region from the
13607 TARGET and expand it in GPGPU kernel fashion. */
13610 grid_expand_target_grid_body (struct omp_region
*target
)
13612 if (!hsa_gen_requested_p ())
13615 gomp_target
*tgt_stmt
= as_a
<gomp_target
*> (last_stmt (target
->entry
));
13616 struct omp_region
**pp
;
13618 for (pp
= &target
->inner
; *pp
; pp
= &(*pp
)->next
)
13619 if ((*pp
)->type
== GIMPLE_OMP_GRID_BODY
)
13622 struct omp_region
*gpukernel
= *pp
;
13624 tree orig_child_fndecl
= gimple_omp_target_child_fn (tgt_stmt
);
13627 /* HSA cannot handle OACC stuff. */
13628 if (gimple_omp_target_kind (tgt_stmt
) != GF_OMP_TARGET_KIND_REGION
)
13630 gcc_checking_assert (orig_child_fndecl
);
13631 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt
),
13632 OMP_CLAUSE__GRIDDIM_
));
13633 cgraph_node
*n
= cgraph_node::get (orig_child_fndecl
);
13635 hsa_register_kernel (n
);
13639 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt
),
13640 OMP_CLAUSE__GRIDDIM_
));
13641 tree inside_block
= gimple_block (first_stmt (single_succ (gpukernel
->entry
)));
13642 *pp
= gpukernel
->next
;
13643 for (pp
= &gpukernel
->inner
; *pp
; pp
= &(*pp
)->next
)
13644 if ((*pp
)->type
== GIMPLE_OMP_FOR
)
13647 struct omp_region
*kfor
= *pp
;
13649 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor
)->entry
))
13650 == GF_OMP_FOR_KIND_GRID_LOOP
);
13653 expand_omp (kfor
->inner
);
13654 if (gpukernel
->inner
)
13655 expand_omp (gpukernel
->inner
);
13657 tree kern_fndecl
= copy_node (orig_child_fndecl
);
13658 DECL_NAME (kern_fndecl
) = clone_function_name (kern_fndecl
, "kernel");
13659 SET_DECL_ASSEMBLER_NAME (kern_fndecl
, DECL_NAME (kern_fndecl
));
13660 tree tgtblock
= gimple_block (tgt_stmt
);
13661 tree fniniblock
= make_node (BLOCK
);
13662 BLOCK_ABSTRACT_ORIGIN (fniniblock
) = tgtblock
;
13663 BLOCK_SOURCE_LOCATION (fniniblock
) = BLOCK_SOURCE_LOCATION (tgtblock
);
13664 BLOCK_SOURCE_END_LOCATION (fniniblock
) = BLOCK_SOURCE_END_LOCATION (tgtblock
);
13665 DECL_INITIAL (kern_fndecl
) = fniniblock
;
13666 push_struct_function (kern_fndecl
);
13667 cfun
->function_end_locus
= gimple_location (tgt_stmt
);
13668 init_tree_ssa (cfun
);
13671 tree old_parm_decl
= DECL_ARGUMENTS (kern_fndecl
);
13672 gcc_assert (!DECL_CHAIN (old_parm_decl
));
13673 tree new_parm_decl
= copy_node (DECL_ARGUMENTS (kern_fndecl
));
13674 DECL_CONTEXT (new_parm_decl
) = kern_fndecl
;
13675 DECL_ARGUMENTS (kern_fndecl
) = new_parm_decl
;
13676 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl
))));
13677 DECL_RESULT (kern_fndecl
) = copy_node (DECL_RESULT (kern_fndecl
));
13678 DECL_CONTEXT (DECL_RESULT (kern_fndecl
)) = kern_fndecl
;
13679 struct function
*kern_cfun
= DECL_STRUCT_FUNCTION (kern_fndecl
);
13680 kern_cfun
->curr_properties
= cfun
->curr_properties
;
13682 remove_edge (BRANCH_EDGE (kfor
->entry
));
13683 grid_expand_omp_for_loop (kfor
);
13685 /* Remove the omp for statement */
13686 gimple_stmt_iterator gsi
= gsi_last_bb (gpukernel
->entry
);
13687 gsi_remove (&gsi
, true);
13688 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13690 gsi
= gsi_last_bb (gpukernel
->exit
);
13691 gcc_assert (!gsi_end_p (gsi
)
13692 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
13693 gimple
*ret_stmt
= gimple_build_return (NULL
);
13694 gsi_insert_after (&gsi
, ret_stmt
, GSI_SAME_STMT
);
13695 gsi_remove (&gsi
, true);
13697 /* Statements in the first BB in the target construct have been produced by
13698 target lowering and must be copied inside the GPUKERNEL, with the two
13699 exceptions of the first OMP statement and the OMP_DATA assignment
13701 gsi
= gsi_start_bb (single_succ (gpukernel
->entry
));
13702 tree data_arg
= gimple_omp_target_data_arg (tgt_stmt
);
13703 tree sender
= data_arg
? TREE_VEC_ELT (data_arg
, 0) : NULL
;
13704 for (gimple_stmt_iterator tsi
= gsi_start_bb (single_succ (target
->entry
));
13705 !gsi_end_p (tsi
); gsi_next (&tsi
))
13707 gimple
*stmt
= gsi_stmt (tsi
);
13708 if (is_gimple_omp (stmt
))
13711 && is_gimple_assign (stmt
)
13712 && TREE_CODE (gimple_assign_rhs1 (stmt
)) == ADDR_EXPR
13713 && TREE_OPERAND (gimple_assign_rhs1 (stmt
), 0) == sender
)
13715 gimple
*copy
= gimple_copy (stmt
);
13716 gsi_insert_before (&gsi
, copy
, GSI_SAME_STMT
);
13717 gimple_set_block (copy
, fniniblock
);
13720 move_sese_region_to_fn (kern_cfun
, single_succ (gpukernel
->entry
),
13721 gpukernel
->exit
, inside_block
);
13723 cgraph_node
*kcn
= cgraph_node::get_create (kern_fndecl
);
13724 kcn
->mark_force_output ();
13725 cgraph_node
*orig_child
= cgraph_node::get (orig_child_fndecl
);
13727 hsa_register_kernel (kcn
, orig_child
);
13729 cgraph_node::add_new_function (kern_fndecl
, true);
13730 push_cfun (kern_cfun
);
13731 cgraph_edge::rebuild_edges ();
13733 /* Re-map any mention of the PARM_DECL of the original function to the
13734 PARM_DECL of the new one.
13736 TODO: It would be great if lowering produced references into the GPU
13737 kernel decl straight away and we did not have to do this. */
13738 struct grid_arg_decl_map adm
;
13739 adm
.old_arg
= old_parm_decl
;
13740 adm
.new_arg
= new_parm_decl
;
13742 FOR_EACH_BB_FN (bb
, kern_cfun
)
13744 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
13746 gimple
*stmt
= gsi_stmt (gsi
);
13747 struct walk_stmt_info wi
;
13748 memset (&wi
, 0, sizeof (wi
));
13750 walk_gimple_op (stmt
, grid_remap_kernel_arg_accesses
, &wi
);
13758 /* Expand the parallel region tree rooted at REGION. Expansion
13759 proceeds in depth-first order. Innermost regions are expanded
13760 first. This way, parallel regions that require a new function to
13761 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13762 internal dependencies in their body. */
13765 expand_omp (struct omp_region
*region
)
13767 omp_any_child_fn_dumped
= false;
13770 location_t saved_location
;
13771 gimple
*inner_stmt
= NULL
;
13773 /* First, determine whether this is a combined parallel+workshare
13775 if (region
->type
== GIMPLE_OMP_PARALLEL
)
13776 determine_parallel_type (region
);
13777 else if (region
->type
== GIMPLE_OMP_TARGET
)
13778 grid_expand_target_grid_body (region
);
13780 if (region
->type
== GIMPLE_OMP_FOR
13781 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
13782 inner_stmt
= last_stmt (region
->inner
->entry
);
13785 expand_omp (region
->inner
);
13787 saved_location
= input_location
;
13788 if (gimple_has_location (last_stmt (region
->entry
)))
13789 input_location
= gimple_location (last_stmt (region
->entry
));
13791 switch (region
->type
)
13793 case GIMPLE_OMP_PARALLEL
:
13794 case GIMPLE_OMP_TASK
:
13795 expand_omp_taskreg (region
);
13798 case GIMPLE_OMP_FOR
:
13799 expand_omp_for (region
, inner_stmt
);
13802 case GIMPLE_OMP_SECTIONS
:
13803 expand_omp_sections (region
);
13806 case GIMPLE_OMP_SECTION
:
13807 /* Individual omp sections are handled together with their
13808 parent GIMPLE_OMP_SECTIONS region. */
13811 case GIMPLE_OMP_SINGLE
:
13812 expand_omp_single (region
);
13815 case GIMPLE_OMP_ORDERED
:
13817 gomp_ordered
*ord_stmt
13818 = as_a
<gomp_ordered
*> (last_stmt (region
->entry
));
13819 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt
),
13820 OMP_CLAUSE_DEPEND
))
13822 /* We'll expand these when expanding corresponding
13823 worksharing region with ordered(n) clause. */
13824 gcc_assert (region
->outer
13825 && region
->outer
->type
== GIMPLE_OMP_FOR
);
13826 region
->ord_stmt
= ord_stmt
;
13831 case GIMPLE_OMP_MASTER
:
13832 case GIMPLE_OMP_TASKGROUP
:
13833 case GIMPLE_OMP_CRITICAL
:
13834 case GIMPLE_OMP_TEAMS
:
13835 expand_omp_synch (region
);
13838 case GIMPLE_OMP_ATOMIC_LOAD
:
13839 expand_omp_atomic (region
);
13842 case GIMPLE_OMP_TARGET
:
13843 expand_omp_target (region
);
13847 gcc_unreachable ();
13850 input_location
= saved_location
;
13851 region
= region
->next
;
13853 if (omp_any_child_fn_dumped
)
13856 dump_function_header (dump_file
, current_function_decl
, dump_flags
);
13857 omp_any_child_fn_dumped
= false;
13862 /* Helper for build_omp_regions. Scan the dominator tree starting at
13863 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13864 true, the function ends once a single tree is built (otherwise, whole
13865 forest of OMP constructs may be built). */
13868 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
13871 gimple_stmt_iterator gsi
;
13875 gsi
= gsi_last_bb (bb
);
13876 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
13878 struct omp_region
*region
;
13879 enum gimple_code code
;
13881 stmt
= gsi_stmt (gsi
);
13882 code
= gimple_code (stmt
);
13883 if (code
== GIMPLE_OMP_RETURN
)
13885 /* STMT is the return point out of region PARENT. Mark it
13886 as the exit point and make PARENT the immediately
13887 enclosing region. */
13888 gcc_assert (parent
);
13891 parent
= parent
->outer
;
13893 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
13895 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13896 GIMPLE_OMP_RETURN, but matches with
13897 GIMPLE_OMP_ATOMIC_LOAD. */
13898 gcc_assert (parent
);
13899 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
13902 parent
= parent
->outer
;
13904 else if (code
== GIMPLE_OMP_CONTINUE
)
13906 gcc_assert (parent
);
13909 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
13911 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13912 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13916 region
= new_omp_region (bb
, code
, parent
);
13918 if (code
== GIMPLE_OMP_TARGET
)
13920 switch (gimple_omp_target_kind (stmt
))
13922 case GF_OMP_TARGET_KIND_REGION
:
13923 case GF_OMP_TARGET_KIND_DATA
:
13924 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
13925 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
13926 case GF_OMP_TARGET_KIND_OACC_DATA
:
13927 case GF_OMP_TARGET_KIND_OACC_HOST_DATA
:
13929 case GF_OMP_TARGET_KIND_UPDATE
:
13930 case GF_OMP_TARGET_KIND_ENTER_DATA
:
13931 case GF_OMP_TARGET_KIND_EXIT_DATA
:
13932 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
13933 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
13934 case GF_OMP_TARGET_KIND_OACC_DECLARE
:
13935 /* ..., other than for those stand-alone directives... */
13939 gcc_unreachable ();
13942 else if (code
== GIMPLE_OMP_ORDERED
13943 && find_omp_clause (gimple_omp_ordered_clauses
13944 (as_a
<gomp_ordered
*> (stmt
)),
13945 OMP_CLAUSE_DEPEND
))
13946 /* #pragma omp ordered depend is also just a stand-alone
13949 /* ..., this directive becomes the parent for a new region. */
13955 if (single_tree
&& !parent
)
13958 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
13960 son
= next_dom_son (CDI_DOMINATORS
, son
))
13961 build_omp_regions_1 (son
, parent
, single_tree
);
13964 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13965 root_omp_region. */
13968 build_omp_regions_root (basic_block root
)
13970 gcc_assert (root_omp_region
== NULL
);
13971 build_omp_regions_1 (root
, NULL
, true);
13972 gcc_assert (root_omp_region
!= NULL
);
13975 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13978 omp_expand_local (basic_block head
)
13980 build_omp_regions_root (head
);
13981 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
13983 fprintf (dump_file
, "\nOMP region tree\n\n");
13984 dump_omp_region (dump_file
, root_omp_region
, 0);
13985 fprintf (dump_file
, "\n");
13988 remove_exit_barriers (root_omp_region
);
13989 expand_omp (root_omp_region
);
13991 free_omp_regions ();
13994 /* Scan the CFG and build a tree of OMP regions. Return the root of
13995 the OMP region tree. */
13998 build_omp_regions (void)
14000 gcc_assert (root_omp_region
== NULL
);
14001 calculate_dominance_info (CDI_DOMINATORS
);
14002 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
14005 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14007 static unsigned int
14008 execute_expand_omp (void)
14010 build_omp_regions ();
14012 if (!root_omp_region
)
14017 fprintf (dump_file
, "\nOMP region tree\n\n");
14018 dump_omp_region (dump_file
, root_omp_region
, 0);
14019 fprintf (dump_file
, "\n");
14022 remove_exit_barriers (root_omp_region
);
14024 expand_omp (root_omp_region
);
14026 if (flag_checking
&& !loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
14027 verify_loop_structure ();
14028 cleanup_tree_cfg ();
14030 free_omp_regions ();
14035 /* OMP expansion -- the default pass, run before creation of SSA form. */
14039 const pass_data pass_data_expand_omp
=
14041 GIMPLE_PASS
, /* type */
14042 "ompexp", /* name */
14043 OPTGROUP_NONE
, /* optinfo_flags */
14044 TV_NONE
, /* tv_id */
14045 PROP_gimple_any
, /* properties_required */
14046 PROP_gimple_eomp
, /* properties_provided */
14047 0, /* properties_destroyed */
14048 0, /* todo_flags_start */
14049 0, /* todo_flags_finish */
14052 class pass_expand_omp
: public gimple_opt_pass
14055 pass_expand_omp (gcc::context
*ctxt
)
14056 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
14059 /* opt_pass methods: */
14060 virtual unsigned int execute (function
*)
14062 bool gate
= ((flag_cilkplus
!= 0 || flag_openacc
!= 0 || flag_openmp
!= 0
14063 || flag_openmp_simd
!= 0)
14064 && !seen_error ());
14066 /* This pass always runs, to provide PROP_gimple_eomp.
14067 But often, there is nothing to do. */
14071 return execute_expand_omp ();
14074 }; // class pass_expand_omp
14076 } // anon namespace
14079 make_pass_expand_omp (gcc::context
*ctxt
)
14081 return new pass_expand_omp (ctxt
);
14086 const pass_data pass_data_expand_omp_ssa
=
14088 GIMPLE_PASS
, /* type */
14089 "ompexpssa", /* name */
14090 OPTGROUP_NONE
, /* optinfo_flags */
14091 TV_NONE
, /* tv_id */
14092 PROP_cfg
| PROP_ssa
, /* properties_required */
14093 PROP_gimple_eomp
, /* properties_provided */
14094 0, /* properties_destroyed */
14095 0, /* todo_flags_start */
14096 TODO_cleanup_cfg
| TODO_rebuild_alias
, /* todo_flags_finish */
14099 class pass_expand_omp_ssa
: public gimple_opt_pass
14102 pass_expand_omp_ssa (gcc::context
*ctxt
)
14103 : gimple_opt_pass (pass_data_expand_omp_ssa
, ctxt
)
14106 /* opt_pass methods: */
14107 virtual bool gate (function
*fun
)
14109 return !(fun
->curr_properties
& PROP_gimple_eomp
);
14111 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
14112 opt_pass
* clone () { return new pass_expand_omp_ssa (m_ctxt
); }
14114 }; // class pass_expand_omp_ssa
14116 } // anon namespace
14119 make_pass_expand_omp_ssa (gcc::context
*ctxt
)
14121 return new pass_expand_omp_ssa (ctxt
);
14124 /* Routines to lower OMP directives into OMP-GIMPLE. */
14126 /* If ctx is a worksharing context inside of a cancellable parallel
14127 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14128 and conditional branch to parallel's cancel_label to handle
14129 cancellation in the implicit barrier. */
14132 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
14134 gimple
*omp_return
= gimple_seq_last_stmt (*body
);
14135 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
14136 if (gimple_omp_return_nowait_p (omp_return
))
14139 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
14140 && ctx
->outer
->cancellable
)
14142 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
14143 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
14144 tree lhs
= create_tmp_var (c_bool_type
);
14145 gimple_omp_return_set_lhs (omp_return
, lhs
);
14146 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
14147 gimple
*g
= gimple_build_cond (NE_EXPR
, lhs
,
14148 fold_convert (c_bool_type
,
14149 boolean_false_node
),
14150 ctx
->outer
->cancel_label
, fallthru_label
);
14151 gimple_seq_add_stmt (body
, g
);
14152 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
14156 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14157 CTX is the enclosing OMP context for the current statement. */
14160 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
14162 tree block
, control
;
14163 gimple_stmt_iterator tgsi
;
14164 gomp_sections
*stmt
;
14166 gbind
*new_stmt
, *bind
;
14167 gimple_seq ilist
, dlist
, olist
, new_body
;
14169 stmt
= as_a
<gomp_sections
*> (gsi_stmt (*gsi_p
));
14171 push_gimplify_context ();
14175 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
14176 &ilist
, &dlist
, ctx
, NULL
);
14178 new_body
= gimple_omp_body (stmt
);
14179 gimple_omp_set_body (stmt
, NULL
);
14180 tgsi
= gsi_start (new_body
);
14181 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
14186 sec_start
= gsi_stmt (tgsi
);
14187 sctx
= maybe_lookup_ctx (sec_start
);
14190 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
14191 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
14192 GSI_CONTINUE_LINKING
);
14193 gimple_omp_set_body (sec_start
, NULL
);
14195 if (gsi_one_before_end_p (tgsi
))
14197 gimple_seq l
= NULL
;
14198 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
14200 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
14201 gimple_omp_section_set_last (sec_start
);
14204 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
14205 GSI_CONTINUE_LINKING
);
14208 block
= make_node (BLOCK
);
14209 bind
= gimple_build_bind (NULL
, new_body
, block
);
14212 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
14214 block
= make_node (BLOCK
);
14215 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
14216 gsi_replace (gsi_p
, new_stmt
, true);
14218 pop_gimplify_context (new_stmt
);
14219 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
14220 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
14221 if (BLOCK_VARS (block
))
14222 TREE_USED (block
) = 1;
14225 gimple_seq_add_seq (&new_body
, ilist
);
14226 gimple_seq_add_stmt (&new_body
, stmt
);
14227 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
14228 gimple_seq_add_stmt (&new_body
, bind
);
14230 control
= create_tmp_var (unsigned_type_node
, ".section");
14231 t
= gimple_build_omp_continue (control
, control
);
14232 gimple_omp_sections_set_control (stmt
, control
);
14233 gimple_seq_add_stmt (&new_body
, t
);
14235 gimple_seq_add_seq (&new_body
, olist
);
14236 if (ctx
->cancellable
)
14237 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
14238 gimple_seq_add_seq (&new_body
, dlist
);
14240 new_body
= maybe_catch_exception (new_body
);
14242 t
= gimple_build_omp_return
14243 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
14244 OMP_CLAUSE_NOWAIT
));
14245 gimple_seq_add_stmt (&new_body
, t
);
14246 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
14248 gimple_bind_set_body (new_stmt
, new_body
);
14252 /* A subroutine of lower_omp_single. Expand the simple form of
14253 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14255 if (GOMP_single_start ())
14257 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14259 FIXME. It may be better to delay expanding the logic of this until
14260 pass_expand_omp. The expanded logic may make the job more difficult
14261 to a synchronization analysis pass. */
14264 lower_omp_single_simple (gomp_single
*single_stmt
, gimple_seq
*pre_p
)
14266 location_t loc
= gimple_location (single_stmt
);
14267 tree tlabel
= create_artificial_label (loc
);
14268 tree flabel
= create_artificial_label (loc
);
14269 gimple
*call
, *cond
;
14272 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
14273 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)));
14274 call
= gimple_build_call (decl
, 0);
14275 gimple_call_set_lhs (call
, lhs
);
14276 gimple_seq_add_stmt (pre_p
, call
);
14278 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
14279 fold_convert_loc (loc
, TREE_TYPE (lhs
),
14280 boolean_true_node
),
14282 gimple_seq_add_stmt (pre_p
, cond
);
14283 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
14284 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
14285 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
14289 /* A subroutine of lower_omp_single. Expand the simple form of
14290 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14292 #pragma omp single copyprivate (a, b, c)
14294 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14297 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14303 GOMP_single_copy_end (©out);
14314 FIXME. It may be better to delay expanding the logic of this until
14315 pass_expand_omp. The expanded logic may make the job more difficult
14316 to a synchronization analysis pass. */
14319 lower_omp_single_copy (gomp_single
*single_stmt
, gimple_seq
*pre_p
,
14322 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
14323 gimple_seq copyin_seq
;
14324 location_t loc
= gimple_location (single_stmt
);
14326 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
14328 ptr_type
= build_pointer_type (ctx
->record_type
);
14329 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
14331 l0
= create_artificial_label (loc
);
14332 l1
= create_artificial_label (loc
);
14333 l2
= create_artificial_label (loc
);
14335 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
14336 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
14337 t
= fold_convert_loc (loc
, ptr_type
, t
);
14338 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
14340 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
14341 build_int_cst (ptr_type
, 0));
14342 t
= build3 (COND_EXPR
, void_type_node
, t
,
14343 build_and_jump (&l0
), build_and_jump (&l1
));
14344 gimplify_and_add (t
, pre_p
);
14346 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
14348 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
14351 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
14354 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
14355 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
14356 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
14357 gimplify_and_add (t
, pre_p
);
14359 t
= build_and_jump (&l2
);
14360 gimplify_and_add (t
, pre_p
);
14362 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
14364 gimple_seq_add_seq (pre_p
, copyin_seq
);
14366 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
14370 /* Expand code for an OpenMP single directive. */
14373 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
14377 gomp_single
*single_stmt
= as_a
<gomp_single
*> (gsi_stmt (*gsi_p
));
14379 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
14381 push_gimplify_context ();
14383 block
= make_node (BLOCK
);
14384 bind
= gimple_build_bind (NULL
, NULL
, block
);
14385 gsi_replace (gsi_p
, bind
, true);
14388 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
14389 &bind_body
, &dlist
, ctx
, NULL
);
14390 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
14392 gimple_seq_add_stmt (&bind_body
, single_stmt
);
14394 if (ctx
->record_type
)
14395 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
14397 lower_omp_single_simple (single_stmt
, &bind_body
);
14399 gimple_omp_set_body (single_stmt
, NULL
);
14401 gimple_seq_add_seq (&bind_body
, dlist
);
14403 bind_body
= maybe_catch_exception (bind_body
);
14405 t
= gimple_build_omp_return
14406 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
14407 OMP_CLAUSE_NOWAIT
));
14408 gimple_seq_add_stmt (&bind_body_tail
, t
);
14409 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
14410 if (ctx
->record_type
)
14412 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
14413 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
14414 TREE_THIS_VOLATILE (clobber
) = 1;
14415 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
14416 clobber
), GSI_SAME_STMT
);
14418 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
14419 gimple_bind_set_body (bind
, bind_body
);
14421 pop_gimplify_context (bind
);
14423 gimple_bind_append_vars (bind
, ctx
->block_vars
);
14424 BLOCK_VARS (block
) = ctx
->block_vars
;
14425 if (BLOCK_VARS (block
))
14426 TREE_USED (block
) = 1;
14430 /* Expand code for an OpenMP master directive. */
14433 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
14435 tree block
, lab
= NULL
, x
, bfn_decl
;
14436 gimple
*stmt
= gsi_stmt (*gsi_p
);
14438 location_t loc
= gimple_location (stmt
);
14441 push_gimplify_context ();
14443 block
= make_node (BLOCK
);
14444 bind
= gimple_build_bind (NULL
, NULL
, block
);
14445 gsi_replace (gsi_p
, bind
, true);
14446 gimple_bind_add_stmt (bind
, stmt
);
14448 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
14449 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
14450 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
14451 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
14453 gimplify_and_add (x
, &tseq
);
14454 gimple_bind_add_seq (bind
, tseq
);
14456 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
14457 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
14458 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
14459 gimple_omp_set_body (stmt
, NULL
);
14461 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
14463 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
14465 pop_gimplify_context (bind
);
14467 gimple_bind_append_vars (bind
, ctx
->block_vars
);
14468 BLOCK_VARS (block
) = ctx
->block_vars
;
14472 /* Expand code for an OpenMP taskgroup directive. */
14475 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
14477 gimple
*stmt
= gsi_stmt (*gsi_p
);
14480 tree block
= make_node (BLOCK
);
14482 bind
= gimple_build_bind (NULL
, NULL
, block
);
14483 gsi_replace (gsi_p
, bind
, true);
14484 gimple_bind_add_stmt (bind
, stmt
);
14486 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
14488 gimple_bind_add_stmt (bind
, x
);
14490 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
14491 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
14492 gimple_omp_set_body (stmt
, NULL
);
14494 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
14496 gimple_bind_append_vars (bind
, ctx
->block_vars
);
14497 BLOCK_VARS (block
) = ctx
->block_vars
;
14501 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14504 lower_omp_ordered_clauses (gimple_stmt_iterator
*gsi_p
, gomp_ordered
*ord_stmt
,
14507 struct omp_for_data fd
;
14508 if (!ctx
->outer
|| gimple_code (ctx
->outer
->stmt
) != GIMPLE_OMP_FOR
)
14511 unsigned int len
= gimple_omp_for_collapse (ctx
->outer
->stmt
);
14512 struct omp_for_data_loop
*loops
= XALLOCAVEC (struct omp_for_data_loop
, len
);
14513 extract_omp_for_data (as_a
<gomp_for
*> (ctx
->outer
->stmt
), &fd
, loops
);
14517 tree
*list_p
= gimple_omp_ordered_clauses_ptr (ord_stmt
);
14518 tree c
= gimple_omp_ordered_clauses (ord_stmt
);
14519 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
14520 && OMP_CLAUSE_DEPEND_KIND (c
) == OMP_CLAUSE_DEPEND_SINK
)
14522 /* Merge depend clauses from multiple adjacent
14523 #pragma omp ordered depend(sink:...) constructs
14524 into one #pragma omp ordered depend(sink:...), so that
14525 we can optimize them together. */
14526 gimple_stmt_iterator gsi
= *gsi_p
;
14528 while (!gsi_end_p (gsi
))
14530 gimple
*stmt
= gsi_stmt (gsi
);
14531 if (is_gimple_debug (stmt
)
14532 || gimple_code (stmt
) == GIMPLE_NOP
)
14537 if (gimple_code (stmt
) != GIMPLE_OMP_ORDERED
)
14539 gomp_ordered
*ord_stmt2
= as_a
<gomp_ordered
*> (stmt
);
14540 c
= gimple_omp_ordered_clauses (ord_stmt2
);
14542 || OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_DEPEND
14543 || OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_SINK
)
14546 list_p
= &OMP_CLAUSE_CHAIN (*list_p
);
14548 gsi_remove (&gsi
, true);
14552 /* Canonicalize sink dependence clauses into one folded clause if
14555 The basic algorithm is to create a sink vector whose first
14556 element is the GCD of all the first elements, and whose remaining
14557 elements are the minimum of the subsequent columns.
14559 We ignore dependence vectors whose first element is zero because
14560 such dependencies are known to be executed by the same thread.
14562 We take into account the direction of the loop, so a minimum
14563 becomes a maximum if the loop is iterating forwards. We also
14564 ignore sink clauses where the loop direction is unknown, or where
14565 the offsets are clearly invalid because they are not a multiple
14566 of the loop increment.
14570 #pragma omp for ordered(2)
14571 for (i=0; i < N; ++i)
14572 for (j=0; j < M; ++j)
14574 #pragma omp ordered \
14575 depend(sink:i-8,j-2) \
14576 depend(sink:i,j-1) \ // Completely ignored because i+0.
14577 depend(sink:i-4,j-3) \
14578 depend(sink:i-6,j-4)
14579 #pragma omp ordered depend(source)
14584 depend(sink:-gcd(8,4,6),-min(2,3,4))
14589 /* FIXME: Computing GCD's where the first element is zero is
14590 non-trivial in the presence of collapsed loops. Do this later. */
14591 if (fd
.collapse
> 1)
14594 wide_int
*folded_deps
= XALLOCAVEC (wide_int
, 2 * len
- 1);
14595 memset (folded_deps
, 0, sizeof (*folded_deps
) * (2 * len
- 1));
14596 tree folded_dep
= NULL_TREE
;
14597 /* TRUE if the first dimension's offset is negative. */
14598 bool neg_offset_p
= false;
14600 list_p
= gimple_omp_ordered_clauses_ptr (ord_stmt
);
14602 while ((c
= *list_p
) != NULL
)
14604 bool remove
= false;
14606 gcc_assert (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
);
14607 if (OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_SINK
)
14608 goto next_ordered_clause
;
14611 for (vec
= OMP_CLAUSE_DECL (c
), i
= 0;
14612 vec
&& TREE_CODE (vec
) == TREE_LIST
;
14613 vec
= TREE_CHAIN (vec
), ++i
)
14615 gcc_assert (i
< len
);
14617 /* extract_omp_for_data has canonicalized the condition. */
14618 gcc_assert (fd
.loops
[i
].cond_code
== LT_EXPR
14619 || fd
.loops
[i
].cond_code
== GT_EXPR
);
14620 bool forward
= fd
.loops
[i
].cond_code
== LT_EXPR
;
14621 bool maybe_lexically_later
= true;
14623 /* While the committee makes up its mind, bail if we have any
14624 non-constant steps. */
14625 if (TREE_CODE (fd
.loops
[i
].step
) != INTEGER_CST
)
14626 goto lower_omp_ordered_ret
;
14628 tree itype
= TREE_TYPE (TREE_VALUE (vec
));
14629 if (POINTER_TYPE_P (itype
))
14631 wide_int offset
= wide_int::from (TREE_PURPOSE (vec
),
14632 TYPE_PRECISION (itype
),
14633 TYPE_SIGN (itype
));
14635 /* Ignore invalid offsets that are not multiples of the step. */
14636 if (!wi::multiple_of_p
14637 (wi::abs (offset
), wi::abs ((wide_int
) fd
.loops
[i
].step
),
14640 warning_at (OMP_CLAUSE_LOCATION (c
), 0,
14641 "ignoring sink clause with offset that is not "
14642 "a multiple of the loop step");
14644 goto next_ordered_clause
;
14647 /* Calculate the first dimension. The first dimension of
14648 the folded dependency vector is the GCD of the first
14649 elements, while ignoring any first elements whose offset
14653 /* Ignore dependence vectors whose first dimension is 0. */
14657 goto next_ordered_clause
;
14661 if (!TYPE_UNSIGNED (itype
) && (forward
^ wi::neg_p (offset
)))
14663 error_at (OMP_CLAUSE_LOCATION (c
),
14664 "first offset must be in opposite direction "
14665 "of loop iterations");
14666 goto lower_omp_ordered_ret
;
14670 neg_offset_p
= forward
;
14671 /* Initialize the first time around. */
14672 if (folded_dep
== NULL_TREE
)
14675 folded_deps
[0] = offset
;
14678 folded_deps
[0] = wi::gcd (folded_deps
[0],
14682 /* Calculate minimum for the remaining dimensions. */
14685 folded_deps
[len
+ i
- 1] = offset
;
14686 if (folded_dep
== c
)
14687 folded_deps
[i
] = offset
;
14688 else if (maybe_lexically_later
14689 && !wi::eq_p (folded_deps
[i
], offset
))
14691 if (forward
^ wi::gts_p (folded_deps
[i
], offset
))
14695 for (j
= 1; j
<= i
; j
++)
14696 folded_deps
[j
] = folded_deps
[len
+ j
- 1];
14699 maybe_lexically_later
= false;
14703 gcc_assert (i
== len
);
14707 next_ordered_clause
:
14709 *list_p
= OMP_CLAUSE_CHAIN (c
);
14711 list_p
= &OMP_CLAUSE_CHAIN (c
);
14717 folded_deps
[0] = -folded_deps
[0];
14719 tree itype
= TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep
)));
14720 if (POINTER_TYPE_P (itype
))
14723 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep
))
14724 = wide_int_to_tree (itype
, folded_deps
[0]);
14725 OMP_CLAUSE_CHAIN (folded_dep
) = gimple_omp_ordered_clauses (ord_stmt
);
14726 *gimple_omp_ordered_clauses_ptr (ord_stmt
) = folded_dep
;
14729 lower_omp_ordered_ret
:
14731 /* Ordered without clauses is #pragma omp threads, while we want
14732 a nop instead if we remove all clauses. */
14733 if (gimple_omp_ordered_clauses (ord_stmt
) == NULL_TREE
)
14734 gsi_replace (gsi_p
, gimple_build_nop (), true);
14738 /* Expand code for an OpenMP ordered directive. */
14741 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
14744 gimple
*stmt
= gsi_stmt (*gsi_p
);
14745 gomp_ordered
*ord_stmt
= as_a
<gomp_ordered
*> (stmt
);
14748 bool simd
= find_omp_clause (gimple_omp_ordered_clauses (ord_stmt
),
14750 bool threads
= find_omp_clause (gimple_omp_ordered_clauses (ord_stmt
),
14751 OMP_CLAUSE_THREADS
);
14753 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt
),
14754 OMP_CLAUSE_DEPEND
))
14756 /* FIXME: This is needs to be moved to the expansion to verify various
14757 conditions only testable on cfg with dominators computed, and also
14758 all the depend clauses to be merged still might need to be available
14759 for the runtime checks. */
14761 lower_omp_ordered_clauses (gsi_p
, ord_stmt
, ctx
);
14765 push_gimplify_context ();
14767 block
= make_node (BLOCK
);
14768 bind
= gimple_build_bind (NULL
, NULL
, block
);
14769 gsi_replace (gsi_p
, bind
, true);
14770 gimple_bind_add_stmt (bind
, stmt
);
14774 x
= gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START
, 1,
14775 build_int_cst (NULL_TREE
, threads
));
14776 cfun
->has_simduid_loops
= true;
14779 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
14781 gimple_bind_add_stmt (bind
, x
);
14783 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
14784 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
14785 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
14786 gimple_omp_set_body (stmt
, NULL
);
14789 x
= gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END
, 1,
14790 build_int_cst (NULL_TREE
, threads
));
14792 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
),
14794 gimple_bind_add_stmt (bind
, x
);
14796 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
14798 pop_gimplify_context (bind
);
14800 gimple_bind_append_vars (bind
, ctx
->block_vars
);
14801 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
14805 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14806 substitution of a couple of function calls. But in the NAMED case,
14807 requires that languages coordinate a symbol name. It is therefore
14808 best put here in common code. */
14810 static GTY(()) hash_map
<tree
, tree
> *critical_name_mutexes
;
14813 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
14816 tree name
, lock
, unlock
;
14817 gomp_critical
*stmt
= as_a
<gomp_critical
*> (gsi_stmt (*gsi_p
));
14819 location_t loc
= gimple_location (stmt
);
14822 name
= gimple_omp_critical_name (stmt
);
14827 if (!critical_name_mutexes
)
14828 critical_name_mutexes
= hash_map
<tree
, tree
>::create_ggc (10);
14830 tree
*n
= critical_name_mutexes
->get (name
);
14835 decl
= create_tmp_var_raw (ptr_type_node
);
14837 new_str
= ACONCAT ((".gomp_critical_user_",
14838 IDENTIFIER_POINTER (name
), NULL
));
14839 DECL_NAME (decl
) = get_identifier (new_str
);
14840 TREE_PUBLIC (decl
) = 1;
14841 TREE_STATIC (decl
) = 1;
14842 DECL_COMMON (decl
) = 1;
14843 DECL_ARTIFICIAL (decl
) = 1;
14844 DECL_IGNORED_P (decl
) = 1;
14846 varpool_node::finalize_decl (decl
);
14848 critical_name_mutexes
->put (name
, decl
);
14853 /* If '#pragma omp critical' is inside offloaded region or
14854 inside function marked as offloadable, the symbol must be
14855 marked as offloadable too. */
14857 if (cgraph_node::get (current_function_decl
)->offloadable
)
14858 varpool_node::get_create (decl
)->offloadable
= 1;
14860 for (octx
= ctx
->outer
; octx
; octx
= octx
->outer
)
14861 if (is_gimple_omp_offloaded (octx
->stmt
))
14863 varpool_node::get_create (decl
)->offloadable
= 1;
14867 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
14868 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
14870 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
14871 unlock
= build_call_expr_loc (loc
, unlock
, 1,
14872 build_fold_addr_expr_loc (loc
, decl
));
14876 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
14877 lock
= build_call_expr_loc (loc
, lock
, 0);
14879 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
14880 unlock
= build_call_expr_loc (loc
, unlock
, 0);
14883 push_gimplify_context ();
14885 block
= make_node (BLOCK
);
14886 bind
= gimple_build_bind (NULL
, NULL
, block
);
14887 gsi_replace (gsi_p
, bind
, true);
14888 gimple_bind_add_stmt (bind
, stmt
);
14890 tbody
= gimple_bind_body (bind
);
14891 gimplify_and_add (lock
, &tbody
);
14892 gimple_bind_set_body (bind
, tbody
);
14894 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
14895 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
14896 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
14897 gimple_omp_set_body (stmt
, NULL
);
14899 tbody
= gimple_bind_body (bind
);
14900 gimplify_and_add (unlock
, &tbody
);
14901 gimple_bind_set_body (bind
, tbody
);
14903 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
14905 pop_gimplify_context (bind
);
14906 gimple_bind_append_vars (bind
, ctx
->block_vars
);
14907 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
14911 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14912 for a lastprivate clause. Given a loop control predicate of (V
14913 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14914 is appended to *DLIST, iterator initialization is appended to
14918 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
14919 gimple_seq
*dlist
, struct omp_context
*ctx
)
14921 tree clauses
, cond
, vinit
;
14922 enum tree_code cond_code
;
14925 cond_code
= fd
->loop
.cond_code
;
14926 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
14928 /* When possible, use a strict equality expression. This can let VRP
14929 type optimizations deduce the value and remove a copy. */
14930 if (tree_fits_shwi_p (fd
->loop
.step
))
14932 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
14933 if (step
== 1 || step
== -1)
14934 cond_code
= EQ_EXPR
;
14937 tree n2
= fd
->loop
.n2
;
14938 if (fd
->collapse
> 1
14939 && TREE_CODE (n2
) != INTEGER_CST
14940 && gimple_omp_for_combined_into_p (fd
->for_stmt
))
14942 struct omp_context
*taskreg_ctx
= NULL
;
14943 if (gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_FOR
)
14945 gomp_for
*gfor
= as_a
<gomp_for
*> (ctx
->outer
->stmt
);
14946 if (gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_FOR
14947 || gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
14949 if (gimple_omp_for_combined_into_p (gfor
))
14951 gcc_assert (ctx
->outer
->outer
14952 && is_parallel_ctx (ctx
->outer
->outer
));
14953 taskreg_ctx
= ctx
->outer
->outer
;
14957 struct omp_for_data outer_fd
;
14958 extract_omp_for_data (gfor
, &outer_fd
, NULL
);
14959 n2
= fold_convert (TREE_TYPE (n2
), outer_fd
.loop
.n2
);
14962 else if (gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_TASKLOOP
)
14963 taskreg_ctx
= ctx
->outer
->outer
;
14965 else if (is_taskreg_ctx (ctx
->outer
))
14966 taskreg_ctx
= ctx
->outer
;
14971 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx
->stmt
),
14972 OMP_CLAUSE__LOOPTEMP_
);
14973 gcc_assert (innerc
);
14974 for (i
= 0; i
< fd
->collapse
; i
++)
14976 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
14977 OMP_CLAUSE__LOOPTEMP_
);
14978 gcc_assert (innerc
);
14980 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
14981 OMP_CLAUSE__LOOPTEMP_
);
14983 n2
= fold_convert (TREE_TYPE (n2
),
14984 lookup_decl (OMP_CLAUSE_DECL (innerc
),
14988 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, n2
);
14990 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
14992 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
14993 if (!gimple_seq_empty_p (stmts
))
14995 gimple_seq_add_seq (&stmts
, *dlist
);
14998 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14999 vinit
= fd
->loop
.n1
;
15000 if (cond_code
== EQ_EXPR
15001 && tree_fits_shwi_p (fd
->loop
.n2
)
15002 && ! integer_zerop (fd
->loop
.n2
))
15003 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
15005 vinit
= unshare_expr (vinit
);
15007 /* Initialize the iterator variable, so that threads that don't execute
15008 any iterations don't execute the lastprivate clauses by accident. */
15009 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
15014 /* Lower code for an OMP loop directive. */
15017 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
15019 tree
*rhs_p
, block
;
15020 struct omp_for_data fd
, *fdp
= NULL
;
15021 gomp_for
*stmt
= as_a
<gomp_for
*> (gsi_stmt (*gsi_p
));
15023 gimple_seq omp_for_body
, body
, dlist
;
15024 gimple_seq oacc_head
= NULL
, oacc_tail
= NULL
;
15027 push_gimplify_context ();
15029 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
15031 block
= make_node (BLOCK
);
15032 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
15033 /* Replace at gsi right away, so that 'stmt' is no member
15034 of a sequence anymore as we're going to add to a different
15036 gsi_replace (gsi_p
, new_stmt
, true);
15038 /* Move declaration of temporaries in the loop body before we make
15040 omp_for_body
= gimple_omp_body (stmt
);
15041 if (!gimple_seq_empty_p (omp_for_body
)
15042 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
15045 = as_a
<gbind
*> (gimple_seq_first_stmt (omp_for_body
));
15046 tree vars
= gimple_bind_vars (inner_bind
);
15047 gimple_bind_append_vars (new_stmt
, vars
);
15048 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15049 keep them on the inner_bind and it's block. */
15050 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
15051 if (gimple_bind_block (inner_bind
))
15052 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
15055 if (gimple_omp_for_combined_into_p (stmt
))
15057 extract_omp_for_data (stmt
, &fd
, NULL
);
15060 /* We need two temporaries with fd.loop.v type (istart/iend)
15061 and then (fd.collapse - 1) temporaries with the same
15062 type for count2 ... countN-1 vars if not constant. */
15064 tree type
= fd
.iter_type
;
15065 if (fd
.collapse
> 1
15066 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
15067 count
+= fd
.collapse
- 1;
15069 = (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
15070 || gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_TASKLOOP
);
15071 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
15072 tree clauses
= *pc
;
15075 = find_omp_clause (gimple_omp_taskreg_clauses (ctx
->outer
->stmt
),
15076 OMP_CLAUSE__LOOPTEMP_
);
15077 for (i
= 0; i
< count
; i
++)
15082 gcc_assert (outerc
);
15083 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
15084 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
15085 OMP_CLAUSE__LOOPTEMP_
);
15089 temp
= create_tmp_var (type
);
15090 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
15092 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
15093 OMP_CLAUSE_DECL (*pc
) = temp
;
15094 pc
= &OMP_CLAUSE_CHAIN (*pc
);
15099 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15102 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
15104 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
15106 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
15108 /* Lower the header expressions. At this point, we can assume that
15109 the header is of the form:
15111 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15113 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15114 using the .omp_data_s mapping, if needed. */
15115 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
15117 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
15118 if (!is_gimple_min_invariant (*rhs_p
))
15119 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
15121 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
15122 if (!is_gimple_min_invariant (*rhs_p
))
15123 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
15125 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
15126 if (!is_gimple_min_invariant (*rhs_p
))
15127 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
15130 /* Once lowered, extract the bounds and clauses. */
15131 extract_omp_for_data (stmt
, &fd
, NULL
);
15133 if (is_gimple_omp_oacc (ctx
->stmt
)
15134 && !ctx_in_oacc_kernels_region (ctx
))
15135 lower_oacc_head_tail (gimple_location (stmt
),
15136 gimple_omp_for_clauses (stmt
),
15137 &oacc_head
, &oacc_tail
, ctx
);
15139 /* Add OpenACC partitioning and reduction markers just before the loop */
15141 gimple_seq_add_seq (&body
, oacc_head
);
15143 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
15145 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
15146 for (tree c
= gimple_omp_for_clauses (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
15147 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
15148 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
15150 OMP_CLAUSE_DECL (c
) = lookup_decl (OMP_CLAUSE_DECL (c
), ctx
);
15151 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c
)))
15152 OMP_CLAUSE_LINEAR_STEP (c
)
15153 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c
),
15157 if (!gimple_omp_for_grid_phony (stmt
))
15158 gimple_seq_add_stmt (&body
, stmt
);
15159 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
15161 if (!gimple_omp_for_grid_phony (stmt
))
15162 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
15165 /* After the loop, add exit clauses. */
15166 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
15168 if (ctx
->cancellable
)
15169 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
15171 gimple_seq_add_seq (&body
, dlist
);
15173 body
= maybe_catch_exception (body
);
15175 if (!gimple_omp_for_grid_phony (stmt
))
15177 /* Region exit marker goes at the end of the loop body. */
15178 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
15179 maybe_add_implicit_barrier_cancel (ctx
, &body
);
15182 /* Add OpenACC joining and reduction markers just after the loop. */
15184 gimple_seq_add_seq (&body
, oacc_tail
);
15186 pop_gimplify_context (new_stmt
);
15188 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
15189 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
15190 if (BLOCK_VARS (block
))
15191 TREE_USED (block
) = 1;
15193 gimple_bind_set_body (new_stmt
, body
);
15194 gimple_omp_set_body (stmt
, NULL
);
15195 gimple_omp_for_set_pre_body (stmt
, NULL
);
15198 /* Callback for walk_stmts. Check if the current statement only contains
15199 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15202 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
15203 bool *handled_ops_p
,
15204 struct walk_stmt_info
*wi
)
15206 int *info
= (int *) wi
->info
;
15207 gimple
*stmt
= gsi_stmt (*gsi_p
);
15209 *handled_ops_p
= true;
15210 switch (gimple_code (stmt
))
15214 case GIMPLE_OMP_FOR
:
15215 case GIMPLE_OMP_SECTIONS
:
15216 *info
= *info
== 0 ? 1 : -1;
15225 struct omp_taskcopy_context
15227 /* This field must be at the beginning, as we do "inheritance": Some
15228 callback functions for tree-inline.c (e.g., omp_copy_decl)
15229 receive a copy_body_data pointer that is up-casted to an
15230 omp_context pointer. */
15236 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
15238 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
15240 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
15241 return create_tmp_var (TREE_TYPE (var
));
15247 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
15249 tree name
, new_fields
= NULL
, type
, f
;
15251 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
15252 name
= DECL_NAME (TYPE_NAME (orig_type
));
15253 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
15254 TYPE_DECL
, name
, type
);
15255 TYPE_NAME (type
) = name
;
15257 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
15259 tree new_f
= copy_node (f
);
15260 DECL_CONTEXT (new_f
) = type
;
15261 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
15262 TREE_CHAIN (new_f
) = new_fields
;
15263 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
15264 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
15265 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
15267 new_fields
= new_f
;
15268 tcctx
->cb
.decl_map
->put (f
, new_f
);
15270 TYPE_FIELDS (type
) = nreverse (new_fields
);
15271 layout_type (type
);
15275 /* Create task copyfn. */
15278 create_task_copyfn (gomp_task
*task_stmt
, omp_context
*ctx
)
15280 struct function
*child_cfun
;
15281 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
15282 tree record_type
, srecord_type
, bind
, list
;
15283 bool record_needs_remap
= false, srecord_needs_remap
= false;
15285 struct omp_taskcopy_context tcctx
;
15286 location_t loc
= gimple_location (task_stmt
);
15288 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
15289 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
15290 gcc_assert (child_cfun
->cfg
== NULL
);
15291 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
15293 /* Reset DECL_CONTEXT on function arguments. */
15294 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
15295 DECL_CONTEXT (t
) = child_fn
;
15297 /* Populate the function. */
15298 push_gimplify_context ();
15299 push_cfun (child_cfun
);
15301 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
15302 TREE_SIDE_EFFECTS (bind
) = 1;
15304 DECL_SAVED_TREE (child_fn
) = bind
;
15305 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
15307 /* Remap src and dst argument types if needed. */
15308 record_type
= ctx
->record_type
;
15309 srecord_type
= ctx
->srecord_type
;
15310 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
15311 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
15313 record_needs_remap
= true;
15316 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
15317 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
15319 srecord_needs_remap
= true;
15323 if (record_needs_remap
|| srecord_needs_remap
)
15325 memset (&tcctx
, '\0', sizeof (tcctx
));
15326 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
15327 tcctx
.cb
.dst_fn
= child_fn
;
15328 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
15329 gcc_checking_assert (tcctx
.cb
.src_node
);
15330 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
15331 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
15332 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
15333 tcctx
.cb
.eh_lp_nr
= 0;
15334 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
15335 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
15338 if (record_needs_remap
)
15339 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
15340 if (srecord_needs_remap
)
15341 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
15344 tcctx
.cb
.decl_map
= NULL
;
15346 arg
= DECL_ARGUMENTS (child_fn
);
15347 TREE_TYPE (arg
) = build_pointer_type (record_type
);
15348 sarg
= DECL_CHAIN (arg
);
15349 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
15351 /* First pass: initialize temporaries used in record_type and srecord_type
15352 sizes and field offsets. */
15353 if (tcctx
.cb
.decl_map
)
15354 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
15355 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
15359 decl
= OMP_CLAUSE_DECL (c
);
15360 p
= tcctx
.cb
.decl_map
->get (decl
);
15363 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
15364 sf
= (tree
) n
->value
;
15365 sf
= *tcctx
.cb
.decl_map
->get (sf
);
15366 src
= build_simple_mem_ref_loc (loc
, sarg
);
15367 src
= omp_build_component_ref (src
, sf
);
15368 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
15369 append_to_statement_list (t
, &list
);
15372 /* Second pass: copy shared var pointers and copy construct non-VLA
15373 firstprivate vars. */
15374 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
15375 switch (OMP_CLAUSE_CODE (c
))
15377 splay_tree_key key
;
15378 case OMP_CLAUSE_SHARED
:
15379 decl
= OMP_CLAUSE_DECL (c
);
15380 key
= (splay_tree_key
) decl
;
15381 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c
))
15382 key
= (splay_tree_key
) &DECL_UID (decl
);
15383 n
= splay_tree_lookup (ctx
->field_map
, key
);
15386 f
= (tree
) n
->value
;
15387 if (tcctx
.cb
.decl_map
)
15388 f
= *tcctx
.cb
.decl_map
->get (f
);
15389 n
= splay_tree_lookup (ctx
->sfield_map
, key
);
15390 sf
= (tree
) n
->value
;
15391 if (tcctx
.cb
.decl_map
)
15392 sf
= *tcctx
.cb
.decl_map
->get (sf
);
15393 src
= build_simple_mem_ref_loc (loc
, sarg
);
15394 src
= omp_build_component_ref (src
, sf
);
15395 dst
= build_simple_mem_ref_loc (loc
, arg
);
15396 dst
= omp_build_component_ref (dst
, f
);
15397 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
15398 append_to_statement_list (t
, &list
);
15400 case OMP_CLAUSE_FIRSTPRIVATE
:
15401 decl
= OMP_CLAUSE_DECL (c
);
15402 if (is_variable_sized (decl
))
15404 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
15407 f
= (tree
) n
->value
;
15408 if (tcctx
.cb
.decl_map
)
15409 f
= *tcctx
.cb
.decl_map
->get (f
);
15410 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
15413 sf
= (tree
) n
->value
;
15414 if (tcctx
.cb
.decl_map
)
15415 sf
= *tcctx
.cb
.decl_map
->get (sf
);
15416 src
= build_simple_mem_ref_loc (loc
, sarg
);
15417 src
= omp_build_component_ref (src
, sf
);
15418 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
15419 src
= build_simple_mem_ref_loc (loc
, src
);
15423 dst
= build_simple_mem_ref_loc (loc
, arg
);
15424 dst
= omp_build_component_ref (dst
, f
);
15425 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
15426 append_to_statement_list (t
, &list
);
15428 case OMP_CLAUSE_PRIVATE
:
15429 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
15431 decl
= OMP_CLAUSE_DECL (c
);
15432 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
15433 f
= (tree
) n
->value
;
15434 if (tcctx
.cb
.decl_map
)
15435 f
= *tcctx
.cb
.decl_map
->get (f
);
15436 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
15439 sf
= (tree
) n
->value
;
15440 if (tcctx
.cb
.decl_map
)
15441 sf
= *tcctx
.cb
.decl_map
->get (sf
);
15442 src
= build_simple_mem_ref_loc (loc
, sarg
);
15443 src
= omp_build_component_ref (src
, sf
);
15444 if (use_pointer_for_field (decl
, NULL
))
15445 src
= build_simple_mem_ref_loc (loc
, src
);
15449 dst
= build_simple_mem_ref_loc (loc
, arg
);
15450 dst
= omp_build_component_ref (dst
, f
);
15451 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
15452 append_to_statement_list (t
, &list
);
15458 /* Last pass: handle VLA firstprivates. */
15459 if (tcctx
.cb
.decl_map
)
15460 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
15461 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
15465 decl
= OMP_CLAUSE_DECL (c
);
15466 if (!is_variable_sized (decl
))
15468 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
15471 f
= (tree
) n
->value
;
15472 f
= *tcctx
.cb
.decl_map
->get (f
);
15473 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
15474 ind
= DECL_VALUE_EXPR (decl
);
15475 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
15476 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
15477 n
= splay_tree_lookup (ctx
->sfield_map
,
15478 (splay_tree_key
) TREE_OPERAND (ind
, 0));
15479 sf
= (tree
) n
->value
;
15480 sf
= *tcctx
.cb
.decl_map
->get (sf
);
15481 src
= build_simple_mem_ref_loc (loc
, sarg
);
15482 src
= omp_build_component_ref (src
, sf
);
15483 src
= build_simple_mem_ref_loc (loc
, src
);
15484 dst
= build_simple_mem_ref_loc (loc
, arg
);
15485 dst
= omp_build_component_ref (dst
, f
);
15486 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
15487 append_to_statement_list (t
, &list
);
15488 n
= splay_tree_lookup (ctx
->field_map
,
15489 (splay_tree_key
) TREE_OPERAND (ind
, 0));
15490 df
= (tree
) n
->value
;
15491 df
= *tcctx
.cb
.decl_map
->get (df
);
15492 ptr
= build_simple_mem_ref_loc (loc
, arg
);
15493 ptr
= omp_build_component_ref (ptr
, df
);
15494 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
15495 build_fold_addr_expr_loc (loc
, dst
));
15496 append_to_statement_list (t
, &list
);
15499 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
15500 append_to_statement_list (t
, &list
);
15502 if (tcctx
.cb
.decl_map
)
15503 delete tcctx
.cb
.decl_map
;
15504 pop_gimplify_context (NULL
);
15505 BIND_EXPR_BODY (bind
) = list
;
15510 lower_depend_clauses (tree
*pclauses
, gimple_seq
*iseq
, gimple_seq
*oseq
)
15514 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
15516 clauses
= find_omp_clause (*pclauses
, OMP_CLAUSE_DEPEND
);
15517 gcc_assert (clauses
);
15518 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
15519 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
15520 switch (OMP_CLAUSE_DEPEND_KIND (c
))
15522 case OMP_CLAUSE_DEPEND_IN
:
15525 case OMP_CLAUSE_DEPEND_OUT
:
15526 case OMP_CLAUSE_DEPEND_INOUT
:
15529 case OMP_CLAUSE_DEPEND_SOURCE
:
15530 case OMP_CLAUSE_DEPEND_SINK
:
15533 gcc_unreachable ();
15535 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
15536 tree array
= create_tmp_var (type
);
15537 TREE_ADDRESSABLE (array
) = 1;
15538 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
15540 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
15541 gimple_seq_add_stmt (iseq
, g
);
15542 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
15544 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
15545 gimple_seq_add_stmt (iseq
, g
);
15546 for (i
= 0; i
< 2; i
++)
15548 if ((i
? n_in
: n_out
) == 0)
15550 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
15551 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
15552 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
15554 tree t
= OMP_CLAUSE_DECL (c
);
15555 t
= fold_convert (ptr_type_node
, t
);
15556 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
15557 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
15558 NULL_TREE
, NULL_TREE
);
15559 g
= gimple_build_assign (r
, t
);
15560 gimple_seq_add_stmt (iseq
, g
);
15563 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
15564 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
15565 OMP_CLAUSE_CHAIN (c
) = *pclauses
;
15567 tree clobber
= build_constructor (type
, NULL
);
15568 TREE_THIS_VOLATILE (clobber
) = 1;
15569 g
= gimple_build_assign (array
, clobber
);
15570 gimple_seq_add_stmt (oseq
, g
);
15573 /* Lower the OpenMP parallel or task directive in the current statement
15574 in GSI_P. CTX holds context information for the directive. */
15577 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
15581 gimple
*stmt
= gsi_stmt (*gsi_p
);
15582 gbind
*par_bind
, *bind
, *dep_bind
= NULL
;
15583 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
15584 location_t loc
= gimple_location (stmt
);
15586 clauses
= gimple_omp_taskreg_clauses (stmt
);
15588 = as_a
<gbind
*> (gimple_seq_first_stmt (gimple_omp_body (stmt
)));
15589 par_body
= gimple_bind_body (par_bind
);
15590 child_fn
= ctx
->cb
.dst_fn
;
15591 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
15592 && !gimple_omp_parallel_combined_p (stmt
))
15594 struct walk_stmt_info wi
;
15597 memset (&wi
, 0, sizeof (wi
));
15599 wi
.val_only
= true;
15600 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
15602 gimple_omp_parallel_set_combined_p (stmt
, true);
15604 gimple_seq dep_ilist
= NULL
;
15605 gimple_seq dep_olist
= NULL
;
15606 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
15607 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
15609 push_gimplify_context ();
15610 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
15611 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt
),
15612 &dep_ilist
, &dep_olist
);
15615 if (ctx
->srecord_type
)
15616 create_task_copyfn (as_a
<gomp_task
*> (stmt
), ctx
);
15618 push_gimplify_context ();
15623 bool phony_construct
= gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
15624 && gimple_omp_parallel_grid_phony (as_a
<gomp_parallel
*> (stmt
));
15625 if (phony_construct
&& ctx
->record_type
)
15627 gcc_checking_assert (!ctx
->receiver_decl
);
15628 ctx
->receiver_decl
= create_tmp_var
15629 (build_reference_type (ctx
->record_type
), ".omp_rec");
15631 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
15632 lower_omp (&par_body
, ctx
);
15633 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
15634 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
15636 /* Declare all the variables created by mapping and the variables
15637 declared in the scope of the parallel body. */
15638 record_vars_into (ctx
->block_vars
, child_fn
);
15639 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
15641 if (ctx
->record_type
)
15644 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
15645 : ctx
->record_type
, ".omp_data_o");
15646 DECL_NAMELESS (ctx
->sender_decl
) = 1;
15647 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
15648 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
15653 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
15654 lower_send_shared_vars (&ilist
, &olist
, ctx
);
15656 if (ctx
->record_type
)
15658 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
15659 TREE_THIS_VOLATILE (clobber
) = 1;
15660 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
15664 /* Once all the expansions are done, sequence all the different
15665 fragments inside gimple_omp_body. */
15669 if (ctx
->record_type
)
15671 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
15672 /* fixup_child_record_type might have changed receiver_decl's type. */
15673 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
15674 gimple_seq_add_stmt (&new_body
,
15675 gimple_build_assign (ctx
->receiver_decl
, t
));
15678 gimple_seq_add_seq (&new_body
, par_ilist
);
15679 gimple_seq_add_seq (&new_body
, par_body
);
15680 gimple_seq_add_seq (&new_body
, par_rlist
);
15681 if (ctx
->cancellable
)
15682 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
15683 gimple_seq_add_seq (&new_body
, par_olist
);
15684 new_body
= maybe_catch_exception (new_body
);
15685 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
)
15686 gimple_seq_add_stmt (&new_body
,
15687 gimple_build_omp_continue (integer_zero_node
,
15688 integer_zero_node
));
15689 if (!phony_construct
)
15691 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
15692 gimple_omp_set_body (stmt
, new_body
);
15695 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
15696 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
15697 gimple_bind_add_seq (bind
, ilist
);
15698 if (!phony_construct
)
15699 gimple_bind_add_stmt (bind
, stmt
);
15701 gimple_bind_add_seq (bind
, new_body
);
15702 gimple_bind_add_seq (bind
, olist
);
15704 pop_gimplify_context (NULL
);
15708 gimple_bind_add_seq (dep_bind
, dep_ilist
);
15709 gimple_bind_add_stmt (dep_bind
, bind
);
15710 gimple_bind_add_seq (dep_bind
, dep_olist
);
15711 pop_gimplify_context (dep_bind
);
15715 /* Lower the GIMPLE_OMP_TARGET in the current statement
15716 in GSI_P. CTX holds context information for the directive. */
15719 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
15722 tree child_fn
, t
, c
;
15723 gomp_target
*stmt
= as_a
<gomp_target
*> (gsi_stmt (*gsi_p
));
15724 gbind
*tgt_bind
, *bind
, *dep_bind
= NULL
;
15725 gimple_seq tgt_body
, olist
, ilist
, fplist
, new_body
;
15726 location_t loc
= gimple_location (stmt
);
15727 bool offloaded
, data_region
;
15728 unsigned int map_cnt
= 0;
15730 offloaded
= is_gimple_omp_offloaded (stmt
);
15731 switch (gimple_omp_target_kind (stmt
))
15733 case GF_OMP_TARGET_KIND_REGION
:
15734 case GF_OMP_TARGET_KIND_UPDATE
:
15735 case GF_OMP_TARGET_KIND_ENTER_DATA
:
15736 case GF_OMP_TARGET_KIND_EXIT_DATA
:
15737 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
15738 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
15739 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
15740 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
15741 case GF_OMP_TARGET_KIND_OACC_DECLARE
:
15742 data_region
= false;
15744 case GF_OMP_TARGET_KIND_DATA
:
15745 case GF_OMP_TARGET_KIND_OACC_DATA
:
15746 case GF_OMP_TARGET_KIND_OACC_HOST_DATA
:
15747 data_region
= true;
15750 gcc_unreachable ();
15753 clauses
= gimple_omp_target_clauses (stmt
);
15755 gimple_seq dep_ilist
= NULL
;
15756 gimple_seq dep_olist
= NULL
;
15757 if (find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
15759 push_gimplify_context ();
15760 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
15761 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt
),
15762 &dep_ilist
, &dep_olist
);
15769 tgt_bind
= gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt
));
15770 tgt_body
= gimple_bind_body (tgt_bind
);
15772 else if (data_region
)
15773 tgt_body
= gimple_omp_body (stmt
);
15774 child_fn
= ctx
->cb
.dst_fn
;
15776 push_gimplify_context ();
15779 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
15780 switch (OMP_CLAUSE_CODE (c
))
15786 case OMP_CLAUSE_MAP
:
15788 /* First check what we're prepared to handle in the following. */
15789 switch (OMP_CLAUSE_MAP_KIND (c
))
15791 case GOMP_MAP_ALLOC
:
15793 case GOMP_MAP_FROM
:
15794 case GOMP_MAP_TOFROM
:
15795 case GOMP_MAP_POINTER
:
15796 case GOMP_MAP_TO_PSET
:
15797 case GOMP_MAP_DELETE
:
15798 case GOMP_MAP_RELEASE
:
15799 case GOMP_MAP_ALWAYS_TO
:
15800 case GOMP_MAP_ALWAYS_FROM
:
15801 case GOMP_MAP_ALWAYS_TOFROM
:
15802 case GOMP_MAP_FIRSTPRIVATE_POINTER
:
15803 case GOMP_MAP_FIRSTPRIVATE_REFERENCE
:
15804 case GOMP_MAP_STRUCT
:
15805 case GOMP_MAP_ALWAYS_POINTER
:
15807 case GOMP_MAP_FORCE_ALLOC
:
15808 case GOMP_MAP_FORCE_TO
:
15809 case GOMP_MAP_FORCE_FROM
:
15810 case GOMP_MAP_FORCE_TOFROM
:
15811 case GOMP_MAP_FORCE_PRESENT
:
15812 case GOMP_MAP_FORCE_DEVICEPTR
:
15813 case GOMP_MAP_DEVICE_RESIDENT
:
15814 case GOMP_MAP_LINK
:
15815 gcc_assert (is_gimple_omp_oacc (stmt
));
15818 gcc_unreachable ();
15822 case OMP_CLAUSE_TO
:
15823 case OMP_CLAUSE_FROM
:
15825 var
= OMP_CLAUSE_DECL (c
);
15828 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
15829 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
15830 && (OMP_CLAUSE_MAP_KIND (c
)
15831 != GOMP_MAP_FIRSTPRIVATE_POINTER
)))
15836 if (DECL_SIZE (var
)
15837 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
15839 tree var2
= DECL_VALUE_EXPR (var
);
15840 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
15841 var2
= TREE_OPERAND (var2
, 0);
15842 gcc_assert (DECL_P (var2
));
15847 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
15848 && (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
15849 || OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
))
15851 if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
15853 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
))
15854 && varpool_node::get_create (var
)->offloadable
)
15857 tree type
= build_pointer_type (TREE_TYPE (var
));
15858 tree new_var
= lookup_decl (var
, ctx
);
15859 x
= create_tmp_var_raw (type
, get_name (new_var
));
15860 gimple_add_tmp_var (x
);
15861 x
= build_simple_mem_ref (x
);
15862 SET_DECL_VALUE_EXPR (new_var
, x
);
15863 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
15868 if (!maybe_lookup_field (var
, ctx
))
15871 /* Don't remap oacc parallel reduction variables, because the
15872 intermediate result must be local to each gang. */
15873 if (offloaded
&& !(OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
15874 && OMP_CLAUSE_MAP_IN_REDUCTION (c
)))
15876 x
= build_receiver_ref (var
, true, ctx
);
15877 tree new_var
= lookup_decl (var
, ctx
);
15879 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
15880 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
15881 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
15882 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
15883 x
= build_simple_mem_ref (x
);
15884 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
15886 gcc_assert (is_gimple_omp_oacc (ctx
->stmt
));
15887 if (is_reference (new_var
))
15889 /* Create a local object to hold the instance
15891 tree type
= TREE_TYPE (TREE_TYPE (new_var
));
15892 const char *id
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
15893 tree inst
= create_tmp_var (type
, id
);
15894 gimplify_assign (inst
, fold_indirect_ref (x
), &fplist
);
15895 x
= build_fold_addr_expr (inst
);
15897 gimplify_assign (new_var
, x
, &fplist
);
15899 else if (DECL_P (new_var
))
15901 SET_DECL_VALUE_EXPR (new_var
, x
);
15902 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
15905 gcc_unreachable ();
15910 case OMP_CLAUSE_FIRSTPRIVATE
:
15911 if (is_oacc_parallel (ctx
))
15912 goto oacc_firstprivate
;
15914 var
= OMP_CLAUSE_DECL (c
);
15915 if (!is_reference (var
)
15916 && !is_gimple_reg_type (TREE_TYPE (var
)))
15918 tree new_var
= lookup_decl (var
, ctx
);
15919 if (is_variable_sized (var
))
15921 tree pvar
= DECL_VALUE_EXPR (var
);
15922 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
15923 pvar
= TREE_OPERAND (pvar
, 0);
15924 gcc_assert (DECL_P (pvar
));
15925 tree new_pvar
= lookup_decl (pvar
, ctx
);
15926 x
= build_fold_indirect_ref (new_pvar
);
15927 TREE_THIS_NOTRAP (x
) = 1;
15930 x
= build_receiver_ref (var
, true, ctx
);
15931 SET_DECL_VALUE_EXPR (new_var
, x
);
15932 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
15936 case OMP_CLAUSE_PRIVATE
:
15937 if (is_gimple_omp_oacc (ctx
->stmt
))
15939 var
= OMP_CLAUSE_DECL (c
);
15940 if (is_variable_sized (var
))
15942 tree new_var
= lookup_decl (var
, ctx
);
15943 tree pvar
= DECL_VALUE_EXPR (var
);
15944 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
15945 pvar
= TREE_OPERAND (pvar
, 0);
15946 gcc_assert (DECL_P (pvar
));
15947 tree new_pvar
= lookup_decl (pvar
, ctx
);
15948 x
= build_fold_indirect_ref (new_pvar
);
15949 TREE_THIS_NOTRAP (x
) = 1;
15950 SET_DECL_VALUE_EXPR (new_var
, x
);
15951 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
15955 case OMP_CLAUSE_USE_DEVICE_PTR
:
15956 case OMP_CLAUSE_IS_DEVICE_PTR
:
15957 var
= OMP_CLAUSE_DECL (c
);
15959 if (is_variable_sized (var
))
15961 tree new_var
= lookup_decl (var
, ctx
);
15962 tree pvar
= DECL_VALUE_EXPR (var
);
15963 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
15964 pvar
= TREE_OPERAND (pvar
, 0);
15965 gcc_assert (DECL_P (pvar
));
15966 tree new_pvar
= lookup_decl (pvar
, ctx
);
15967 x
= build_fold_indirect_ref (new_pvar
);
15968 TREE_THIS_NOTRAP (x
) = 1;
15969 SET_DECL_VALUE_EXPR (new_var
, x
);
15970 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
15972 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
15974 tree new_var
= lookup_decl (var
, ctx
);
15975 tree type
= build_pointer_type (TREE_TYPE (var
));
15976 x
= create_tmp_var_raw (type
, get_name (new_var
));
15977 gimple_add_tmp_var (x
);
15978 x
= build_simple_mem_ref (x
);
15979 SET_DECL_VALUE_EXPR (new_var
, x
);
15980 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
15984 tree new_var
= lookup_decl (var
, ctx
);
15985 x
= create_tmp_var_raw (TREE_TYPE (new_var
), get_name (new_var
));
15986 gimple_add_tmp_var (x
);
15987 SET_DECL_VALUE_EXPR (new_var
, x
);
15988 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
15995 target_nesting_level
++;
15996 lower_omp (&tgt_body
, ctx
);
15997 target_nesting_level
--;
15999 else if (data_region
)
16000 lower_omp (&tgt_body
, ctx
);
16004 /* Declare all the variables created by mapping and the variables
16005 declared in the scope of the target body. */
16006 record_vars_into (ctx
->block_vars
, child_fn
);
16007 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
16012 if (ctx
->record_type
)
16015 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
16016 DECL_NAMELESS (ctx
->sender_decl
) = 1;
16017 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
16018 t
= make_tree_vec (3);
16019 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
16020 TREE_VEC_ELT (t
, 1)
16021 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
16022 ".omp_data_sizes");
16023 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
16024 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
16025 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
16026 tree tkind_type
= short_unsigned_type_node
;
16027 int talign_shift
= 8;
16028 TREE_VEC_ELT (t
, 2)
16029 = create_tmp_var (build_array_type_nelts (tkind_type
, map_cnt
),
16030 ".omp_data_kinds");
16031 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
16032 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
16033 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
16034 gimple_omp_target_set_data_arg (stmt
, t
);
16036 vec
<constructor_elt
, va_gc
> *vsize
;
16037 vec
<constructor_elt
, va_gc
> *vkind
;
16038 vec_alloc (vsize
, map_cnt
);
16039 vec_alloc (vkind
, map_cnt
);
16040 unsigned int map_idx
= 0;
16042 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
16043 switch (OMP_CLAUSE_CODE (c
))
16045 tree ovar
, nc
, s
, purpose
, var
, x
, type
;
16046 unsigned int talign
;
16051 case OMP_CLAUSE_MAP
:
16052 case OMP_CLAUSE_TO
:
16053 case OMP_CLAUSE_FROM
:
16054 oacc_firstprivate_map
:
16056 ovar
= OMP_CLAUSE_DECL (c
);
16057 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
16058 && (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
16059 || (OMP_CLAUSE_MAP_KIND (c
)
16060 == GOMP_MAP_FIRSTPRIVATE_REFERENCE
)))
16062 if (!DECL_P (ovar
))
16064 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
16065 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
16067 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
16068 == get_base_address (ovar
));
16069 nc
= OMP_CLAUSE_CHAIN (c
);
16070 ovar
= OMP_CLAUSE_DECL (nc
);
16074 tree x
= build_sender_ref (ovar
, ctx
);
16076 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
16077 gimplify_assign (x
, v
, &ilist
);
16083 if (DECL_SIZE (ovar
)
16084 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
16086 tree ovar2
= DECL_VALUE_EXPR (ovar
);
16087 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
16088 ovar2
= TREE_OPERAND (ovar2
, 0);
16089 gcc_assert (DECL_P (ovar2
));
16092 if (!maybe_lookup_field (ovar
, ctx
))
16096 talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
16097 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
16098 talign
= DECL_ALIGN_UNIT (ovar
);
16101 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
16102 x
= build_sender_ref (ovar
, ctx
);
16104 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
16105 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
16106 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
16107 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
16109 gcc_assert (offloaded
);
16111 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)));
16112 mark_addressable (avar
);
16113 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
16114 talign
= DECL_ALIGN_UNIT (avar
);
16115 avar
= build_fold_addr_expr (avar
);
16116 gimplify_assign (x
, avar
, &ilist
);
16118 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
16120 gcc_assert (is_gimple_omp_oacc (ctx
->stmt
));
16121 if (!is_reference (var
))
16123 if (is_gimple_reg (var
)
16124 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c
))
16125 TREE_NO_WARNING (var
) = 1;
16126 var
= build_fold_addr_expr (var
);
16129 talign
= TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar
)));
16130 gimplify_assign (x
, var
, &ilist
);
16132 else if (is_gimple_reg (var
))
16134 gcc_assert (offloaded
);
16135 tree avar
= create_tmp_var (TREE_TYPE (var
));
16136 mark_addressable (avar
);
16137 enum gomp_map_kind map_kind
= OMP_CLAUSE_MAP_KIND (c
);
16138 if (GOMP_MAP_COPY_TO_P (map_kind
)
16139 || map_kind
== GOMP_MAP_POINTER
16140 || map_kind
== GOMP_MAP_TO_PSET
16141 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
16143 /* If we need to initialize a temporary
16144 with VAR because it is not addressable, and
16145 the variable hasn't been initialized yet, then
16146 we'll get a warning for the store to avar.
16147 Don't warn in that case, the mapping might
16149 TREE_NO_WARNING (var
) = 1;
16150 gimplify_assign (avar
, var
, &ilist
);
16152 avar
= build_fold_addr_expr (avar
);
16153 gimplify_assign (x
, avar
, &ilist
);
16154 if ((GOMP_MAP_COPY_FROM_P (map_kind
)
16155 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
16156 && !TYPE_READONLY (TREE_TYPE (var
)))
16158 x
= unshare_expr (x
);
16159 x
= build_simple_mem_ref (x
);
16160 gimplify_assign (var
, x
, &olist
);
16165 var
= build_fold_addr_expr (var
);
16166 gimplify_assign (x
, var
, &ilist
);
16170 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
16172 gcc_checking_assert (is_gimple_omp_oacc (ctx
->stmt
));
16173 s
= TREE_TYPE (ovar
);
16174 if (TREE_CODE (s
) == REFERENCE_TYPE
)
16176 s
= TYPE_SIZE_UNIT (s
);
16179 s
= OMP_CLAUSE_SIZE (c
);
16180 if (s
== NULL_TREE
)
16181 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
16182 s
= fold_convert (size_type_node
, s
);
16183 purpose
= size_int (map_idx
++);
16184 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
16185 if (TREE_CODE (s
) != INTEGER_CST
)
16186 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
16188 unsigned HOST_WIDE_INT tkind
, tkind_zero
;
16189 switch (OMP_CLAUSE_CODE (c
))
16191 case OMP_CLAUSE_MAP
:
16192 tkind
= OMP_CLAUSE_MAP_KIND (c
);
16193 tkind_zero
= tkind
;
16194 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c
))
16197 case GOMP_MAP_ALLOC
:
16199 case GOMP_MAP_FROM
:
16200 case GOMP_MAP_TOFROM
:
16201 case GOMP_MAP_ALWAYS_TO
:
16202 case GOMP_MAP_ALWAYS_FROM
:
16203 case GOMP_MAP_ALWAYS_TOFROM
:
16204 case GOMP_MAP_RELEASE
:
16205 tkind_zero
= GOMP_MAP_ZERO_LEN_ARRAY_SECTION
;
16207 case GOMP_MAP_DELETE
:
16208 tkind_zero
= GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION
;
16212 if (tkind_zero
!= tkind
)
16214 if (integer_zerop (s
))
16215 tkind
= tkind_zero
;
16216 else if (integer_nonzerop (s
))
16217 tkind_zero
= tkind
;
16220 case OMP_CLAUSE_FIRSTPRIVATE
:
16221 gcc_checking_assert (is_gimple_omp_oacc (ctx
->stmt
));
16222 tkind
= GOMP_MAP_TO
;
16223 tkind_zero
= tkind
;
16225 case OMP_CLAUSE_TO
:
16226 tkind
= GOMP_MAP_TO
;
16227 tkind_zero
= tkind
;
16229 case OMP_CLAUSE_FROM
:
16230 tkind
= GOMP_MAP_FROM
;
16231 tkind_zero
= tkind
;
16234 gcc_unreachable ();
16236 gcc_checking_assert (tkind
16237 < (HOST_WIDE_INT_C (1U) << talign_shift
));
16238 gcc_checking_assert (tkind_zero
16239 < (HOST_WIDE_INT_C (1U) << talign_shift
));
16240 talign
= ceil_log2 (talign
);
16241 tkind
|= talign
<< talign_shift
;
16242 tkind_zero
|= talign
<< talign_shift
;
16243 gcc_checking_assert (tkind
16244 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
16245 gcc_checking_assert (tkind_zero
16246 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
16247 if (tkind
== tkind_zero
)
16248 x
= build_int_cstu (tkind_type
, tkind
);
16251 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 0;
16252 x
= build3 (COND_EXPR
, tkind_type
,
16253 fold_build2 (EQ_EXPR
, boolean_type_node
,
16254 unshare_expr (s
), size_zero_node
),
16255 build_int_cstu (tkind_type
, tkind_zero
),
16256 build_int_cstu (tkind_type
, tkind
));
16258 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
, x
);
16263 case OMP_CLAUSE_FIRSTPRIVATE
:
16264 if (is_oacc_parallel (ctx
))
16265 goto oacc_firstprivate_map
;
16266 ovar
= OMP_CLAUSE_DECL (c
);
16267 if (is_reference (ovar
))
16268 talign
= TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar
)));
16270 talign
= DECL_ALIGN_UNIT (ovar
);
16271 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
16272 x
= build_sender_ref (ovar
, ctx
);
16273 tkind
= GOMP_MAP_FIRSTPRIVATE
;
16274 type
= TREE_TYPE (ovar
);
16275 if (is_reference (ovar
))
16276 type
= TREE_TYPE (type
);
16277 if ((INTEGRAL_TYPE_P (type
)
16278 && TYPE_PRECISION (type
) <= POINTER_SIZE
)
16279 || TREE_CODE (type
) == POINTER_TYPE
)
16281 tkind
= GOMP_MAP_FIRSTPRIVATE_INT
;
16283 if (is_reference (var
))
16284 t
= build_simple_mem_ref (var
);
16285 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c
))
16286 TREE_NO_WARNING (var
) = 1;
16287 if (TREE_CODE (type
) != POINTER_TYPE
)
16288 t
= fold_convert (pointer_sized_int_node
, t
);
16289 t
= fold_convert (TREE_TYPE (x
), t
);
16290 gimplify_assign (x
, t
, &ilist
);
16292 else if (is_reference (var
))
16293 gimplify_assign (x
, var
, &ilist
);
16294 else if (is_gimple_reg (var
))
16296 tree avar
= create_tmp_var (TREE_TYPE (var
));
16297 mark_addressable (avar
);
16298 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c
))
16299 TREE_NO_WARNING (var
) = 1;
16300 gimplify_assign (avar
, var
, &ilist
);
16301 avar
= build_fold_addr_expr (avar
);
16302 gimplify_assign (x
, avar
, &ilist
);
16306 var
= build_fold_addr_expr (var
);
16307 gimplify_assign (x
, var
, &ilist
);
16309 if (tkind
== GOMP_MAP_FIRSTPRIVATE_INT
)
16311 else if (is_reference (var
))
16312 s
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar
)));
16314 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
16315 s
= fold_convert (size_type_node
, s
);
16316 purpose
= size_int (map_idx
++);
16317 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
16318 if (TREE_CODE (s
) != INTEGER_CST
)
16319 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
16321 gcc_checking_assert (tkind
16322 < (HOST_WIDE_INT_C (1U) << talign_shift
));
16323 talign
= ceil_log2 (talign
);
16324 tkind
|= talign
<< talign_shift
;
16325 gcc_checking_assert (tkind
16326 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
16327 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
16328 build_int_cstu (tkind_type
, tkind
));
16331 case OMP_CLAUSE_USE_DEVICE_PTR
:
16332 case OMP_CLAUSE_IS_DEVICE_PTR
:
16333 ovar
= OMP_CLAUSE_DECL (c
);
16334 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
16335 x
= build_sender_ref (ovar
, ctx
);
16336 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_USE_DEVICE_PTR
)
16337 tkind
= GOMP_MAP_USE_DEVICE_PTR
;
16339 tkind
= GOMP_MAP_FIRSTPRIVATE_INT
;
16340 type
= TREE_TYPE (ovar
);
16341 if (TREE_CODE (type
) == ARRAY_TYPE
)
16342 var
= build_fold_addr_expr (var
);
16345 if (is_reference (ovar
))
16347 type
= TREE_TYPE (type
);
16348 if (TREE_CODE (type
) != ARRAY_TYPE
)
16349 var
= build_simple_mem_ref (var
);
16350 var
= fold_convert (TREE_TYPE (x
), var
);
16353 gimplify_assign (x
, var
, &ilist
);
16355 purpose
= size_int (map_idx
++);
16356 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
16357 gcc_checking_assert (tkind
16358 < (HOST_WIDE_INT_C (1U) << talign_shift
));
16359 gcc_checking_assert (tkind
16360 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
16361 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
16362 build_int_cstu (tkind_type
, tkind
));
16366 gcc_assert (map_idx
== map_cnt
);
16368 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
16369 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
16370 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
16371 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
16372 for (int i
= 1; i
<= 2; i
++)
16373 if (!TREE_STATIC (TREE_VEC_ELT (t
, i
)))
16375 gimple_seq initlist
= NULL
;
16376 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
16377 TREE_VEC_ELT (t
, i
)),
16378 &initlist
, true, NULL_TREE
);
16379 gimple_seq_add_seq (&ilist
, initlist
);
16381 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, i
)),
16383 TREE_THIS_VOLATILE (clobber
) = 1;
16384 gimple_seq_add_stmt (&olist
,
16385 gimple_build_assign (TREE_VEC_ELT (t
, i
),
16389 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
16390 TREE_THIS_VOLATILE (clobber
) = 1;
16391 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
16395 /* Once all the expansions are done, sequence all the different
16396 fragments inside gimple_omp_body. */
16401 && ctx
->record_type
)
16403 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
16404 /* fixup_child_record_type might have changed receiver_decl's type. */
16405 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
16406 gimple_seq_add_stmt (&new_body
,
16407 gimple_build_assign (ctx
->receiver_decl
, t
));
16409 gimple_seq_add_seq (&new_body
, fplist
);
16411 if (offloaded
|| data_region
)
16413 tree prev
= NULL_TREE
;
16414 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
16415 switch (OMP_CLAUSE_CODE (c
))
16420 case OMP_CLAUSE_FIRSTPRIVATE
:
16421 if (is_gimple_omp_oacc (ctx
->stmt
))
16423 var
= OMP_CLAUSE_DECL (c
);
16424 if (is_reference (var
)
16425 || is_gimple_reg_type (TREE_TYPE (var
)))
16427 tree new_var
= lookup_decl (var
, ctx
);
16429 type
= TREE_TYPE (var
);
16430 if (is_reference (var
))
16431 type
= TREE_TYPE (type
);
16432 if ((INTEGRAL_TYPE_P (type
)
16433 && TYPE_PRECISION (type
) <= POINTER_SIZE
)
16434 || TREE_CODE (type
) == POINTER_TYPE
)
16436 x
= build_receiver_ref (var
, false, ctx
);
16437 if (TREE_CODE (type
) != POINTER_TYPE
)
16438 x
= fold_convert (pointer_sized_int_node
, x
);
16439 x
= fold_convert (type
, x
);
16440 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
,
16442 if (is_reference (var
))
16444 tree v
= create_tmp_var_raw (type
, get_name (var
));
16445 gimple_add_tmp_var (v
);
16446 TREE_ADDRESSABLE (v
) = 1;
16447 gimple_seq_add_stmt (&new_body
,
16448 gimple_build_assign (v
, x
));
16449 x
= build_fold_addr_expr (v
);
16451 gimple_seq_add_stmt (&new_body
,
16452 gimple_build_assign (new_var
, x
));
16456 x
= build_receiver_ref (var
, !is_reference (var
), ctx
);
16457 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
,
16459 gimple_seq_add_stmt (&new_body
,
16460 gimple_build_assign (new_var
, x
));
16463 else if (is_variable_sized (var
))
16465 tree pvar
= DECL_VALUE_EXPR (var
);
16466 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
16467 pvar
= TREE_OPERAND (pvar
, 0);
16468 gcc_assert (DECL_P (pvar
));
16469 tree new_var
= lookup_decl (pvar
, ctx
);
16470 x
= build_receiver_ref (var
, false, ctx
);
16471 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16472 gimple_seq_add_stmt (&new_body
,
16473 gimple_build_assign (new_var
, x
));
16476 case OMP_CLAUSE_PRIVATE
:
16477 if (is_gimple_omp_oacc (ctx
->stmt
))
16479 var
= OMP_CLAUSE_DECL (c
);
16480 if (is_reference (var
))
16482 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
16483 tree new_var
= lookup_decl (var
, ctx
);
16484 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
16485 if (TREE_CONSTANT (x
))
16487 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
16489 gimple_add_tmp_var (x
);
16490 TREE_ADDRESSABLE (x
) = 1;
16491 x
= build_fold_addr_expr_loc (clause_loc
, x
);
16496 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
16497 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16498 gimple_seq_add_stmt (&new_body
,
16499 gimple_build_assign (new_var
, x
));
16502 case OMP_CLAUSE_USE_DEVICE_PTR
:
16503 case OMP_CLAUSE_IS_DEVICE_PTR
:
16504 var
= OMP_CLAUSE_DECL (c
);
16505 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_USE_DEVICE_PTR
)
16506 x
= build_sender_ref (var
, ctx
);
16508 x
= build_receiver_ref (var
, false, ctx
);
16509 if (is_variable_sized (var
))
16511 tree pvar
= DECL_VALUE_EXPR (var
);
16512 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
16513 pvar
= TREE_OPERAND (pvar
, 0);
16514 gcc_assert (DECL_P (pvar
));
16515 tree new_var
= lookup_decl (pvar
, ctx
);
16516 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16517 gimple_seq_add_stmt (&new_body
,
16518 gimple_build_assign (new_var
, x
));
16520 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
16522 tree new_var
= lookup_decl (var
, ctx
);
16523 new_var
= DECL_VALUE_EXPR (new_var
);
16524 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
16525 new_var
= TREE_OPERAND (new_var
, 0);
16526 gcc_assert (DECL_P (new_var
));
16527 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16528 gimple_seq_add_stmt (&new_body
,
16529 gimple_build_assign (new_var
, x
));
16533 tree type
= TREE_TYPE (var
);
16534 tree new_var
= lookup_decl (var
, ctx
);
16535 if (is_reference (var
))
16537 type
= TREE_TYPE (type
);
16538 if (TREE_CODE (type
) != ARRAY_TYPE
)
16540 tree v
= create_tmp_var_raw (type
, get_name (var
));
16541 gimple_add_tmp_var (v
);
16542 TREE_ADDRESSABLE (v
) = 1;
16543 x
= fold_convert (type
, x
);
16544 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
,
16546 gimple_seq_add_stmt (&new_body
,
16547 gimple_build_assign (v
, x
));
16548 x
= build_fold_addr_expr (v
);
16551 new_var
= DECL_VALUE_EXPR (new_var
);
16552 x
= fold_convert (TREE_TYPE (new_var
), x
);
16553 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16554 gimple_seq_add_stmt (&new_body
,
16555 gimple_build_assign (new_var
, x
));
16559 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16560 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16561 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16562 or references to VLAs. */
16563 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
16564 switch (OMP_CLAUSE_CODE (c
))
16569 case OMP_CLAUSE_MAP
:
16570 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_POINTER
16571 || OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
)
16573 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
16574 HOST_WIDE_INT offset
= 0;
16576 var
= OMP_CLAUSE_DECL (c
);
16578 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
16579 && is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
16581 && varpool_node::get_create (var
)->offloadable
)
16583 if (TREE_CODE (var
) == INDIRECT_REF
16584 && TREE_CODE (TREE_OPERAND (var
, 0)) == COMPONENT_REF
)
16585 var
= TREE_OPERAND (var
, 0);
16586 if (TREE_CODE (var
) == COMPONENT_REF
)
16588 var
= get_addr_base_and_unit_offset (var
, &offset
);
16589 gcc_assert (var
!= NULL_TREE
&& DECL_P (var
));
16591 else if (DECL_SIZE (var
)
16592 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
16594 tree var2
= DECL_VALUE_EXPR (var
);
16595 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
16596 var2
= TREE_OPERAND (var2
, 0);
16597 gcc_assert (DECL_P (var2
));
16600 tree new_var
= lookup_decl (var
, ctx
), x
;
16601 tree type
= TREE_TYPE (new_var
);
16603 if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == INDIRECT_REF
16604 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c
), 0))
16607 type
= TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c
), 0));
16609 new_var
= build2 (MEM_REF
, type
,
16610 build_fold_addr_expr (new_var
),
16611 build_int_cst (build_pointer_type (type
),
16614 else if (TREE_CODE (OMP_CLAUSE_DECL (c
)) == COMPONENT_REF
)
16616 type
= TREE_TYPE (OMP_CLAUSE_DECL (c
));
16617 is_ref
= TREE_CODE (type
) == REFERENCE_TYPE
;
16618 new_var
= build2 (MEM_REF
, type
,
16619 build_fold_addr_expr (new_var
),
16620 build_int_cst (build_pointer_type (type
),
16624 is_ref
= is_reference (var
);
16625 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
)
16627 bool ref_to_array
= false;
16630 type
= TREE_TYPE (type
);
16631 if (TREE_CODE (type
) == ARRAY_TYPE
)
16633 type
= build_pointer_type (type
);
16634 ref_to_array
= true;
16637 else if (TREE_CODE (type
) == ARRAY_TYPE
)
16639 tree decl2
= DECL_VALUE_EXPR (new_var
);
16640 gcc_assert (TREE_CODE (decl2
) == MEM_REF
);
16641 decl2
= TREE_OPERAND (decl2
, 0);
16642 gcc_assert (DECL_P (decl2
));
16644 type
= TREE_TYPE (new_var
);
16646 x
= build_receiver_ref (OMP_CLAUSE_DECL (prev
), false, ctx
);
16647 x
= fold_convert_loc (clause_loc
, type
, x
);
16648 if (!integer_zerop (OMP_CLAUSE_SIZE (c
)))
16650 tree bias
= OMP_CLAUSE_SIZE (c
);
16652 bias
= lookup_decl (bias
, ctx
);
16653 bias
= fold_convert_loc (clause_loc
, sizetype
, bias
);
16654 bias
= fold_build1_loc (clause_loc
, NEGATE_EXPR
, sizetype
,
16656 x
= fold_build2_loc (clause_loc
, POINTER_PLUS_EXPR
,
16657 TREE_TYPE (x
), x
, bias
);
16660 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
16661 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16662 if (is_ref
&& !ref_to_array
)
16664 tree t
= create_tmp_var_raw (type
, get_name (var
));
16665 gimple_add_tmp_var (t
);
16666 TREE_ADDRESSABLE (t
) = 1;
16667 gimple_seq_add_stmt (&new_body
,
16668 gimple_build_assign (t
, x
));
16669 x
= build_fold_addr_expr_loc (clause_loc
, t
);
16671 gimple_seq_add_stmt (&new_body
,
16672 gimple_build_assign (new_var
, x
));
16675 else if (OMP_CLAUSE_CHAIN (c
)
16676 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c
))
16678 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c
))
16679 == GOMP_MAP_FIRSTPRIVATE_POINTER
16680 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c
))
16681 == GOMP_MAP_FIRSTPRIVATE_REFERENCE
)))
16684 case OMP_CLAUSE_PRIVATE
:
16685 var
= OMP_CLAUSE_DECL (c
);
16686 if (is_variable_sized (var
))
16688 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
16689 tree new_var
= lookup_decl (var
, ctx
);
16690 tree pvar
= DECL_VALUE_EXPR (var
);
16691 gcc_assert (TREE_CODE (pvar
) == INDIRECT_REF
);
16692 pvar
= TREE_OPERAND (pvar
, 0);
16693 gcc_assert (DECL_P (pvar
));
16694 tree new_pvar
= lookup_decl (pvar
, ctx
);
16695 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
16696 tree al
= size_int (DECL_ALIGN (var
));
16697 tree x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
16698 x
= build_call_expr_loc (clause_loc
, atmp
, 2, x
, al
);
16699 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_pvar
), x
);
16700 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16701 gimple_seq_add_stmt (&new_body
,
16702 gimple_build_assign (new_pvar
, x
));
16704 else if (is_reference (var
) && !is_gimple_omp_oacc (ctx
->stmt
))
16706 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
16707 tree new_var
= lookup_decl (var
, ctx
);
16708 tree x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
16709 if (TREE_CONSTANT (x
))
16714 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN
);
16715 tree rtype
= TREE_TYPE (TREE_TYPE (new_var
));
16716 tree al
= size_int (TYPE_ALIGN (rtype
));
16717 x
= build_call_expr_loc (clause_loc
, atmp
, 2, x
, al
);
16720 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
16721 gimplify_expr (&x
, &new_body
, NULL
, is_gimple_val
, fb_rvalue
);
16722 gimple_seq_add_stmt (&new_body
,
16723 gimple_build_assign (new_var
, x
));
16728 gimple_seq fork_seq
= NULL
;
16729 gimple_seq join_seq
= NULL
;
16731 if (is_oacc_parallel (ctx
))
16733 /* If there are reductions on the offloaded region itself, treat
16734 them as a dummy GANG loop. */
16735 tree level
= build_int_cst (integer_type_node
, GOMP_DIM_GANG
);
16737 lower_oacc_reductions (gimple_location (ctx
->stmt
), clauses
, level
,
16738 false, NULL
, NULL
, &fork_seq
, &join_seq
, ctx
);
16741 gimple_seq_add_seq (&new_body
, fork_seq
);
16742 gimple_seq_add_seq (&new_body
, tgt_body
);
16743 gimple_seq_add_seq (&new_body
, join_seq
);
16746 new_body
= maybe_catch_exception (new_body
);
16748 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
16749 gimple_omp_set_body (stmt
, new_body
);
16752 bind
= gimple_build_bind (NULL
, NULL
,
16753 tgt_bind
? gimple_bind_block (tgt_bind
)
16755 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
16756 gimple_bind_add_seq (bind
, ilist
);
16757 gimple_bind_add_stmt (bind
, stmt
);
16758 gimple_bind_add_seq (bind
, olist
);
16760 pop_gimplify_context (NULL
);
16764 gimple_bind_add_seq (dep_bind
, dep_ilist
);
16765 gimple_bind_add_stmt (dep_bind
, bind
);
16766 gimple_bind_add_seq (dep_bind
, dep_olist
);
16767 pop_gimplify_context (dep_bind
);
16771 /* Expand code for an OpenMP teams directive. */
16774 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
16776 gomp_teams
*teams_stmt
= as_a
<gomp_teams
*> (gsi_stmt (*gsi_p
));
16777 push_gimplify_context ();
16779 tree block
= make_node (BLOCK
);
16780 gbind
*bind
= gimple_build_bind (NULL
, NULL
, block
);
16781 gsi_replace (gsi_p
, bind
, true);
16782 gimple_seq bind_body
= NULL
;
16783 gimple_seq dlist
= NULL
;
16784 gimple_seq olist
= NULL
;
16786 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
16787 OMP_CLAUSE_NUM_TEAMS
);
16788 if (num_teams
== NULL_TREE
)
16789 num_teams
= build_int_cst (unsigned_type_node
, 0);
16792 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
16793 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
16794 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
16796 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
16797 OMP_CLAUSE_THREAD_LIMIT
);
16798 if (thread_limit
== NULL_TREE
)
16799 thread_limit
= build_int_cst (unsigned_type_node
, 0);
16802 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
16803 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
16804 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
16808 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
16809 &bind_body
, &dlist
, ctx
, NULL
);
16810 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
16811 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
16812 if (!gimple_omp_teams_grid_phony (teams_stmt
))
16814 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
16815 location_t loc
= gimple_location (teams_stmt
);
16816 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
16817 gimple
*call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
16818 gimple_set_location (call
, loc
);
16819 gimple_seq_add_stmt (&bind_body
, call
);
16822 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
16823 gimple_omp_set_body (teams_stmt
, NULL
);
16824 gimple_seq_add_seq (&bind_body
, olist
);
16825 gimple_seq_add_seq (&bind_body
, dlist
);
16826 if (!gimple_omp_teams_grid_phony (teams_stmt
))
16827 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
16828 gimple_bind_set_body (bind
, bind_body
);
16830 pop_gimplify_context (bind
);
16832 gimple_bind_append_vars (bind
, ctx
->block_vars
);
16833 BLOCK_VARS (block
) = ctx
->block_vars
;
16834 if (BLOCK_VARS (block
))
16835 TREE_USED (block
) = 1;
16838 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16841 lower_omp_grid_body (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
16843 gimple
*stmt
= gsi_stmt (*gsi_p
);
16844 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
16845 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt
),
16846 gimple_build_omp_return (false));
16850 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16851 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16852 of OMP context, but with task_shared_vars set. */
16855 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
16860 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16861 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
16864 if (task_shared_vars
16866 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
16869 /* If a global variable has been privatized, TREE_CONSTANT on
16870 ADDR_EXPR might be wrong. */
16871 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
16872 recompute_tree_invariant_for_addr_expr (t
);
16874 *walk_subtrees
= !IS_TYPE_OR_DECL_P (t
);
16878 /* Data to be communicated between lower_omp_regimplify_operands and
16879 lower_omp_regimplify_operands_p. */
16881 struct lower_omp_regimplify_operands_data
16887 /* Helper function for lower_omp_regimplify_operands. Find
16888 omp_member_access_dummy_var vars and adjust temporarily their
16889 DECL_VALUE_EXPRs if needed. */
16892 lower_omp_regimplify_operands_p (tree
*tp
, int *walk_subtrees
,
16895 tree t
= omp_member_access_dummy_var (*tp
);
16898 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
16899 lower_omp_regimplify_operands_data
*ldata
16900 = (lower_omp_regimplify_operands_data
*) wi
->info
;
16901 tree o
= maybe_lookup_decl (t
, ldata
->ctx
);
16904 ldata
->decls
->safe_push (DECL_VALUE_EXPR (*tp
));
16905 ldata
->decls
->safe_push (*tp
);
16906 tree v
= unshare_and_remap (DECL_VALUE_EXPR (*tp
), t
, o
);
16907 SET_DECL_VALUE_EXPR (*tp
, v
);
16910 *walk_subtrees
= !IS_TYPE_OR_DECL_P (*tp
);
16914 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16915 of omp_member_access_dummy_var vars during regimplification. */
16918 lower_omp_regimplify_operands (omp_context
*ctx
, gimple
*stmt
,
16919 gimple_stmt_iterator
*gsi_p
)
16921 auto_vec
<tree
, 10> decls
;
16924 struct walk_stmt_info wi
;
16925 memset (&wi
, '\0', sizeof (wi
));
16926 struct lower_omp_regimplify_operands_data data
;
16928 data
.decls
= &decls
;
16930 walk_gimple_op (stmt
, lower_omp_regimplify_operands_p
, &wi
);
16932 gimple_regimplify_operands (stmt
, gsi_p
);
16933 while (!decls
.is_empty ())
16935 tree t
= decls
.pop ();
16936 tree v
= decls
.pop ();
16937 SET_DECL_VALUE_EXPR (t
, v
);
16942 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
16944 gimple
*stmt
= gsi_stmt (*gsi_p
);
16945 struct walk_stmt_info wi
;
16948 if (gimple_has_location (stmt
))
16949 input_location
= gimple_location (stmt
);
16951 if (task_shared_vars
)
16952 memset (&wi
, '\0', sizeof (wi
));
16954 /* If we have issued syntax errors, avoid doing any heavy lifting.
16955 Just replace the OMP directives with a NOP to avoid
16956 confusing RTL expansion. */
16957 if (seen_error () && is_gimple_omp (stmt
))
16959 gsi_replace (gsi_p
, gimple_build_nop (), true);
16963 switch (gimple_code (stmt
))
16967 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
16968 if ((ctx
|| task_shared_vars
)
16969 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
16970 lower_omp_regimplify_p
,
16971 ctx
? NULL
: &wi
, NULL
)
16972 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
16973 lower_omp_regimplify_p
,
16974 ctx
? NULL
: &wi
, NULL
)))
16975 lower_omp_regimplify_operands (ctx
, cond_stmt
, gsi_p
);
16979 lower_omp (gimple_catch_handler_ptr (as_a
<gcatch
*> (stmt
)), ctx
);
16981 case GIMPLE_EH_FILTER
:
16982 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
16985 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
16986 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
16988 case GIMPLE_TRANSACTION
:
16989 lower_omp (gimple_transaction_body_ptr (
16990 as_a
<gtransaction
*> (stmt
)),
16994 lower_omp (gimple_bind_body_ptr (as_a
<gbind
*> (stmt
)), ctx
);
16996 case GIMPLE_OMP_PARALLEL
:
16997 case GIMPLE_OMP_TASK
:
16998 ctx
= maybe_lookup_ctx (stmt
);
17000 if (ctx
->cancellable
)
17001 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
17002 lower_omp_taskreg (gsi_p
, ctx
);
17004 case GIMPLE_OMP_FOR
:
17005 ctx
= maybe_lookup_ctx (stmt
);
17007 if (ctx
->cancellable
)
17008 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
17009 lower_omp_for (gsi_p
, ctx
);
17011 case GIMPLE_OMP_SECTIONS
:
17012 ctx
= maybe_lookup_ctx (stmt
);
17014 if (ctx
->cancellable
)
17015 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
17016 lower_omp_sections (gsi_p
, ctx
);
17018 case GIMPLE_OMP_SINGLE
:
17019 ctx
= maybe_lookup_ctx (stmt
);
17021 lower_omp_single (gsi_p
, ctx
);
17023 case GIMPLE_OMP_MASTER
:
17024 ctx
= maybe_lookup_ctx (stmt
);
17026 lower_omp_master (gsi_p
, ctx
);
17028 case GIMPLE_OMP_TASKGROUP
:
17029 ctx
= maybe_lookup_ctx (stmt
);
17031 lower_omp_taskgroup (gsi_p
, ctx
);
17033 case GIMPLE_OMP_ORDERED
:
17034 ctx
= maybe_lookup_ctx (stmt
);
17036 lower_omp_ordered (gsi_p
, ctx
);
17038 case GIMPLE_OMP_CRITICAL
:
17039 ctx
= maybe_lookup_ctx (stmt
);
17041 lower_omp_critical (gsi_p
, ctx
);
17043 case GIMPLE_OMP_ATOMIC_LOAD
:
17044 if ((ctx
|| task_shared_vars
)
17045 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17046 as_a
<gomp_atomic_load
*> (stmt
)),
17047 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
17048 lower_omp_regimplify_operands (ctx
, stmt
, gsi_p
);
17050 case GIMPLE_OMP_TARGET
:
17051 ctx
= maybe_lookup_ctx (stmt
);
17053 lower_omp_target (gsi_p
, ctx
);
17055 case GIMPLE_OMP_TEAMS
:
17056 ctx
= maybe_lookup_ctx (stmt
);
17058 lower_omp_teams (gsi_p
, ctx
);
17060 case GIMPLE_OMP_GRID_BODY
:
17061 ctx
= maybe_lookup_ctx (stmt
);
17063 lower_omp_grid_body (gsi_p
, ctx
);
17067 call_stmt
= as_a
<gcall
*> (stmt
);
17068 fndecl
= gimple_call_fndecl (call_stmt
);
17070 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
17071 switch (DECL_FUNCTION_CODE (fndecl
))
17073 case BUILT_IN_GOMP_BARRIER
:
17077 case BUILT_IN_GOMP_CANCEL
:
17078 case BUILT_IN_GOMP_CANCELLATION_POINT
:
17081 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
17082 cctx
= cctx
->outer
;
17083 gcc_assert (gimple_call_lhs (call_stmt
) == NULL_TREE
);
17084 if (!cctx
->cancellable
)
17086 if (DECL_FUNCTION_CODE (fndecl
)
17087 == BUILT_IN_GOMP_CANCELLATION_POINT
)
17089 stmt
= gimple_build_nop ();
17090 gsi_replace (gsi_p
, stmt
, false);
17094 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
17096 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
17097 gimple_call_set_fndecl (call_stmt
, fndecl
);
17098 gimple_call_set_fntype (call_stmt
, TREE_TYPE (fndecl
));
17101 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)));
17102 gimple_call_set_lhs (call_stmt
, lhs
);
17103 tree fallthru_label
;
17104 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
17106 g
= gimple_build_label (fallthru_label
);
17107 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
17108 g
= gimple_build_cond (NE_EXPR
, lhs
,
17109 fold_convert (TREE_TYPE (lhs
),
17110 boolean_false_node
),
17111 cctx
->cancel_label
, fallthru_label
);
17112 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
17119 if ((ctx
|| task_shared_vars
)
17120 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
17123 /* Just remove clobbers, this should happen only if we have
17124 "privatized" local addressable variables in SIMD regions,
17125 the clobber isn't needed in that case and gimplifying address
17126 of the ARRAY_REF into a pointer and creating MEM_REF based
17127 clobber would create worse code than we get with the clobber
17129 if (gimple_clobber_p (stmt
))
17131 gsi_replace (gsi_p
, gimple_build_nop (), true);
17134 lower_omp_regimplify_operands (ctx
, stmt
, gsi_p
);
17141 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
17143 location_t saved_location
= input_location
;
17144 gimple_stmt_iterator gsi
;
17145 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
17146 lower_omp_1 (&gsi
, ctx
);
17147 /* During gimplification, we haven't folded statments inside offloading
17148 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17149 if (target_nesting_level
|| taskreg_nesting_level
)
17150 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
17152 input_location
= saved_location
;
17155 /* Returen true if STMT is an assignment of a register-type into a local
17159 grid_reg_assignment_to_local_var_p (gimple
*stmt
)
17161 gassign
*assign
= dyn_cast
<gassign
*> (stmt
);
17164 tree lhs
= gimple_assign_lhs (assign
);
17165 if (TREE_CODE (lhs
) != VAR_DECL
17166 || !is_gimple_reg_type (TREE_TYPE (lhs
))
17167 || is_global_var (lhs
))
17172 /* Return true if all statements in SEQ are assignments to local register-type
17176 grid_seq_only_contains_local_assignments (gimple_seq seq
)
17181 gimple_stmt_iterator gsi
;
17182 for (gsi
= gsi_start (seq
); !gsi_end_p (gsi
); gsi_next (&gsi
))
17183 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi
)))
17188 /* Scan statements in SEQ and call itself recursively on any bind. If during
17189 whole search only assignments to register-type local variables and one
17190 single OMP statement is encountered, return true, otherwise return false.
17191 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17192 are used for dumping a note about a failure. */
17195 grid_find_single_omp_among_assignments_1 (gimple_seq seq
, location_t target_loc
,
17196 const char *name
, gimple
**ret
)
17198 gimple_stmt_iterator gsi
;
17199 for (gsi
= gsi_start (seq
); !gsi_end_p (gsi
); gsi_next (&gsi
))
17201 gimple
*stmt
= gsi_stmt (gsi
);
17203 if (grid_reg_assignment_to_local_var_p (stmt
))
17205 if (gbind
*bind
= dyn_cast
<gbind
*> (stmt
))
17207 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind
),
17208 target_loc
, name
, ret
))
17211 else if (is_gimple_omp (stmt
))
17215 if (dump_enabled_p ())
17216 dump_printf_loc (MSG_NOTE
, target_loc
,
17217 "Will not turn target construct into a simple "
17218 "GPGPU kernel because %s construct contains "
17219 "multiple OpenMP constructs\n", name
);
17226 if (dump_enabled_p ())
17227 dump_printf_loc (MSG_NOTE
, target_loc
,
17228 "Will not turn target construct into a simple "
17229 "GPGPU kernel because %s construct contains "
17230 "a complex statement\n", name
);
17237 /* Scan statements in SEQ and make sure that it and any binds in it contain
17238 only assignments to local register-type variables and one OMP construct. If
17239 so, return that construct, otherwise return NULL. If dumping is enabled and
17240 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17244 grid_find_single_omp_among_assignments (gimple_seq seq
, location_t target_loc
,
17249 if (dump_enabled_p ())
17250 dump_printf_loc (MSG_NOTE
, target_loc
,
17251 "Will not turn target construct into a simple "
17252 "GPGPU kernel because %s construct has empty "
17258 gimple
*ret
= NULL
;
17259 if (grid_find_single_omp_among_assignments_1 (seq
, target_loc
, name
, &ret
))
17261 if (!ret
&& dump_enabled_p ())
17262 dump_printf_loc (MSG_NOTE
, target_loc
,
17263 "Will not turn target construct into a simple "
17264 "GPGPU kernel because %s construct does not contain"
17265 "any other OpenMP construct\n", name
);
17272 /* Walker function looking for statements there is no point gridifying (and for
17273 noreturn function calls which we cannot do). Return non-NULL if such a
17274 function is found. */
17277 grid_find_ungridifiable_statement (gimple_stmt_iterator
*gsi
,
17278 bool *handled_ops_p
,
17279 struct walk_stmt_info
*wi
)
17281 *handled_ops_p
= false;
17282 gimple
*stmt
= gsi_stmt (*gsi
);
17283 switch (gimple_code (stmt
))
17286 if (gimple_call_noreturn_p (as_a
<gcall
*> (stmt
)))
17288 *handled_ops_p
= true;
17290 return error_mark_node
;
17294 /* We may reduce the following list if we find a way to implement the
17295 clauses, but now there is no point trying further. */
17296 case GIMPLE_OMP_CRITICAL
:
17297 case GIMPLE_OMP_TASKGROUP
:
17298 case GIMPLE_OMP_TASK
:
17299 case GIMPLE_OMP_SECTION
:
17300 case GIMPLE_OMP_SECTIONS
:
17301 case GIMPLE_OMP_SECTIONS_SWITCH
:
17302 case GIMPLE_OMP_TARGET
:
17303 case GIMPLE_OMP_ORDERED
:
17304 *handled_ops_p
= true;
17306 return error_mark_node
;
17308 case GIMPLE_OMP_FOR
:
17309 if ((gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
17310 && gimple_omp_for_combined_into_p (stmt
))
17312 *handled_ops_p
= true;
17314 return error_mark_node
;
17325 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17326 kernel, return true, otherwise return false. In the case of success, also
17327 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17331 grid_target_follows_gridifiable_pattern (gomp_target
*target
, tree
*group_size_p
)
17333 if (gimple_omp_target_kind (target
) != GF_OMP_TARGET_KIND_REGION
)
17336 location_t tloc
= gimple_location (target
);
17338 = grid_find_single_omp_among_assignments (gimple_omp_body (target
),
17342 gomp_teams
*teams
= dyn_cast
<gomp_teams
*> (stmt
);
17343 tree group_size
= NULL
;
17346 dump_printf_loc (MSG_NOTE
, tloc
,
17347 "Will not turn target construct into a simple "
17348 "GPGPU kernel because it does not have a sole teams "
17349 "construct in it.\n");
17353 tree clauses
= gimple_omp_teams_clauses (teams
);
17356 switch (OMP_CLAUSE_CODE (clauses
))
17358 case OMP_CLAUSE_NUM_TEAMS
:
17359 if (dump_enabled_p ())
17360 dump_printf_loc (MSG_NOTE
, tloc
,
17361 "Will not turn target construct into a "
17362 "gridified GPGPU kernel because we cannot "
17363 "handle num_teams clause of teams "
17367 case OMP_CLAUSE_REDUCTION
:
17368 if (dump_enabled_p ())
17369 dump_printf_loc (MSG_NOTE
, tloc
,
17370 "Will not turn target construct into a "
17371 "gridified GPGPU kernel because a reduction "
17372 "clause is present\n ");
17375 case OMP_CLAUSE_LASTPRIVATE
:
17376 if (dump_enabled_p ())
17377 dump_printf_loc (MSG_NOTE
, tloc
,
17378 "Will not turn target construct into a "
17379 "gridified GPGPU kernel because a lastprivate "
17380 "clause is present\n ");
17383 case OMP_CLAUSE_THREAD_LIMIT
:
17384 group_size
= OMP_CLAUSE_OPERAND (clauses
, 0);
17390 clauses
= OMP_CLAUSE_CHAIN (clauses
);
17393 stmt
= grid_find_single_omp_among_assignments (gimple_omp_body (teams
), tloc
,
17397 gomp_for
*dist
= dyn_cast
<gomp_for
*> (stmt
);
17400 dump_printf_loc (MSG_NOTE
, tloc
,
17401 "Will not turn target construct into a simple "
17402 "GPGPU kernel because the teams construct does not have "
17403 "a sole distribute construct in it.\n");
17407 gcc_assert (gimple_omp_for_kind (dist
) == GF_OMP_FOR_KIND_DISTRIBUTE
);
17408 if (!gimple_omp_for_combined_p (dist
))
17410 if (dump_enabled_p ())
17411 dump_printf_loc (MSG_NOTE
, tloc
,
17412 "Will not turn target construct into a gridified GPGPU "
17413 "kernel because we cannot handle a standalone "
17414 "distribute construct\n ");
17417 if (dist
->collapse
> 1)
17419 if (dump_enabled_p ())
17420 dump_printf_loc (MSG_NOTE
, tloc
,
17421 "Will not turn target construct into a gridified GPGPU "
17422 "kernel because the distribute construct contains "
17423 "collapse clause\n");
17426 struct omp_for_data fd
;
17427 extract_omp_for_data (dist
, &fd
, NULL
);
17430 if (group_size
&& !operand_equal_p (group_size
, fd
.chunk_size
, 0))
17432 if (dump_enabled_p ())
17433 dump_printf_loc (MSG_NOTE
, tloc
,
17434 "Will not turn target construct into a "
17435 "gridified GPGPU kernel because the teams "
17436 "thread limit is different from distribute "
17437 "schedule chunk\n");
17440 group_size
= fd
.chunk_size
;
17442 stmt
= grid_find_single_omp_among_assignments (gimple_omp_body (dist
), tloc
,
17444 gomp_parallel
*par
;
17445 if (!stmt
|| !(par
= dyn_cast
<gomp_parallel
*> (stmt
)))
17448 clauses
= gimple_omp_parallel_clauses (par
);
17451 switch (OMP_CLAUSE_CODE (clauses
))
17453 case OMP_CLAUSE_NUM_THREADS
:
17454 if (dump_enabled_p ())
17455 dump_printf_loc (MSG_NOTE
, tloc
,
17456 "Will not turn target construct into a gridified"
17457 "GPGPU kernel because there is a num_threads "
17458 "clause of the parallel construct\n");
17461 case OMP_CLAUSE_REDUCTION
:
17462 if (dump_enabled_p ())
17463 dump_printf_loc (MSG_NOTE
, tloc
,
17464 "Will not turn target construct into a "
17465 "gridified GPGPU kernel because a reduction "
17466 "clause is present\n ");
17469 case OMP_CLAUSE_LASTPRIVATE
:
17470 if (dump_enabled_p ())
17471 dump_printf_loc (MSG_NOTE
, tloc
,
17472 "Will not turn target construct into a "
17473 "gridified GPGPU kernel because a lastprivate "
17474 "clause is present\n ");
17480 clauses
= OMP_CLAUSE_CHAIN (clauses
);
17483 stmt
= grid_find_single_omp_among_assignments (gimple_omp_body (par
), tloc
,
17486 if (!stmt
|| !(gfor
= dyn_cast
<gomp_for
*> (stmt
)))
17489 if (gimple_omp_for_kind (gfor
) != GF_OMP_FOR_KIND_FOR
)
17491 if (dump_enabled_p ())
17492 dump_printf_loc (MSG_NOTE
, tloc
,
17493 "Will not turn target construct into a gridified GPGPU "
17494 "kernel because the inner loop is not a simple for "
17498 if (gfor
->collapse
> 1)
17500 if (dump_enabled_p ())
17501 dump_printf_loc (MSG_NOTE
, tloc
,
17502 "Will not turn target construct into a gridified GPGPU "
17503 "kernel because the inner loop contains collapse "
17508 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor
)))
17510 if (dump_enabled_p ())
17511 dump_printf_loc (MSG_NOTE
, tloc
,
17512 "Will not turn target construct into a gridified GPGPU "
17513 "kernel because the inner loop pre_body contains"
17514 "a complex instruction\n");
17518 clauses
= gimple_omp_for_clauses (gfor
);
17521 switch (OMP_CLAUSE_CODE (clauses
))
17523 case OMP_CLAUSE_SCHEDULE
:
17524 if (OMP_CLAUSE_SCHEDULE_KIND (clauses
) != OMP_CLAUSE_SCHEDULE_AUTO
)
17526 if (dump_enabled_p ())
17527 dump_printf_loc (MSG_NOTE
, tloc
,
17528 "Will not turn target construct into a "
17529 "gridified GPGPU kernel because the inner "
17530 "loop has a non-automatic scheduling clause\n");
17535 case OMP_CLAUSE_REDUCTION
:
17536 if (dump_enabled_p ())
17537 dump_printf_loc (MSG_NOTE
, tloc
,
17538 "Will not turn target construct into a "
17539 "gridified GPGPU kernel because a reduction "
17540 "clause is present\n ");
17543 case OMP_CLAUSE_LASTPRIVATE
:
17544 if (dump_enabled_p ())
17545 dump_printf_loc (MSG_NOTE
, tloc
,
17546 "Will not turn target construct into a "
17547 "gridified GPGPU kernel because a lastprivate "
17548 "clause is present\n ");
17554 clauses
= OMP_CLAUSE_CHAIN (clauses
);
17557 struct walk_stmt_info wi
;
17558 memset (&wi
, 0, sizeof (wi
));
17559 if (walk_gimple_seq (gimple_omp_body (gfor
),
17560 grid_find_ungridifiable_statement
,
17563 gimple
*bad
= (gimple
*) wi
.info
;
17564 if (dump_enabled_p ())
17566 if (is_gimple_call (bad
))
17567 dump_printf_loc (MSG_NOTE
, tloc
,
17568 "Will not turn target construct into a gridified "
17569 " GPGPU kernel because the inner loop contains "
17570 "call to a noreturn function\n");
17571 if (gimple_code (bad
) == GIMPLE_OMP_FOR
)
17572 dump_printf_loc (MSG_NOTE
, tloc
,
17573 "Will not turn target construct into a gridified "
17574 " GPGPU kernel because the inner loop contains "
17575 "a simd construct\n");
17577 dump_printf_loc (MSG_NOTE
, tloc
,
17578 "Will not turn target construct into a gridified "
17579 "GPGPU kernel because the inner loop contains "
17580 "statement %s which cannot be transformed\n",
17581 gimple_code_name
[(int) gimple_code (bad
)]);
17586 *group_size_p
= group_size
;
17590 /* Operand walker, used to remap pre-body declarations according to a hash map
17591 provided in DATA. */
17594 grid_remap_prebody_decls (tree
*tp
, int *walk_subtrees
, void *data
)
17598 if (DECL_P (t
) || TYPE_P (t
))
17599 *walk_subtrees
= 0;
17601 *walk_subtrees
= 1;
17603 if (TREE_CODE (t
) == VAR_DECL
)
17605 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
17606 hash_map
<tree
, tree
> *declmap
= (hash_map
<tree
, tree
> *) wi
->info
;
17607 tree
*repl
= declmap
->get (t
);
17614 /* Copy leading register-type assignments to local variables in SRC to just
17615 before DST, Creating temporaries, adjusting mapping of operands in WI and
17616 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17617 Return the first statement that does not conform to
17618 grid_reg_assignment_to_local_var_p or NULL. */
17621 grid_copy_leading_local_assignments (gimple_seq src
, gimple_stmt_iterator
*dst
,
17622 gbind
*tgt_bind
, struct walk_stmt_info
*wi
)
17624 hash_map
<tree
, tree
> *declmap
= (hash_map
<tree
, tree
> *) wi
->info
;
17625 gimple_stmt_iterator gsi
;
17626 for (gsi
= gsi_start (src
); !gsi_end_p (gsi
); gsi_next (&gsi
))
17628 gimple
*stmt
= gsi_stmt (gsi
);
17629 if (gbind
*bind
= dyn_cast
<gbind
*> (stmt
))
17631 gimple
*r
= grid_copy_leading_local_assignments
17632 (gimple_bind_body (bind
), dst
, tgt_bind
, wi
);
17638 if (!grid_reg_assignment_to_local_var_p (stmt
))
17640 tree lhs
= gimple_assign_lhs (as_a
<gassign
*> (stmt
));
17641 tree repl
= copy_var_decl (lhs
, create_tmp_var_name (NULL
),
17643 DECL_CONTEXT (repl
) = current_function_decl
;
17644 gimple_bind_append_vars (tgt_bind
, repl
);
17646 declmap
->put (lhs
, repl
);
17647 gassign
*copy
= as_a
<gassign
*> (gimple_copy (stmt
));
17648 walk_gimple_op (copy
, grid_remap_prebody_decls
, wi
);
17649 gsi_insert_before (dst
, copy
, GSI_SAME_STMT
);
17654 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17655 components, mark them as part of kernel and return the inner loop, and copy
17656 assignment leading to them just before DST, remapping them using WI and
17657 adding new temporaries to TGT_BIND. */
17660 grid_process_kernel_body_copy (gimple_seq seq
, gimple_stmt_iterator
*dst
,
17661 gbind
*tgt_bind
, struct walk_stmt_info
*wi
)
17663 gimple
*stmt
= grid_copy_leading_local_assignments (seq
, dst
, tgt_bind
, wi
);
17664 gomp_teams
*teams
= dyn_cast
<gomp_teams
*> (stmt
);
17665 gcc_assert (teams
);
17666 gimple_omp_teams_set_grid_phony (teams
, true);
17667 stmt
= grid_copy_leading_local_assignments (gimple_omp_body (teams
), dst
,
17669 gcc_checking_assert (stmt
);
17670 gomp_for
*dist
= dyn_cast
<gomp_for
*> (stmt
);
17672 gimple_seq prebody
= gimple_omp_for_pre_body (dist
);
17674 grid_copy_leading_local_assignments (prebody
, dst
, tgt_bind
, wi
);
17675 gimple_omp_for_set_grid_phony (dist
, true);
17676 stmt
= grid_copy_leading_local_assignments (gimple_omp_body (dist
), dst
,
17678 gcc_checking_assert (stmt
);
17680 gomp_parallel
*parallel
= as_a
<gomp_parallel
*> (stmt
);
17681 gimple_omp_parallel_set_grid_phony (parallel
, true);
17682 stmt
= grid_copy_leading_local_assignments (gimple_omp_body (parallel
), dst
,
17684 gomp_for
*inner_loop
= as_a
<gomp_for
*> (stmt
);
17685 gimple_omp_for_set_kind (inner_loop
, GF_OMP_FOR_KIND_GRID_LOOP
);
17686 prebody
= gimple_omp_for_pre_body (inner_loop
);
17688 grid_copy_leading_local_assignments (prebody
, dst
, tgt_bind
, wi
);
17693 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17694 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17695 is the bind into which temporaries inserted before TARGET should be
17699 grid_attempt_target_gridification (gomp_target
*target
,
17700 gimple_stmt_iterator
*gsi
,
17704 if (!target
|| !grid_target_follows_gridifiable_pattern (target
, &group_size
))
17707 location_t loc
= gimple_location (target
);
17708 if (dump_enabled_p ())
17709 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS
, loc
,
17710 "Target construct will be turned into a gridified GPGPU "
17713 /* Copy target body to a GPUKERNEL construct: */
17714 gimple_seq kernel_seq
= copy_gimple_seq_and_replace_locals
17715 (gimple_omp_body (target
));
17717 hash_map
<tree
, tree
> *declmap
= new hash_map
<tree
, tree
>;
17718 struct walk_stmt_info wi
;
17719 memset (&wi
, 0, sizeof (struct walk_stmt_info
));
17722 /* Copy assignments in between OMP statements before target, mark OMP
17723 statements within copy appropriatly. */
17724 gomp_for
*inner_loop
= grid_process_kernel_body_copy (kernel_seq
, gsi
,
17727 gbind
*old_bind
= as_a
<gbind
*> (gimple_seq_first (gimple_omp_body (target
)));
17728 gbind
*new_bind
= as_a
<gbind
*> (gimple_seq_first (kernel_seq
));
17729 tree new_block
= gimple_bind_block (new_bind
);
17730 tree enc_block
= BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind
));
17731 BLOCK_CHAIN (new_block
) = BLOCK_SUBBLOCKS (enc_block
);
17732 BLOCK_SUBBLOCKS (enc_block
) = new_block
;
17733 BLOCK_SUPERCONTEXT (new_block
) = enc_block
;
17734 gimple
*gpukernel
= gimple_build_omp_grid_body (kernel_seq
);
17735 gimple_seq_add_stmt
17736 (gimple_bind_body_ptr (as_a
<gbind
*> (gimple_omp_body (target
))),
17739 walk_tree (&group_size
, grid_remap_prebody_decls
, &wi
, NULL
);
17740 push_gimplify_context ();
17741 size_t collapse
= gimple_omp_for_collapse (inner_loop
);
17742 for (size_t i
= 0; i
< collapse
; i
++)
17744 tree itype
, type
= TREE_TYPE (gimple_omp_for_index (inner_loop
, i
));
17745 if (POINTER_TYPE_P (type
))
17746 itype
= signed_type_for (type
);
17750 enum tree_code cond_code
= gimple_omp_for_cond (inner_loop
, i
);
17751 tree n1
= unshare_expr (gimple_omp_for_initial (inner_loop
, i
));
17752 walk_tree (&n1
, grid_remap_prebody_decls
, &wi
, NULL
);
17753 tree n2
= unshare_expr (gimple_omp_for_final (inner_loop
, i
));
17754 walk_tree (&n2
, grid_remap_prebody_decls
, &wi
, NULL
);
17755 adjust_for_condition (loc
, &cond_code
, &n2
);
17757 step
= get_omp_for_step_from_incr (loc
,
17758 gimple_omp_for_incr (inner_loop
, i
));
17759 gimple_seq tmpseq
= NULL
;
17760 n1
= fold_convert (itype
, n1
);
17761 n2
= fold_convert (itype
, n2
);
17762 tree t
= build_int_cst (itype
, (cond_code
== LT_EXPR
? -1 : 1));
17763 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
17764 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
17765 t
= fold_build2 (MINUS_EXPR
, itype
, t
, n1
);
17766 if (TYPE_UNSIGNED (itype
) && cond_code
== GT_EXPR
)
17767 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
17768 fold_build1 (NEGATE_EXPR
, itype
, t
),
17769 fold_build1 (NEGATE_EXPR
, itype
, step
));
17771 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
17772 tree gs
= fold_convert (uint32_type_node
, t
);
17773 gimplify_expr (&gs
, &tmpseq
, NULL
, is_gimple_val
, fb_rvalue
);
17774 if (!gimple_seq_empty_p (tmpseq
))
17775 gsi_insert_seq_before (gsi
, tmpseq
, GSI_SAME_STMT
);
17778 if (i
== 0 && group_size
)
17780 ws
= fold_convert (uint32_type_node
, group_size
);
17782 gimplify_expr (&ws
, &tmpseq
, NULL
, is_gimple_val
, fb_rvalue
);
17783 if (!gimple_seq_empty_p (tmpseq
))
17784 gsi_insert_seq_before (gsi
, tmpseq
, GSI_SAME_STMT
);
17787 ws
= build_zero_cst (uint32_type_node
);
17789 tree c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__GRIDDIM_
);
17790 OMP_CLAUSE__GRIDDIM__DIMENSION (c
) = i
;
17791 OMP_CLAUSE__GRIDDIM__SIZE (c
) = gs
;
17792 OMP_CLAUSE__GRIDDIM__GROUP (c
) = ws
;
17793 OMP_CLAUSE_CHAIN (c
) = gimple_omp_target_clauses (target
);
17794 gimple_omp_target_set_clauses (target
, c
);
17796 pop_gimplify_context (tgt_bind
);
17801 /* Walker function doing all the work for create_target_kernels. */
17804 grid_gridify_all_targets_stmt (gimple_stmt_iterator
*gsi
,
17805 bool *handled_ops_p
,
17806 struct walk_stmt_info
*incoming
)
17808 *handled_ops_p
= false;
17810 gimple
*stmt
= gsi_stmt (*gsi
);
17811 gomp_target
*target
= dyn_cast
<gomp_target
*> (stmt
);
17814 gbind
*tgt_bind
= (gbind
*) incoming
->info
;
17815 gcc_checking_assert (tgt_bind
);
17816 grid_attempt_target_gridification (target
, gsi
, tgt_bind
);
17819 gbind
*bind
= dyn_cast
<gbind
*> (stmt
);
17822 *handled_ops_p
= true;
17823 struct walk_stmt_info wi
;
17824 memset (&wi
, 0, sizeof (wi
));
17826 walk_gimple_seq_mod (gimple_bind_body_ptr (bind
),
17827 grid_gridify_all_targets_stmt
, NULL
, &wi
);
17832 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17833 have their bodies duplicated, with the new copy being put into a
17834 gimple_omp_grid_body statement. All kernel-related construct within the
17835 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17836 re-structuring is often needed, such as copying pre-bodies before the target
17837 construct so that kernel grid sizes can be computed. */
17840 grid_gridify_all_targets (gimple_seq
*body_p
)
17842 struct walk_stmt_info wi
;
17843 memset (&wi
, 0, sizeof (wi
));
17844 walk_gimple_seq_mod (body_p
, grid_gridify_all_targets_stmt
, NULL
, &wi
);
17848 /* Main entry point. */
17850 static unsigned int
17851 execute_lower_omp (void)
17857 /* This pass always runs, to provide PROP_gimple_lomp.
17858 But often, there is nothing to do. */
17859 if (flag_cilkplus
== 0 && flag_openacc
== 0 && flag_openmp
== 0
17860 && flag_openmp_simd
== 0)
17863 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
17864 delete_omp_context
);
17866 body
= gimple_body (current_function_decl
);
17868 if (hsa_gen_requested_p ())
17869 grid_gridify_all_targets (&body
);
17871 scan_omp (&body
, NULL
);
17872 gcc_assert (taskreg_nesting_level
== 0);
17873 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
17874 finish_taskreg_scan (ctx
);
17875 taskreg_contexts
.release ();
17877 if (all_contexts
->root
)
17879 if (task_shared_vars
)
17880 push_gimplify_context ();
17881 lower_omp (&body
, NULL
);
17882 if (task_shared_vars
)
17883 pop_gimplify_context (NULL
);
17888 splay_tree_delete (all_contexts
);
17889 all_contexts
= NULL
;
17891 BITMAP_FREE (task_shared_vars
);
17897 const pass_data pass_data_lower_omp
=
17899 GIMPLE_PASS
, /* type */
17900 "omplower", /* name */
17901 OPTGROUP_NONE
, /* optinfo_flags */
17902 TV_NONE
, /* tv_id */
17903 PROP_gimple_any
, /* properties_required */
17904 PROP_gimple_lomp
, /* properties_provided */
17905 0, /* properties_destroyed */
17906 0, /* todo_flags_start */
17907 0, /* todo_flags_finish */
17910 class pass_lower_omp
: public gimple_opt_pass
17913 pass_lower_omp (gcc::context
*ctxt
)
17914 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
17917 /* opt_pass methods: */
17918 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
17920 }; // class pass_lower_omp
17922 } // anon namespace
17925 make_pass_lower_omp (gcc::context
*ctxt
)
17927 return new pass_lower_omp (ctxt
);
17930 /* The following is a utility to diagnose structured block violations.
17931 It is not part of the "omplower" pass, as that's invoked too late. It
17932 should be invoked by the respective front ends after gimplification. */
17934 static splay_tree all_labels
;
17936 /* Check for mismatched contexts and generate an error if needed. Return
17937 true if an error is detected. */
17940 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
17941 gimple
*branch_ctx
, gimple
*label_ctx
)
17943 gcc_checking_assert (!branch_ctx
|| is_gimple_omp (branch_ctx
));
17944 gcc_checking_assert (!label_ctx
|| is_gimple_omp (label_ctx
));
17946 if (label_ctx
== branch_ctx
)
17949 const char* kind
= NULL
;
17954 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
17955 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
17957 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
17958 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
17959 kind
= "Cilk Plus";
17963 if ((branch_ctx
&& is_gimple_omp_oacc (branch_ctx
))
17964 || (label_ctx
&& is_gimple_omp_oacc (label_ctx
)))
17966 gcc_checking_assert (kind
== NULL
);
17972 gcc_checking_assert (flag_openmp
);
17977 Previously we kept track of the label's entire context in diagnose_sb_[12]
17978 so we could traverse it and issue a correct "exit" or "enter" error
17979 message upon a structured block violation.
17981 We built the context by building a list with tree_cons'ing, but there is
17982 no easy counterpart in gimple tuples. It seems like far too much work
17983 for issuing exit/enter error messages. If someone really misses the
17984 distinct error message... patches welcome.
17988 /* Try to avoid confusing the user by producing and error message
17989 with correct "exit" or "enter" verbiage. We prefer "exit"
17990 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17991 if (branch_ctx
== NULL
)
17997 if (TREE_VALUE (label_ctx
) == branch_ctx
)
18002 label_ctx
= TREE_CHAIN (label_ctx
);
18007 error ("invalid exit from %s structured block", kind
);
18009 error ("invalid entry to %s structured block", kind
);
18012 /* If it's obvious we have an invalid entry, be specific about the error. */
18013 if (branch_ctx
== NULL
)
18014 error ("invalid entry to %s structured block", kind
);
18017 /* Otherwise, be vague and lazy, but efficient. */
18018 error ("invalid branch to/from %s structured block", kind
);
18021 gsi_replace (gsi_p
, gimple_build_nop (), false);
18025 /* Pass 1: Create a minimal tree of structured blocks, and record
18026 where each label is found. */
18029 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
18030 struct walk_stmt_info
*wi
)
18032 gimple
*context
= (gimple
*) wi
->info
;
18033 gimple
*inner_context
;
18034 gimple
*stmt
= gsi_stmt (*gsi_p
);
18036 *handled_ops_p
= true;
18038 switch (gimple_code (stmt
))
18042 case GIMPLE_OMP_PARALLEL
:
18043 case GIMPLE_OMP_TASK
:
18044 case GIMPLE_OMP_SECTIONS
:
18045 case GIMPLE_OMP_SINGLE
:
18046 case GIMPLE_OMP_SECTION
:
18047 case GIMPLE_OMP_MASTER
:
18048 case GIMPLE_OMP_ORDERED
:
18049 case GIMPLE_OMP_CRITICAL
:
18050 case GIMPLE_OMP_TARGET
:
18051 case GIMPLE_OMP_TEAMS
:
18052 case GIMPLE_OMP_TASKGROUP
:
18053 /* The minimal context here is just the current OMP construct. */
18054 inner_context
= stmt
;
18055 wi
->info
= inner_context
;
18056 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
18057 wi
->info
= context
;
18060 case GIMPLE_OMP_FOR
:
18061 inner_context
= stmt
;
18062 wi
->info
= inner_context
;
18063 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18065 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
18066 diagnose_sb_1
, NULL
, wi
);
18067 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
18068 wi
->info
= context
;
18072 splay_tree_insert (all_labels
,
18073 (splay_tree_key
) gimple_label_label (
18074 as_a
<glabel
*> (stmt
)),
18075 (splay_tree_value
) context
);
18085 /* Pass 2: Check each branch and see if its context differs from that of
18086 the destination label's context. */
18089 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
18090 struct walk_stmt_info
*wi
)
18092 gimple
*context
= (gimple
*) wi
->info
;
18094 gimple
*stmt
= gsi_stmt (*gsi_p
);
18096 *handled_ops_p
= true;
18098 switch (gimple_code (stmt
))
18102 case GIMPLE_OMP_PARALLEL
:
18103 case GIMPLE_OMP_TASK
:
18104 case GIMPLE_OMP_SECTIONS
:
18105 case GIMPLE_OMP_SINGLE
:
18106 case GIMPLE_OMP_SECTION
:
18107 case GIMPLE_OMP_MASTER
:
18108 case GIMPLE_OMP_ORDERED
:
18109 case GIMPLE_OMP_CRITICAL
:
18110 case GIMPLE_OMP_TARGET
:
18111 case GIMPLE_OMP_TEAMS
:
18112 case GIMPLE_OMP_TASKGROUP
:
18114 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
18115 wi
->info
= context
;
18118 case GIMPLE_OMP_FOR
:
18120 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18122 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
18123 diagnose_sb_2
, NULL
, wi
);
18124 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
18125 wi
->info
= context
;
18130 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
18131 tree lab
= gimple_cond_true_label (cond_stmt
);
18134 n
= splay_tree_lookup (all_labels
,
18135 (splay_tree_key
) lab
);
18136 diagnose_sb_0 (gsi_p
, context
,
18137 n
? (gimple
*) n
->value
: NULL
);
18139 lab
= gimple_cond_false_label (cond_stmt
);
18142 n
= splay_tree_lookup (all_labels
,
18143 (splay_tree_key
) lab
);
18144 diagnose_sb_0 (gsi_p
, context
,
18145 n
? (gimple
*) n
->value
: NULL
);
18152 tree lab
= gimple_goto_dest (stmt
);
18153 if (TREE_CODE (lab
) != LABEL_DECL
)
18156 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
18157 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
*) n
->value
: NULL
);
18161 case GIMPLE_SWITCH
:
18163 gswitch
*switch_stmt
= as_a
<gswitch
*> (stmt
);
18165 for (i
= 0; i
< gimple_switch_num_labels (switch_stmt
); ++i
)
18167 tree lab
= CASE_LABEL (gimple_switch_label (switch_stmt
, i
));
18168 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
18169 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
*) n
->value
))
18175 case GIMPLE_RETURN
:
18176 diagnose_sb_0 (gsi_p
, context
, NULL
);
18186 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18189 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
18192 gimple
*last
= last_stmt (bb
);
18193 enum gimple_code code
= gimple_code (last
);
18194 struct omp_region
*cur_region
= *region
;
18195 bool fallthru
= false;
18199 case GIMPLE_OMP_PARALLEL
:
18200 case GIMPLE_OMP_TASK
:
18201 case GIMPLE_OMP_FOR
:
18202 case GIMPLE_OMP_SINGLE
:
18203 case GIMPLE_OMP_TEAMS
:
18204 case GIMPLE_OMP_MASTER
:
18205 case GIMPLE_OMP_TASKGROUP
:
18206 case GIMPLE_OMP_CRITICAL
:
18207 case GIMPLE_OMP_SECTION
:
18208 case GIMPLE_OMP_GRID_BODY
:
18209 cur_region
= new_omp_region (bb
, code
, cur_region
);
18213 case GIMPLE_OMP_ORDERED
:
18214 cur_region
= new_omp_region (bb
, code
, cur_region
);
18216 if (find_omp_clause (gimple_omp_ordered_clauses
18217 (as_a
<gomp_ordered
*> (last
)),
18218 OMP_CLAUSE_DEPEND
))
18219 cur_region
= cur_region
->outer
;
18222 case GIMPLE_OMP_TARGET
:
18223 cur_region
= new_omp_region (bb
, code
, cur_region
);
18225 switch (gimple_omp_target_kind (last
))
18227 case GF_OMP_TARGET_KIND_REGION
:
18228 case GF_OMP_TARGET_KIND_DATA
:
18229 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
18230 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
18231 case GF_OMP_TARGET_KIND_OACC_DATA
:
18232 case GF_OMP_TARGET_KIND_OACC_HOST_DATA
:
18234 case GF_OMP_TARGET_KIND_UPDATE
:
18235 case GF_OMP_TARGET_KIND_ENTER_DATA
:
18236 case GF_OMP_TARGET_KIND_EXIT_DATA
:
18237 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
18238 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
18239 case GF_OMP_TARGET_KIND_OACC_DECLARE
:
18240 cur_region
= cur_region
->outer
;
18243 gcc_unreachable ();
18247 case GIMPLE_OMP_SECTIONS
:
18248 cur_region
= new_omp_region (bb
, code
, cur_region
);
18252 case GIMPLE_OMP_SECTIONS_SWITCH
:
18256 case GIMPLE_OMP_ATOMIC_LOAD
:
18257 case GIMPLE_OMP_ATOMIC_STORE
:
18261 case GIMPLE_OMP_RETURN
:
18262 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18263 somewhere other than the next block. This will be
18265 cur_region
->exit
= bb
;
18266 if (cur_region
->type
== GIMPLE_OMP_TASK
)
18267 /* Add an edge corresponding to not scheduling the task
18269 make_edge (cur_region
->entry
, bb
, EDGE_ABNORMAL
);
18270 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
18271 cur_region
= cur_region
->outer
;
18274 case GIMPLE_OMP_CONTINUE
:
18275 cur_region
->cont
= bb
;
18276 switch (cur_region
->type
)
18278 case GIMPLE_OMP_FOR
:
18279 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18280 succs edges as abnormal to prevent splitting
18282 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
18283 /* Make the loopback edge. */
18284 make_edge (bb
, single_succ (cur_region
->entry
),
18287 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18288 corresponds to the case that the body of the loop
18289 is not executed at all. */
18290 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
18291 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
18295 case GIMPLE_OMP_SECTIONS
:
18296 /* Wire up the edges into and out of the nested sections. */
18298 basic_block switch_bb
= single_succ (cur_region
->entry
);
18300 struct omp_region
*i
;
18301 for (i
= cur_region
->inner
; i
; i
= i
->next
)
18303 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
18304 make_edge (switch_bb
, i
->entry
, 0);
18305 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
18308 /* Make the loopback edge to the block with
18309 GIMPLE_OMP_SECTIONS_SWITCH. */
18310 make_edge (bb
, switch_bb
, 0);
18312 /* Make the edge from the switch to exit. */
18313 make_edge (switch_bb
, bb
->next_bb
, 0);
18318 case GIMPLE_OMP_TASK
:
18323 gcc_unreachable ();
18328 gcc_unreachable ();
18331 if (*region
!= cur_region
)
18333 *region
= cur_region
;
18335 *region_idx
= cur_region
->entry
->index
;
18343 static unsigned int
18344 diagnose_omp_structured_block_errors (void)
18346 struct walk_stmt_info wi
;
18347 gimple_seq body
= gimple_body (current_function_decl
);
18349 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
18351 memset (&wi
, 0, sizeof (wi
));
18352 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
18354 memset (&wi
, 0, sizeof (wi
));
18355 wi
.want_locations
= true;
18356 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
18358 gimple_set_body (current_function_decl
, body
);
18360 splay_tree_delete (all_labels
);
18368 const pass_data pass_data_diagnose_omp_blocks
=
18370 GIMPLE_PASS
, /* type */
18371 "*diagnose_omp_blocks", /* name */
18372 OPTGROUP_NONE
, /* optinfo_flags */
18373 TV_NONE
, /* tv_id */
18374 PROP_gimple_any
, /* properties_required */
18375 0, /* properties_provided */
18376 0, /* properties_destroyed */
18377 0, /* todo_flags_start */
18378 0, /* todo_flags_finish */
18381 class pass_diagnose_omp_blocks
: public gimple_opt_pass
18384 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
18385 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
18388 /* opt_pass methods: */
18389 virtual bool gate (function
*)
18391 return flag_cilkplus
|| flag_openacc
|| flag_openmp
;
18393 virtual unsigned int execute (function
*)
18395 return diagnose_omp_structured_block_errors ();
18398 }; // class pass_diagnose_omp_blocks
18400 } // anon namespace
18403 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
18405 return new pass_diagnose_omp_blocks (ctxt
);
18408 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18409 adds their addresses and sizes to constructor-vector V_CTOR. */
18411 add_decls_addresses_to_decl_constructor (vec
<tree
, va_gc
> *v_decls
,
18412 vec
<constructor_elt
, va_gc
> *v_ctor
)
18414 unsigned len
= vec_safe_length (v_decls
);
18415 for (unsigned i
= 0; i
< len
; i
++)
18417 tree it
= (*v_decls
)[i
];
18418 bool is_var
= TREE_CODE (it
) == VAR_DECL
;
18421 #ifdef ACCEL_COMPILER
18422 && DECL_HAS_VALUE_EXPR_P (it
)
18424 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it
));
18426 tree size
= NULL_TREE
;
18428 size
= fold_convert (const_ptr_type_node
, DECL_SIZE_UNIT (it
));
18432 addr
= build_fold_addr_expr (it
);
18435 #ifdef ACCEL_COMPILER
18436 /* For "omp declare target link" vars add address of the pointer to
18437 the target table, instead of address of the var. */
18438 tree value_expr
= DECL_VALUE_EXPR (it
);
18439 tree link_ptr_decl
= TREE_OPERAND (value_expr
, 0);
18440 varpool_node::finalize_decl (link_ptr_decl
);
18441 addr
= build_fold_addr_expr (link_ptr_decl
);
18443 addr
= build_fold_addr_expr (it
);
18446 /* Most significant bit of the size marks "omp declare target link"
18447 vars in host and target tables. */
18448 unsigned HOST_WIDE_INT isize
= tree_to_uhwi (size
);
18449 isize
|= 1ULL << (int_size_in_bytes (const_ptr_type_node
)
18450 * BITS_PER_UNIT
- 1);
18451 size
= wide_int_to_tree (const_ptr_type_node
, isize
);
18454 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, addr
);
18456 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, size
);
18460 /* Create new symbols containing (address, size) pairs for global variables,
18461 marked with "omp declare target" attribute, as well as addresses for the
18462 functions, which are outlined offloading regions. */
18464 omp_finish_file (void)
18466 unsigned num_funcs
= vec_safe_length (offload_funcs
);
18467 unsigned num_vars
= vec_safe_length (offload_vars
);
18469 if (num_funcs
== 0 && num_vars
== 0)
18472 if (targetm_common
.have_named_sections
)
18474 vec
<constructor_elt
, va_gc
> *v_f
, *v_v
;
18475 vec_alloc (v_f
, num_funcs
);
18476 vec_alloc (v_v
, num_vars
* 2);
18478 add_decls_addresses_to_decl_constructor (offload_funcs
, v_f
);
18479 add_decls_addresses_to_decl_constructor (offload_vars
, v_v
);
18481 tree vars_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
18483 tree funcs_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
18485 SET_TYPE_ALIGN (vars_decl_type
, TYPE_ALIGN (pointer_sized_int_node
));
18486 SET_TYPE_ALIGN (funcs_decl_type
, TYPE_ALIGN (pointer_sized_int_node
));
18487 tree ctor_v
= build_constructor (vars_decl_type
, v_v
);
18488 tree ctor_f
= build_constructor (funcs_decl_type
, v_f
);
18489 TREE_CONSTANT (ctor_v
) = TREE_CONSTANT (ctor_f
) = 1;
18490 TREE_STATIC (ctor_v
) = TREE_STATIC (ctor_f
) = 1;
18491 tree funcs_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
18492 get_identifier (".offload_func_table"),
18494 tree vars_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
18495 get_identifier (".offload_var_table"),
18497 TREE_STATIC (funcs_decl
) = TREE_STATIC (vars_decl
) = 1;
18498 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18499 otherwise a joint table in a binary will contain padding between
18500 tables from multiple object files. */
18501 DECL_USER_ALIGN (funcs_decl
) = DECL_USER_ALIGN (vars_decl
) = 1;
18502 SET_DECL_ALIGN (funcs_decl
, TYPE_ALIGN (funcs_decl_type
));
18503 SET_DECL_ALIGN (vars_decl
, TYPE_ALIGN (vars_decl_type
));
18504 DECL_INITIAL (funcs_decl
) = ctor_f
;
18505 DECL_INITIAL (vars_decl
) = ctor_v
;
18506 set_decl_section_name (funcs_decl
, OFFLOAD_FUNC_TABLE_SECTION_NAME
);
18507 set_decl_section_name (vars_decl
, OFFLOAD_VAR_TABLE_SECTION_NAME
);
18509 varpool_node::finalize_decl (vars_decl
);
18510 varpool_node::finalize_decl (funcs_decl
);
18514 for (unsigned i
= 0; i
< num_funcs
; i
++)
18516 tree it
= (*offload_funcs
)[i
];
18517 targetm
.record_offload_symbol (it
);
18519 for (unsigned i
= 0; i
< num_vars
; i
++)
18521 tree it
= (*offload_vars
)[i
];
18522 targetm
.record_offload_symbol (it
);
18527 /* Find the number of threads (POS = false), or thread number (POS =
18528 true) for an OpenACC region partitioned as MASK. Setup code
18529 required for the calculation is added to SEQ. */
18532 oacc_thread_numbers (bool pos
, int mask
, gimple_seq
*seq
)
18534 tree res
= pos
? NULL_TREE
: build_int_cst (unsigned_type_node
, 1);
18537 /* Start at gang level, and examine relevant dimension indices. */
18538 for (ix
= GOMP_DIM_GANG
; ix
!= GOMP_DIM_MAX
; ix
++)
18539 if (GOMP_DIM_MASK (ix
) & mask
)
18541 tree arg
= build_int_cst (unsigned_type_node
, ix
);
18545 /* We had an outer index, so scale that by the size of
18547 tree n
= create_tmp_var (integer_type_node
);
18549 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE
, 1, arg
);
18551 gimple_call_set_lhs (call
, n
);
18552 gimple_seq_add_stmt (seq
, call
);
18553 res
= fold_build2 (MULT_EXPR
, integer_type_node
, res
, n
);
18557 /* Determine index in this dimension. */
18558 tree id
= create_tmp_var (integer_type_node
);
18559 gimple
*call
= gimple_build_call_internal
18560 (IFN_GOACC_DIM_POS
, 1, arg
);
18562 gimple_call_set_lhs (call
, id
);
18563 gimple_seq_add_stmt (seq
, call
);
18565 res
= fold_build2 (PLUS_EXPR
, integer_type_node
, res
, id
);
18571 if (res
== NULL_TREE
)
18572 res
= integer_zero_node
;
18577 /* Transform IFN_GOACC_LOOP calls to actual code. See
18578 expand_oacc_for for where these are generated. At the vector
18579 level, we stride loops, such that each member of a warp will
18580 operate on adjacent iterations. At the worker and gang level,
18581 each gang/warp executes a set of contiguous iterations. Chunking
18582 can override this such that each iteration engine executes a
18583 contiguous chunk, and then moves on to stride to the next chunk. */
18586 oacc_xform_loop (gcall
*call
)
18588 gimple_stmt_iterator gsi
= gsi_for_stmt (call
);
18589 enum ifn_goacc_loop_kind code
18590 = (enum ifn_goacc_loop_kind
) TREE_INT_CST_LOW (gimple_call_arg (call
, 0));
18591 tree dir
= gimple_call_arg (call
, 1);
18592 tree range
= gimple_call_arg (call
, 2);
18593 tree step
= gimple_call_arg (call
, 3);
18594 tree chunk_size
= NULL_TREE
;
18595 unsigned mask
= (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call
, 5));
18596 tree lhs
= gimple_call_lhs (call
);
18597 tree type
= TREE_TYPE (lhs
);
18598 tree diff_type
= TREE_TYPE (range
);
18599 tree r
= NULL_TREE
;
18600 gimple_seq seq
= NULL
;
18601 bool chunking
= false, striding
= true;
18602 unsigned outer_mask
= mask
& (~mask
+ 1); // Outermost partitioning
18603 unsigned inner_mask
= mask
& ~outer_mask
; // Inner partitioning (if any)
18605 #ifdef ACCEL_COMPILER
18606 chunk_size
= gimple_call_arg (call
, 4);
18607 if (integer_minus_onep (chunk_size
) /* Force static allocation. */
18608 || integer_zerop (chunk_size
)) /* Default (also static). */
18610 /* If we're at the gang level, we want each to execute a
18611 contiguous run of iterations. Otherwise we want each element
18613 striding
= !(outer_mask
& GOMP_DIM_MASK (GOMP_DIM_GANG
));
18618 /* Chunk of size 1 is striding. */
18619 striding
= integer_onep (chunk_size
);
18620 chunking
= !striding
;
18624 /* striding=true, chunking=true
18626 striding=true, chunking=false
18628 striding=false,chunking=true
18629 -> chunks=ceil (range/(chunksize*threads*step))
18630 striding=false,chunking=false
18631 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18632 push_gimplify_context (true);
18636 default: gcc_unreachable ();
18638 case IFN_GOACC_LOOP_CHUNKS
:
18640 r
= build_int_cst (type
, 1);
18644 = (range - dir) / (chunks * step * num_threads) + dir */
18645 tree per
= oacc_thread_numbers (false, mask
, &seq
);
18646 per
= fold_convert (type
, per
);
18647 chunk_size
= fold_convert (type
, chunk_size
);
18648 per
= fold_build2 (MULT_EXPR
, type
, per
, chunk_size
);
18649 per
= fold_build2 (MULT_EXPR
, type
, per
, step
);
18650 r
= build2 (MINUS_EXPR
, type
, range
, dir
);
18651 r
= build2 (PLUS_EXPR
, type
, r
, per
);
18652 r
= build2 (TRUNC_DIV_EXPR
, type
, r
, per
);
18656 case IFN_GOACC_LOOP_STEP
:
18658 /* If striding, step by the entire compute volume, otherwise
18659 step by the inner volume. */
18660 unsigned volume
= striding
? mask
: inner_mask
;
18662 r
= oacc_thread_numbers (false, volume
, &seq
);
18663 r
= build2 (MULT_EXPR
, type
, fold_convert (type
, r
), step
);
18667 case IFN_GOACC_LOOP_OFFSET
:
18670 r
= oacc_thread_numbers (true, mask
, &seq
);
18671 r
= fold_convert (diff_type
, r
);
18675 tree inner_size
= oacc_thread_numbers (false, inner_mask
, &seq
);
18676 tree outer_size
= oacc_thread_numbers (false, outer_mask
, &seq
);
18677 tree volume
= fold_build2 (MULT_EXPR
, TREE_TYPE (inner_size
),
18678 inner_size
, outer_size
);
18680 volume
= fold_convert (diff_type
, volume
);
18682 chunk_size
= fold_convert (diff_type
, chunk_size
);
18685 tree per
= fold_build2 (MULT_EXPR
, diff_type
, volume
, step
);
18687 chunk_size
= build2 (MINUS_EXPR
, diff_type
, range
, dir
);
18688 chunk_size
= build2 (PLUS_EXPR
, diff_type
, chunk_size
, per
);
18689 chunk_size
= build2 (TRUNC_DIV_EXPR
, diff_type
, chunk_size
, per
);
18692 tree span
= build2 (MULT_EXPR
, diff_type
, chunk_size
,
18693 fold_convert (diff_type
, inner_size
));
18694 r
= oacc_thread_numbers (true, outer_mask
, &seq
);
18695 r
= fold_convert (diff_type
, r
);
18696 r
= build2 (MULT_EXPR
, diff_type
, r
, span
);
18698 tree inner
= oacc_thread_numbers (true, inner_mask
, &seq
);
18699 inner
= fold_convert (diff_type
, inner
);
18700 r
= fold_build2 (PLUS_EXPR
, diff_type
, r
, inner
);
18704 tree chunk
= fold_convert (diff_type
, gimple_call_arg (call
, 6));
18706 = fold_build2 (MULT_EXPR
, diff_type
, volume
, chunk_size
);
18707 per
= build2 (MULT_EXPR
, diff_type
, per
, chunk
);
18709 r
= build2 (PLUS_EXPR
, diff_type
, r
, per
);
18712 r
= fold_build2 (MULT_EXPR
, diff_type
, r
, step
);
18713 if (type
!= diff_type
)
18714 r
= fold_convert (type
, r
);
18717 case IFN_GOACC_LOOP_BOUND
:
18722 tree inner_size
= oacc_thread_numbers (false, inner_mask
, &seq
);
18723 tree outer_size
= oacc_thread_numbers (false, outer_mask
, &seq
);
18724 tree volume
= fold_build2 (MULT_EXPR
, TREE_TYPE (inner_size
),
18725 inner_size
, outer_size
);
18727 volume
= fold_convert (diff_type
, volume
);
18729 chunk_size
= fold_convert (diff_type
, chunk_size
);
18732 tree per
= fold_build2 (MULT_EXPR
, diff_type
, volume
, step
);
18734 chunk_size
= build2 (MINUS_EXPR
, diff_type
, range
, dir
);
18735 chunk_size
= build2 (PLUS_EXPR
, diff_type
, chunk_size
, per
);
18736 chunk_size
= build2 (TRUNC_DIV_EXPR
, diff_type
, chunk_size
, per
);
18739 tree span
= build2 (MULT_EXPR
, diff_type
, chunk_size
,
18740 fold_convert (diff_type
, inner_size
));
18742 r
= fold_build2 (MULT_EXPR
, diff_type
, span
, step
);
18744 tree offset
= gimple_call_arg (call
, 6);
18745 r
= build2 (PLUS_EXPR
, diff_type
, r
,
18746 fold_convert (diff_type
, offset
));
18747 r
= build2 (integer_onep (dir
) ? MIN_EXPR
: MAX_EXPR
,
18748 diff_type
, r
, range
);
18750 if (diff_type
!= type
)
18751 r
= fold_convert (type
, r
);
18755 gimplify_assign (lhs
, r
, &seq
);
18757 pop_gimplify_context (NULL
);
18759 gsi_replace_with_seq (&gsi
, seq
, true);
18762 /* Default partitioned and minimum partitioned dimensions. */
18764 static int oacc_default_dims
[GOMP_DIM_MAX
];
18765 static int oacc_min_dims
[GOMP_DIM_MAX
];
18767 /* Parse the default dimension parameter. This is a set of
18768 :-separated optional compute dimensions. Each specified dimension
18769 is a positive integer. When device type support is added, it is
18770 planned to be a comma separated list of such compute dimensions,
18771 with all but the first prefixed by the colon-terminated device
18775 oacc_parse_default_dims (const char *dims
)
18779 for (ix
= GOMP_DIM_MAX
; ix
--;)
18781 oacc_default_dims
[ix
] = -1;
18782 oacc_min_dims
[ix
] = 1;
18785 #ifndef ACCEL_COMPILER
18786 /* Cannot be overridden on the host. */
18791 const char *pos
= dims
;
18793 for (ix
= 0; *pos
&& ix
!= GOMP_DIM_MAX
; ix
++)
18808 val
= strtol (pos
, CONST_CAST (char **, &eptr
), 10);
18809 if (errno
|| val
<= 0 || (int) val
!= val
)
18812 oacc_default_dims
[ix
] = (int) val
;
18818 error_at (UNKNOWN_LOCATION
,
18819 "-fopenacc-dim operand is malformed at '%s'", pos
);
18823 /* Allow the backend to validate the dimensions. */
18824 targetm
.goacc
.validate_dims (NULL_TREE
, oacc_default_dims
, -1);
18825 targetm
.goacc
.validate_dims (NULL_TREE
, oacc_min_dims
, -2);
18828 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18829 raw attribute. DIMS is an array of dimensions, which is filled in.
18830 LEVEL is the partitioning level of a routine, or -1 for an offload
18831 region itself. USED is the mask of partitioned execution in the
18835 oacc_validate_dims (tree fn
, tree attrs
, int *dims
, int level
, unsigned used
)
18837 tree purpose
[GOMP_DIM_MAX
];
18839 tree pos
= TREE_VALUE (attrs
);
18840 bool is_kernel
= oacc_fn_attrib_kernels_p (attrs
);
18842 /* Make sure the attribute creator attached the dimension
18846 for (ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
18848 purpose
[ix
] = TREE_PURPOSE (pos
);
18849 tree val
= TREE_VALUE (pos
);
18850 dims
[ix
] = val
? TREE_INT_CST_LOW (val
) : -1;
18851 pos
= TREE_CHAIN (pos
);
18854 bool changed
= targetm
.goacc
.validate_dims (fn
, dims
, level
);
18856 /* Default anything left to 1 or a partitioned default. */
18857 for (ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
18860 /* The OpenACC spec says 'If the [num_gangs] clause is not
18861 specified, an implementation-defined default will be used;
18862 the default may depend on the code within the construct.'
18863 (2.5.6). Thus an implementation is free to choose
18864 non-unity default for a parallel region that doesn't have
18865 any gang-partitioned loops. However, it appears that there
18866 is a sufficient body of user code that expects non-gang
18867 partitioned regions to not execute in gang-redundant mode.
18868 So we (a) don't warn about the non-portability and (b) pick
18869 the minimum permissible dimension size when there is no
18870 partitioned execution. Otherwise we pick the global
18871 default for the dimension, which the user can control. The
18872 same wording and logic applies to num_workers and
18873 vector_length, however the worker- or vector- single
18874 execution doesn't have the same impact as gang-redundant
18875 execution. (If the minimum gang-level partioning is not 1,
18876 the target is probably too confusing.) */
18877 dims
[ix
] = (used
& GOMP_DIM_MASK (ix
)
18878 ? oacc_default_dims
[ix
] : oacc_min_dims
[ix
]);
18884 /* Replace the attribute with new values. */
18886 for (ix
= GOMP_DIM_MAX
; ix
--;)
18888 pos
= tree_cons (purpose
[ix
],
18889 build_int_cst (integer_type_node
, dims
[ix
]),
18892 TREE_PUBLIC (pos
) = 1;
18894 replace_oacc_fn_attrib (fn
, pos
);
18898 /* Create an empty OpenACC loop structure at LOC. */
18901 new_oacc_loop_raw (oacc_loop
*parent
, location_t loc
)
18903 oacc_loop
*loop
= XCNEW (oacc_loop
);
18905 loop
->parent
= parent
;
18906 loop
->child
= loop
->sibling
= NULL
;
18910 loop
->sibling
= parent
->child
;
18911 parent
->child
= loop
;
18915 loop
->marker
= NULL
;
18916 memset (loop
->heads
, 0, sizeof (loop
->heads
));
18917 memset (loop
->tails
, 0, sizeof (loop
->tails
));
18918 loop
->routine
= NULL_TREE
;
18920 loop
->mask
= loop
->flags
= loop
->inner
= 0;
18922 loop
->chunk_size
= 0;
18923 loop
->head_end
= NULL
;
18928 /* Create an outermost, dummy OpenACC loop for offloaded function
18932 new_oacc_loop_outer (tree decl
)
18934 return new_oacc_loop_raw (NULL
, DECL_SOURCE_LOCATION (decl
));
18937 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18938 Link into PARENT loop. Return the new loop. */
18941 new_oacc_loop (oacc_loop
*parent
, gcall
*marker
)
18943 oacc_loop
*loop
= new_oacc_loop_raw (parent
, gimple_location (marker
));
18945 loop
->marker
= marker
;
18947 /* TODO: This is where device_type flattening would occur for the loop
18950 loop
->flags
= TREE_INT_CST_LOW (gimple_call_arg (marker
, 3));
18952 tree chunk_size
= integer_zero_node
;
18953 if (loop
->flags
& OLF_GANG_STATIC
)
18954 chunk_size
= gimple_call_arg (marker
, 4);
18955 loop
->chunk_size
= chunk_size
;
18960 /* Create a dummy loop encompassing a call to a openACC routine.
18961 Extract the routine's partitioning requirements. */
18964 new_oacc_loop_routine (oacc_loop
*parent
, gcall
*call
, tree decl
, tree attrs
)
18966 oacc_loop
*loop
= new_oacc_loop_raw (parent
, gimple_location (call
));
18967 int level
= oacc_fn_attrib_level (attrs
);
18969 gcc_assert (level
>= 0);
18971 loop
->marker
= call
;
18972 loop
->routine
= decl
;
18973 loop
->mask
= ((GOMP_DIM_MASK (GOMP_DIM_MAX
) - 1)
18974 ^ (GOMP_DIM_MASK (level
) - 1));
18977 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18978 Return the parent loop. */
18981 finish_oacc_loop (oacc_loop
*loop
)
18983 /* If the loop has been collapsed, don't partition it. */
18985 loop
->mask
= loop
->flags
= 0;
18986 return loop
->parent
;
18989 /* Free all OpenACC loop structures within LOOP (inclusive). */
18992 free_oacc_loop (oacc_loop
*loop
)
18995 free_oacc_loop (loop
->sibling
);
18997 free_oacc_loop (loop
->child
);
19002 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19005 dump_oacc_loop_part (FILE *file
, gcall
*from
, int depth
,
19006 const char *title
, int level
)
19008 enum ifn_unique_kind kind
19009 = (enum ifn_unique_kind
) TREE_INT_CST_LOW (gimple_call_arg (from
, 0));
19011 fprintf (file
, "%*s%s-%d:\n", depth
* 2, "", title
, level
);
19012 for (gimple_stmt_iterator gsi
= gsi_for_stmt (from
);;)
19014 gimple
*stmt
= gsi_stmt (gsi
);
19016 if (is_gimple_call (stmt
)
19017 && gimple_call_internal_p (stmt
)
19018 && gimple_call_internal_fn (stmt
) == IFN_UNIQUE
)
19020 enum ifn_unique_kind k
19021 = ((enum ifn_unique_kind
) TREE_INT_CST_LOW
19022 (gimple_call_arg (stmt
, 0)));
19024 if (k
== kind
&& stmt
!= from
)
19027 print_gimple_stmt (file
, stmt
, depth
* 2 + 2, 0);
19030 while (gsi_end_p (gsi
))
19031 gsi
= gsi_start_bb (single_succ (gsi_bb (gsi
)));
19035 /* Dump OpenACC loops LOOP, its siblings and its children. */
19038 dump_oacc_loop (FILE *file
, oacc_loop
*loop
, int depth
)
19042 fprintf (file
, "%*sLoop %x(%x) %s:%u\n", depth
* 2, "",
19043 loop
->flags
, loop
->mask
,
19044 LOCATION_FILE (loop
->loc
), LOCATION_LINE (loop
->loc
));
19047 print_gimple_stmt (file
, loop
->marker
, depth
* 2, 0);
19050 fprintf (file
, "%*sRoutine %s:%u:%s\n",
19051 depth
* 2, "", DECL_SOURCE_FILE (loop
->routine
),
19052 DECL_SOURCE_LINE (loop
->routine
),
19053 IDENTIFIER_POINTER (DECL_NAME (loop
->routine
)));
19055 for (ix
= GOMP_DIM_GANG
; ix
!= GOMP_DIM_MAX
; ix
++)
19056 if (loop
->heads
[ix
])
19057 dump_oacc_loop_part (file
, loop
->heads
[ix
], depth
, "Head", ix
);
19058 for (ix
= GOMP_DIM_MAX
; ix
--;)
19059 if (loop
->tails
[ix
])
19060 dump_oacc_loop_part (file
, loop
->tails
[ix
], depth
, "Tail", ix
);
19063 dump_oacc_loop (file
, loop
->child
, depth
+ 1);
19065 dump_oacc_loop (file
, loop
->sibling
, depth
);
19068 void debug_oacc_loop (oacc_loop
*);
19070 /* Dump loops to stderr. */
19072 DEBUG_FUNCTION
void
19073 debug_oacc_loop (oacc_loop
*loop
)
19075 dump_oacc_loop (stderr
, loop
, 0);
19078 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19079 structures as we go. By construction these loops are properly
19083 oacc_loop_discover_walk (oacc_loop
*loop
, basic_block bb
)
19088 if (bb
->flags
& BB_VISITED
)
19092 bb
->flags
|= BB_VISITED
;
19094 /* Scan for loop markers. */
19095 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);
19098 gimple
*stmt
= gsi_stmt (gsi
);
19100 if (!is_gimple_call (stmt
))
19103 gcall
*call
= as_a
<gcall
*> (stmt
);
19105 /* If this is a routine, make a dummy loop for it. */
19106 if (tree decl
= gimple_call_fndecl (call
))
19107 if (tree attrs
= get_oacc_fn_attrib (decl
))
19109 gcc_assert (!marker
);
19110 new_oacc_loop_routine (loop
, call
, decl
, attrs
);
19113 if (!gimple_call_internal_p (call
))
19116 switch (gimple_call_internal_fn (call
))
19121 case IFN_GOACC_LOOP
:
19122 /* Count the goacc loop abstraction fns, to determine if the
19123 loop was collapsed already. */
19128 enum ifn_unique_kind kind
19129 = (enum ifn_unique_kind
) (TREE_INT_CST_LOW
19130 (gimple_call_arg (call
, 0)));
19131 if (kind
== IFN_UNIQUE_OACC_HEAD_MARK
19132 || kind
== IFN_UNIQUE_OACC_TAIL_MARK
)
19134 if (gimple_call_num_args (call
) == 2)
19136 gcc_assert (marker
&& !remaining
);
19138 if (kind
== IFN_UNIQUE_OACC_TAIL_MARK
)
19139 loop
= finish_oacc_loop (loop
);
19141 loop
->head_end
= call
;
19145 int count
= TREE_INT_CST_LOW (gimple_call_arg (call
, 2));
19149 if (kind
== IFN_UNIQUE_OACC_HEAD_MARK
)
19150 loop
= new_oacc_loop (loop
, call
);
19153 gcc_assert (count
== remaining
);
19157 if (kind
== IFN_UNIQUE_OACC_HEAD_MARK
)
19158 loop
->heads
[marker
] = call
;
19160 loop
->tails
[remaining
] = call
;
19167 if (remaining
|| marker
)
19169 bb
= single_succ (bb
);
19170 gcc_assert (single_pred_p (bb
) && !(bb
->flags
& BB_VISITED
));
19174 /* Walk successor blocks. */
19178 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
19179 oacc_loop_discover_walk (loop
, e
->dest
);
19182 /* LOOP is the first sibling. Reverse the order in place and return
19183 the new first sibling. Recurse to child loops. */
19186 oacc_loop_sibling_nreverse (oacc_loop
*loop
)
19188 oacc_loop
*last
= NULL
;
19192 loop
->child
= oacc_loop_sibling_nreverse (loop
->child
);
19194 oacc_loop
*next
= loop
->sibling
;
19195 loop
->sibling
= last
;
19204 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19205 the current function. */
19208 oacc_loop_discovery ()
19212 oacc_loop
*top
= new_oacc_loop_outer (current_function_decl
);
19213 oacc_loop_discover_walk (top
, ENTRY_BLOCK_PTR_FOR_FN (cfun
));
19215 /* The siblings were constructed in reverse order, reverse them so
19216 that diagnostics come out in an unsurprising order. */
19217 top
= oacc_loop_sibling_nreverse (top
);
19219 /* Reset the visited flags. */
19220 FOR_ALL_BB_FN (bb
, cfun
)
19221 bb
->flags
&= ~BB_VISITED
;
19226 /* Transform the abstract internal function markers starting at FROM
19227 to be for partitioning level LEVEL. Stop when we meet another HEAD
19231 oacc_loop_xform_head_tail (gcall
*from
, int level
)
19233 enum ifn_unique_kind kind
19234 = (enum ifn_unique_kind
) TREE_INT_CST_LOW (gimple_call_arg (from
, 0));
19235 tree replacement
= build_int_cst (unsigned_type_node
, level
);
19237 for (gimple_stmt_iterator gsi
= gsi_for_stmt (from
);;)
19239 gimple
*stmt
= gsi_stmt (gsi
);
19241 if (is_gimple_call (stmt
)
19242 && gimple_call_internal_p (stmt
)
19243 && gimple_call_internal_fn (stmt
) == IFN_UNIQUE
)
19245 enum ifn_unique_kind k
19246 = ((enum ifn_unique_kind
)
19247 TREE_INT_CST_LOW (gimple_call_arg (stmt
, 0)));
19249 if (k
== IFN_UNIQUE_OACC_FORK
|| k
== IFN_UNIQUE_OACC_JOIN
)
19250 *gimple_call_arg_ptr (stmt
, 2) = replacement
;
19251 else if (k
== kind
&& stmt
!= from
)
19254 else if (is_gimple_call (stmt
)
19255 && gimple_call_internal_p (stmt
)
19256 && gimple_call_internal_fn (stmt
) == IFN_GOACC_REDUCTION
)
19257 *gimple_call_arg_ptr (stmt
, 3) = replacement
;
19260 while (gsi_end_p (gsi
))
19261 gsi
= gsi_start_bb (single_succ (gsi_bb (gsi
)));
19265 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19266 determined partitioning mask and chunking argument. END_MARKER
19267 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19268 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19269 the replacement partitioning mask and CHUNK_ARG is the replacement
19273 oacc_loop_xform_loop (gcall
*end_marker
, unsigned ifns
,
19274 tree mask_arg
, tree chunk_arg
)
19276 gimple_stmt_iterator gsi
= gsi_for_stmt (end_marker
);
19278 gcc_checking_assert (ifns
);
19281 for (; !gsi_end_p (gsi
); gsi_next (&gsi
))
19283 gimple
*stmt
= gsi_stmt (gsi
);
19285 if (!is_gimple_call (stmt
))
19288 gcall
*call
= as_a
<gcall
*> (stmt
);
19290 if (!gimple_call_internal_p (call
))
19293 if (gimple_call_internal_fn (call
) != IFN_GOACC_LOOP
)
19296 *gimple_call_arg_ptr (call
, 5) = mask_arg
;
19297 *gimple_call_arg_ptr (call
, 4) = chunk_arg
;
19303 /* The LOOP_BOUND ifn could be in the single successor
19305 basic_block bb
= single_succ (gsi_bb (gsi
));
19306 gsi
= gsi_start_bb (bb
);
19310 /* Process the discovered OpenACC loops, setting the correct
19311 partitioning level etc. */
19314 oacc_loop_process (oacc_loop
*loop
)
19317 oacc_loop_process (loop
->child
);
19319 if (loop
->mask
&& !loop
->routine
)
19322 unsigned mask
= loop
->mask
;
19323 unsigned dim
= GOMP_DIM_GANG
;
19324 tree mask_arg
= build_int_cst (unsigned_type_node
, mask
);
19325 tree chunk_arg
= loop
->chunk_size
;
19327 oacc_loop_xform_loop (loop
->head_end
, loop
->ifns
, mask_arg
, chunk_arg
);
19329 for (ix
= 0; ix
!= GOMP_DIM_MAX
&& mask
; ix
++)
19331 while (!(GOMP_DIM_MASK (dim
) & mask
))
19334 oacc_loop_xform_head_tail (loop
->heads
[ix
], dim
);
19335 oacc_loop_xform_head_tail (loop
->tails
[ix
], dim
);
19337 mask
^= GOMP_DIM_MASK (dim
);
19342 oacc_loop_process (loop
->sibling
);
19345 /* Walk the OpenACC loop heirarchy checking and assigning the
19346 programmer-specified partitionings. OUTER_MASK is the partitioning
19347 this loop is contained within. Return mask of partitioning
19348 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19352 oacc_loop_fixed_partitions (oacc_loop
*loop
, unsigned outer_mask
)
19354 unsigned this_mask
= loop
->mask
;
19355 unsigned mask_all
= 0;
19358 #ifdef ACCEL_COMPILER
19359 /* When device_type is supported, we want the device compiler to be
19360 noisy, if the loop parameters are device_type-specific. */
19364 if (!loop
->routine
)
19366 bool auto_par
= (loop
->flags
& OLF_AUTO
) != 0;
19367 bool seq_par
= (loop
->flags
& OLF_SEQ
) != 0;
19369 this_mask
= ((loop
->flags
>> OLF_DIM_BASE
)
19370 & (GOMP_DIM_MASK (GOMP_DIM_MAX
) - 1));
19372 if ((this_mask
!= 0) + auto_par
+ seq_par
> 1)
19375 error_at (loop
->loc
,
19377 ? "%<seq%> overrides other OpenACC loop specifiers"
19378 : "%<auto%> conflicts with other OpenACC loop specifiers");
19380 loop
->flags
&= ~OLF_AUTO
;
19384 ~((GOMP_DIM_MASK (GOMP_DIM_MAX
) - 1) << OLF_DIM_BASE
);
19388 if (auto_par
&& (loop
->flags
& OLF_INDEPENDENT
))
19389 mask_all
|= GOMP_DIM_MASK (GOMP_DIM_MAX
);
19392 if (this_mask
& outer_mask
)
19394 const oacc_loop
*outer
;
19395 for (outer
= loop
->parent
; outer
; outer
= outer
->parent
)
19396 if (outer
->mask
& this_mask
)
19403 error_at (loop
->loc
,
19404 "%s uses same OpenACC parallelism as containing loop",
19405 loop
->routine
? "routine call" : "inner loop");
19406 inform (outer
->loc
, "containing loop here");
19409 error_at (loop
->loc
,
19410 "%s uses OpenACC parallelism disallowed by containing routine",
19411 loop
->routine
? "routine call" : "loop");
19414 inform (DECL_SOURCE_LOCATION (loop
->routine
),
19415 "routine %qD declared here", loop
->routine
);
19417 this_mask
&= ~outer_mask
;
19421 unsigned outermost
= this_mask
& -this_mask
;
19423 if (outermost
&& outermost
<= outer_mask
)
19427 error_at (loop
->loc
,
19428 "incorrectly nested OpenACC loop parallelism");
19430 const oacc_loop
*outer
;
19431 for (outer
= loop
->parent
;
19432 outer
->flags
&& outer
->flags
< outermost
;
19433 outer
= outer
->parent
)
19435 inform (outer
->loc
, "containing loop here");
19438 this_mask
&= ~outermost
;
19442 loop
->mask
= this_mask
;
19443 mask_all
|= this_mask
;
19447 loop
->inner
= oacc_loop_fixed_partitions (loop
->child
,
19448 outer_mask
| this_mask
);
19449 mask_all
|= loop
->inner
;
19453 mask_all
|= oacc_loop_fixed_partitions (loop
->sibling
, outer_mask
);
19458 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19459 OUTER_MASK is the partitioning this loop is contained within.
19460 Return the cumulative partitioning used by this loop, siblings and
19464 oacc_loop_auto_partitions (oacc_loop
*loop
, unsigned outer_mask
)
19466 bool assign
= (loop
->flags
& OLF_AUTO
) && (loop
->flags
& OLF_INDEPENDENT
);
19469 #ifdef ACCEL_COMPILER
19470 /* When device_type is supported, we want the device compiler to be
19471 noisy, if the loop parameters are device_type-specific. */
19475 if (assign
&& outer_mask
< GOMP_DIM_MASK (GOMP_DIM_MAX
- 1))
19477 /* Allocate the outermost loop at the outermost available
19479 unsigned this_mask
= outer_mask
+ 1;
19481 if (!(this_mask
& loop
->inner
))
19482 loop
->mask
= this_mask
;
19487 unsigned child_mask
= outer_mask
| loop
->mask
;
19489 if (loop
->mask
|| assign
)
19490 child_mask
|= GOMP_DIM_MASK (GOMP_DIM_MAX
);
19492 loop
->inner
= oacc_loop_auto_partitions (loop
->child
, child_mask
);
19495 if (assign
&& !loop
->mask
)
19497 /* Allocate the loop at the innermost available level. */
19498 unsigned this_mask
= 0;
19500 /* Determine the outermost partitioning used within this loop. */
19501 this_mask
= loop
->inner
| GOMP_DIM_MASK (GOMP_DIM_MAX
);
19502 this_mask
= (this_mask
& -this_mask
);
19504 /* Pick the partitioning just inside that one. */
19507 /* And avoid picking one use by an outer loop. */
19508 this_mask
&= ~outer_mask
;
19510 if (!this_mask
&& noisy
)
19511 warning_at (loop
->loc
, 0,
19512 "insufficient partitioning available to parallelize loop");
19514 loop
->mask
= this_mask
;
19517 if (assign
&& dump_file
)
19518 fprintf (dump_file
, "Auto loop %s:%d assigned %d\n",
19519 LOCATION_FILE (loop
->loc
), LOCATION_LINE (loop
->loc
),
19522 unsigned inner_mask
= 0;
19525 inner_mask
|= oacc_loop_auto_partitions (loop
->sibling
, outer_mask
);
19527 inner_mask
|= loop
->inner
| loop
->mask
;
19532 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19533 axes. Return mask of partitioning. */
19536 oacc_loop_partition (oacc_loop
*loop
, unsigned outer_mask
)
19538 unsigned mask_all
= oacc_loop_fixed_partitions (loop
, outer_mask
);
19540 if (mask_all
& GOMP_DIM_MASK (GOMP_DIM_MAX
))
19542 mask_all
^= GOMP_DIM_MASK (GOMP_DIM_MAX
);
19543 mask_all
|= oacc_loop_auto_partitions (loop
, outer_mask
);
19548 /* Default fork/join early expander. Delete the function calls if
19549 there is no RTL expander. */
19552 default_goacc_fork_join (gcall
*ARG_UNUSED (call
),
19553 const int *ARG_UNUSED (dims
), bool is_fork
)
19556 return targetm
.have_oacc_fork ();
19558 return targetm
.have_oacc_join ();
19561 /* Default goacc.reduction early expander.
19563 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19564 If RES_PTR is not integer-zerop:
19565 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19566 TEARDOWN - emit '*RES_PTR = VAR'
19568 emit 'LHS = VAR' */
19571 default_goacc_reduction (gcall
*call
)
19573 unsigned code
= (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call
, 0));
19574 gimple_stmt_iterator gsi
= gsi_for_stmt (call
);
19575 tree lhs
= gimple_call_lhs (call
);
19576 tree var
= gimple_call_arg (call
, 2);
19577 gimple_seq seq
= NULL
;
19579 if (code
== IFN_GOACC_REDUCTION_SETUP
19580 || code
== IFN_GOACC_REDUCTION_TEARDOWN
)
19582 /* Setup and Teardown need to copy from/to the receiver object,
19583 if there is one. */
19584 tree ref_to_res
= gimple_call_arg (call
, 1);
19586 if (!integer_zerop (ref_to_res
))
19588 tree dst
= build_simple_mem_ref (ref_to_res
);
19591 if (code
== IFN_GOACC_REDUCTION_SETUP
)
19597 gimple_seq_add_stmt (&seq
, gimple_build_assign (dst
, src
));
19601 /* Copy VAR to LHS, if there is an LHS. */
19603 gimple_seq_add_stmt (&seq
, gimple_build_assign (lhs
, var
));
19605 gsi_replace_with_seq (&gsi
, seq
, true);
19608 /* Main entry point for oacc transformations which run on the device
19609 compiler after LTO, so we know what the target device is at this
19610 point (including the host fallback). */
19612 static unsigned int
19613 execute_oacc_device_lower ()
19615 tree attrs
= get_oacc_fn_attrib (current_function_decl
);
19618 /* Not an offloaded function. */
19621 /* Parse the default dim argument exactly once. */
19622 if ((const void *)flag_openacc_dims
!= &flag_openacc_dims
)
19624 oacc_parse_default_dims (flag_openacc_dims
);
19625 flag_openacc_dims
= (char *)&flag_openacc_dims
;
19628 /* Discover, partition and process the loops. */
19629 oacc_loop
*loops
= oacc_loop_discovery ();
19630 int fn_level
= oacc_fn_attrib_level (attrs
);
19633 fprintf (dump_file
, oacc_fn_attrib_kernels_p (attrs
)
19634 ? "Function is kernels offload\n"
19635 : fn_level
< 0 ? "Function is parallel offload\n"
19636 : "Function is routine level %d\n", fn_level
);
19638 unsigned outer_mask
= fn_level
>= 0 ? GOMP_DIM_MASK (fn_level
) - 1 : 0;
19639 unsigned used_mask
= oacc_loop_partition (loops
, outer_mask
);
19640 int dims
[GOMP_DIM_MAX
];
19642 oacc_validate_dims (current_function_decl
, attrs
, dims
, fn_level
, used_mask
);
19646 const char *comma
= "Compute dimensions [";
19647 for (int ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++, comma
= ", ")
19648 fprintf (dump_file
, "%s%d", comma
, dims
[ix
]);
19649 fprintf (dump_file
, "]\n");
19652 oacc_loop_process (loops
);
19655 fprintf (dump_file
, "OpenACC loops\n");
19656 dump_oacc_loop (dump_file
, loops
, 0);
19657 fprintf (dump_file
, "\n");
19660 /* Offloaded targets may introduce new basic blocks, which require
19661 dominance information to update SSA. */
19662 calculate_dominance_info (CDI_DOMINATORS
);
19664 /* Now lower internal loop functions to target-specific code
19667 FOR_ALL_BB_FN (bb
, cfun
)
19668 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
19670 gimple
*stmt
= gsi_stmt (gsi
);
19671 if (!is_gimple_call (stmt
))
19677 gcall
*call
= as_a
<gcall
*> (stmt
);
19678 if (!gimple_call_internal_p (call
))
19684 /* Rewind to allow rescan. */
19686 bool rescan
= false, remove
= false;
19687 enum internal_fn ifn_code
= gimple_call_internal_fn (call
);
19693 case IFN_GOACC_LOOP
:
19694 oacc_xform_loop (call
);
19698 case IFN_GOACC_REDUCTION
:
19699 /* Mark the function for SSA renaming. */
19700 mark_virtual_operands_for_renaming (cfun
);
19702 /* If the level is -1, this ended up being an unused
19703 axis. Handle as a default. */
19704 if (integer_minus_onep (gimple_call_arg (call
, 3)))
19705 default_goacc_reduction (call
);
19707 targetm
.goacc
.reduction (call
);
19713 enum ifn_unique_kind kind
19714 = ((enum ifn_unique_kind
)
19715 TREE_INT_CST_LOW (gimple_call_arg (call
, 0)));
19720 gcc_unreachable ();
19722 case IFN_UNIQUE_OACC_FORK
:
19723 case IFN_UNIQUE_OACC_JOIN
:
19724 if (integer_minus_onep (gimple_call_arg (call
, 2)))
19726 else if (!targetm
.goacc
.fork_join
19727 (call
, dims
, kind
== IFN_UNIQUE_OACC_FORK
))
19731 case IFN_UNIQUE_OACC_HEAD_MARK
:
19732 case IFN_UNIQUE_OACC_TAIL_MARK
:
19740 if (gsi_end_p (gsi
))
19741 /* We rewound past the beginning of the BB. */
19742 gsi
= gsi_start_bb (bb
);
19744 /* Undo the rewind. */
19749 if (gimple_vdef (call
))
19750 replace_uses_by (gimple_vdef (call
), gimple_vuse (call
));
19751 if (gimple_call_lhs (call
))
19753 /* Propagate the data dependency var. */
19754 gimple
*ass
= gimple_build_assign (gimple_call_lhs (call
),
19755 gimple_call_arg (call
, 1));
19756 gsi_replace (&gsi
, ass
, false);
19759 gsi_remove (&gsi
, true);
19762 /* If not rescanning, advance over the call. */
19766 free_oacc_loop (loops
);
19771 /* Default launch dimension validator. Force everything to 1. A
19772 backend that wants to provide larger dimensions must override this
19776 default_goacc_validate_dims (tree
ARG_UNUSED (decl
), int *dims
,
19777 int ARG_UNUSED (fn_level
))
19779 bool changed
= false;
19781 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
19793 /* Default dimension bound is unknown on accelerator and 1 on host. */
19796 default_goacc_dim_limit (int ARG_UNUSED (axis
))
19798 #ifdef ACCEL_COMPILER
19807 const pass_data pass_data_oacc_device_lower
=
19809 GIMPLE_PASS
, /* type */
19810 "oaccdevlow", /* name */
19811 OPTGROUP_NONE
, /* optinfo_flags */
19812 TV_NONE
, /* tv_id */
19813 PROP_cfg
, /* properties_required */
19814 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19815 0, /* properties_destroyed */
19816 0, /* todo_flags_start */
19817 TODO_update_ssa
| TODO_cleanup_cfg
, /* todo_flags_finish */
19820 class pass_oacc_device_lower
: public gimple_opt_pass
19823 pass_oacc_device_lower (gcc::context
*ctxt
)
19824 : gimple_opt_pass (pass_data_oacc_device_lower
, ctxt
)
19827 /* opt_pass methods: */
19828 virtual unsigned int execute (function
*)
19830 bool gate
= flag_openacc
!= 0;
19835 return execute_oacc_device_lower ();
19838 }; // class pass_oacc_device_lower
19840 } // anon namespace
19843 make_pass_oacc_device_lower (gcc::context
*ctxt
)
19845 return new pass_oacc_device_lower (ctxt
);
19848 /* "omp declare target link" handling pass. */
19852 const pass_data pass_data_omp_target_link
=
19854 GIMPLE_PASS
, /* type */
19855 "omptargetlink", /* name */
19856 OPTGROUP_NONE
, /* optinfo_flags */
19857 TV_NONE
, /* tv_id */
19858 PROP_ssa
, /* properties_required */
19859 0, /* properties_provided */
19860 0, /* properties_destroyed */
19861 0, /* todo_flags_start */
19862 TODO_update_ssa
, /* todo_flags_finish */
19865 class pass_omp_target_link
: public gimple_opt_pass
19868 pass_omp_target_link (gcc::context
*ctxt
)
19869 : gimple_opt_pass (pass_data_omp_target_link
, ctxt
)
19872 /* opt_pass methods: */
19873 virtual bool gate (function
*fun
)
19875 #ifdef ACCEL_COMPILER
19876 tree attrs
= DECL_ATTRIBUTES (fun
->decl
);
19877 return lookup_attribute ("omp declare target", attrs
)
19878 || lookup_attribute ("omp target entrypoint", attrs
);
19885 virtual unsigned execute (function
*);
19888 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19891 find_link_var_op (tree
*tp
, int *walk_subtrees
, void *)
19895 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
)
19896 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t
)))
19898 *walk_subtrees
= 0;
19906 pass_omp_target_link::execute (function
*fun
)
19909 FOR_EACH_BB_FN (bb
, fun
)
19911 gimple_stmt_iterator gsi
;
19912 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
19913 if (walk_gimple_stmt (&gsi
, NULL
, find_link_var_op
, NULL
))
19914 gimple_regimplify_operands (gsi_stmt (gsi
), &gsi
);
19920 } // anon namespace
19923 make_pass_omp_target_link (gcc::context
*ctxt
)
19925 return new pass_omp_target_link (ctxt
);
19928 #include "gt-omp-low.h"