1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
27 #include "coretypes.h"
34 #include "fold-const.h"
35 #include "stor-layout.h"
37 #include "internal-fn.h"
38 #include "gimple-fold.h"
40 #include "gimple-iterator.h"
41 #include "gimplify-me.h"
42 #include "gimple-walk.h"
43 #include "tree-iterator.h"
44 #include "tree-inline.h"
45 #include "langhooks.h"
46 #include "diagnostic-core.h"
49 #include "tree-into-ssa.h"
51 #include "insn-config.h"
62 #include "tree-pass.h"
64 #include "splay-tree.h"
65 #include "insn-codes.h"
69 #include "common/common-target.h"
71 #include "gimple-low.h"
72 #include "tree-cfgcleanup.h"
73 #include "pretty-print.h"
74 #include "alloc-pool.h"
75 #include "symbol-summary.h"
77 #include "tree-nested.h"
81 #include "lto-section-names.h"
82 #include "gomp-constants.h"
85 /* Lowering of OMP parallel and workshare constructs proceeds in two
86 phases. The first phase scans the function looking for OMP statements
87 and then for variables that must be replaced to satisfy data sharing
88 clauses. The second phase expands code for the constructs, as well as
89 re-gimplifying things when variables have been replaced with complex
92 Final code generation is done by pass_expand_omp. The flowgraph is
93 scanned for regions which are then moved to a new
94 function, to be invoked by the thread library, or offloaded. */
96 /* OMP region information. Every parallel and workshare
97 directive is enclosed between two markers, the OMP_* directive
98 and a corresponding OMP_RETURN statement. */
102 /* The enclosing region. */
103 struct omp_region
*outer
;
105 /* First child region. */
106 struct omp_region
*inner
;
108 /* Next peer region. */
109 struct omp_region
*next
;
111 /* Block containing the omp directive as its last stmt. */
114 /* Block containing the OMP_RETURN as its last stmt. */
117 /* Block containing the OMP_CONTINUE as its last stmt. */
120 /* If this is a combined parallel+workshare region, this is a list
121 of additional arguments needed by the combined parallel+workshare
123 vec
<tree
, va_gc
> *ws_args
;
125 /* The code for the omp directive of this region. */
126 enum gimple_code type
;
128 /* Schedule kind, only used for OMP_FOR type regions. */
129 enum omp_clause_schedule_kind sched_kind
;
131 /* True if this is a combined parallel+workshare region. */
132 bool is_combined_parallel
;
135 /* Levels of parallelism as defined by OpenACC. Increasing numbers
136 correspond to deeper loop nesting levels. */
138 #define MASK_WORKER 2
139 #define MASK_VECTOR 4
141 /* Context structure. Used to store information about each parallel
142 directive in the code. */
144 typedef struct omp_context
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context
*outer
;
156 /* Map variables to fields in a structure that allows communication
157 between sending and receiving threads. */
158 splay_tree field_map
;
163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map
;
171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
175 /* A map of reduction pointer variables. For accelerators, each
176 reduction variable is replaced with an array. Each thread, in turn,
177 is assigned to a slot on that array. */
178 splay_tree reduction_map
;
180 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
181 barriers should jump to during omplower pass. */
184 /* What to do with variables with implicitly determined sharing
186 enum omp_clause_default_kind default_kind
;
188 /* Nesting depth of this context. Used to beautify error messages re
189 invalid gotos. The outermost ctx is depth 1, with depth 0 being
190 reserved for the main body of the function. */
193 /* True if this parallel directive is nested within another. */
196 /* True if this construct can be cancelled. */
199 /* For OpenACC loops, a mask of gang, worker and vector used at
200 levels below this one. */
202 /* For OpenACC loops, a mask of gang, worker and vector used at
203 this level and above. For parallel and kernels clauses, a mask
204 indicating which of num_gangs/num_workers/num_vectors was used. */
208 /* A structure holding the elements of:
209 for (V = N1; V cond N2; V += STEP) [...] */
211 struct omp_for_data_loop
213 tree v
, n1
, n2
, step
;
214 enum tree_code cond_code
;
217 /* A structure describing the main elements of a parallel loop. */
221 struct omp_for_data_loop loop
;
226 bool have_nowait
, have_ordered
;
227 enum omp_clause_schedule_kind sched_kind
;
228 struct omp_for_data_loop
*loops
;
232 static splay_tree all_contexts
;
233 static int taskreg_nesting_level
;
234 static int target_nesting_level
;
235 static struct omp_region
*root_omp_region
;
236 static bitmap task_shared_vars
;
237 static vec
<omp_context
*> taskreg_contexts
;
239 static void scan_omp (gimple_seq
*, omp_context
*);
240 static tree
scan_omp_1_op (tree
*, int *, void *);
242 #define WALK_SUBSTMTS \
246 case GIMPLE_EH_FILTER: \
247 case GIMPLE_TRANSACTION: \
248 /* The sub-statements for these should be walked. */ \
249 *handled_ops_p = false; \
252 /* Helper function to get the name of the array containing the partial
253 reductions for OpenACC reductions. */
255 oacc_get_reduction_array_id (tree node
)
257 const char *id
= IDENTIFIER_POINTER (DECL_NAME (node
));
258 int len
= strlen ("OACC") + strlen (id
);
259 char *temp_name
= XALLOCAVEC (char, len
+ 1);
260 snprintf (temp_name
, len
+ 1, "OACC%s", id
);
261 return IDENTIFIER_POINTER (get_identifier (temp_name
));
264 /* Determine the number of threads OpenACC threads used to determine the
265 size of the array of partial reductions. Currently, this is num_gangs
266 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
267 because it is independed of the device used. */
270 oacc_max_threads (omp_context
*ctx
)
272 tree nthreads
, vector_length
, gangs
, clauses
;
274 gangs
= fold_convert (sizetype
, integer_one_node
);
275 vector_length
= gangs
;
277 /* The reduction clause may be nested inside a loop directive.
278 Scan for the innermost vector_length clause. */
279 for (omp_context
*oc
= ctx
; oc
; oc
= oc
->outer
)
281 if (gimple_code (oc
->stmt
) != GIMPLE_OMP_TARGET
282 || (gimple_omp_target_kind (oc
->stmt
)
283 != GF_OMP_TARGET_KIND_OACC_PARALLEL
))
286 clauses
= gimple_omp_target_clauses (oc
->stmt
);
288 vector_length
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
290 vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length
),
292 OMP_CLAUSE_VECTOR_LENGTH_EXPR
295 vector_length
= fold_convert (sizetype
, integer_one_node
);
297 gangs
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
299 gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (gangs
), sizetype
,
300 OMP_CLAUSE_NUM_GANGS_EXPR (gangs
));
302 gangs
= fold_convert (sizetype
, integer_one_node
);
307 nthreads
= fold_build2 (MULT_EXPR
, sizetype
, gangs
, vector_length
);
312 /* Holds offload tables with decls. */
313 vec
<tree
, va_gc
> *offload_funcs
, *offload_vars
;
315 /* Convenience function for calling scan_omp_1_op on tree operands. */
318 scan_omp_op (tree
*tp
, omp_context
*ctx
)
320 struct walk_stmt_info wi
;
322 memset (&wi
, 0, sizeof (wi
));
324 wi
.want_locations
= true;
326 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
329 static void lower_omp (gimple_seq
*, omp_context
*);
330 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
331 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
333 /* Find an OMP clause of type KIND within CLAUSES. */
336 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
338 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
339 if (OMP_CLAUSE_CODE (clauses
) == kind
)
345 /* Return true if CTX is for an omp parallel. */
348 is_parallel_ctx (omp_context
*ctx
)
350 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
354 /* Return true if CTX is for an omp task. */
357 is_task_ctx (omp_context
*ctx
)
359 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
363 /* Return true if CTX is for an omp parallel or omp task. */
366 is_taskreg_ctx (omp_context
*ctx
)
368 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
369 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
373 /* Return true if REGION is a combined parallel+workshare region. */
376 is_combined_parallel (struct omp_region
*region
)
378 return region
->is_combined_parallel
;
382 /* Extract the header elements of parallel loop FOR_STMT and store
386 extract_omp_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
387 struct omp_for_data_loop
*loops
)
389 tree t
, var
, *collapse_iter
, *collapse_count
;
390 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
391 struct omp_for_data_loop
*loop
;
393 struct omp_for_data_loop dummy_loop
;
394 location_t loc
= gimple_location (for_stmt
);
395 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
396 bool distribute
= gimple_omp_for_kind (for_stmt
)
397 == GF_OMP_FOR_KIND_DISTRIBUTE
;
399 fd
->for_stmt
= for_stmt
;
401 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
402 if (fd
->collapse
> 1)
405 fd
->loops
= &fd
->loop
;
407 fd
->have_nowait
= distribute
|| simd
;
408 fd
->have_ordered
= false;
409 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
410 fd
->chunk_size
= NULL_TREE
;
411 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
412 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
413 collapse_iter
= NULL
;
414 collapse_count
= NULL
;
416 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
417 switch (OMP_CLAUSE_CODE (t
))
419 case OMP_CLAUSE_NOWAIT
:
420 fd
->have_nowait
= true;
422 case OMP_CLAUSE_ORDERED
:
423 fd
->have_ordered
= true;
425 case OMP_CLAUSE_SCHEDULE
:
426 gcc_assert (!distribute
);
427 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
428 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
430 case OMP_CLAUSE_DIST_SCHEDULE
:
431 gcc_assert (distribute
);
432 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
434 case OMP_CLAUSE_COLLAPSE
:
435 if (fd
->collapse
> 1)
437 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
438 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
445 /* FIXME: for now map schedule(auto) to schedule(static).
446 There should be analysis to determine whether all iterations
447 are approximately the same amount of work (then schedule(static)
448 is best) or if it varies (then schedule(dynamic,N) is better). */
449 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
451 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
452 gcc_assert (fd
->chunk_size
== NULL
);
454 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
455 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
456 gcc_assert (fd
->chunk_size
== NULL
);
457 else if (fd
->chunk_size
== NULL
)
459 /* We only need to compute a default chunk size for ordered
460 static loops and dynamic loops. */
461 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
463 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
464 ? integer_zero_node
: integer_one_node
;
467 for (i
= 0; i
< fd
->collapse
; i
++)
469 if (fd
->collapse
== 1)
471 else if (loops
!= NULL
)
476 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
477 gcc_assert (SSA_VAR_P (loop
->v
));
478 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
479 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
480 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
481 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
483 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
484 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
485 switch (loop
->cond_code
)
491 gcc_assert (gimple_omp_for_kind (for_stmt
)
492 == GF_OMP_FOR_KIND_CILKSIMD
493 || (gimple_omp_for_kind (for_stmt
)
494 == GF_OMP_FOR_KIND_CILKFOR
));
497 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
498 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
500 loop
->n2
= fold_build2_loc (loc
,
501 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
502 build_int_cst (TREE_TYPE (loop
->n2
), 1));
503 loop
->cond_code
= LT_EXPR
;
506 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
507 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
509 loop
->n2
= fold_build2_loc (loc
,
510 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
511 build_int_cst (TREE_TYPE (loop
->n2
), 1));
512 loop
->cond_code
= GT_EXPR
;
518 t
= gimple_omp_for_incr (for_stmt
, i
);
519 gcc_assert (TREE_OPERAND (t
, 0) == var
);
520 switch (TREE_CODE (t
))
523 loop
->step
= TREE_OPERAND (t
, 1);
525 case POINTER_PLUS_EXPR
:
526 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
529 loop
->step
= TREE_OPERAND (t
, 1);
530 loop
->step
= fold_build1_loc (loc
,
531 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
539 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
540 && !fd
->have_ordered
))
542 if (fd
->collapse
== 1)
543 iter_type
= TREE_TYPE (loop
->v
);
545 || TYPE_PRECISION (iter_type
)
546 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
548 = build_nonstandard_integer_type
549 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
551 else if (iter_type
!= long_long_unsigned_type_node
)
553 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
554 iter_type
= long_long_unsigned_type_node
;
555 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
556 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
557 >= TYPE_PRECISION (iter_type
))
561 if (loop
->cond_code
== LT_EXPR
)
562 n
= fold_build2_loc (loc
,
563 PLUS_EXPR
, TREE_TYPE (loop
->v
),
564 loop
->n2
, loop
->step
);
567 if (TREE_CODE (n
) != INTEGER_CST
568 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
569 iter_type
= long_long_unsigned_type_node
;
571 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
572 > TYPE_PRECISION (iter_type
))
576 if (loop
->cond_code
== LT_EXPR
)
579 n2
= fold_build2_loc (loc
,
580 PLUS_EXPR
, TREE_TYPE (loop
->v
),
581 loop
->n2
, loop
->step
);
585 n1
= fold_build2_loc (loc
,
586 MINUS_EXPR
, TREE_TYPE (loop
->v
),
587 loop
->n2
, loop
->step
);
590 if (TREE_CODE (n1
) != INTEGER_CST
591 || TREE_CODE (n2
) != INTEGER_CST
592 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
593 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
594 iter_type
= long_long_unsigned_type_node
;
598 if (collapse_count
&& *collapse_count
== NULL
)
600 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
601 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
602 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
603 if (t
&& integer_zerop (t
))
604 count
= build_zero_cst (long_long_unsigned_type_node
);
605 else if ((i
== 0 || count
!= NULL_TREE
)
606 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
607 && TREE_CONSTANT (loop
->n1
)
608 && TREE_CONSTANT (loop
->n2
)
609 && TREE_CODE (loop
->step
) == INTEGER_CST
)
611 tree itype
= TREE_TYPE (loop
->v
);
613 if (POINTER_TYPE_P (itype
))
614 itype
= signed_type_for (itype
);
615 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
616 t
= fold_build2_loc (loc
,
618 fold_convert_loc (loc
, itype
, loop
->step
), t
);
619 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
620 fold_convert_loc (loc
, itype
, loop
->n2
));
621 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
622 fold_convert_loc (loc
, itype
, loop
->n1
));
623 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
624 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
625 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
626 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
627 fold_convert_loc (loc
, itype
,
630 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
631 fold_convert_loc (loc
, itype
, loop
->step
));
632 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
633 if (count
!= NULL_TREE
)
634 count
= fold_build2_loc (loc
,
635 MULT_EXPR
, long_long_unsigned_type_node
,
639 if (TREE_CODE (count
) != INTEGER_CST
)
642 else if (count
&& !integer_zerop (count
))
649 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
650 || fd
->have_ordered
))
652 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
653 iter_type
= long_long_unsigned_type_node
;
655 iter_type
= long_integer_type_node
;
657 else if (collapse_iter
&& *collapse_iter
!= NULL
)
658 iter_type
= TREE_TYPE (*collapse_iter
);
659 fd
->iter_type
= iter_type
;
660 if (collapse_iter
&& *collapse_iter
== NULL
)
661 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
662 if (collapse_count
&& *collapse_count
== NULL
)
665 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
667 *collapse_count
= create_tmp_var (iter_type
, ".count");
670 if (fd
->collapse
> 1)
672 fd
->loop
.v
= *collapse_iter
;
673 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
674 fd
->loop
.n2
= *collapse_count
;
675 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
676 fd
->loop
.cond_code
= LT_EXPR
;
679 /* For OpenACC loops, force a chunk size of one, as this avoids the default
680 scheduling where several subsequent iterations are being executed by the
682 if (gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
684 gcc_assert (fd
->chunk_size
== NULL_TREE
);
685 fd
->chunk_size
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
690 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
691 is the immediate dominator of PAR_ENTRY_BB, return true if there
692 are no data dependencies that would prevent expanding the parallel
693 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
695 When expanding a combined parallel+workshare region, the call to
696 the child function may need additional arguments in the case of
697 GIMPLE_OMP_FOR regions. In some cases, these arguments are
698 computed out of variables passed in from the parent to the child
699 via 'struct .omp_data_s'. For instance:
701 #pragma omp parallel for schedule (guided, i * 4)
706 # BLOCK 2 (PAR_ENTRY_BB)
708 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
710 # BLOCK 3 (WS_ENTRY_BB)
711 .omp_data_i = &.omp_data_o;
712 D.1667 = .omp_data_i->i;
714 #pragma omp for schedule (guided, D.1598)
716 When we outline the parallel region, the call to the child function
717 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
718 that value is computed *after* the call site. So, in principle we
719 cannot do the transformation.
721 To see whether the code in WS_ENTRY_BB blocks the combined
722 parallel+workshare call, we collect all the variables used in the
723 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
724 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
727 FIXME. If we had the SSA form built at this point, we could merely
728 hoist the code in block 3 into block 2 and be done with it. But at
729 this point we don't have dataflow information and though we could
730 hack something up here, it is really not worth the aggravation. */
733 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
735 struct omp_for_data fd
;
736 gimple ws_stmt
= last_stmt (ws_entry_bb
);
738 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
741 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
743 extract_omp_for_data (as_a
<gomp_for
*> (ws_stmt
), &fd
, NULL
);
745 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
747 if (fd
.iter_type
!= long_integer_type_node
)
750 /* FIXME. We give up too easily here. If any of these arguments
751 are not constants, they will likely involve variables that have
752 been mapped into fields of .omp_data_s for sharing with the child
753 function. With appropriate data flow, it would be possible to
755 if (!is_gimple_min_invariant (fd
.loop
.n1
)
756 || !is_gimple_min_invariant (fd
.loop
.n2
)
757 || !is_gimple_min_invariant (fd
.loop
.step
)
758 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
765 /* Collect additional arguments needed to emit a combined
766 parallel+workshare call. WS_STMT is the workshare directive being
769 static vec
<tree
, va_gc
> *
770 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
773 location_t loc
= gimple_location (ws_stmt
);
774 vec
<tree
, va_gc
> *ws_args
;
776 if (gomp_for
*for_stmt
= dyn_cast
<gomp_for
*> (ws_stmt
))
778 struct omp_for_data fd
;
781 extract_omp_for_data (for_stmt
, &fd
, NULL
);
785 if (gimple_omp_for_combined_into_p (for_stmt
))
788 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
789 OMP_CLAUSE__LOOPTEMP_
);
791 n1
= OMP_CLAUSE_DECL (innerc
);
792 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
793 OMP_CLAUSE__LOOPTEMP_
);
795 n2
= OMP_CLAUSE_DECL (innerc
);
798 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
800 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
801 ws_args
->quick_push (t
);
803 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
804 ws_args
->quick_push (t
);
806 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
807 ws_args
->quick_push (t
);
811 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
812 ws_args
->quick_push (t
);
817 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
819 /* Number of sections is equal to the number of edges from the
820 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
821 the exit of the sections region. */
822 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
823 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
824 vec_alloc (ws_args
, 1);
825 ws_args
->quick_push (t
);
833 /* Discover whether REGION is a combined parallel+workshare region. */
836 determine_parallel_type (struct omp_region
*region
)
838 basic_block par_entry_bb
, par_exit_bb
;
839 basic_block ws_entry_bb
, ws_exit_bb
;
841 if (region
== NULL
|| region
->inner
== NULL
842 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
843 || region
->inner
->cont
== NULL
)
846 /* We only support parallel+for and parallel+sections. */
847 if (region
->type
!= GIMPLE_OMP_PARALLEL
848 || (region
->inner
->type
!= GIMPLE_OMP_FOR
849 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
852 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
853 WS_EXIT_BB -> PAR_EXIT_BB. */
854 par_entry_bb
= region
->entry
;
855 par_exit_bb
= region
->exit
;
856 ws_entry_bb
= region
->inner
->entry
;
857 ws_exit_bb
= region
->inner
->exit
;
859 if (single_succ (par_entry_bb
) == ws_entry_bb
860 && single_succ (ws_exit_bb
) == par_exit_bb
861 && workshare_safe_to_combine_p (ws_entry_bb
)
862 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
863 || (last_and_only_stmt (ws_entry_bb
)
864 && last_and_only_stmt (par_exit_bb
))))
866 gimple par_stmt
= last_stmt (par_entry_bb
);
867 gimple ws_stmt
= last_stmt (ws_entry_bb
);
869 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
871 /* If this is a combined parallel loop, we need to determine
872 whether or not to use the combined library calls. There
873 are two cases where we do not apply the transformation:
874 static loops and any kind of ordered loop. In the first
875 case, we already open code the loop so there is no need
876 to do anything else. In the latter case, the combined
877 parallel loop call would still need extra synchronization
878 to implement ordered semantics, so there would not be any
879 gain in using the combined call. */
880 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
881 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
883 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
884 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
886 region
->is_combined_parallel
= false;
887 region
->inner
->is_combined_parallel
= false;
892 region
->is_combined_parallel
= true;
893 region
->inner
->is_combined_parallel
= true;
894 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
899 /* Return true if EXPR is variable sized. */
902 is_variable_sized (const_tree expr
)
904 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
907 /* Return true if DECL is a reference type. */
910 is_reference (tree decl
)
912 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
915 /* Return the type of a decl. If the decl is reference type,
916 return its base type. */
918 get_base_type (tree decl
)
920 tree type
= TREE_TYPE (decl
);
921 if (is_reference (decl
))
922 type
= TREE_TYPE (type
);
926 /* Lookup variables. The "maybe" form
927 allows for the variable form to not have been entered, otherwise we
928 assert that the variable must have been entered. */
931 lookup_decl (tree var
, omp_context
*ctx
)
933 tree
*n
= ctx
->cb
.decl_map
->get (var
);
938 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
940 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
941 return n
? *n
: NULL_TREE
;
945 lookup_field (tree var
, omp_context
*ctx
)
948 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
949 return (tree
) n
->value
;
953 lookup_sfield (tree var
, omp_context
*ctx
)
956 n
= splay_tree_lookup (ctx
->sfield_map
957 ? ctx
->sfield_map
: ctx
->field_map
,
958 (splay_tree_key
) var
);
959 return (tree
) n
->value
;
963 maybe_lookup_field (tree var
, omp_context
*ctx
)
966 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
967 return n
? (tree
) n
->value
: NULL_TREE
;
971 lookup_oacc_reduction (const char *id
, omp_context
*ctx
)
974 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) id
);
975 return (tree
) n
->value
;
979 maybe_lookup_oacc_reduction (tree var
, omp_context
*ctx
)
981 splay_tree_node n
= NULL
;
982 if (ctx
->reduction_map
)
983 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) var
);
984 return n
? (tree
) n
->value
: NULL_TREE
;
987 /* Return true if DECL should be copied by pointer. SHARED_CTX is
988 the parallel context if DECL is to be shared. */
991 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
993 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
996 /* We can only use copy-in/copy-out semantics for shared variables
997 when we know the value is not accessible from an outer scope. */
1000 gcc_assert (!is_gimple_omp_oacc (shared_ctx
->stmt
));
1002 /* ??? Trivially accessible from anywhere. But why would we even
1003 be passing an address in this case? Should we simply assert
1004 this to be false, or should we have a cleanup pass that removes
1005 these from the list of mappings? */
1006 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
1009 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1010 without analyzing the expression whether or not its location
1011 is accessible to anyone else. In the case of nested parallel
1012 regions it certainly may be. */
1013 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
1016 /* Do not use copy-in/copy-out for variables that have their
1018 if (TREE_ADDRESSABLE (decl
))
1021 /* lower_send_shared_vars only uses copy-in, but not copy-out
1023 if (TREE_READONLY (decl
)
1024 || ((TREE_CODE (decl
) == RESULT_DECL
1025 || TREE_CODE (decl
) == PARM_DECL
)
1026 && DECL_BY_REFERENCE (decl
)))
1029 /* Disallow copy-in/out in nested parallel if
1030 decl is shared in outer parallel, otherwise
1031 each thread could store the shared variable
1032 in its own copy-in location, making the
1033 variable no longer really shared. */
1034 if (shared_ctx
->is_nested
)
1038 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
1039 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
1046 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
1047 c
; c
= OMP_CLAUSE_CHAIN (c
))
1048 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1049 && OMP_CLAUSE_DECL (c
) == decl
)
1053 goto maybe_mark_addressable_and_ret
;
1057 /* For tasks avoid using copy-in/out. As tasks can be
1058 deferred or executed in different thread, when GOMP_task
1059 returns, the task hasn't necessarily terminated. */
1060 if (is_task_ctx (shared_ctx
))
1063 maybe_mark_addressable_and_ret
:
1064 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
1065 if (is_gimple_reg (outer
))
1067 /* Taking address of OUTER in lower_send_shared_vars
1068 might need regimplification of everything that uses the
1070 if (!task_shared_vars
)
1071 task_shared_vars
= BITMAP_ALLOC (NULL
);
1072 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
1073 TREE_ADDRESSABLE (outer
) = 1;
1082 /* Construct a new automatic decl similar to VAR. */
1085 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
1087 tree copy
= copy_var_decl (var
, name
, type
);
1089 DECL_CONTEXT (copy
) = current_function_decl
;
1090 DECL_CHAIN (copy
) = ctx
->block_vars
;
1091 ctx
->block_vars
= copy
;
1097 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
1099 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
1102 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1105 omp_build_component_ref (tree obj
, tree field
)
1107 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
1108 if (TREE_THIS_VOLATILE (field
))
1109 TREE_THIS_VOLATILE (ret
) |= 1;
1110 if (TREE_READONLY (field
))
1111 TREE_READONLY (ret
) |= 1;
1115 /* Build tree nodes to access the field for VAR on the receiver side. */
1118 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1120 tree x
, field
= lookup_field (var
, ctx
);
1122 /* If the receiver record type was remapped in the child function,
1123 remap the field into the new record type. */
1124 x
= maybe_lookup_field (field
, ctx
);
1128 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1129 x
= omp_build_component_ref (x
, field
);
1131 x
= build_simple_mem_ref (x
);
1136 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1137 of a parallel, this is a component reference; for workshare constructs
1138 this is some variable. */
1141 build_outer_var_ref (tree var
, omp_context
*ctx
)
1145 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1147 else if (is_variable_sized (var
))
1149 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1150 x
= build_outer_var_ref (x
, ctx
);
1151 x
= build_simple_mem_ref (x
);
1153 else if (is_taskreg_ctx (ctx
))
1155 bool by_ref
= use_pointer_for_field (var
, NULL
);
1156 x
= build_receiver_ref (var
, by_ref
, ctx
);
1158 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1159 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1161 /* #pragma omp simd isn't a worksharing construct, and can reference even
1162 private vars in its linear etc. clauses. */
1164 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1165 x
= lookup_decl (var
, ctx
->outer
);
1166 else if (ctx
->outer
)
1167 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1171 else if (ctx
->outer
)
1172 x
= lookup_decl (var
, ctx
->outer
);
1173 else if (is_reference (var
))
1174 /* This can happen with orphaned constructs. If var is reference, it is
1175 possible it is shared and as such valid. */
1180 if (is_reference (var
))
1181 x
= build_simple_mem_ref (x
);
1186 /* Build tree nodes to access the field for VAR on the sender side. */
1189 build_sender_ref (tree var
, omp_context
*ctx
)
1191 tree field
= lookup_sfield (var
, ctx
);
1192 return omp_build_component_ref (ctx
->sender_decl
, field
);
1195 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1198 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1200 tree field
, type
, sfield
= NULL_TREE
;
1202 gcc_assert ((mask
& 1) == 0
1203 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1204 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1205 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1206 gcc_assert ((mask
& 3) == 3
1207 || !is_gimple_omp_oacc (ctx
->stmt
));
1209 type
= TREE_TYPE (var
);
1212 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1213 type
= build_pointer_type (build_pointer_type (type
));
1216 type
= build_pointer_type (type
);
1217 else if ((mask
& 3) == 1 && is_reference (var
))
1218 type
= TREE_TYPE (type
);
1220 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1221 FIELD_DECL
, DECL_NAME (var
), type
);
1223 /* Remember what variable this field was created for. This does have a
1224 side effect of making dwarf2out ignore this member, so for helpful
1225 debugging we clear it later in delete_omp_context. */
1226 DECL_ABSTRACT_ORIGIN (field
) = var
;
1227 if (type
== TREE_TYPE (var
))
1229 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1230 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1231 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1234 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1236 if ((mask
& 3) == 3)
1238 insert_field_into_struct (ctx
->record_type
, field
);
1239 if (ctx
->srecord_type
)
1241 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1242 FIELD_DECL
, DECL_NAME (var
), type
);
1243 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1244 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1245 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1246 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1247 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1252 if (ctx
->srecord_type
== NULL_TREE
)
1256 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1257 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1258 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1260 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1261 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1262 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1263 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1264 splay_tree_insert (ctx
->sfield_map
,
1265 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1266 (splay_tree_value
) sfield
);
1270 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1271 : ctx
->srecord_type
, field
);
1275 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1276 (splay_tree_value
) field
);
1277 if ((mask
& 2) && ctx
->sfield_map
)
1278 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1279 (splay_tree_value
) sfield
);
1283 install_var_local (tree var
, omp_context
*ctx
)
1285 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1286 insert_decl_map (&ctx
->cb
, var
, new_var
);
1290 /* Adjust the replacement for DECL in CTX for the new context. This means
1291 copying the DECL_VALUE_EXPR, and fixing up the type. */
1294 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1296 tree new_decl
, size
;
1298 new_decl
= lookup_decl (decl
, ctx
);
1300 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1302 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1303 && DECL_HAS_VALUE_EXPR_P (decl
))
1305 tree ve
= DECL_VALUE_EXPR (decl
);
1306 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1307 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1308 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1311 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1313 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1314 if (size
== error_mark_node
)
1315 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1316 DECL_SIZE (new_decl
) = size
;
1318 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1319 if (size
== error_mark_node
)
1320 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1321 DECL_SIZE_UNIT (new_decl
) = size
;
1325 /* The callback for remap_decl. Search all containing contexts for a
1326 mapping of the variable; this avoids having to duplicate the splay
1327 tree ahead of time. We know a mapping doesn't already exist in the
1328 given context. Create new mappings to implement default semantics. */
1331 omp_copy_decl (tree var
, copy_body_data
*cb
)
1333 omp_context
*ctx
= (omp_context
*) cb
;
1336 if (TREE_CODE (var
) == LABEL_DECL
)
1338 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1339 DECL_CONTEXT (new_var
) = current_function_decl
;
1340 insert_decl_map (&ctx
->cb
, var
, new_var
);
1344 while (!is_taskreg_ctx (ctx
))
1349 new_var
= maybe_lookup_decl (var
, ctx
);
1354 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1357 return error_mark_node
;
1361 /* Debugging dumps for parallel regions. */
1362 void dump_omp_region (FILE *, struct omp_region
*, int);
1363 void debug_omp_region (struct omp_region
*);
1364 void debug_all_omp_regions (void);
1366 /* Dump the parallel region tree rooted at REGION. */
1369 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1371 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1372 gimple_code_name
[region
->type
]);
1375 dump_omp_region (file
, region
->inner
, indent
+ 4);
1379 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1380 region
->cont
->index
);
1384 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1385 region
->exit
->index
);
1387 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1390 dump_omp_region (file
, region
->next
, indent
);
1394 debug_omp_region (struct omp_region
*region
)
1396 dump_omp_region (stderr
, region
, 0);
1400 debug_all_omp_regions (void)
1402 dump_omp_region (stderr
, root_omp_region
, 0);
1406 /* Create a new parallel region starting at STMT inside region PARENT. */
1408 static struct omp_region
*
1409 new_omp_region (basic_block bb
, enum gimple_code type
,
1410 struct omp_region
*parent
)
1412 struct omp_region
*region
= XCNEW (struct omp_region
);
1414 region
->outer
= parent
;
1416 region
->type
= type
;
1420 /* This is a nested region. Add it to the list of inner
1421 regions in PARENT. */
1422 region
->next
= parent
->inner
;
1423 parent
->inner
= region
;
1427 /* This is a toplevel region. Add it to the list of toplevel
1428 regions in ROOT_OMP_REGION. */
1429 region
->next
= root_omp_region
;
1430 root_omp_region
= region
;
1436 /* Release the memory associated with the region tree rooted at REGION. */
1439 free_omp_region_1 (struct omp_region
*region
)
1441 struct omp_region
*i
, *n
;
1443 for (i
= region
->inner
; i
; i
= n
)
1446 free_omp_region_1 (i
);
1452 /* Release the memory for the entire omp region tree. */
1455 free_omp_regions (void)
1457 struct omp_region
*r
, *n
;
1458 for (r
= root_omp_region
; r
; r
= n
)
1461 free_omp_region_1 (r
);
1463 root_omp_region
= NULL
;
1467 /* Create a new context, with OUTER_CTX being the surrounding context. */
1469 static omp_context
*
1470 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1472 omp_context
*ctx
= XCNEW (omp_context
);
1474 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1475 (splay_tree_value
) ctx
);
1480 ctx
->outer
= outer_ctx
;
1481 ctx
->cb
= outer_ctx
->cb
;
1482 ctx
->cb
.block
= NULL
;
1483 ctx
->depth
= outer_ctx
->depth
+ 1;
1484 ctx
->reduction_map
= outer_ctx
->reduction_map
;
1488 ctx
->cb
.src_fn
= current_function_decl
;
1489 ctx
->cb
.dst_fn
= current_function_decl
;
1490 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1491 gcc_checking_assert (ctx
->cb
.src_node
);
1492 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1493 ctx
->cb
.src_cfun
= cfun
;
1494 ctx
->cb
.copy_decl
= omp_copy_decl
;
1495 ctx
->cb
.eh_lp_nr
= 0;
1496 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1500 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1505 static gimple_seq
maybe_catch_exception (gimple_seq
);
1507 /* Finalize task copyfn. */
1510 finalize_task_copyfn (gomp_task
*task_stmt
)
1512 struct function
*child_cfun
;
1514 gimple_seq seq
= NULL
, new_seq
;
1517 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1518 if (child_fn
== NULL_TREE
)
1521 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1522 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1524 push_cfun (child_cfun
);
1525 bind
= gimplify_body (child_fn
, false);
1526 gimple_seq_add_stmt (&seq
, bind
);
1527 new_seq
= maybe_catch_exception (seq
);
1530 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1532 gimple_seq_add_stmt (&seq
, bind
);
1534 gimple_set_body (child_fn
, seq
);
1537 /* Inform the callgraph about the new function. */
1538 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
1539 node
->parallelized_function
= 1;
1540 cgraph_node::add_new_function (child_fn
, false);
1543 /* Destroy a omp_context data structures. Called through the splay tree
1544 value delete callback. */
1547 delete_omp_context (splay_tree_value value
)
1549 omp_context
*ctx
= (omp_context
*) value
;
1551 delete ctx
->cb
.decl_map
;
1554 splay_tree_delete (ctx
->field_map
);
1555 if (ctx
->sfield_map
)
1556 splay_tree_delete (ctx
->sfield_map
);
1557 /* Reduction map is copied to nested contexts, so only delete it in the
1559 if (ctx
->reduction_map
1560 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
1561 && is_gimple_omp_offloaded (ctx
->stmt
)
1562 && is_gimple_omp_oacc (ctx
->stmt
))
1563 splay_tree_delete (ctx
->reduction_map
);
1565 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1566 it produces corrupt debug information. */
1567 if (ctx
->record_type
)
1570 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1571 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1573 if (ctx
->srecord_type
)
1576 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1577 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1580 if (is_task_ctx (ctx
))
1581 finalize_task_copyfn (as_a
<gomp_task
*> (ctx
->stmt
));
1586 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1590 fixup_child_record_type (omp_context
*ctx
)
1592 tree f
, type
= ctx
->record_type
;
1594 /* ??? It isn't sufficient to just call remap_type here, because
1595 variably_modified_type_p doesn't work the way we expect for
1596 record types. Testing each field for whether it needs remapping
1597 and creating a new record by hand works, however. */
1598 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1599 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1603 tree name
, new_fields
= NULL
;
1605 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1606 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1607 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1608 TYPE_DECL
, name
, type
);
1609 TYPE_NAME (type
) = name
;
1611 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1613 tree new_f
= copy_node (f
);
1614 DECL_CONTEXT (new_f
) = type
;
1615 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1616 DECL_CHAIN (new_f
) = new_fields
;
1617 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1618 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1620 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1624 /* Arrange to be able to look up the receiver field
1625 given the sender field. */
1626 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1627 (splay_tree_value
) new_f
);
1629 TYPE_FIELDS (type
) = nreverse (new_fields
);
1633 TREE_TYPE (ctx
->receiver_decl
)
1634 = build_qualified_type (build_reference_type (type
), TYPE_QUAL_RESTRICT
);
1637 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1638 specified by CLAUSES. */
1641 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1644 bool scan_array_reductions
= false;
1646 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1650 switch (OMP_CLAUSE_CODE (c
))
1652 case OMP_CLAUSE_PRIVATE
:
1653 decl
= OMP_CLAUSE_DECL (c
);
1654 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1656 else if (!is_variable_sized (decl
))
1657 install_var_local (decl
, ctx
);
1660 case OMP_CLAUSE_SHARED
:
1661 decl
= OMP_CLAUSE_DECL (c
);
1662 /* Ignore shared directives in teams construct. */
1663 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1665 /* Global variables don't need to be copied,
1666 the receiver side will use them directly. */
1667 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1668 if (is_global_var (odecl
))
1670 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1673 gcc_assert (is_taskreg_ctx (ctx
));
1674 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1675 || !is_variable_sized (decl
));
1676 /* Global variables don't need to be copied,
1677 the receiver side will use them directly. */
1678 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1680 by_ref
= use_pointer_for_field (decl
, ctx
);
1681 if (! TREE_READONLY (decl
)
1682 || TREE_ADDRESSABLE (decl
)
1684 || is_reference (decl
))
1686 install_var_field (decl
, by_ref
, 3, ctx
);
1687 install_var_local (decl
, ctx
);
1690 /* We don't need to copy const scalar vars back. */
1691 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1694 case OMP_CLAUSE_LASTPRIVATE
:
1695 /* Let the corresponding firstprivate clause create
1697 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1701 case OMP_CLAUSE_FIRSTPRIVATE
:
1702 if (is_gimple_omp_oacc (ctx
->stmt
))
1704 sorry ("clause not supported yet");
1708 case OMP_CLAUSE_REDUCTION
:
1709 case OMP_CLAUSE_LINEAR
:
1710 decl
= OMP_CLAUSE_DECL (c
);
1712 if (is_variable_sized (decl
))
1714 if (is_task_ctx (ctx
))
1715 install_var_field (decl
, false, 1, ctx
);
1718 else if (is_taskreg_ctx (ctx
))
1721 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1722 by_ref
= use_pointer_for_field (decl
, NULL
);
1724 if (is_task_ctx (ctx
)
1725 && (global
|| by_ref
|| is_reference (decl
)))
1727 install_var_field (decl
, false, 1, ctx
);
1729 install_var_field (decl
, by_ref
, 2, ctx
);
1732 install_var_field (decl
, by_ref
, 3, ctx
);
1734 install_var_local (decl
, ctx
);
1735 if (is_gimple_omp_oacc (ctx
->stmt
)
1736 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
1738 /* Create a decl for the reduction array. */
1739 tree var
= OMP_CLAUSE_DECL (c
);
1740 tree type
= get_base_type (var
);
1741 tree ptype
= build_pointer_type (type
);
1742 tree array
= create_tmp_var (ptype
,
1743 oacc_get_reduction_array_id (var
));
1744 omp_context
*c
= (ctx
->field_map
? ctx
: ctx
->outer
);
1745 install_var_field (array
, true, 3, c
);
1746 install_var_local (array
, c
);
1748 /* Insert it into the current context. */
1749 splay_tree_insert (ctx
->reduction_map
, (splay_tree_key
)
1750 oacc_get_reduction_array_id (var
),
1751 (splay_tree_value
) array
);
1752 splay_tree_insert (ctx
->reduction_map
,
1753 (splay_tree_key
) array
,
1754 (splay_tree_value
) array
);
1758 case OMP_CLAUSE__LOOPTEMP_
:
1759 gcc_assert (is_parallel_ctx (ctx
));
1760 decl
= OMP_CLAUSE_DECL (c
);
1761 install_var_field (decl
, false, 3, ctx
);
1762 install_var_local (decl
, ctx
);
1765 case OMP_CLAUSE_COPYPRIVATE
:
1766 case OMP_CLAUSE_COPYIN
:
1767 decl
= OMP_CLAUSE_DECL (c
);
1768 by_ref
= use_pointer_for_field (decl
, NULL
);
1769 install_var_field (decl
, by_ref
, 3, ctx
);
1772 case OMP_CLAUSE_DEFAULT
:
1773 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1776 case OMP_CLAUSE_FINAL
:
1778 case OMP_CLAUSE_NUM_THREADS
:
1779 case OMP_CLAUSE_NUM_TEAMS
:
1780 case OMP_CLAUSE_THREAD_LIMIT
:
1781 case OMP_CLAUSE_DEVICE
:
1782 case OMP_CLAUSE_SCHEDULE
:
1783 case OMP_CLAUSE_DIST_SCHEDULE
:
1784 case OMP_CLAUSE_DEPEND
:
1785 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1786 case OMP_CLAUSE_NUM_GANGS
:
1787 case OMP_CLAUSE_NUM_WORKERS
:
1788 case OMP_CLAUSE_VECTOR_LENGTH
:
1790 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1794 case OMP_CLAUSE_FROM
:
1795 case OMP_CLAUSE_MAP
:
1797 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1798 decl
= OMP_CLAUSE_DECL (c
);
1799 /* Global variables with "omp declare target" attribute
1800 don't need to be copied, the receiver side will use them
1802 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1804 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1805 && varpool_node::get_create (decl
)->offloadable
)
1807 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1808 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
)
1810 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1811 not offloaded; there is nothing to map for those. */
1812 if (!is_gimple_omp_offloaded (ctx
->stmt
)
1813 && !POINTER_TYPE_P (TREE_TYPE (decl
))
1814 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
1819 if (DECL_SIZE (decl
)
1820 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1822 tree decl2
= DECL_VALUE_EXPR (decl
);
1823 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1824 decl2
= TREE_OPERAND (decl2
, 0);
1825 gcc_assert (DECL_P (decl2
));
1826 install_var_field (decl2
, true, 3, ctx
);
1827 install_var_local (decl2
, ctx
);
1828 install_var_local (decl
, ctx
);
1832 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1833 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1834 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1835 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1836 install_var_field (decl
, true, 7, ctx
);
1838 install_var_field (decl
, true, 3, ctx
);
1839 if (is_gimple_omp_offloaded (ctx
->stmt
))
1840 install_var_local (decl
, ctx
);
1845 tree base
= get_base_address (decl
);
1846 tree nc
= OMP_CLAUSE_CHAIN (c
);
1849 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1850 && OMP_CLAUSE_DECL (nc
) == base
1851 && OMP_CLAUSE_MAP_KIND (nc
) == GOMP_MAP_POINTER
1852 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1854 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1855 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1861 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1862 decl
= OMP_CLAUSE_DECL (c
);
1864 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1865 (splay_tree_key
) decl
));
1867 = build_decl (OMP_CLAUSE_LOCATION (c
),
1868 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1869 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1870 insert_field_into_struct (ctx
->record_type
, field
);
1871 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1872 (splay_tree_value
) field
);
1877 case OMP_CLAUSE_NOWAIT
:
1878 case OMP_CLAUSE_ORDERED
:
1879 case OMP_CLAUSE_COLLAPSE
:
1880 case OMP_CLAUSE_UNTIED
:
1881 case OMP_CLAUSE_MERGEABLE
:
1882 case OMP_CLAUSE_PROC_BIND
:
1883 case OMP_CLAUSE_SAFELEN
:
1884 case OMP_CLAUSE_ASYNC
:
1885 case OMP_CLAUSE_WAIT
:
1886 case OMP_CLAUSE_GANG
:
1887 case OMP_CLAUSE_WORKER
:
1888 case OMP_CLAUSE_VECTOR
:
1891 case OMP_CLAUSE_ALIGNED
:
1892 decl
= OMP_CLAUSE_DECL (c
);
1893 if (is_global_var (decl
)
1894 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1895 install_var_local (decl
, ctx
);
1898 case OMP_CLAUSE_DEVICE_RESIDENT
:
1899 case OMP_CLAUSE_USE_DEVICE
:
1900 case OMP_CLAUSE__CACHE_
:
1901 case OMP_CLAUSE_INDEPENDENT
:
1902 case OMP_CLAUSE_AUTO
:
1903 case OMP_CLAUSE_SEQ
:
1904 sorry ("Clause not supported yet");
1912 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1914 switch (OMP_CLAUSE_CODE (c
))
1916 case OMP_CLAUSE_LASTPRIVATE
:
1917 /* Let the corresponding firstprivate clause create
1919 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1920 scan_array_reductions
= true;
1921 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1925 case OMP_CLAUSE_FIRSTPRIVATE
:
1926 if (is_gimple_omp_oacc (ctx
->stmt
))
1928 sorry ("clause not supported yet");
1932 case OMP_CLAUSE_PRIVATE
:
1933 case OMP_CLAUSE_REDUCTION
:
1934 case OMP_CLAUSE_LINEAR
:
1935 decl
= OMP_CLAUSE_DECL (c
);
1936 if (is_variable_sized (decl
))
1937 install_var_local (decl
, ctx
);
1938 fixup_remapped_decl (decl
, ctx
,
1939 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1940 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1941 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1942 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1943 scan_array_reductions
= true;
1944 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1945 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1946 scan_array_reductions
= true;
1949 case OMP_CLAUSE_SHARED
:
1950 /* Ignore shared directives in teams construct. */
1951 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1953 decl
= OMP_CLAUSE_DECL (c
);
1954 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1955 fixup_remapped_decl (decl
, ctx
, false);
1958 case OMP_CLAUSE_MAP
:
1959 if (!is_gimple_omp_offloaded (ctx
->stmt
))
1961 decl
= OMP_CLAUSE_DECL (c
);
1963 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1964 && varpool_node::get_create (decl
)->offloadable
)
1968 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1969 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1970 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1972 tree new_decl
= lookup_decl (decl
, ctx
);
1973 TREE_TYPE (new_decl
)
1974 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1976 else if (DECL_SIZE (decl
)
1977 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1979 tree decl2
= DECL_VALUE_EXPR (decl
);
1980 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1981 decl2
= TREE_OPERAND (decl2
, 0);
1982 gcc_assert (DECL_P (decl2
));
1983 fixup_remapped_decl (decl2
, ctx
, false);
1984 fixup_remapped_decl (decl
, ctx
, true);
1987 fixup_remapped_decl (decl
, ctx
, false);
1991 case OMP_CLAUSE_COPYPRIVATE
:
1992 case OMP_CLAUSE_COPYIN
:
1993 case OMP_CLAUSE_DEFAULT
:
1995 case OMP_CLAUSE_NUM_THREADS
:
1996 case OMP_CLAUSE_NUM_TEAMS
:
1997 case OMP_CLAUSE_THREAD_LIMIT
:
1998 case OMP_CLAUSE_DEVICE
:
1999 case OMP_CLAUSE_SCHEDULE
:
2000 case OMP_CLAUSE_DIST_SCHEDULE
:
2001 case OMP_CLAUSE_NOWAIT
:
2002 case OMP_CLAUSE_ORDERED
:
2003 case OMP_CLAUSE_COLLAPSE
:
2004 case OMP_CLAUSE_UNTIED
:
2005 case OMP_CLAUSE_FINAL
:
2006 case OMP_CLAUSE_MERGEABLE
:
2007 case OMP_CLAUSE_PROC_BIND
:
2008 case OMP_CLAUSE_SAFELEN
:
2009 case OMP_CLAUSE_ALIGNED
:
2010 case OMP_CLAUSE_DEPEND
:
2011 case OMP_CLAUSE__LOOPTEMP_
:
2013 case OMP_CLAUSE_FROM
:
2014 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2015 case OMP_CLAUSE_ASYNC
:
2016 case OMP_CLAUSE_WAIT
:
2017 case OMP_CLAUSE_NUM_GANGS
:
2018 case OMP_CLAUSE_NUM_WORKERS
:
2019 case OMP_CLAUSE_VECTOR_LENGTH
:
2020 case OMP_CLAUSE_GANG
:
2021 case OMP_CLAUSE_WORKER
:
2022 case OMP_CLAUSE_VECTOR
:
2025 case OMP_CLAUSE_DEVICE_RESIDENT
:
2026 case OMP_CLAUSE_USE_DEVICE
:
2027 case OMP_CLAUSE__CACHE_
:
2028 case OMP_CLAUSE_INDEPENDENT
:
2029 case OMP_CLAUSE_AUTO
:
2030 case OMP_CLAUSE_SEQ
:
2031 sorry ("Clause not supported yet");
2039 gcc_checking_assert (!scan_array_reductions
2040 || !is_gimple_omp_oacc (ctx
->stmt
));
2041 if (scan_array_reductions
)
2042 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2043 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
2044 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2046 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
2047 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
2049 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2050 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2051 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
2052 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2053 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2054 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
2057 /* Create a new name for omp child function. Returns an identifier. If
2058 IS_CILK_FOR is true then the suffix for the child function is
2062 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
2065 return clone_function_name (current_function_decl
, "_cilk_for_fn");
2066 return clone_function_name (current_function_decl
,
2067 task_copy
? "_omp_cpyfn" : "_omp_fn");
2070 /* Returns the type of the induction variable for the child function for
2071 _Cilk_for and the types for _high and _low variables based on TYPE. */
2074 cilk_for_check_loop_diff_type (tree type
)
2076 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
2078 if (TYPE_UNSIGNED (type
))
2079 return uint32_type_node
;
2081 return integer_type_node
;
2085 if (TYPE_UNSIGNED (type
))
2086 return uint64_type_node
;
2088 return long_long_integer_type_node
;
2092 /* Build a decl for the omp child function. It'll not contain a body
2093 yet, just the bare decl. */
2096 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
2098 tree decl
, type
, name
, t
;
2101 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2102 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2103 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
2104 tree cilk_var_type
= NULL_TREE
;
2106 name
= create_omp_child_function_name (task_copy
,
2107 cilk_for_count
!= NULL_TREE
);
2109 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2110 ptr_type_node
, NULL_TREE
);
2111 else if (cilk_for_count
)
2113 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
2114 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
2115 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2116 cilk_var_type
, cilk_var_type
, NULL_TREE
);
2119 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
2121 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
2123 gcc_checking_assert (!is_gimple_omp_oacc (ctx
->stmt
)
2126 ctx
->cb
.dst_fn
= decl
;
2128 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
2130 TREE_STATIC (decl
) = 1;
2131 TREE_USED (decl
) = 1;
2132 DECL_ARTIFICIAL (decl
) = 1;
2133 DECL_IGNORED_P (decl
) = 0;
2134 TREE_PUBLIC (decl
) = 0;
2135 DECL_UNINLINABLE (decl
) = 1;
2136 DECL_EXTERNAL (decl
) = 0;
2137 DECL_CONTEXT (decl
) = NULL_TREE
;
2138 DECL_INITIAL (decl
) = make_node (BLOCK
);
2139 if (cgraph_node::get (current_function_decl
)->offloadable
)
2140 cgraph_node::get_create (decl
)->offloadable
= 1;
2144 for (octx
= ctx
; octx
; octx
= octx
->outer
)
2145 if (is_gimple_omp_offloaded (octx
->stmt
))
2147 cgraph_node::get_create (decl
)->offloadable
= 1;
2148 #ifdef ENABLE_OFFLOADING
2149 g
->have_offload
= true;
2155 if (cgraph_node::get_create (decl
)->offloadable
2156 && !lookup_attribute ("omp declare target",
2157 DECL_ATTRIBUTES (current_function_decl
)))
2158 DECL_ATTRIBUTES (decl
)
2159 = tree_cons (get_identifier ("omp target entrypoint"),
2160 NULL_TREE
, DECL_ATTRIBUTES (decl
));
2162 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2163 RESULT_DECL
, NULL_TREE
, void_type_node
);
2164 DECL_ARTIFICIAL (t
) = 1;
2165 DECL_IGNORED_P (t
) = 1;
2166 DECL_CONTEXT (t
) = decl
;
2167 DECL_RESULT (decl
) = t
;
2169 /* _Cilk_for's child function requires two extra parameters called
2170 __low and __high that are set the by Cilk runtime when it calls this
2174 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2175 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
2176 DECL_ARTIFICIAL (t
) = 1;
2177 DECL_NAMELESS (t
) = 1;
2178 DECL_ARG_TYPE (t
) = ptr_type_node
;
2179 DECL_CONTEXT (t
) = current_function_decl
;
2181 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2182 DECL_ARGUMENTS (decl
) = t
;
2184 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2185 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
2186 DECL_ARTIFICIAL (t
) = 1;
2187 DECL_NAMELESS (t
) = 1;
2188 DECL_ARG_TYPE (t
) = ptr_type_node
;
2189 DECL_CONTEXT (t
) = current_function_decl
;
2191 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2192 DECL_ARGUMENTS (decl
) = t
;
2195 tree data_name
= get_identifier (".omp_data_i");
2196 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
2198 DECL_ARTIFICIAL (t
) = 1;
2199 DECL_NAMELESS (t
) = 1;
2200 DECL_ARG_TYPE (t
) = ptr_type_node
;
2201 DECL_CONTEXT (t
) = current_function_decl
;
2204 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2205 DECL_ARGUMENTS (decl
) = t
;
2207 ctx
->receiver_decl
= t
;
2210 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2211 PARM_DECL
, get_identifier (".omp_data_o"),
2213 DECL_ARTIFICIAL (t
) = 1;
2214 DECL_NAMELESS (t
) = 1;
2215 DECL_ARG_TYPE (t
) = ptr_type_node
;
2216 DECL_CONTEXT (t
) = current_function_decl
;
2218 TREE_ADDRESSABLE (t
) = 1;
2219 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2220 DECL_ARGUMENTS (decl
) = t
;
2223 /* Allocate memory for the function structure. The call to
2224 allocate_struct_function clobbers CFUN, so we need to restore
2226 push_struct_function (decl
);
2227 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2231 /* Callback for walk_gimple_seq. Check if combined parallel
2232 contains gimple_omp_for_combined_into_p OMP_FOR. */
2235 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2236 bool *handled_ops_p
,
2237 struct walk_stmt_info
*wi
)
2239 gimple stmt
= gsi_stmt (*gsi_p
);
2241 *handled_ops_p
= true;
2242 switch (gimple_code (stmt
))
2246 case GIMPLE_OMP_FOR
:
2247 if (gimple_omp_for_combined_into_p (stmt
)
2248 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
2251 return integer_zero_node
;
2260 /* Scan an OpenMP parallel directive. */
2263 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2267 gomp_parallel
*stmt
= as_a
<gomp_parallel
*> (gsi_stmt (*gsi
));
2269 /* Ignore parallel directives with empty bodies, unless there
2270 are copyin clauses. */
2272 && empty_body_p (gimple_omp_body (stmt
))
2273 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2274 OMP_CLAUSE_COPYIN
) == NULL
)
2276 gsi_replace (gsi
, gimple_build_nop (), false);
2280 if (gimple_omp_parallel_combined_p (stmt
))
2282 struct walk_stmt_info wi
;
2284 memset (&wi
, 0, sizeof (wi
));
2286 walk_gimple_seq (gimple_omp_body (stmt
),
2287 find_combined_for
, NULL
, &wi
);
2290 gomp_for
*for_stmt
= as_a
<gomp_for
*> ((gimple
) wi
.info
);
2291 struct omp_for_data fd
;
2292 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2293 /* We need two temporaries with fd.loop.v type (istart/iend)
2294 and then (fd.collapse - 1) temporaries with the same
2295 type for count2 ... countN-1 vars if not constant. */
2296 size_t count
= 2, i
;
2297 tree type
= fd
.iter_type
;
2299 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2300 count
+= fd
.collapse
- 1;
2301 for (i
= 0; i
< count
; i
++)
2303 tree temp
= create_tmp_var (type
);
2304 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2305 OMP_CLAUSE__LOOPTEMP_
);
2306 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2307 OMP_CLAUSE_DECL (c
) = temp
;
2308 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2309 gimple_omp_parallel_set_clauses (stmt
, c
);
2314 ctx
= new_omp_context (stmt
, outer_ctx
);
2315 taskreg_contexts
.safe_push (ctx
);
2316 if (taskreg_nesting_level
> 1)
2317 ctx
->is_nested
= true;
2318 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2319 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2320 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2321 name
= create_tmp_var_name (".omp_data_s");
2322 name
= build_decl (gimple_location (stmt
),
2323 TYPE_DECL
, name
, ctx
->record_type
);
2324 DECL_ARTIFICIAL (name
) = 1;
2325 DECL_NAMELESS (name
) = 1;
2326 TYPE_NAME (ctx
->record_type
) = name
;
2327 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2328 create_omp_child_function (ctx
, false);
2329 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2331 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2332 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2334 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2335 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2338 /* Scan an OpenMP task directive. */
2341 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2345 gomp_task
*stmt
= as_a
<gomp_task
*> (gsi_stmt (*gsi
));
2347 /* Ignore task directives with empty bodies. */
2349 && empty_body_p (gimple_omp_body (stmt
)))
2351 gsi_replace (gsi
, gimple_build_nop (), false);
2355 ctx
= new_omp_context (stmt
, outer_ctx
);
2356 taskreg_contexts
.safe_push (ctx
);
2357 if (taskreg_nesting_level
> 1)
2358 ctx
->is_nested
= true;
2359 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2360 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2361 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2362 name
= create_tmp_var_name (".omp_data_s");
2363 name
= build_decl (gimple_location (stmt
),
2364 TYPE_DECL
, name
, ctx
->record_type
);
2365 DECL_ARTIFICIAL (name
) = 1;
2366 DECL_NAMELESS (name
) = 1;
2367 TYPE_NAME (ctx
->record_type
) = name
;
2368 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2369 create_omp_child_function (ctx
, false);
2370 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2372 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2374 if (ctx
->srecord_type
)
2376 name
= create_tmp_var_name (".omp_data_a");
2377 name
= build_decl (gimple_location (stmt
),
2378 TYPE_DECL
, name
, ctx
->srecord_type
);
2379 DECL_ARTIFICIAL (name
) = 1;
2380 DECL_NAMELESS (name
) = 1;
2381 TYPE_NAME (ctx
->srecord_type
) = name
;
2382 TYPE_ARTIFICIAL (ctx
->srecord_type
) = 1;
2383 create_omp_child_function (ctx
, true);
2386 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2388 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2390 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2391 t
= build_int_cst (long_integer_type_node
, 0);
2392 gimple_omp_task_set_arg_size (stmt
, t
);
2393 t
= build_int_cst (long_integer_type_node
, 1);
2394 gimple_omp_task_set_arg_align (stmt
, t
);
2399 /* If any decls have been made addressable during scan_omp,
2400 adjust their fields if needed, and layout record types
2401 of parallel/task constructs. */
2404 finish_taskreg_scan (omp_context
*ctx
)
2406 if (ctx
->record_type
== NULL_TREE
)
2409 /* If any task_shared_vars were needed, verify all
2410 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2411 statements if use_pointer_for_field hasn't changed
2412 because of that. If it did, update field types now. */
2413 if (task_shared_vars
)
2417 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2418 c
; c
= OMP_CLAUSE_CHAIN (c
))
2419 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
2421 tree decl
= OMP_CLAUSE_DECL (c
);
2423 /* Global variables don't need to be copied,
2424 the receiver side will use them directly. */
2425 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2427 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2428 || !use_pointer_for_field (decl
, ctx
))
2430 tree field
= lookup_field (decl
, ctx
);
2431 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2432 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2434 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2435 TREE_THIS_VOLATILE (field
) = 0;
2436 DECL_USER_ALIGN (field
) = 0;
2437 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2438 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2439 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2440 if (ctx
->srecord_type
)
2442 tree sfield
= lookup_sfield (decl
, ctx
);
2443 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2444 TREE_THIS_VOLATILE (sfield
) = 0;
2445 DECL_USER_ALIGN (sfield
) = 0;
2446 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2447 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2448 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2453 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2455 layout_type (ctx
->record_type
);
2456 fixup_child_record_type (ctx
);
2460 location_t loc
= gimple_location (ctx
->stmt
);
2461 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2462 /* Move VLA fields to the end. */
2463 p
= &TYPE_FIELDS (ctx
->record_type
);
2465 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2466 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2469 *p
= TREE_CHAIN (*p
);
2470 TREE_CHAIN (*q
) = NULL_TREE
;
2471 q
= &TREE_CHAIN (*q
);
2474 p
= &DECL_CHAIN (*p
);
2476 layout_type (ctx
->record_type
);
2477 fixup_child_record_type (ctx
);
2478 if (ctx
->srecord_type
)
2479 layout_type (ctx
->srecord_type
);
2480 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2481 TYPE_SIZE_UNIT (ctx
->record_type
));
2482 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2483 t
= build_int_cst (long_integer_type_node
,
2484 TYPE_ALIGN_UNIT (ctx
->record_type
));
2485 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2490 static omp_context
*
2491 enclosing_target_ctx (omp_context
*ctx
)
2494 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
2496 gcc_assert (ctx
!= NULL
);
2501 oacc_loop_or_target_p (gimple stmt
)
2503 enum gimple_code outer_type
= gimple_code (stmt
);
2504 return ((outer_type
== GIMPLE_OMP_TARGET
2505 && ((gimple_omp_target_kind (stmt
)
2506 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2507 || (gimple_omp_target_kind (stmt
)
2508 == GF_OMP_TARGET_KIND_OACC_KERNELS
)))
2509 || (outer_type
== GIMPLE_OMP_FOR
2510 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
));
2513 /* Scan a GIMPLE_OMP_FOR. */
2516 scan_omp_for (gomp_for
*stmt
, omp_context
*outer_ctx
)
2518 enum gimple_code outer_type
= GIMPLE_ERROR_MARK
;
2521 tree clauses
= gimple_omp_for_clauses (stmt
);
2524 outer_type
= gimple_code (outer_ctx
->stmt
);
2526 ctx
= new_omp_context (stmt
, outer_ctx
);
2528 if (is_gimple_omp_oacc (stmt
))
2530 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2531 ctx
->gwv_this
= outer_ctx
->gwv_this
;
2532 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2535 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_GANG
)
2537 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WORKER
)
2539 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR
)
2543 ctx
->gwv_this
|= val
;
2546 /* Skip; not nested inside a region. */
2549 if (!oacc_loop_or_target_p (outer_ctx
->stmt
))
2551 /* Skip; not nested inside an OpenACC region. */
2554 if (outer_type
== GIMPLE_OMP_FOR
)
2555 outer_ctx
->gwv_below
|= val
;
2556 if (OMP_CLAUSE_OPERAND (c
, 0) != NULL_TREE
)
2558 omp_context
*enclosing
= enclosing_target_ctx (outer_ctx
);
2559 if (gimple_omp_target_kind (enclosing
->stmt
)
2560 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2561 error_at (gimple_location (stmt
),
2562 "no arguments allowed to gang, worker and vector clauses inside parallel");
2567 scan_sharing_clauses (clauses
, ctx
);
2569 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2570 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2572 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2573 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2574 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2575 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2577 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2579 if (is_gimple_omp_oacc (stmt
))
2581 if (ctx
->gwv_this
& ctx
->gwv_below
)
2582 error_at (gimple_location (stmt
),
2583 "gang, worker and vector may occur only once in a loop nest");
2584 else if (ctx
->gwv_below
!= 0
2585 && ctx
->gwv_this
> ctx
->gwv_below
)
2586 error_at (gimple_location (stmt
),
2587 "gang, worker and vector must occur in this order in a loop nest");
2588 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2589 outer_ctx
->gwv_below
|= ctx
->gwv_below
;
2593 /* Scan an OpenMP sections directive. */
2596 scan_omp_sections (gomp_sections
*stmt
, omp_context
*outer_ctx
)
2600 ctx
= new_omp_context (stmt
, outer_ctx
);
2601 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2602 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2605 /* Scan an OpenMP single directive. */
2608 scan_omp_single (gomp_single
*stmt
, omp_context
*outer_ctx
)
2613 ctx
= new_omp_context (stmt
, outer_ctx
);
2614 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2615 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2616 name
= create_tmp_var_name (".omp_copy_s");
2617 name
= build_decl (gimple_location (stmt
),
2618 TYPE_DECL
, name
, ctx
->record_type
);
2619 TYPE_NAME (ctx
->record_type
) = name
;
2621 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2622 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2624 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2625 ctx
->record_type
= NULL
;
2627 layout_type (ctx
->record_type
);
2630 /* Scan a GIMPLE_OMP_TARGET. */
2633 scan_omp_target (gomp_target
*stmt
, omp_context
*outer_ctx
)
2637 bool offloaded
= is_gimple_omp_offloaded (stmt
);
2638 tree clauses
= gimple_omp_target_clauses (stmt
);
2640 ctx
= new_omp_context (stmt
, outer_ctx
);
2641 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2642 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2643 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2644 name
= create_tmp_var_name (".omp_data_t");
2645 name
= build_decl (gimple_location (stmt
),
2646 TYPE_DECL
, name
, ctx
->record_type
);
2647 DECL_ARTIFICIAL (name
) = 1;
2648 DECL_NAMELESS (name
) = 1;
2649 TYPE_NAME (ctx
->record_type
) = name
;
2650 TYPE_ARTIFICIAL (ctx
->record_type
) = 1;
2653 if (is_gimple_omp_oacc (stmt
))
2654 ctx
->reduction_map
= splay_tree_new (splay_tree_compare_pointers
,
2657 create_omp_child_function (ctx
, false);
2658 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2661 if (is_gimple_omp_oacc (stmt
))
2663 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2665 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_GANGS
)
2666 ctx
->gwv_this
|= MASK_GANG
;
2667 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_WORKERS
)
2668 ctx
->gwv_this
|= MASK_WORKER
;
2669 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR_LENGTH
)
2670 ctx
->gwv_this
|= MASK_VECTOR
;
2674 scan_sharing_clauses (clauses
, ctx
);
2675 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2677 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2678 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2681 TYPE_FIELDS (ctx
->record_type
)
2682 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2683 #ifdef ENABLE_CHECKING
2685 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2686 for (field
= TYPE_FIELDS (ctx
->record_type
);
2688 field
= DECL_CHAIN (field
))
2689 gcc_assert (DECL_ALIGN (field
) == align
);
2691 layout_type (ctx
->record_type
);
2693 fixup_child_record_type (ctx
);
2697 /* Scan an OpenMP teams directive. */
2700 scan_omp_teams (gomp_teams
*stmt
, omp_context
*outer_ctx
)
2702 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2703 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2704 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2707 /* Check nesting restrictions. */
2709 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2711 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2712 inside an OpenACC CTX. */
2713 if (!(is_gimple_omp (stmt
)
2714 && is_gimple_omp_oacc (stmt
)))
2716 for (omp_context
*ctx_
= ctx
; ctx_
!= NULL
; ctx_
= ctx_
->outer
)
2717 if (is_gimple_omp (ctx_
->stmt
)
2718 && is_gimple_omp_oacc (ctx_
->stmt
))
2720 error_at (gimple_location (stmt
),
2721 "non-OpenACC construct inside of OpenACC region");
2728 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2729 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2731 error_at (gimple_location (stmt
),
2732 "OpenMP constructs may not be nested inside simd region");
2735 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2737 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2738 || (gimple_omp_for_kind (stmt
)
2739 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2740 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2742 error_at (gimple_location (stmt
),
2743 "only distribute or parallel constructs are allowed to "
2744 "be closely nested inside teams construct");
2749 switch (gimple_code (stmt
))
2751 case GIMPLE_OMP_FOR
:
2752 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2754 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2756 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2758 error_at (gimple_location (stmt
),
2759 "distribute construct must be closely nested inside "
2767 if (is_gimple_call (stmt
)
2768 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2769 == BUILT_IN_GOMP_CANCEL
2770 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2771 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2773 const char *bad
= NULL
;
2774 const char *kind
= NULL
;
2777 error_at (gimple_location (stmt
), "orphaned %qs construct",
2778 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2779 == BUILT_IN_GOMP_CANCEL
2780 ? "#pragma omp cancel"
2781 : "#pragma omp cancellation point");
2784 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2785 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2789 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2790 bad
= "#pragma omp parallel";
2791 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2792 == BUILT_IN_GOMP_CANCEL
2793 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2794 ctx
->cancellable
= true;
2798 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2799 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2800 bad
= "#pragma omp for";
2801 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2802 == BUILT_IN_GOMP_CANCEL
2803 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2805 ctx
->cancellable
= true;
2806 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2808 warning_at (gimple_location (stmt
), 0,
2809 "%<#pragma omp cancel for%> inside "
2810 "%<nowait%> for construct");
2811 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2812 OMP_CLAUSE_ORDERED
))
2813 warning_at (gimple_location (stmt
), 0,
2814 "%<#pragma omp cancel for%> inside "
2815 "%<ordered%> for construct");
2820 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2821 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2822 bad
= "#pragma omp sections";
2823 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2824 == BUILT_IN_GOMP_CANCEL
2825 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2827 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2829 ctx
->cancellable
= true;
2830 if (find_omp_clause (gimple_omp_sections_clauses
2833 warning_at (gimple_location (stmt
), 0,
2834 "%<#pragma omp cancel sections%> inside "
2835 "%<nowait%> sections construct");
2839 gcc_assert (ctx
->outer
2840 && gimple_code (ctx
->outer
->stmt
)
2841 == GIMPLE_OMP_SECTIONS
);
2842 ctx
->outer
->cancellable
= true;
2843 if (find_omp_clause (gimple_omp_sections_clauses
2846 warning_at (gimple_location (stmt
), 0,
2847 "%<#pragma omp cancel sections%> inside "
2848 "%<nowait%> sections construct");
2854 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2855 bad
= "#pragma omp task";
2857 ctx
->cancellable
= true;
2861 error_at (gimple_location (stmt
), "invalid arguments");
2866 error_at (gimple_location (stmt
),
2867 "%<%s %s%> construct not closely nested inside of %qs",
2868 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2869 == BUILT_IN_GOMP_CANCEL
2870 ? "#pragma omp cancel"
2871 : "#pragma omp cancellation point", kind
, bad
);
2876 case GIMPLE_OMP_SECTIONS
:
2877 case GIMPLE_OMP_SINGLE
:
2878 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2879 switch (gimple_code (ctx
->stmt
))
2881 case GIMPLE_OMP_FOR
:
2882 case GIMPLE_OMP_SECTIONS
:
2883 case GIMPLE_OMP_SINGLE
:
2884 case GIMPLE_OMP_ORDERED
:
2885 case GIMPLE_OMP_MASTER
:
2886 case GIMPLE_OMP_TASK
:
2887 case GIMPLE_OMP_CRITICAL
:
2888 if (is_gimple_call (stmt
))
2890 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2891 != BUILT_IN_GOMP_BARRIER
)
2893 error_at (gimple_location (stmt
),
2894 "barrier region may not be closely nested inside "
2895 "of work-sharing, critical, ordered, master or "
2896 "explicit task region");
2899 error_at (gimple_location (stmt
),
2900 "work-sharing region may not be closely nested inside "
2901 "of work-sharing, critical, ordered, master or explicit "
2904 case GIMPLE_OMP_PARALLEL
:
2910 case GIMPLE_OMP_MASTER
:
2911 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2912 switch (gimple_code (ctx
->stmt
))
2914 case GIMPLE_OMP_FOR
:
2915 case GIMPLE_OMP_SECTIONS
:
2916 case GIMPLE_OMP_SINGLE
:
2917 case GIMPLE_OMP_TASK
:
2918 error_at (gimple_location (stmt
),
2919 "master region may not be closely nested inside "
2920 "of work-sharing or explicit task region");
2922 case GIMPLE_OMP_PARALLEL
:
2928 case GIMPLE_OMP_ORDERED
:
2929 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2930 switch (gimple_code (ctx
->stmt
))
2932 case GIMPLE_OMP_CRITICAL
:
2933 case GIMPLE_OMP_TASK
:
2934 error_at (gimple_location (stmt
),
2935 "ordered region may not be closely nested inside "
2936 "of critical or explicit task region");
2938 case GIMPLE_OMP_FOR
:
2939 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2940 OMP_CLAUSE_ORDERED
) == NULL
)
2942 error_at (gimple_location (stmt
),
2943 "ordered region must be closely nested inside "
2944 "a loop region with an ordered clause");
2948 case GIMPLE_OMP_PARALLEL
:
2949 error_at (gimple_location (stmt
),
2950 "ordered region must be closely nested inside "
2951 "a loop region with an ordered clause");
2957 case GIMPLE_OMP_CRITICAL
:
2960 = gimple_omp_critical_name (as_a
<gomp_critical
*> (stmt
));
2961 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2962 if (gomp_critical
*other_crit
2963 = dyn_cast
<gomp_critical
*> (ctx
->stmt
))
2964 if (this_stmt_name
== gimple_omp_critical_name (other_crit
))
2966 error_at (gimple_location (stmt
),
2967 "critical region may not be nested inside a critical "
2968 "region with the same name");
2973 case GIMPLE_OMP_TEAMS
:
2975 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2976 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
2978 error_at (gimple_location (stmt
),
2979 "teams construct not closely nested inside of target "
2984 case GIMPLE_OMP_TARGET
:
2985 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2987 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
2989 if (is_gimple_omp (stmt
)
2990 && is_gimple_omp_oacc (stmt
)
2991 && is_gimple_omp (ctx
->stmt
))
2993 error_at (gimple_location (stmt
),
2994 "OpenACC construct inside of non-OpenACC region");
3000 const char *stmt_name
, *ctx_stmt_name
;
3001 switch (gimple_omp_target_kind (stmt
))
3003 case GF_OMP_TARGET_KIND_REGION
: stmt_name
= "target"; break;
3004 case GF_OMP_TARGET_KIND_DATA
: stmt_name
= "target data"; break;
3005 case GF_OMP_TARGET_KIND_UPDATE
: stmt_name
= "target update"; break;
3006 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: stmt_name
= "parallel"; break;
3007 case GF_OMP_TARGET_KIND_OACC_KERNELS
: stmt_name
= "kernels"; break;
3008 case GF_OMP_TARGET_KIND_OACC_DATA
: stmt_name
= "data"; break;
3009 case GF_OMP_TARGET_KIND_OACC_UPDATE
: stmt_name
= "update"; break;
3010 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
: stmt_name
= "enter/exit data"; break;
3011 default: gcc_unreachable ();
3013 switch (gimple_omp_target_kind (ctx
->stmt
))
3015 case GF_OMP_TARGET_KIND_REGION
: ctx_stmt_name
= "target"; break;
3016 case GF_OMP_TARGET_KIND_DATA
: ctx_stmt_name
= "target data"; break;
3017 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: ctx_stmt_name
= "parallel"; break;
3018 case GF_OMP_TARGET_KIND_OACC_KERNELS
: ctx_stmt_name
= "kernels"; break;
3019 case GF_OMP_TARGET_KIND_OACC_DATA
: ctx_stmt_name
= "data"; break;
3020 default: gcc_unreachable ();
3023 /* OpenACC/OpenMP mismatch? */
3024 if (is_gimple_omp_oacc (stmt
)
3025 != is_gimple_omp_oacc (ctx
->stmt
))
3027 error_at (gimple_location (stmt
),
3028 "%s %s construct inside of %s %s region",
3029 (is_gimple_omp_oacc (stmt
)
3030 ? "OpenACC" : "OpenMP"), stmt_name
,
3031 (is_gimple_omp_oacc (ctx
->stmt
)
3032 ? "OpenACC" : "OpenMP"), ctx_stmt_name
);
3035 if (is_gimple_omp_offloaded (ctx
->stmt
))
3037 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3038 if (is_gimple_omp_oacc (ctx
->stmt
))
3040 error_at (gimple_location (stmt
),
3041 "%s construct inside of %s region",
3042 stmt_name
, ctx_stmt_name
);
3047 gcc_checking_assert (!is_gimple_omp_oacc (stmt
));
3048 warning_at (gimple_location (stmt
), 0,
3049 "%s construct inside of %s region",
3050 stmt_name
, ctx_stmt_name
);
3062 /* Helper function scan_omp.
3064 Callback for walk_tree or operators in walk_gimple_stmt used to
3065 scan for OMP directives in TP. */
3068 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
3070 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
3071 omp_context
*ctx
= (omp_context
*) wi
->info
;
3074 switch (TREE_CODE (t
))
3081 *tp
= remap_decl (t
, &ctx
->cb
);
3085 if (ctx
&& TYPE_P (t
))
3086 *tp
= remap_type (t
, &ctx
->cb
);
3087 else if (!DECL_P (t
))
3092 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
3093 if (tem
!= TREE_TYPE (t
))
3095 if (TREE_CODE (t
) == INTEGER_CST
)
3096 *tp
= wide_int_to_tree (tem
, t
);
3098 TREE_TYPE (t
) = tem
;
3108 /* Return true if FNDECL is a setjmp or a longjmp. */
3111 setjmp_or_longjmp_p (const_tree fndecl
)
3113 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
3114 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
3115 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
3118 tree declname
= DECL_NAME (fndecl
);
3121 const char *name
= IDENTIFIER_POINTER (declname
);
3122 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
3126 /* Helper function for scan_omp.
3128 Callback for walk_gimple_stmt used to scan for OMP directives in
3129 the current statement in GSI. */
3132 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
3133 struct walk_stmt_info
*wi
)
3135 gimple stmt
= gsi_stmt (*gsi
);
3136 omp_context
*ctx
= (omp_context
*) wi
->info
;
3138 if (gimple_has_location (stmt
))
3139 input_location
= gimple_location (stmt
);
3141 /* Check the nesting restrictions. */
3142 bool remove
= false;
3143 if (is_gimple_omp (stmt
))
3144 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3145 else if (is_gimple_call (stmt
))
3147 tree fndecl
= gimple_call_fndecl (stmt
);
3150 if (setjmp_or_longjmp_p (fndecl
)
3152 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3153 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3156 error_at (gimple_location (stmt
),
3157 "setjmp/longjmp inside simd construct");
3159 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
3160 switch (DECL_FUNCTION_CODE (fndecl
))
3162 case BUILT_IN_GOMP_BARRIER
:
3163 case BUILT_IN_GOMP_CANCEL
:
3164 case BUILT_IN_GOMP_CANCELLATION_POINT
:
3165 case BUILT_IN_GOMP_TASKYIELD
:
3166 case BUILT_IN_GOMP_TASKWAIT
:
3167 case BUILT_IN_GOMP_TASKGROUP_START
:
3168 case BUILT_IN_GOMP_TASKGROUP_END
:
3169 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3178 stmt
= gimple_build_nop ();
3179 gsi_replace (gsi
, stmt
, false);
3182 *handled_ops_p
= true;
3184 switch (gimple_code (stmt
))
3186 case GIMPLE_OMP_PARALLEL
:
3187 taskreg_nesting_level
++;
3188 scan_omp_parallel (gsi
, ctx
);
3189 taskreg_nesting_level
--;
3192 case GIMPLE_OMP_TASK
:
3193 taskreg_nesting_level
++;
3194 scan_omp_task (gsi
, ctx
);
3195 taskreg_nesting_level
--;
3198 case GIMPLE_OMP_FOR
:
3199 scan_omp_for (as_a
<gomp_for
*> (stmt
), ctx
);
3202 case GIMPLE_OMP_SECTIONS
:
3203 scan_omp_sections (as_a
<gomp_sections
*> (stmt
), ctx
);
3206 case GIMPLE_OMP_SINGLE
:
3207 scan_omp_single (as_a
<gomp_single
*> (stmt
), ctx
);
3210 case GIMPLE_OMP_SECTION
:
3211 case GIMPLE_OMP_MASTER
:
3212 case GIMPLE_OMP_TASKGROUP
:
3213 case GIMPLE_OMP_ORDERED
:
3214 case GIMPLE_OMP_CRITICAL
:
3215 ctx
= new_omp_context (stmt
, ctx
);
3216 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3219 case GIMPLE_OMP_TARGET
:
3220 scan_omp_target (as_a
<gomp_target
*> (stmt
), ctx
);
3223 case GIMPLE_OMP_TEAMS
:
3224 scan_omp_teams (as_a
<gomp_teams
*> (stmt
), ctx
);
3231 *handled_ops_p
= false;
3233 for (var
= gimple_bind_vars (as_a
<gbind
*> (stmt
));
3235 var
= DECL_CHAIN (var
))
3236 insert_decl_map (&ctx
->cb
, var
, var
);
3240 *handled_ops_p
= false;
3248 /* Scan all the statements starting at the current statement. CTX
3249 contains context information about the OMP directives and
3250 clauses found during the scan. */
3253 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
3255 location_t saved_location
;
3256 struct walk_stmt_info wi
;
3258 memset (&wi
, 0, sizeof (wi
));
3260 wi
.want_locations
= true;
3262 saved_location
= input_location
;
3263 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
3264 input_location
= saved_location
;
3267 /* Re-gimplification and code generation routines. */
3269 /* Build a call to GOMP_barrier. */
3272 build_omp_barrier (tree lhs
)
3274 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
3275 : BUILT_IN_GOMP_BARRIER
);
3276 gcall
*g
= gimple_build_call (fndecl
, 0);
3278 gimple_call_set_lhs (g
, lhs
);
3282 /* If a context was created for STMT when it was scanned, return it. */
3284 static omp_context
*
3285 maybe_lookup_ctx (gimple stmt
)
3288 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
3289 return n
? (omp_context
*) n
->value
: NULL
;
3293 /* Find the mapping for DECL in CTX or the immediately enclosing
3294 context that has a mapping for DECL.
3296 If CTX is a nested parallel directive, we may have to use the decl
3297 mappings created in CTX's parent context. Suppose that we have the
3298 following parallel nesting (variable UIDs showed for clarity):
3301 #omp parallel shared(iD.1562) -> outer parallel
3302 iD.1562 = iD.1562 + 1;
3304 #omp parallel shared (iD.1562) -> inner parallel
3305 iD.1562 = iD.1562 - 1;
3307 Each parallel structure will create a distinct .omp_data_s structure
3308 for copying iD.1562 in/out of the directive:
3310 outer parallel .omp_data_s.1.i -> iD.1562
3311 inner parallel .omp_data_s.2.i -> iD.1562
3313 A shared variable mapping will produce a copy-out operation before
3314 the parallel directive and a copy-in operation after it. So, in
3315 this case we would have:
3318 .omp_data_o.1.i = iD.1562;
3319 #omp parallel shared(iD.1562) -> outer parallel
3320 .omp_data_i.1 = &.omp_data_o.1
3321 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3323 .omp_data_o.2.i = iD.1562; -> **
3324 #omp parallel shared(iD.1562) -> inner parallel
3325 .omp_data_i.2 = &.omp_data_o.2
3326 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3329 ** This is a problem. The symbol iD.1562 cannot be referenced
3330 inside the body of the outer parallel region. But since we are
3331 emitting this copy operation while expanding the inner parallel
3332 directive, we need to access the CTX structure of the outer
3333 parallel directive to get the correct mapping:
3335 .omp_data_o.2.i = .omp_data_i.1->i
3337 Since there may be other workshare or parallel directives enclosing
3338 the parallel directive, it may be necessary to walk up the context
3339 parent chain. This is not a problem in general because nested
3340 parallelism happens only rarely. */
3343 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3348 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3349 t
= maybe_lookup_decl (decl
, up
);
3351 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
3353 return t
? t
: decl
;
3357 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3358 in outer contexts. */
3361 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3366 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3367 t
= maybe_lookup_decl (decl
, up
);
3369 return t
? t
: decl
;
3373 /* Construct the initialization value for reduction CLAUSE. */
3376 omp_reduction_init (tree clause
, tree type
)
3378 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
3379 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
3386 case TRUTH_ORIF_EXPR
:
3387 case TRUTH_XOR_EXPR
:
3389 return build_zero_cst (type
);
3392 case TRUTH_AND_EXPR
:
3393 case TRUTH_ANDIF_EXPR
:
3395 return fold_convert_loc (loc
, type
, integer_one_node
);
3398 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3401 if (SCALAR_FLOAT_TYPE_P (type
))
3403 REAL_VALUE_TYPE max
, min
;
3404 if (HONOR_INFINITIES (type
))
3407 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3410 real_maxval (&min
, 1, TYPE_MODE (type
));
3411 return build_real (type
, min
);
3415 gcc_assert (INTEGRAL_TYPE_P (type
));
3416 return TYPE_MIN_VALUE (type
);
3420 if (SCALAR_FLOAT_TYPE_P (type
))
3422 REAL_VALUE_TYPE max
;
3423 if (HONOR_INFINITIES (type
))
3426 real_maxval (&max
, 0, TYPE_MODE (type
));
3427 return build_real (type
, max
);
3431 gcc_assert (INTEGRAL_TYPE_P (type
));
3432 return TYPE_MAX_VALUE (type
);
3440 /* Return alignment to be assumed for var in CLAUSE, which should be
3441 OMP_CLAUSE_ALIGNED. */
3444 omp_clause_aligned_alignment (tree clause
)
3446 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3447 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3449 /* Otherwise return implementation defined alignment. */
3450 unsigned int al
= 1;
3451 machine_mode mode
, vmode
;
3452 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3454 vs
= 1 << floor_log2 (vs
);
3455 static enum mode_class classes
[]
3456 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3457 for (int i
= 0; i
< 4; i
+= 2)
3458 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3460 mode
= GET_MODE_WIDER_MODE (mode
))
3462 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3463 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3466 && GET_MODE_SIZE (vmode
) < vs
3467 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3468 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3470 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3471 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3473 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3474 / GET_MODE_SIZE (mode
));
3475 if (TYPE_MODE (type
) != vmode
)
3477 if (TYPE_ALIGN_UNIT (type
) > al
)
3478 al
= TYPE_ALIGN_UNIT (type
);
3480 return build_int_cst (integer_type_node
, al
);
3483 /* Return maximum possible vectorization factor for the target. */
3490 || !flag_tree_loop_optimize
3491 || (!flag_tree_loop_vectorize
3492 && (global_options_set
.x_flag_tree_loop_vectorize
3493 || global_options_set
.x_flag_tree_vectorize
)))
3496 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3499 vs
= 1 << floor_log2 (vs
);
3502 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
3503 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
3504 return GET_MODE_NUNITS (vqimode
);
3508 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3512 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
3513 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
3517 max_vf
= omp_max_vf ();
3520 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3521 OMP_CLAUSE_SAFELEN
);
3522 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3524 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3526 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3530 idx
= create_tmp_var (unsigned_type_node
);
3531 lane
= create_tmp_var (unsigned_type_node
);
3537 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3538 tree avar
= create_tmp_var_raw (atype
);
3539 if (TREE_ADDRESSABLE (new_var
))
3540 TREE_ADDRESSABLE (avar
) = 1;
3541 DECL_ATTRIBUTES (avar
)
3542 = tree_cons (get_identifier ("omp simd array"), NULL
,
3543 DECL_ATTRIBUTES (avar
));
3544 gimple_add_tmp_var (avar
);
3545 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3546 NULL_TREE
, NULL_TREE
);
3547 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3548 NULL_TREE
, NULL_TREE
);
3549 if (DECL_P (new_var
))
3551 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3552 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3557 /* Helper function of lower_rec_input_clauses. For a reference
3558 in simd reduction, add an underlying variable it will reference. */
3561 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3563 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3564 if (TREE_CONSTANT (z
))
3566 const char *name
= NULL
;
3567 if (DECL_NAME (new_vard
))
3568 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3570 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3571 gimple_add_tmp_var (z
);
3572 TREE_ADDRESSABLE (z
) = 1;
3573 z
= build_fold_addr_expr_loc (loc
, z
);
3574 gimplify_assign (new_vard
, z
, ilist
);
3578 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3579 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3580 private variables. Initialization statements go in ILIST, while calls
3581 to destructors go in DLIST. */
3584 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3585 omp_context
*ctx
, struct omp_for_data
*fd
)
3587 tree c
, dtor
, copyin_seq
, x
, ptr
;
3588 bool copyin_by_ref
= false;
3589 bool lastprivate_firstprivate
= false;
3590 bool reduction_omp_orig_ref
= false;
3592 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3593 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3595 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3596 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3597 gimple_seq llist
[2] = { NULL
, NULL
};
3601 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3602 with data sharing clauses referencing variable sized vars. That
3603 is unnecessarily hard to support and very unlikely to result in
3604 vectorized code anyway. */
3606 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3607 switch (OMP_CLAUSE_CODE (c
))
3609 case OMP_CLAUSE_LINEAR
:
3610 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3613 case OMP_CLAUSE_REDUCTION
:
3614 case OMP_CLAUSE_PRIVATE
:
3615 case OMP_CLAUSE_FIRSTPRIVATE
:
3616 case OMP_CLAUSE_LASTPRIVATE
:
3617 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3624 /* Do all the fixed sized types in the first pass, and the variable sized
3625 types in the second pass. This makes sure that the scalar arguments to
3626 the variable sized types are processed before we use them in the
3627 variable sized operations. */
3628 for (pass
= 0; pass
< 2; ++pass
)
3630 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3632 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3635 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3639 case OMP_CLAUSE_PRIVATE
:
3640 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3643 case OMP_CLAUSE_SHARED
:
3644 /* Ignore shared directives in teams construct. */
3645 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3647 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3649 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3652 case OMP_CLAUSE_FIRSTPRIVATE
:
3653 case OMP_CLAUSE_COPYIN
:
3654 case OMP_CLAUSE_LINEAR
:
3656 case OMP_CLAUSE_REDUCTION
:
3657 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3658 reduction_omp_orig_ref
= true;
3660 case OMP_CLAUSE__LOOPTEMP_
:
3661 /* Handle _looptemp_ clauses only on parallel. */
3665 case OMP_CLAUSE_LASTPRIVATE
:
3666 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3668 lastprivate_firstprivate
= true;
3672 /* Even without corresponding firstprivate, if
3673 decl is Fortran allocatable, it needs outer var
3676 && lang_hooks
.decls
.omp_private_outer_ref
3677 (OMP_CLAUSE_DECL (c
)))
3678 lastprivate_firstprivate
= true;
3680 case OMP_CLAUSE_ALIGNED
:
3683 var
= OMP_CLAUSE_DECL (c
);
3684 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3685 && !is_global_var (var
))
3687 new_var
= maybe_lookup_decl (var
, ctx
);
3688 if (new_var
== NULL_TREE
)
3689 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3690 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3691 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3692 omp_clause_aligned_alignment (c
));
3693 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3694 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3695 gimplify_and_add (x
, ilist
);
3697 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3698 && is_global_var (var
))
3700 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3701 new_var
= lookup_decl (var
, ctx
);
3702 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3703 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3704 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3705 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3706 omp_clause_aligned_alignment (c
));
3707 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3708 x
= create_tmp_var (ptype
);
3709 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3710 gimplify_and_add (t
, ilist
);
3711 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3712 SET_DECL_VALUE_EXPR (new_var
, t
);
3713 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3720 new_var
= var
= OMP_CLAUSE_DECL (c
);
3721 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3722 new_var
= lookup_decl (var
, ctx
);
3724 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3729 else if (is_variable_sized (var
))
3731 /* For variable sized types, we need to allocate the
3732 actual storage here. Call alloca and store the
3733 result in the pointer decl that we created elsewhere. */
3737 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3742 ptr
= DECL_VALUE_EXPR (new_var
);
3743 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3744 ptr
= TREE_OPERAND (ptr
, 0);
3745 gcc_assert (DECL_P (ptr
));
3746 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3748 /* void *tmp = __builtin_alloca */
3749 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3750 stmt
= gimple_build_call (atmp
, 1, x
);
3751 tmp
= create_tmp_var_raw (ptr_type_node
);
3752 gimple_add_tmp_var (tmp
);
3753 gimple_call_set_lhs (stmt
, tmp
);
3755 gimple_seq_add_stmt (ilist
, stmt
);
3757 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3758 gimplify_assign (ptr
, x
, ilist
);
3761 else if (is_reference (var
))
3763 /* For references that are being privatized for Fortran,
3764 allocate new backing storage for the new pointer
3765 variable. This allows us to avoid changing all the
3766 code that expects a pointer to something that expects
3767 a direct variable. */
3771 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3772 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3774 x
= build_receiver_ref (var
, false, ctx
);
3775 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3777 else if (TREE_CONSTANT (x
))
3779 /* For reduction in SIMD loop, defer adding the
3780 initialization of the reference, because if we decide
3781 to use SIMD array for it, the initilization could cause
3783 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3787 const char *name
= NULL
;
3788 if (DECL_NAME (var
))
3789 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3791 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3793 gimple_add_tmp_var (x
);
3794 TREE_ADDRESSABLE (x
) = 1;
3795 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3800 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3801 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3806 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3807 gimplify_assign (new_var
, x
, ilist
);
3810 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3812 else if (c_kind
== OMP_CLAUSE_REDUCTION
3813 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3821 switch (OMP_CLAUSE_CODE (c
))
3823 case OMP_CLAUSE_SHARED
:
3824 /* Ignore shared directives in teams construct. */
3825 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3827 /* Shared global vars are just accessed directly. */
3828 if (is_global_var (new_var
))
3830 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3831 needs to be delayed until after fixup_child_record_type so
3832 that we get the correct type during the dereference. */
3833 by_ref
= use_pointer_for_field (var
, ctx
);
3834 x
= build_receiver_ref (var
, by_ref
, ctx
);
3835 SET_DECL_VALUE_EXPR (new_var
, x
);
3836 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3838 /* ??? If VAR is not passed by reference, and the variable
3839 hasn't been initialized yet, then we'll get a warning for
3840 the store into the omp_data_s structure. Ideally, we'd be
3841 able to notice this and not store anything at all, but
3842 we're generating code too early. Suppress the warning. */
3844 TREE_NO_WARNING (var
) = 1;
3847 case OMP_CLAUSE_LASTPRIVATE
:
3848 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3852 case OMP_CLAUSE_PRIVATE
:
3853 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3854 x
= build_outer_var_ref (var
, ctx
);
3855 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3857 if (is_task_ctx (ctx
))
3858 x
= build_receiver_ref (var
, false, ctx
);
3860 x
= build_outer_var_ref (var
, ctx
);
3866 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3869 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3870 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3871 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3872 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3873 idx
, lane
, ivar
, lvar
))
3876 x
= lang_hooks
.decls
.omp_clause_default_ctor
3877 (c
, unshare_expr (ivar
), x
);
3879 gimplify_and_add (x
, &llist
[0]);
3882 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3885 gimple_seq tseq
= NULL
;
3888 gimplify_stmt (&dtor
, &tseq
);
3889 gimple_seq_add_seq (&llist
[1], tseq
);
3896 gimplify_and_add (nx
, ilist
);
3900 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3903 gimple_seq tseq
= NULL
;
3906 gimplify_stmt (&dtor
, &tseq
);
3907 gimple_seq_add_seq (dlist
, tseq
);
3911 case OMP_CLAUSE_LINEAR
:
3912 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3913 goto do_firstprivate
;
3914 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3917 x
= build_outer_var_ref (var
, ctx
);
3920 case OMP_CLAUSE_FIRSTPRIVATE
:
3921 if (is_task_ctx (ctx
))
3923 if (is_reference (var
) || is_variable_sized (var
))
3925 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3927 || use_pointer_for_field (var
, NULL
))
3929 x
= build_receiver_ref (var
, false, ctx
);
3930 SET_DECL_VALUE_EXPR (new_var
, x
);
3931 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3936 x
= build_outer_var_ref (var
, ctx
);
3939 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3940 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3942 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3943 tree stept
= TREE_TYPE (t
);
3944 tree ct
= find_omp_clause (clauses
,
3945 OMP_CLAUSE__LOOPTEMP_
);
3947 tree l
= OMP_CLAUSE_DECL (ct
);
3948 tree n1
= fd
->loop
.n1
;
3949 tree step
= fd
->loop
.step
;
3950 tree itype
= TREE_TYPE (l
);
3951 if (POINTER_TYPE_P (itype
))
3952 itype
= signed_type_for (itype
);
3953 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3954 if (TYPE_UNSIGNED (itype
)
3955 && fd
->loop
.cond_code
== GT_EXPR
)
3956 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3957 fold_build1 (NEGATE_EXPR
, itype
, l
),
3958 fold_build1 (NEGATE_EXPR
,
3961 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3962 t
= fold_build2 (MULT_EXPR
, stept
,
3963 fold_convert (stept
, l
), t
);
3965 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3967 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3969 gimplify_and_add (x
, ilist
);
3973 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3974 x
= fold_build2 (POINTER_PLUS_EXPR
,
3975 TREE_TYPE (x
), x
, t
);
3977 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
3980 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
3981 || TREE_ADDRESSABLE (new_var
))
3982 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3983 idx
, lane
, ivar
, lvar
))
3985 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
3987 tree iv
= create_tmp_var (TREE_TYPE (new_var
));
3988 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
3989 gimplify_and_add (x
, ilist
);
3990 gimple_stmt_iterator gsi
3991 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
3993 = gimple_build_assign (unshare_expr (lvar
), iv
);
3994 gsi_insert_before_without_update (&gsi
, g
,
3996 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3997 enum tree_code code
= PLUS_EXPR
;
3998 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
3999 code
= POINTER_PLUS_EXPR
;
4000 g
= gimple_build_assign (iv
, code
, iv
, t
);
4001 gsi_insert_before_without_update (&gsi
, g
,
4005 x
= lang_hooks
.decls
.omp_clause_copy_ctor
4006 (c
, unshare_expr (ivar
), x
);
4007 gimplify_and_add (x
, &llist
[0]);
4008 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4011 gimple_seq tseq
= NULL
;
4014 gimplify_stmt (&dtor
, &tseq
);
4015 gimple_seq_add_seq (&llist
[1], tseq
);
4020 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
4021 gimplify_and_add (x
, ilist
);
4024 case OMP_CLAUSE__LOOPTEMP_
:
4025 gcc_assert (is_parallel_ctx (ctx
));
4026 x
= build_outer_var_ref (var
, ctx
);
4027 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
4028 gimplify_and_add (x
, ilist
);
4031 case OMP_CLAUSE_COPYIN
:
4032 by_ref
= use_pointer_for_field (var
, NULL
);
4033 x
= build_receiver_ref (var
, by_ref
, ctx
);
4034 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
4035 append_to_statement_list (x
, ©in_seq
);
4036 copyin_by_ref
|= by_ref
;
4039 case OMP_CLAUSE_REDUCTION
:
4040 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4042 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4044 x
= build_outer_var_ref (var
, ctx
);
4046 if (is_reference (var
)
4047 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4049 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4050 SET_DECL_VALUE_EXPR (placeholder
, x
);
4051 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4052 tree new_vard
= new_var
;
4053 if (is_reference (var
))
4055 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4056 new_vard
= TREE_OPERAND (new_var
, 0);
4057 gcc_assert (DECL_P (new_vard
));
4060 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4061 idx
, lane
, ivar
, lvar
))
4063 if (new_vard
== new_var
)
4065 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
4066 SET_DECL_VALUE_EXPR (new_var
, ivar
);
4070 SET_DECL_VALUE_EXPR (new_vard
,
4071 build_fold_addr_expr (ivar
));
4072 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4074 x
= lang_hooks
.decls
.omp_clause_default_ctor
4075 (c
, unshare_expr (ivar
),
4076 build_outer_var_ref (var
, ctx
));
4078 gimplify_and_add (x
, &llist
[0]);
4079 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4081 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4082 lower_omp (&tseq
, ctx
);
4083 gimple_seq_add_seq (&llist
[0], tseq
);
4085 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4086 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4087 lower_omp (&tseq
, ctx
);
4088 gimple_seq_add_seq (&llist
[1], tseq
);
4089 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4090 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4091 if (new_vard
== new_var
)
4092 SET_DECL_VALUE_EXPR (new_var
, lvar
);
4094 SET_DECL_VALUE_EXPR (new_vard
,
4095 build_fold_addr_expr (lvar
));
4096 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4101 gimplify_stmt (&dtor
, &tseq
);
4102 gimple_seq_add_seq (&llist
[1], tseq
);
4106 /* If this is a reference to constant size reduction var
4107 with placeholder, we haven't emitted the initializer
4108 for it because it is undesirable if SIMD arrays are used.
4109 But if they aren't used, we need to emit the deferred
4110 initialization now. */
4111 else if (is_reference (var
) && is_simd
)
4112 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4113 x
= lang_hooks
.decls
.omp_clause_default_ctor
4114 (c
, unshare_expr (new_var
),
4115 build_outer_var_ref (var
, ctx
));
4117 gimplify_and_add (x
, ilist
);
4118 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4120 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4121 lower_omp (&tseq
, ctx
);
4122 gimple_seq_add_seq (ilist
, tseq
);
4124 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4127 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4128 lower_omp (&tseq
, ctx
);
4129 gimple_seq_add_seq (dlist
, tseq
);
4130 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4132 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4137 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
4138 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
4139 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4141 /* reduction(-:var) sums up the partial results, so it
4142 acts identically to reduction(+:var). */
4143 if (code
== MINUS_EXPR
)
4146 tree new_vard
= new_var
;
4147 if (is_simd
&& is_reference (var
))
4149 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4150 new_vard
= TREE_OPERAND (new_var
, 0);
4151 gcc_assert (DECL_P (new_vard
));
4154 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4155 idx
, lane
, ivar
, lvar
))
4157 tree ref
= build_outer_var_ref (var
, ctx
);
4159 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
4161 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
4162 ref
= build_outer_var_ref (var
, ctx
);
4163 gimplify_assign (ref
, x
, &llist
[1]);
4165 if (new_vard
!= new_var
)
4167 SET_DECL_VALUE_EXPR (new_vard
,
4168 build_fold_addr_expr (lvar
));
4169 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4174 if (is_reference (var
) && is_simd
)
4175 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4176 gimplify_assign (new_var
, x
, ilist
);
4179 tree ref
= build_outer_var_ref (var
, ctx
);
4181 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4182 ref
= build_outer_var_ref (var
, ctx
);
4183 gimplify_assign (ref
, x
, dlist
);
4197 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
4198 /* Don't want uninit warnings on simduid, it is always uninitialized,
4199 but we use it not for the value, but for the DECL_UID only. */
4200 TREE_NO_WARNING (uid
) = 1;
4202 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
4203 gimple_call_set_lhs (g
, lane
);
4204 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4205 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
4206 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
4207 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
4208 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4209 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4210 g
= gimple_build_assign (lane
, INTEGER_CST
,
4211 build_int_cst (unsigned_type_node
, 0));
4212 gimple_seq_add_stmt (ilist
, g
);
4213 for (int i
= 0; i
< 2; i
++)
4216 tree vf
= create_tmp_var (unsigned_type_node
);
4217 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
4218 gimple_call_set_lhs (g
, vf
);
4219 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
4220 gimple_seq_add_stmt (seq
, g
);
4221 tree t
= build_int_cst (unsigned_type_node
, 0);
4222 g
= gimple_build_assign (idx
, INTEGER_CST
, t
);
4223 gimple_seq_add_stmt (seq
, g
);
4224 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
4225 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
4226 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
4227 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
4228 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
4229 gimple_seq_add_seq (seq
, llist
[i
]);
4230 t
= build_int_cst (unsigned_type_node
, 1);
4231 g
= gimple_build_assign (idx
, PLUS_EXPR
, idx
, t
);
4232 gimple_seq_add_stmt (seq
, g
);
4233 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
4234 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
4235 gimple_seq_add_stmt (seq
, g
);
4236 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
4240 /* The copyin sequence is not to be executed by the main thread, since
4241 that would result in self-copies. Perhaps not visible to scalars,
4242 but it certainly is to C++ operator=. */
4245 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
4247 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
4248 build_int_cst (TREE_TYPE (x
), 0));
4249 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
4250 gimplify_and_add (x
, ilist
);
4253 /* If any copyin variable is passed by reference, we must ensure the
4254 master thread doesn't modify it before it is copied over in all
4255 threads. Similarly for variables in both firstprivate and
4256 lastprivate clauses we need to ensure the lastprivate copying
4257 happens after firstprivate copying in all threads. And similarly
4258 for UDRs if initializer expression refers to omp_orig. */
4259 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
4261 /* Don't add any barrier for #pragma omp simd or
4262 #pragma omp distribute. */
4263 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
4264 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
4265 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
4268 /* If max_vf is non-zero, then we can use only a vectorization factor
4269 up to the max_vf we chose. So stick it into the safelen clause. */
4272 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
4273 OMP_CLAUSE_SAFELEN
);
4275 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
4276 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
4279 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
4280 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
4282 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4283 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4289 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4290 both parallel and workshare constructs. PREDICATE may be NULL if it's
4294 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
4297 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
4298 bool par_clauses
= false;
4299 tree simduid
= NULL
, lastlane
= NULL
;
4301 /* Early exit if there are no lastprivate or linear clauses. */
4302 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
4303 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
4304 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
4305 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
4307 if (clauses
== NULL
)
4309 /* If this was a workshare clause, see if it had been combined
4310 with its parallel. In that case, look for the clauses on the
4311 parallel statement itself. */
4312 if (is_parallel_ctx (ctx
))
4316 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4319 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4320 OMP_CLAUSE_LASTPRIVATE
);
4321 if (clauses
== NULL
)
4329 tree label_true
, arm1
, arm2
;
4331 label
= create_artificial_label (UNKNOWN_LOCATION
);
4332 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
4333 arm1
= TREE_OPERAND (predicate
, 0);
4334 arm2
= TREE_OPERAND (predicate
, 1);
4335 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4336 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4337 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
4339 gimple_seq_add_stmt (stmt_list
, stmt
);
4340 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
4343 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4344 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4346 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
4348 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
4351 for (c
= clauses
; c
;)
4354 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4356 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4357 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4358 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
4360 var
= OMP_CLAUSE_DECL (c
);
4361 new_var
= lookup_decl (var
, ctx
);
4363 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
4365 tree val
= DECL_VALUE_EXPR (new_var
);
4366 if (TREE_CODE (val
) == ARRAY_REF
4367 && VAR_P (TREE_OPERAND (val
, 0))
4368 && lookup_attribute ("omp simd array",
4369 DECL_ATTRIBUTES (TREE_OPERAND (val
,
4372 if (lastlane
== NULL
)
4374 lastlane
= create_tmp_var (unsigned_type_node
);
4376 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
4378 TREE_OPERAND (val
, 1));
4379 gimple_call_set_lhs (g
, lastlane
);
4380 gimple_seq_add_stmt (stmt_list
, g
);
4382 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
4383 TREE_OPERAND (val
, 0), lastlane
,
4384 NULL_TREE
, NULL_TREE
);
4388 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4389 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
4391 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
4392 gimple_seq_add_seq (stmt_list
,
4393 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
4394 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
4396 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4397 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
4399 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
4400 gimple_seq_add_seq (stmt_list
,
4401 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
4402 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
4405 x
= build_outer_var_ref (var
, ctx
);
4406 if (is_reference (var
))
4407 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4408 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
4409 gimplify_and_add (x
, stmt_list
);
4411 c
= OMP_CLAUSE_CHAIN (c
);
4412 if (c
== NULL
&& !par_clauses
)
4414 /* If this was a workshare clause, see if it had been combined
4415 with its parallel. In that case, continue looking for the
4416 clauses also on the parallel statement itself. */
4417 if (is_parallel_ctx (ctx
))
4421 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4424 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4425 OMP_CLAUSE_LASTPRIVATE
);
4431 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
4435 oacc_lower_reduction_var_helper (gimple_seq
*stmt_seqp
, omp_context
*ctx
,
4436 tree tid
, tree var
, tree new_var
)
4438 /* The atomic add at the end of the sum creates unnecessary
4439 write contention on accelerators. To work around this,
4440 create an array to store the partial reductions. Later, in
4441 lower_omp_for (for openacc), the values of array will be
4444 tree t
= NULL_TREE
, array
, x
;
4445 tree type
= get_base_type (var
);
4448 /* Now insert the partial reductions into the array. */
4450 /* Find the reduction array. */
4452 tree ptype
= build_pointer_type (type
);
4454 t
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
), ctx
);
4455 t
= build_receiver_ref (t
, false, ctx
->outer
);
4457 array
= create_tmp_var (ptype
);
4458 gimplify_assign (array
, t
, stmt_seqp
);
4460 tree ptr
= create_tmp_var (TREE_TYPE (array
));
4462 /* Find the reduction array. */
4464 /* testing a unary conversion. */
4465 tree offset
= create_tmp_var (sizetype
);
4466 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
),
4468 t
= create_tmp_var (sizetype
);
4469 gimplify_assign (t
, unshare_expr (fold_build1 (NOP_EXPR
, sizetype
, tid
)),
4471 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, t
);
4472 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4474 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4475 of adding sizeof(var) to the array? */
4476 ptr
= create_tmp_var (ptype
);
4477 stmt
= gimple_build_assign (unshare_expr (ptr
), POINTER_PLUS_EXPR
, array
,
4479 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4481 /* Move the local sum to gfc$sum[i]. */
4482 x
= unshare_expr (build_simple_mem_ref (ptr
));
4483 stmt
= gimplify_assign (x
, new_var
, stmt_seqp
);
4486 /* Generate code to implement the REDUCTION clauses. */
4489 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
4491 gimple_seq sub_seq
= NULL
;
4493 tree x
, c
, tid
= NULL_TREE
;
4496 /* SIMD reductions are handled in lower_rec_input_clauses. */
4497 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4498 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4501 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4502 update in that case, otherwise use a lock. */
4503 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
4504 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
4506 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4508 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4518 /* Initialize thread info for OpenACC. */
4519 if (is_gimple_omp_oacc (ctx
->stmt
))
4521 /* Get the current thread id. */
4522 tree call
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
4523 tid
= create_tmp_var (TREE_TYPE (TREE_TYPE (call
)));
4524 gimple stmt
= gimple_build_call (call
, 0);
4525 gimple_call_set_lhs (stmt
, tid
);
4526 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4529 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4531 tree var
, ref
, new_var
;
4532 enum tree_code code
;
4533 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4535 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
4538 var
= OMP_CLAUSE_DECL (c
);
4539 new_var
= lookup_decl (var
, ctx
);
4540 if (is_reference (var
))
4541 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4542 ref
= build_outer_var_ref (var
, ctx
);
4543 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4545 /* reduction(-:var) sums up the partial results, so it acts
4546 identically to reduction(+:var). */
4547 if (code
== MINUS_EXPR
)
4550 if (is_gimple_omp_oacc (ctx
->stmt
))
4552 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
));
4554 oacc_lower_reduction_var_helper (stmt_seqp
, ctx
, tid
, var
, new_var
);
4556 else if (count
== 1)
4558 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
4560 addr
= save_expr (addr
);
4561 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
4562 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
4563 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
4564 gimplify_and_add (x
, stmt_seqp
);
4567 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4569 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4571 if (is_reference (var
)
4572 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4574 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
4575 SET_DECL_VALUE_EXPR (placeholder
, ref
);
4576 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4577 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
4578 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
4579 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4580 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
4584 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4585 ref
= build_outer_var_ref (var
, ctx
);
4586 gimplify_assign (ref
, x
, &sub_seq
);
4590 if (is_gimple_omp_oacc (ctx
->stmt
))
4593 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4595 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4597 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4599 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4601 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4605 /* Generate code to implement the COPYPRIVATE clauses. */
4608 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4613 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4615 tree var
, new_var
, ref
, x
;
4617 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4619 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4622 var
= OMP_CLAUSE_DECL (c
);
4623 by_ref
= use_pointer_for_field (var
, NULL
);
4625 ref
= build_sender_ref (var
, ctx
);
4626 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4629 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4630 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4632 gimplify_assign (ref
, x
, slist
);
4634 ref
= build_receiver_ref (var
, false, ctx
);
4637 ref
= fold_convert_loc (clause_loc
,
4638 build_pointer_type (TREE_TYPE (new_var
)),
4640 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4642 if (is_reference (var
))
4644 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4645 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4646 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4648 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4649 gimplify_and_add (x
, rlist
);
4654 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4655 and REDUCTION from the sender (aka parent) side. */
4658 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4663 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4665 tree val
, ref
, x
, var
;
4666 bool by_ref
, do_in
= false, do_out
= false;
4667 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4669 switch (OMP_CLAUSE_CODE (c
))
4671 case OMP_CLAUSE_PRIVATE
:
4672 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4675 case OMP_CLAUSE_FIRSTPRIVATE
:
4676 case OMP_CLAUSE_COPYIN
:
4677 case OMP_CLAUSE_LASTPRIVATE
:
4678 case OMP_CLAUSE_REDUCTION
:
4679 case OMP_CLAUSE__LOOPTEMP_
:
4685 val
= OMP_CLAUSE_DECL (c
);
4686 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4688 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4689 && is_global_var (var
))
4691 if (is_variable_sized (val
))
4693 by_ref
= use_pointer_for_field (val
, NULL
);
4695 switch (OMP_CLAUSE_CODE (c
))
4697 case OMP_CLAUSE_PRIVATE
:
4698 case OMP_CLAUSE_FIRSTPRIVATE
:
4699 case OMP_CLAUSE_COPYIN
:
4700 case OMP_CLAUSE__LOOPTEMP_
:
4704 case OMP_CLAUSE_LASTPRIVATE
:
4705 if (by_ref
|| is_reference (val
))
4707 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4714 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4719 case OMP_CLAUSE_REDUCTION
:
4721 do_out
= !(by_ref
|| is_reference (val
));
4730 ref
= build_sender_ref (val
, ctx
);
4731 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4732 gimplify_assign (ref
, x
, ilist
);
4733 if (is_task_ctx (ctx
))
4734 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4739 ref
= build_sender_ref (val
, ctx
);
4740 gimplify_assign (var
, ref
, olist
);
4745 /* Generate code to implement SHARED from the sender (aka parent)
4746 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4747 list things that got automatically shared. */
4750 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4752 tree var
, ovar
, nvar
, f
, x
, record_type
;
4754 if (ctx
->record_type
== NULL
)
4757 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4758 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4760 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4761 nvar
= maybe_lookup_decl (ovar
, ctx
);
4762 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4765 /* If CTX is a nested parallel directive. Find the immediately
4766 enclosing parallel or workshare construct that contains a
4767 mapping for OVAR. */
4768 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4770 if (use_pointer_for_field (ovar
, ctx
))
4772 x
= build_sender_ref (ovar
, ctx
);
4773 var
= build_fold_addr_expr (var
);
4774 gimplify_assign (x
, var
, ilist
);
4778 x
= build_sender_ref (ovar
, ctx
);
4779 gimplify_assign (x
, var
, ilist
);
4781 if (!TREE_READONLY (var
)
4782 /* We don't need to receive a new reference to a result
4783 or parm decl. In fact we may not store to it as we will
4784 invalidate any pending RSO and generate wrong gimple
4786 && !((TREE_CODE (var
) == RESULT_DECL
4787 || TREE_CODE (var
) == PARM_DECL
)
4788 && DECL_BY_REFERENCE (var
)))
4790 x
= build_sender_ref (ovar
, ctx
);
4791 gimplify_assign (var
, x
, olist
);
4798 /* A convenience function to build an empty GIMPLE_COND with just the
4802 gimple_build_cond_empty (tree cond
)
4804 enum tree_code pred_code
;
4807 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4808 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4812 /* Build the function calls to GOMP_parallel_start etc to actually
4813 generate the parallel operation. REGION is the parallel region
4814 being expanded. BB is the block where to insert the code. WS_ARGS
4815 will be set if this is a call to a combined parallel+workshare
4816 construct, it contains the list of additional arguments needed by
4817 the workshare construct. */
4820 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4821 gomp_parallel
*entry_stmt
,
4822 vec
<tree
, va_gc
> *ws_args
)
4824 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4825 gimple_stmt_iterator gsi
;
4827 enum built_in_function start_ix
;
4829 location_t clause_loc
;
4830 vec
<tree
, va_gc
> *args
;
4832 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4834 /* Determine what flavor of GOMP_parallel we will be
4836 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4837 if (is_combined_parallel (region
))
4839 switch (region
->inner
->type
)
4841 case GIMPLE_OMP_FOR
:
4842 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4843 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4844 + (region
->inner
->sched_kind
4845 == OMP_CLAUSE_SCHEDULE_RUNTIME
4846 ? 3 : region
->inner
->sched_kind
));
4847 start_ix
= (enum built_in_function
)start_ix2
;
4849 case GIMPLE_OMP_SECTIONS
:
4850 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4857 /* By default, the value of NUM_THREADS is zero (selected at run time)
4858 and there is no conditional. */
4860 val
= build_int_cst (unsigned_type_node
, 0);
4861 flags
= build_int_cst (unsigned_type_node
, 0);
4863 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4865 cond
= OMP_CLAUSE_IF_EXPR (c
);
4867 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4870 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4871 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4874 clause_loc
= gimple_location (entry_stmt
);
4876 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4878 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4880 /* Ensure 'val' is of the correct type. */
4881 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4883 /* If we found the clause 'if (cond)', build either
4884 (cond != 0) or (cond ? val : 1u). */
4887 cond
= gimple_boolify (cond
);
4889 if (integer_zerop (val
))
4890 val
= fold_build2_loc (clause_loc
,
4891 EQ_EXPR
, unsigned_type_node
, cond
,
4892 build_int_cst (TREE_TYPE (cond
), 0));
4895 basic_block cond_bb
, then_bb
, else_bb
;
4896 edge e
, e_then
, e_else
;
4897 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4899 tmp_var
= create_tmp_var (TREE_TYPE (val
));
4900 if (gimple_in_ssa_p (cfun
))
4902 tmp_then
= make_ssa_name (tmp_var
);
4903 tmp_else
= make_ssa_name (tmp_var
);
4904 tmp_join
= make_ssa_name (tmp_var
);
4913 e
= split_block_after_labels (bb
);
4918 then_bb
= create_empty_bb (cond_bb
);
4919 else_bb
= create_empty_bb (then_bb
);
4920 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4921 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4923 stmt
= gimple_build_cond_empty (cond
);
4924 gsi
= gsi_start_bb (cond_bb
);
4925 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4927 gsi
= gsi_start_bb (then_bb
);
4928 stmt
= gimple_build_assign (tmp_then
, val
);
4929 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4931 gsi
= gsi_start_bb (else_bb
);
4932 stmt
= gimple_build_assign
4933 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4934 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4936 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4937 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4938 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4939 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4940 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4941 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4943 if (gimple_in_ssa_p (cfun
))
4945 gphi
*phi
= create_phi_node (tmp_join
, bb
);
4946 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4947 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4953 gsi
= gsi_start_bb (bb
);
4954 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4955 false, GSI_CONTINUE_LINKING
);
4958 gsi
= gsi_last_bb (bb
);
4959 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4961 t1
= null_pointer_node
;
4963 t1
= build_fold_addr_expr (t
);
4964 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4966 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4967 args
->quick_push (t2
);
4968 args
->quick_push (t1
);
4969 args
->quick_push (val
);
4971 args
->splice (*ws_args
);
4972 args
->quick_push (flags
);
4974 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4975 builtin_decl_explicit (start_ix
), args
);
4977 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4978 false, GSI_CONTINUE_LINKING
);
4981 /* Insert a function call whose name is FUNC_NAME with the information from
4982 ENTRY_STMT into the basic_block BB. */
4985 expand_cilk_for_call (basic_block bb
, gomp_parallel
*entry_stmt
,
4986 vec
<tree
, va_gc
> *ws_args
)
4989 gimple_stmt_iterator gsi
;
4990 vec
<tree
, va_gc
> *args
;
4992 gcc_assert (vec_safe_length (ws_args
) == 2);
4993 tree func_name
= (*ws_args
)[0];
4994 tree grain
= (*ws_args
)[1];
4996 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4997 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
4998 gcc_assert (count
!= NULL_TREE
);
4999 count
= OMP_CLAUSE_OPERAND (count
, 0);
5001 gsi
= gsi_last_bb (bb
);
5002 t
= gimple_omp_parallel_data_arg (entry_stmt
);
5004 t1
= null_pointer_node
;
5006 t1
= build_fold_addr_expr (t
);
5007 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
5009 vec_alloc (args
, 4);
5010 args
->quick_push (t2
);
5011 args
->quick_push (t1
);
5012 args
->quick_push (count
);
5013 args
->quick_push (grain
);
5014 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
5016 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
5017 GSI_CONTINUE_LINKING
);
5020 /* Build the function call to GOMP_task to actually
5021 generate the task operation. BB is the block where to insert the code. */
5024 expand_task_call (basic_block bb
, gomp_task
*entry_stmt
)
5026 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
5027 gimple_stmt_iterator gsi
;
5028 location_t loc
= gimple_location (entry_stmt
);
5030 clauses
= gimple_omp_task_clauses (entry_stmt
);
5032 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
5034 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
5036 cond
= boolean_true_node
;
5038 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
5039 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
5040 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
5041 flags
= build_int_cst (unsigned_type_node
,
5042 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
5044 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
5047 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
5048 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
5049 build_int_cst (unsigned_type_node
, 2),
5050 build_int_cst (unsigned_type_node
, 0));
5051 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
5054 depend
= OMP_CLAUSE_DECL (depend
);
5056 depend
= build_int_cst (ptr_type_node
, 0);
5058 gsi
= gsi_last_bb (bb
);
5059 t
= gimple_omp_task_data_arg (entry_stmt
);
5061 t2
= null_pointer_node
;
5063 t2
= build_fold_addr_expr_loc (loc
, t
);
5064 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
5065 t
= gimple_omp_task_copy_fn (entry_stmt
);
5067 t3
= null_pointer_node
;
5069 t3
= build_fold_addr_expr_loc (loc
, t
);
5071 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
5073 gimple_omp_task_arg_size (entry_stmt
),
5074 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
5077 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5078 false, GSI_CONTINUE_LINKING
);
5082 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5083 catch handler and return it. This prevents programs from violating the
5084 structured block semantics with throws. */
5087 maybe_catch_exception (gimple_seq body
)
5092 if (!flag_exceptions
)
5095 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
5096 decl
= lang_hooks
.eh_protect_cleanup_actions ();
5098 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
5100 g
= gimple_build_eh_must_not_throw (decl
);
5101 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
5104 return gimple_seq_alloc_with_stmt (g
);
5107 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5110 vec2chain (vec
<tree
, va_gc
> *v
)
5112 tree chain
= NULL_TREE
, t
;
5115 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
5117 DECL_CHAIN (t
) = chain
;
5125 /* Remove barriers in REGION->EXIT's block. Note that this is only
5126 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5127 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5128 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5132 remove_exit_barrier (struct omp_region
*region
)
5134 gimple_stmt_iterator gsi
;
5135 basic_block exit_bb
;
5139 int any_addressable_vars
= -1;
5141 exit_bb
= region
->exit
;
5143 /* If the parallel region doesn't return, we don't have REGION->EXIT
5148 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5149 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5150 statements that can appear in between are extremely limited -- no
5151 memory operations at all. Here, we allow nothing at all, so the
5152 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5153 gsi
= gsi_last_bb (exit_bb
);
5154 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5156 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
5159 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
5161 gsi
= gsi_last_bb (e
->src
);
5162 if (gsi_end_p (gsi
))
5164 stmt
= gsi_stmt (gsi
);
5165 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
5166 && !gimple_omp_return_nowait_p (stmt
))
5168 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5169 in many cases. If there could be tasks queued, the barrier
5170 might be needed to let the tasks run before some local
5171 variable of the parallel that the task uses as shared
5172 runs out of scope. The task can be spawned either
5173 from within current function (this would be easy to check)
5174 or from some function it calls and gets passed an address
5175 of such a variable. */
5176 if (any_addressable_vars
< 0)
5178 gomp_parallel
*parallel_stmt
5179 = as_a
<gomp_parallel
*> (last_stmt (region
->entry
));
5180 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
5181 tree local_decls
, block
, decl
;
5184 any_addressable_vars
= 0;
5185 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
5186 if (TREE_ADDRESSABLE (decl
))
5188 any_addressable_vars
= 1;
5191 for (block
= gimple_block (stmt
);
5192 !any_addressable_vars
5194 && TREE_CODE (block
) == BLOCK
;
5195 block
= BLOCK_SUPERCONTEXT (block
))
5197 for (local_decls
= BLOCK_VARS (block
);
5199 local_decls
= DECL_CHAIN (local_decls
))
5200 if (TREE_ADDRESSABLE (local_decls
))
5202 any_addressable_vars
= 1;
5205 if (block
== gimple_block (parallel_stmt
))
5209 if (!any_addressable_vars
)
5210 gimple_omp_return_set_nowait (stmt
);
5216 remove_exit_barriers (struct omp_region
*region
)
5218 if (region
->type
== GIMPLE_OMP_PARALLEL
)
5219 remove_exit_barrier (region
);
5223 region
= region
->inner
;
5224 remove_exit_barriers (region
);
5225 while (region
->next
)
5227 region
= region
->next
;
5228 remove_exit_barriers (region
);
5233 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5234 calls. These can't be declared as const functions, but
5235 within one parallel body they are constant, so they can be
5236 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5237 which are declared const. Similarly for task body, except
5238 that in untied task omp_get_thread_num () can change at any task
5239 scheduling point. */
5242 optimize_omp_library_calls (gimple entry_stmt
)
5245 gimple_stmt_iterator gsi
;
5246 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5247 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
5248 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5249 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
5250 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
5251 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
5252 OMP_CLAUSE_UNTIED
) != NULL
);
5254 FOR_EACH_BB_FN (bb
, cfun
)
5255 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5257 gimple call
= gsi_stmt (gsi
);
5260 if (is_gimple_call (call
)
5261 && (decl
= gimple_call_fndecl (call
))
5262 && DECL_EXTERNAL (decl
)
5263 && TREE_PUBLIC (decl
)
5264 && DECL_INITIAL (decl
) == NULL
)
5268 if (DECL_NAME (decl
) == thr_num_id
)
5270 /* In #pragma omp task untied omp_get_thread_num () can change
5271 during the execution of the task region. */
5274 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5276 else if (DECL_NAME (decl
) == num_thr_id
)
5277 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5281 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
5282 || gimple_call_num_args (call
) != 0)
5285 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
5288 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
5289 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
5290 TREE_TYPE (TREE_TYPE (built_in
))))
5293 gimple_call_set_fndecl (call
, built_in
);
5298 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5302 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
5306 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5307 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
5310 if (TREE_CODE (t
) == ADDR_EXPR
)
5311 recompute_tree_invariant_for_addr_expr (t
);
5313 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
5317 /* Prepend TO = FROM assignment before *GSI_P. */
5320 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
5322 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
5323 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
5324 true, GSI_SAME_STMT
);
5325 gimple stmt
= gimple_build_assign (to
, from
);
5326 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
5327 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
5328 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
5330 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
5331 gimple_regimplify_operands (stmt
, &gsi
);
5335 /* Expand the OpenMP parallel or task directive starting at REGION. */
5338 expand_omp_taskreg (struct omp_region
*region
)
5340 basic_block entry_bb
, exit_bb
, new_bb
;
5341 struct function
*child_cfun
;
5342 tree child_fn
, block
, t
;
5343 gimple_stmt_iterator gsi
;
5344 gimple entry_stmt
, stmt
;
5346 vec
<tree
, va_gc
> *ws_args
;
5348 entry_stmt
= last_stmt (region
->entry
);
5349 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
5350 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
5352 entry_bb
= region
->entry
;
5353 if (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
)
5354 exit_bb
= region
->cont
;
5356 exit_bb
= region
->exit
;
5360 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
5361 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
5362 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
5365 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5366 and the inner statement contains the name of the built-in function
5368 ws_args
= region
->inner
->ws_args
;
5369 else if (is_combined_parallel (region
))
5370 ws_args
= region
->ws_args
;
5374 if (child_cfun
->cfg
)
5376 /* Due to inlining, it may happen that we have already outlined
5377 the region, in which case all we need to do is make the
5378 sub-graph unreachable and emit the parallel call. */
5379 edge entry_succ_e
, exit_succ_e
;
5381 entry_succ_e
= single_succ_edge (entry_bb
);
5383 gsi
= gsi_last_bb (entry_bb
);
5384 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
5385 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
5386 gsi_remove (&gsi
, true);
5391 exit_succ_e
= single_succ_edge (exit_bb
);
5392 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
5394 remove_edge_and_dominated_blocks (entry_succ_e
);
5398 unsigned srcidx
, dstidx
, num
;
5400 /* If the parallel region needs data sent from the parent
5401 function, then the very first statement (except possible
5402 tree profile counter updates) of the parallel body
5403 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5404 &.OMP_DATA_O is passed as an argument to the child function,
5405 we need to replace it with the argument as seen by the child
5408 In most cases, this will end up being the identity assignment
5409 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5410 a function call that has been inlined, the original PARM_DECL
5411 .OMP_DATA_I may have been converted into a different local
5412 variable. In which case, we need to keep the assignment. */
5413 if (gimple_omp_taskreg_data_arg (entry_stmt
))
5415 basic_block entry_succ_bb
5416 = single_succ_p (entry_bb
) ? single_succ (entry_bb
)
5417 : FALLTHRU_EDGE (entry_bb
)->dest
;
5419 gimple parcopy_stmt
= NULL
;
5421 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
5425 gcc_assert (!gsi_end_p (gsi
));
5426 stmt
= gsi_stmt (gsi
);
5427 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
5430 if (gimple_num_ops (stmt
) == 2)
5432 tree arg
= gimple_assign_rhs1 (stmt
);
5434 /* We're ignore the subcode because we're
5435 effectively doing a STRIP_NOPS. */
5437 if (TREE_CODE (arg
) == ADDR_EXPR
5438 && TREE_OPERAND (arg
, 0)
5439 == gimple_omp_taskreg_data_arg (entry_stmt
))
5441 parcopy_stmt
= stmt
;
5447 gcc_assert (parcopy_stmt
!= NULL
);
5448 arg
= DECL_ARGUMENTS (child_fn
);
5450 if (!gimple_in_ssa_p (cfun
))
5452 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
5453 gsi_remove (&gsi
, true);
5456 /* ?? Is setting the subcode really necessary ?? */
5457 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
5458 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
5463 /* If we are in ssa form, we must load the value from the default
5464 definition of the argument. That should not be defined now,
5465 since the argument is not used uninitialized. */
5466 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
5467 narg
= make_ssa_name (arg
, gimple_build_nop ());
5468 set_ssa_default_def (cfun
, arg
, narg
);
5469 /* ?? Is setting the subcode really necessary ?? */
5470 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
5471 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
5472 update_stmt (parcopy_stmt
);
5476 /* Declare local variables needed in CHILD_CFUN. */
5477 block
= DECL_INITIAL (child_fn
);
5478 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
5479 /* The gimplifier could record temporaries in parallel/task block
5480 rather than in containing function's local_decls chain,
5481 which would mean cgraph missed finalizing them. Do it now. */
5482 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
5483 if (TREE_CODE (t
) == VAR_DECL
5485 && !DECL_EXTERNAL (t
))
5486 varpool_node::finalize_decl (t
);
5487 DECL_SAVED_TREE (child_fn
) = NULL
;
5488 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5489 gimple_set_body (child_fn
, NULL
);
5490 TREE_USED (block
) = 1;
5492 /* Reset DECL_CONTEXT on function arguments. */
5493 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
5494 DECL_CONTEXT (t
) = child_fn
;
5496 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5497 so that it can be moved to the child function. */
5498 gsi
= gsi_last_bb (entry_bb
);
5499 stmt
= gsi_stmt (gsi
);
5500 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
5501 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
5502 e
= split_block (entry_bb
, stmt
);
5503 gsi_remove (&gsi
, true);
5506 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5507 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5510 e2
= make_edge (e
->src
, BRANCH_EDGE (entry_bb
)->dest
, EDGE_ABNORMAL
);
5511 gcc_assert (e2
->dest
== region
->exit
);
5512 remove_edge (BRANCH_EDGE (entry_bb
));
5513 set_immediate_dominator (CDI_DOMINATORS
, e2
->dest
, e
->src
);
5514 gsi
= gsi_last_bb (region
->exit
);
5515 gcc_assert (!gsi_end_p (gsi
)
5516 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5517 gsi_remove (&gsi
, true);
5520 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5523 gsi
= gsi_last_bb (exit_bb
);
5524 gcc_assert (!gsi_end_p (gsi
)
5525 && (gimple_code (gsi_stmt (gsi
))
5526 == (e2
? GIMPLE_OMP_CONTINUE
: GIMPLE_OMP_RETURN
)));
5527 stmt
= gimple_build_return (NULL
);
5528 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5529 gsi_remove (&gsi
, true);
5532 /* Move the parallel region into CHILD_CFUN. */
5534 if (gimple_in_ssa_p (cfun
))
5536 init_tree_ssa (child_cfun
);
5537 init_ssa_operands (child_cfun
);
5538 child_cfun
->gimple_df
->in_ssa_p
= true;
5542 block
= gimple_block (entry_stmt
);
5544 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
5546 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
5549 basic_block dest_bb
= e2
->dest
;
5551 make_edge (new_bb
, dest_bb
, EDGE_FALLTHRU
);
5553 set_immediate_dominator (CDI_DOMINATORS
, dest_bb
, new_bb
);
5555 /* When the OMP expansion process cannot guarantee an up-to-date
5556 loop tree arrange for the child function to fixup loops. */
5557 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5558 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
5560 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5561 num
= vec_safe_length (child_cfun
->local_decls
);
5562 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
5564 t
= (*child_cfun
->local_decls
)[srcidx
];
5565 if (DECL_CONTEXT (t
) == cfun
->decl
)
5567 if (srcidx
!= dstidx
)
5568 (*child_cfun
->local_decls
)[dstidx
] = t
;
5572 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
5574 /* Inform the callgraph about the new function. */
5575 child_cfun
->curr_properties
= cfun
->curr_properties
;
5576 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
5577 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
5578 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
5579 node
->parallelized_function
= 1;
5580 cgraph_node::add_new_function (child_fn
, true);
5582 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5583 fixed in a following pass. */
5584 push_cfun (child_cfun
);
5586 optimize_omp_library_calls (entry_stmt
);
5587 cgraph_edge::rebuild_edges ();
5589 /* Some EH regions might become dead, see PR34608. If
5590 pass_cleanup_cfg isn't the first pass to happen with the
5591 new child, these dead EH edges might cause problems.
5592 Clean them up now. */
5593 if (flag_exceptions
)
5596 bool changed
= false;
5598 FOR_EACH_BB_FN (bb
, cfun
)
5599 changed
|= gimple_purge_dead_eh_edges (bb
);
5601 cleanup_tree_cfg ();
5603 if (gimple_in_ssa_p (cfun
))
5604 update_ssa (TODO_update_ssa
);
5608 /* Emit a library call to launch the children threads. */
5610 expand_cilk_for_call (new_bb
,
5611 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5612 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5613 expand_parallel_call (region
, new_bb
,
5614 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5616 expand_task_call (new_bb
, as_a
<gomp_task
*> (entry_stmt
));
5617 if (gimple_in_ssa_p (cfun
))
5618 update_ssa (TODO_update_ssa_only_virtuals
);
5622 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5623 of the combined collapse > 1 loop constructs, generate code like:
5624 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5629 count3 = (adj + N32 - N31) / STEP3;
5630 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5635 count2 = (adj + N22 - N21) / STEP2;
5636 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5641 count1 = (adj + N12 - N11) / STEP1;
5642 count = count1 * count2 * count3;
5643 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5645 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5646 of the combined loop constructs, just initialize COUNTS array
5647 from the _looptemp_ clauses. */
5649 /* NOTE: It *could* be better to moosh all of the BBs together,
5650 creating one larger BB with all the computation and the unexpected
5651 jump at the end. I.e.
5653 bool zero3, zero2, zero1, zero;
5656 count3 = (N32 - N31) /[cl] STEP3;
5658 count2 = (N22 - N21) /[cl] STEP2;
5660 count1 = (N12 - N11) /[cl] STEP1;
5661 zero = zero3 || zero2 || zero1;
5662 count = count1 * count2 * count3;
5663 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5665 After all, we expect the zero=false, and thus we expect to have to
5666 evaluate all of the comparison expressions, so short-circuiting
5667 oughtn't be a win. Since the condition isn't protecting a
5668 denominator, we're not concerned about divide-by-zero, so we can
5669 fully evaluate count even if a numerator turned out to be wrong.
5671 It seems like putting this all together would create much better
5672 scheduling opportunities, and less pressure on the chip's branch
5676 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5677 basic_block
&entry_bb
, tree
*counts
,
5678 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5679 basic_block
&l2_dom_bb
)
5681 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5685 /* Collapsed loops need work for expansion into SSA form. */
5686 gcc_assert (!gimple_in_ssa_p (cfun
));
5688 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5689 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5691 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5692 isn't supposed to be handled, as the inner loop doesn't
5694 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5695 OMP_CLAUSE__LOOPTEMP_
);
5696 gcc_assert (innerc
);
5697 for (i
= 0; i
< fd
->collapse
; i
++)
5699 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5700 OMP_CLAUSE__LOOPTEMP_
);
5701 gcc_assert (innerc
);
5703 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5705 counts
[0] = NULL_TREE
;
5710 for (i
= 0; i
< fd
->collapse
; i
++)
5712 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5714 if (SSA_VAR_P (fd
->loop
.n2
)
5715 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5716 fold_convert (itype
, fd
->loops
[i
].n1
),
5717 fold_convert (itype
, fd
->loops
[i
].n2
)))
5718 == NULL_TREE
|| !integer_onep (t
)))
5722 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5723 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5724 true, GSI_SAME_STMT
);
5725 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5726 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5727 true, GSI_SAME_STMT
);
5728 cond_stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5729 NULL_TREE
, NULL_TREE
);
5730 gsi_insert_before (gsi
, cond_stmt
, GSI_SAME_STMT
);
5731 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
5732 expand_omp_regimplify_p
, NULL
, NULL
)
5733 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
5734 expand_omp_regimplify_p
, NULL
, NULL
))
5736 *gsi
= gsi_for_stmt (cond_stmt
);
5737 gimple_regimplify_operands (cond_stmt
, gsi
);
5739 e
= split_block (entry_bb
, cond_stmt
);
5740 if (zero_iter_bb
== NULL
)
5742 gassign
*assign_stmt
;
5743 first_zero_iter
= i
;
5744 zero_iter_bb
= create_empty_bb (entry_bb
);
5745 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5746 *gsi
= gsi_after_labels (zero_iter_bb
);
5747 assign_stmt
= gimple_build_assign (fd
->loop
.n2
,
5748 build_zero_cst (type
));
5749 gsi_insert_before (gsi
, assign_stmt
, GSI_SAME_STMT
);
5750 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5753 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5754 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5755 e
->flags
= EDGE_TRUE_VALUE
;
5756 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5757 if (l2_dom_bb
== NULL
)
5758 l2_dom_bb
= entry_bb
;
5760 *gsi
= gsi_last_bb (entry_bb
);
5763 if (POINTER_TYPE_P (itype
))
5764 itype
= signed_type_for (itype
);
5765 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5767 t
= fold_build2 (PLUS_EXPR
, itype
,
5768 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5769 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5770 fold_convert (itype
, fd
->loops
[i
].n2
));
5771 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5772 fold_convert (itype
, fd
->loops
[i
].n1
));
5773 /* ?? We could probably use CEIL_DIV_EXPR instead of
5774 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5775 generate the same code in the end because generically we
5776 don't know that the values involved must be negative for
5778 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5779 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5780 fold_build1 (NEGATE_EXPR
, itype
, t
),
5781 fold_build1 (NEGATE_EXPR
, itype
,
5782 fold_convert (itype
,
5783 fd
->loops
[i
].step
)));
5785 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5786 fold_convert (itype
, fd
->loops
[i
].step
));
5787 t
= fold_convert (type
, t
);
5788 if (TREE_CODE (t
) == INTEGER_CST
)
5792 counts
[i
] = create_tmp_reg (type
, ".count");
5793 expand_omp_build_assign (gsi
, counts
[i
], t
);
5795 if (SSA_VAR_P (fd
->loop
.n2
))
5800 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5801 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5807 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5809 V3 = N31 + (T % count3) * STEP3;
5811 V2 = N21 + (T % count2) * STEP2;
5813 V1 = N11 + T * STEP1;
5814 if this loop doesn't have an inner loop construct combined with it.
5815 If it does have an inner loop construct combined with it and the
5816 iteration count isn't known constant, store values from counts array
5817 into its _looptemp_ temporaries instead. */
5820 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5821 tree
*counts
, gimple inner_stmt
, tree startvar
)
5824 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5826 /* If fd->loop.n2 is constant, then no propagation of the counts
5827 is needed, they are constant. */
5828 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5831 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5832 ? gimple_omp_parallel_clauses (inner_stmt
)
5833 : gimple_omp_for_clauses (inner_stmt
);
5834 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5835 isn't supposed to be handled, as the inner loop doesn't
5837 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5838 gcc_assert (innerc
);
5839 for (i
= 0; i
< fd
->collapse
; i
++)
5841 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5842 OMP_CLAUSE__LOOPTEMP_
);
5843 gcc_assert (innerc
);
5846 tree tem
= OMP_CLAUSE_DECL (innerc
);
5847 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5848 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5849 false, GSI_CONTINUE_LINKING
);
5850 gassign
*stmt
= gimple_build_assign (tem
, t
);
5851 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5857 tree type
= TREE_TYPE (fd
->loop
.v
);
5858 tree tem
= create_tmp_reg (type
, ".tem");
5859 gassign
*stmt
= gimple_build_assign (tem
, startvar
);
5860 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5862 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5864 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5866 if (POINTER_TYPE_P (vtype
))
5867 itype
= signed_type_for (vtype
);
5869 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5872 t
= fold_convert (itype
, t
);
5873 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5874 fold_convert (itype
, fd
->loops
[i
].step
));
5875 if (POINTER_TYPE_P (vtype
))
5876 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5878 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5879 t
= force_gimple_operand_gsi (gsi
, t
,
5880 DECL_P (fd
->loops
[i
].v
)
5881 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5883 GSI_CONTINUE_LINKING
);
5884 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5885 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5888 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5889 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5890 false, GSI_CONTINUE_LINKING
);
5891 stmt
= gimple_build_assign (tem
, t
);
5892 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5898 /* Helper function for expand_omp_for_*. Generate code like:
5901 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5905 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5912 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5913 basic_block body_bb
)
5915 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5917 gimple_stmt_iterator gsi
;
5923 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5925 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5927 bb
= create_empty_bb (last_bb
);
5928 add_bb_to_loop (bb
, last_bb
->loop_father
);
5929 gsi
= gsi_start_bb (bb
);
5931 if (i
< fd
->collapse
- 1)
5933 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5934 e
->probability
= REG_BR_PROB_BASE
/ 8;
5936 t
= fd
->loops
[i
+ 1].n1
;
5937 t
= force_gimple_operand_gsi (&gsi
, t
,
5938 DECL_P (fd
->loops
[i
+ 1].v
)
5939 && TREE_ADDRESSABLE (fd
->loops
[i
5942 GSI_CONTINUE_LINKING
);
5943 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5944 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5949 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5951 if (POINTER_TYPE_P (vtype
))
5952 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5954 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5955 t
= force_gimple_operand_gsi (&gsi
, t
,
5956 DECL_P (fd
->loops
[i
].v
)
5957 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5958 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5959 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5960 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5964 t
= fd
->loops
[i
].n2
;
5965 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5966 false, GSI_CONTINUE_LINKING
);
5967 tree v
= fd
->loops
[i
].v
;
5968 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5969 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5970 false, GSI_CONTINUE_LINKING
);
5971 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5972 stmt
= gimple_build_cond_empty (t
);
5973 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5974 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5975 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5978 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5986 /* A subroutine of expand_omp_for. Generate code for a parallel
5987 loop with any schedule. Given parameters:
5989 for (V = N1; V cond N2; V += STEP) BODY;
5991 where COND is "<" or ">", we generate pseudocode
5993 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5994 if (more) goto L0; else goto L3;
6001 if (V cond iend) goto L1; else goto L2;
6003 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6006 If this is a combined omp parallel loop, instead of the call to
6007 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6008 If this is gimple_omp_for_combined_p loop, then instead of assigning
6009 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6010 inner GIMPLE_OMP_FOR and V += STEP; and
6011 if (V cond iend) goto L1; else goto L2; are removed.
6013 For collapsed loops, given parameters:
6015 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6016 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6017 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6020 we generate pseudocode
6022 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6027 count3 = (adj + N32 - N31) / STEP3;
6028 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6033 count2 = (adj + N22 - N21) / STEP2;
6034 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6039 count1 = (adj + N12 - N11) / STEP1;
6040 count = count1 * count2 * count3;
6045 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6046 if (more) goto L0; else goto L3;
6050 V3 = N31 + (T % count3) * STEP3;
6052 V2 = N21 + (T % count2) * STEP2;
6054 V1 = N11 + T * STEP1;
6059 if (V < iend) goto L10; else goto L2;
6062 if (V3 cond3 N32) goto L1; else goto L11;
6066 if (V2 cond2 N22) goto L1; else goto L12;
6072 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6078 expand_omp_for_generic (struct omp_region
*region
,
6079 struct omp_for_data
*fd
,
6080 enum built_in_function start_fn
,
6081 enum built_in_function next_fn
,
6084 tree type
, istart0
, iend0
, iend
;
6085 tree t
, vmain
, vback
, bias
= NULL_TREE
;
6086 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
6087 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
6088 gimple_stmt_iterator gsi
;
6089 gassign
*assign_stmt
;
6090 bool in_combined_parallel
= is_combined_parallel (region
);
6091 bool broken_loop
= region
->cont
== NULL
;
6093 tree
*counts
= NULL
;
6096 gcc_assert (!broken_loop
|| !in_combined_parallel
);
6097 gcc_assert (fd
->iter_type
== long_integer_type_node
6098 || !in_combined_parallel
);
6100 type
= TREE_TYPE (fd
->loop
.v
);
6101 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
6102 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
6103 TREE_ADDRESSABLE (istart0
) = 1;
6104 TREE_ADDRESSABLE (iend0
) = 1;
6106 /* See if we need to bias by LLONG_MIN. */
6107 if (fd
->iter_type
== long_long_unsigned_type_node
6108 && TREE_CODE (type
) == INTEGER_TYPE
6109 && !TYPE_UNSIGNED (type
))
6113 if (fd
->loop
.cond_code
== LT_EXPR
)
6116 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6120 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6123 if (TREE_CODE (n1
) != INTEGER_CST
6124 || TREE_CODE (n2
) != INTEGER_CST
6125 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
6126 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
6129 entry_bb
= region
->entry
;
6130 cont_bb
= region
->cont
;
6132 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6133 gcc_assert (broken_loop
6134 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6135 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6136 l1_bb
= single_succ (l0_bb
);
6139 l2_bb
= create_empty_bb (cont_bb
);
6140 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
6141 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6145 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6146 exit_bb
= region
->exit
;
6148 gsi
= gsi_last_bb (entry_bb
);
6150 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6151 if (fd
->collapse
> 1)
6153 int first_zero_iter
= -1;
6154 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
6156 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6157 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6158 zero_iter_bb
, first_zero_iter
,
6163 /* Some counts[i] vars might be uninitialized if
6164 some loop has zero iterations. But the body shouldn't
6165 be executed in that case, so just avoid uninit warnings. */
6166 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
6167 if (SSA_VAR_P (counts
[i
]))
6168 TREE_NO_WARNING (counts
[i
]) = 1;
6170 e
= split_block (entry_bb
, gsi_stmt (gsi
));
6172 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
6173 gsi
= gsi_last_bb (entry_bb
);
6174 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
6175 get_immediate_dominator (CDI_DOMINATORS
,
6179 if (in_combined_parallel
)
6181 /* In a combined parallel loop, emit a call to
6182 GOMP_loop_foo_next. */
6183 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6184 build_fold_addr_expr (istart0
),
6185 build_fold_addr_expr (iend0
));
6189 tree t0
, t1
, t2
, t3
, t4
;
6190 /* If this is not a combined parallel loop, emit a call to
6191 GOMP_loop_foo_start in ENTRY_BB. */
6192 t4
= build_fold_addr_expr (iend0
);
6193 t3
= build_fold_addr_expr (istart0
);
6194 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
6197 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6199 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6200 OMP_CLAUSE__LOOPTEMP_
);
6201 gcc_assert (innerc
);
6202 t0
= OMP_CLAUSE_DECL (innerc
);
6203 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6204 OMP_CLAUSE__LOOPTEMP_
);
6205 gcc_assert (innerc
);
6206 t1
= OMP_CLAUSE_DECL (innerc
);
6208 if (POINTER_TYPE_P (TREE_TYPE (t0
))
6209 && TYPE_PRECISION (TREE_TYPE (t0
))
6210 != TYPE_PRECISION (fd
->iter_type
))
6212 /* Avoid casting pointers to integer of a different size. */
6213 tree itype
= signed_type_for (type
);
6214 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
6215 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
6219 t1
= fold_convert (fd
->iter_type
, t1
);
6220 t0
= fold_convert (fd
->iter_type
, t0
);
6224 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
6225 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
6227 if (fd
->iter_type
== long_integer_type_node
)
6231 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6232 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6233 6, t0
, t1
, t2
, t
, t3
, t4
);
6236 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6237 5, t0
, t1
, t2
, t3
, t4
);
6245 /* The GOMP_loop_ull_*start functions have additional boolean
6246 argument, true for < loops and false for > loops.
6247 In Fortran, the C bool type can be different from
6248 boolean_type_node. */
6249 bfn_decl
= builtin_decl_explicit (start_fn
);
6250 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
6251 t5
= build_int_cst (c_bool_type
,
6252 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
6255 tree bfn_decl
= builtin_decl_explicit (start_fn
);
6256 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6257 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
6260 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6261 6, t5
, t0
, t1
, t2
, t3
, t4
);
6264 if (TREE_TYPE (t
) != boolean_type_node
)
6265 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6266 t
, build_int_cst (TREE_TYPE (t
), 0));
6267 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6268 true, GSI_SAME_STMT
);
6269 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6271 /* Remove the GIMPLE_OMP_FOR statement. */
6272 gsi_remove (&gsi
, true);
6274 /* Iteration setup for sequential loop goes in L0_BB. */
6275 tree startvar
= fd
->loop
.v
;
6276 tree endvar
= NULL_TREE
;
6278 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6280 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
6281 && gimple_omp_for_kind (inner_stmt
)
6282 == GF_OMP_FOR_KIND_SIMD
);
6283 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
6284 OMP_CLAUSE__LOOPTEMP_
);
6285 gcc_assert (innerc
);
6286 startvar
= OMP_CLAUSE_DECL (innerc
);
6287 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6288 OMP_CLAUSE__LOOPTEMP_
);
6289 gcc_assert (innerc
);
6290 endvar
= OMP_CLAUSE_DECL (innerc
);
6293 gsi
= gsi_start_bb (l0_bb
);
6296 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6297 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6298 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6299 t
= fold_convert (TREE_TYPE (startvar
), t
);
6300 t
= force_gimple_operand_gsi (&gsi
, t
,
6302 && TREE_ADDRESSABLE (startvar
),
6303 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6304 assign_stmt
= gimple_build_assign (startvar
, t
);
6305 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6309 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6310 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6311 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6312 t
= fold_convert (TREE_TYPE (startvar
), t
);
6313 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6314 false, GSI_CONTINUE_LINKING
);
6317 assign_stmt
= gimple_build_assign (endvar
, iend
);
6318 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6319 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
6320 assign_stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
6322 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, iend
);
6323 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6325 if (fd
->collapse
> 1)
6326 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6330 /* Code to control the increment and predicate for the sequential
6331 loop goes in the CONT_BB. */
6332 gsi
= gsi_last_bb (cont_bb
);
6333 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6334 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6335 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6336 vback
= gimple_omp_continue_control_def (cont_stmt
);
6338 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6340 if (POINTER_TYPE_P (type
))
6341 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
6343 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
6344 t
= force_gimple_operand_gsi (&gsi
, t
,
6346 && TREE_ADDRESSABLE (vback
),
6347 NULL_TREE
, true, GSI_SAME_STMT
);
6348 assign_stmt
= gimple_build_assign (vback
, t
);
6349 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6351 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6352 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
6354 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6355 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6358 /* Remove GIMPLE_OMP_CONTINUE. */
6359 gsi_remove (&gsi
, true);
6361 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6362 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
6364 /* Emit code to get the next parallel iteration in L2_BB. */
6365 gsi
= gsi_start_bb (l2_bb
);
6367 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6368 build_fold_addr_expr (istart0
),
6369 build_fold_addr_expr (iend0
));
6370 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6371 false, GSI_CONTINUE_LINKING
);
6372 if (TREE_TYPE (t
) != boolean_type_node
)
6373 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6374 t
, build_int_cst (TREE_TYPE (t
), 0));
6375 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6376 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
6379 /* Add the loop cleanup function. */
6380 gsi
= gsi_last_bb (exit_bb
);
6381 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6382 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
6383 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6384 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
6386 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
6387 gcall
*call_stmt
= gimple_build_call (t
, 0);
6388 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6389 gimple_call_set_lhs (call_stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
6390 gsi_insert_after (&gsi
, call_stmt
, GSI_SAME_STMT
);
6391 gsi_remove (&gsi
, true);
6393 /* Connect the new blocks. */
6394 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
6395 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
6401 e
= find_edge (cont_bb
, l3_bb
);
6402 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
6404 phis
= phi_nodes (l3_bb
);
6405 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
6407 gimple phi
= gsi_stmt (gsi
);
6408 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
6409 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
6413 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
6414 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
6415 e
= find_edge (cont_bb
, l1_bb
);
6416 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6421 else if (fd
->collapse
> 1)
6424 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6427 e
->flags
= EDGE_TRUE_VALUE
;
6430 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6431 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
6435 e
= find_edge (cont_bb
, l2_bb
);
6436 e
->flags
= EDGE_FALLTHRU
;
6438 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6440 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
6441 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
6442 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
6443 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
6444 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
6445 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
6446 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
6447 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
6449 struct loop
*outer_loop
= alloc_loop ();
6450 outer_loop
->header
= l0_bb
;
6451 outer_loop
->latch
= l2_bb
;
6452 add_loop (outer_loop
, l0_bb
->loop_father
);
6454 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6456 struct loop
*loop
= alloc_loop ();
6457 loop
->header
= l1_bb
;
6458 /* The loop may have multiple latches. */
6459 add_loop (loop
, outer_loop
);
6465 /* A subroutine of expand_omp_for. Generate code for a parallel
6466 loop with static schedule and no specified chunk size. Given
6469 for (V = N1; V cond N2; V += STEP) BODY;
6471 where COND is "<" or ">", we generate pseudocode
6473 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6478 if ((__typeof (V)) -1 > 0 && cond is >)
6479 n = -(adj + N2 - N1) / -STEP;
6481 n = (adj + N2 - N1) / STEP;
6484 if (threadid < tt) goto L3; else goto L4;
6489 s0 = q * threadid + tt;
6492 if (s0 >= e0) goto L2; else goto L0;
6498 if (V cond e) goto L1;
6503 expand_omp_for_static_nochunk (struct omp_region
*region
,
6504 struct omp_for_data
*fd
,
6507 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
6508 tree type
, itype
, vmain
, vback
;
6509 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
6510 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
6512 gimple_stmt_iterator gsi
;
6514 bool broken_loop
= region
->cont
== NULL
;
6515 tree
*counts
= NULL
;
6518 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6519 != GF_OMP_FOR_KIND_OACC_LOOP
)
6522 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6523 if (POINTER_TYPE_P (type
))
6524 itype
= signed_type_for (type
);
6526 entry_bb
= region
->entry
;
6527 cont_bb
= region
->cont
;
6528 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6529 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6530 gcc_assert (broken_loop
6531 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
6532 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6533 body_bb
= single_succ (seq_start_bb
);
6536 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6537 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6539 exit_bb
= region
->exit
;
6541 /* Iteration space partitioning goes in ENTRY_BB. */
6542 gsi
= gsi_last_bb (entry_bb
);
6543 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6545 if (fd
->collapse
> 1)
6547 int first_zero_iter
= -1;
6548 basic_block l2_dom_bb
= NULL
;
6550 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6551 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6552 fin_bb
, first_zero_iter
,
6556 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6557 t
= integer_one_node
;
6559 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6560 fold_convert (type
, fd
->loop
.n1
),
6561 fold_convert (type
, fd
->loop
.n2
));
6562 if (fd
->collapse
== 1
6563 && TYPE_UNSIGNED (type
)
6564 && (t
== NULL_TREE
|| !integer_onep (t
)))
6566 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6567 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6568 true, GSI_SAME_STMT
);
6569 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6570 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6571 true, GSI_SAME_STMT
);
6572 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6573 NULL_TREE
, NULL_TREE
);
6574 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6575 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6576 expand_omp_regimplify_p
, NULL
, NULL
)
6577 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6578 expand_omp_regimplify_p
, NULL
, NULL
))
6580 gsi
= gsi_for_stmt (cond_stmt
);
6581 gimple_regimplify_operands (cond_stmt
, &gsi
);
6583 ep
= split_block (entry_bb
, cond_stmt
);
6584 ep
->flags
= EDGE_TRUE_VALUE
;
6585 entry_bb
= ep
->dest
;
6586 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6587 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6588 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6589 if (gimple_in_ssa_p (cfun
))
6591 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6592 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6593 !gsi_end_p (gpi
); gsi_next (&gpi
))
6595 gphi
*phi
= gpi
.phi ();
6596 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6597 ep
, UNKNOWN_LOCATION
);
6600 gsi
= gsi_last_bb (entry_bb
);
6603 switch (gimple_omp_for_kind (fd
->for_stmt
))
6605 case GF_OMP_FOR_KIND_FOR
:
6606 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
6607 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
6609 case GF_OMP_FOR_KIND_DISTRIBUTE
:
6610 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
6611 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
6613 case GF_OMP_FOR_KIND_OACC_LOOP
:
6614 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
6615 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
6620 nthreads
= build_call_expr (nthreads
, 0);
6621 nthreads
= fold_convert (itype
, nthreads
);
6622 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
6623 true, GSI_SAME_STMT
);
6624 threadid
= build_call_expr (threadid
, 0);
6625 threadid
= fold_convert (itype
, threadid
);
6626 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
6627 true, GSI_SAME_STMT
);
6631 step
= fd
->loop
.step
;
6632 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6634 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6635 OMP_CLAUSE__LOOPTEMP_
);
6636 gcc_assert (innerc
);
6637 n1
= OMP_CLAUSE_DECL (innerc
);
6638 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6639 OMP_CLAUSE__LOOPTEMP_
);
6640 gcc_assert (innerc
);
6641 n2
= OMP_CLAUSE_DECL (innerc
);
6643 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6644 true, NULL_TREE
, true, GSI_SAME_STMT
);
6645 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6646 true, NULL_TREE
, true, GSI_SAME_STMT
);
6647 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6648 true, NULL_TREE
, true, GSI_SAME_STMT
);
6650 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6651 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6652 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6653 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6654 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6655 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6656 fold_build1 (NEGATE_EXPR
, itype
, t
),
6657 fold_build1 (NEGATE_EXPR
, itype
, step
));
6659 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6660 t
= fold_convert (itype
, t
);
6661 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6663 q
= create_tmp_reg (itype
, "q");
6664 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
6665 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6666 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
6668 tt
= create_tmp_reg (itype
, "tt");
6669 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
6670 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6671 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
6673 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
6674 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6675 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6677 second_bb
= split_block (entry_bb
, cond_stmt
)->dest
;
6678 gsi
= gsi_last_bb (second_bb
);
6679 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6681 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
6683 gassign
*assign_stmt
6684 = gimple_build_assign (q
, PLUS_EXPR
, q
, build_int_cst (itype
, 1));
6685 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6687 third_bb
= split_block (second_bb
, assign_stmt
)->dest
;
6688 gsi
= gsi_last_bb (third_bb
);
6689 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6691 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6692 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6693 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6695 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6696 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6698 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6699 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6701 /* Remove the GIMPLE_OMP_FOR statement. */
6702 gsi_remove (&gsi
, true);
6704 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6705 gsi
= gsi_start_bb (seq_start_bb
);
6707 tree startvar
= fd
->loop
.v
;
6708 tree endvar
= NULL_TREE
;
6710 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6712 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6713 ? gimple_omp_parallel_clauses (inner_stmt
)
6714 : gimple_omp_for_clauses (inner_stmt
);
6715 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6716 gcc_assert (innerc
);
6717 startvar
= OMP_CLAUSE_DECL (innerc
);
6718 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6719 OMP_CLAUSE__LOOPTEMP_
);
6720 gcc_assert (innerc
);
6721 endvar
= OMP_CLAUSE_DECL (innerc
);
6723 t
= fold_convert (itype
, s0
);
6724 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6725 if (POINTER_TYPE_P (type
))
6726 t
= fold_build_pointer_plus (n1
, t
);
6728 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6729 t
= fold_convert (TREE_TYPE (startvar
), t
);
6730 t
= force_gimple_operand_gsi (&gsi
, t
,
6732 && TREE_ADDRESSABLE (startvar
),
6733 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6734 assign_stmt
= gimple_build_assign (startvar
, t
);
6735 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6737 t
= fold_convert (itype
, e0
);
6738 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6739 if (POINTER_TYPE_P (type
))
6740 t
= fold_build_pointer_plus (n1
, t
);
6742 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6743 t
= fold_convert (TREE_TYPE (startvar
), t
);
6744 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6745 false, GSI_CONTINUE_LINKING
);
6748 assign_stmt
= gimple_build_assign (endvar
, e
);
6749 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6750 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6751 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6753 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
6754 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6756 if (fd
->collapse
> 1)
6757 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6761 /* The code controlling the sequential loop replaces the
6762 GIMPLE_OMP_CONTINUE. */
6763 gsi
= gsi_last_bb (cont_bb
);
6764 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6765 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6766 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6767 vback
= gimple_omp_continue_control_def (cont_stmt
);
6769 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6771 if (POINTER_TYPE_P (type
))
6772 t
= fold_build_pointer_plus (vmain
, step
);
6774 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6775 t
= force_gimple_operand_gsi (&gsi
, t
,
6777 && TREE_ADDRESSABLE (vback
),
6778 NULL_TREE
, true, GSI_SAME_STMT
);
6779 assign_stmt
= gimple_build_assign (vback
, t
);
6780 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6782 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6783 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6785 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6788 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6789 gsi_remove (&gsi
, true);
6791 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6792 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6795 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6796 gsi
= gsi_last_bb (exit_bb
);
6797 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6799 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6800 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
6801 gcc_checking_assert (t
== NULL_TREE
);
6803 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6805 gsi_remove (&gsi
, true);
6807 /* Connect all the blocks. */
6808 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6809 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6810 ep
= find_edge (entry_bb
, second_bb
);
6811 ep
->flags
= EDGE_TRUE_VALUE
;
6812 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6813 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6814 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6818 ep
= find_edge (cont_bb
, body_bb
);
6819 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6824 else if (fd
->collapse
> 1)
6827 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6830 ep
->flags
= EDGE_TRUE_VALUE
;
6831 find_edge (cont_bb
, fin_bb
)->flags
6832 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6835 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6836 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6837 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6839 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6840 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6841 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6842 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6844 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6846 struct loop
*loop
= alloc_loop ();
6847 loop
->header
= body_bb
;
6848 if (collapse_bb
== NULL
)
6849 loop
->latch
= cont_bb
;
6850 add_loop (loop
, body_bb
->loop_father
);
6855 /* A subroutine of expand_omp_for. Generate code for a parallel
6856 loop with static schedule and a specified chunk size. Given
6859 for (V = N1; V cond N2; V += STEP) BODY;
6861 where COND is "<" or ">", we generate pseudocode
6863 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6868 if ((__typeof (V)) -1 > 0 && cond is >)
6869 n = -(adj + N2 - N1) / -STEP;
6871 n = (adj + N2 - N1) / STEP;
6873 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6874 here so that V is defined
6875 if the loop is not entered
6877 s0 = (trip * nthreads + threadid) * CHUNK;
6878 e0 = min(s0 + CHUNK, n);
6879 if (s0 < n) goto L1; else goto L4;
6886 if (V cond e) goto L2; else goto L3;
6894 expand_omp_for_static_chunk (struct omp_region
*region
,
6895 struct omp_for_data
*fd
, gimple inner_stmt
)
6897 tree n
, s0
, e0
, e
, t
;
6898 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6899 tree type
, itype
, vmain
, vback
, vextra
;
6900 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6901 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6902 gimple_stmt_iterator gsi
;
6904 bool broken_loop
= region
->cont
== NULL
;
6905 tree
*counts
= NULL
;
6908 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6909 != GF_OMP_FOR_KIND_OACC_LOOP
)
6912 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6913 if (POINTER_TYPE_P (type
))
6914 itype
= signed_type_for (type
);
6916 entry_bb
= region
->entry
;
6917 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6919 iter_part_bb
= se
->dest
;
6920 cont_bb
= region
->cont
;
6921 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6922 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6923 gcc_assert (broken_loop
6924 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6925 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6926 body_bb
= single_succ (seq_start_bb
);
6929 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6930 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6931 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6933 exit_bb
= region
->exit
;
6935 /* Trip and adjustment setup goes in ENTRY_BB. */
6936 gsi
= gsi_last_bb (entry_bb
);
6937 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6939 if (fd
->collapse
> 1)
6941 int first_zero_iter
= -1;
6942 basic_block l2_dom_bb
= NULL
;
6944 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6945 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6946 fin_bb
, first_zero_iter
,
6950 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6951 t
= integer_one_node
;
6953 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6954 fold_convert (type
, fd
->loop
.n1
),
6955 fold_convert (type
, fd
->loop
.n2
));
6956 if (fd
->collapse
== 1
6957 && TYPE_UNSIGNED (type
)
6958 && (t
== NULL_TREE
|| !integer_onep (t
)))
6960 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6961 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6962 true, GSI_SAME_STMT
);
6963 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6964 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6965 true, GSI_SAME_STMT
);
6966 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6967 NULL_TREE
, NULL_TREE
);
6968 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6969 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6970 expand_omp_regimplify_p
, NULL
, NULL
)
6971 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6972 expand_omp_regimplify_p
, NULL
, NULL
))
6974 gsi
= gsi_for_stmt (cond_stmt
);
6975 gimple_regimplify_operands (cond_stmt
, &gsi
);
6977 se
= split_block (entry_bb
, cond_stmt
);
6978 se
->flags
= EDGE_TRUE_VALUE
;
6979 entry_bb
= se
->dest
;
6980 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6981 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6982 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6983 if (gimple_in_ssa_p (cfun
))
6985 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6986 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6987 !gsi_end_p (gpi
); gsi_next (&gpi
))
6989 gphi
*phi
= gpi
.phi ();
6990 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6991 se
, UNKNOWN_LOCATION
);
6994 gsi
= gsi_last_bb (entry_bb
);
6997 switch (gimple_omp_for_kind (fd
->for_stmt
))
6999 case GF_OMP_FOR_KIND_FOR
:
7000 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
7001 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
7003 case GF_OMP_FOR_KIND_DISTRIBUTE
:
7004 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
7005 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
7007 case GF_OMP_FOR_KIND_OACC_LOOP
:
7008 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
7009 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
7014 nthreads
= build_call_expr (nthreads
, 0);
7015 nthreads
= fold_convert (itype
, nthreads
);
7016 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
7017 true, GSI_SAME_STMT
);
7018 threadid
= build_call_expr (threadid
, 0);
7019 threadid
= fold_convert (itype
, threadid
);
7020 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
7021 true, GSI_SAME_STMT
);
7025 step
= fd
->loop
.step
;
7026 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7028 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7029 OMP_CLAUSE__LOOPTEMP_
);
7030 gcc_assert (innerc
);
7031 n1
= OMP_CLAUSE_DECL (innerc
);
7032 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7033 OMP_CLAUSE__LOOPTEMP_
);
7034 gcc_assert (innerc
);
7035 n2
= OMP_CLAUSE_DECL (innerc
);
7037 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
7038 true, NULL_TREE
, true, GSI_SAME_STMT
);
7039 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
7040 true, NULL_TREE
, true, GSI_SAME_STMT
);
7041 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
7042 true, NULL_TREE
, true, GSI_SAME_STMT
);
7044 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
7045 true, NULL_TREE
, true, GSI_SAME_STMT
);
7047 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
7048 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
7049 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
7050 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
7051 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
7052 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
7053 fold_build1 (NEGATE_EXPR
, itype
, t
),
7054 fold_build1 (NEGATE_EXPR
, itype
, step
));
7056 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
7057 t
= fold_convert (itype
, t
);
7058 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7059 true, GSI_SAME_STMT
);
7061 trip_var
= create_tmp_reg (itype
, ".trip");
7062 if (gimple_in_ssa_p (cfun
))
7064 trip_init
= make_ssa_name (trip_var
);
7065 trip_main
= make_ssa_name (trip_var
);
7066 trip_back
= make_ssa_name (trip_var
);
7070 trip_init
= trip_var
;
7071 trip_main
= trip_var
;
7072 trip_back
= trip_var
;
7075 gassign
*assign_stmt
7076 = gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
7077 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7079 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
7080 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7081 if (POINTER_TYPE_P (type
))
7082 t
= fold_build_pointer_plus (n1
, t
);
7084 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7085 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7086 true, GSI_SAME_STMT
);
7088 /* Remove the GIMPLE_OMP_FOR. */
7089 gsi_remove (&gsi
, true);
7091 /* Iteration space partitioning goes in ITER_PART_BB. */
7092 gsi
= gsi_last_bb (iter_part_bb
);
7094 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
7095 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
7096 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
7097 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7098 false, GSI_CONTINUE_LINKING
);
7100 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
7101 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
7102 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7103 false, GSI_CONTINUE_LINKING
);
7105 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
7106 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
7108 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7109 gsi
= gsi_start_bb (seq_start_bb
);
7111 tree startvar
= fd
->loop
.v
;
7112 tree endvar
= NULL_TREE
;
7114 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7116 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
7117 ? gimple_omp_parallel_clauses (inner_stmt
)
7118 : gimple_omp_for_clauses (inner_stmt
);
7119 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
7120 gcc_assert (innerc
);
7121 startvar
= OMP_CLAUSE_DECL (innerc
);
7122 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7123 OMP_CLAUSE__LOOPTEMP_
);
7124 gcc_assert (innerc
);
7125 endvar
= OMP_CLAUSE_DECL (innerc
);
7128 t
= fold_convert (itype
, s0
);
7129 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7130 if (POINTER_TYPE_P (type
))
7131 t
= fold_build_pointer_plus (n1
, t
);
7133 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7134 t
= fold_convert (TREE_TYPE (startvar
), t
);
7135 t
= force_gimple_operand_gsi (&gsi
, t
,
7137 && TREE_ADDRESSABLE (startvar
),
7138 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
7139 assign_stmt
= gimple_build_assign (startvar
, t
);
7140 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7142 t
= fold_convert (itype
, e0
);
7143 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7144 if (POINTER_TYPE_P (type
))
7145 t
= fold_build_pointer_plus (n1
, t
);
7147 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7148 t
= fold_convert (TREE_TYPE (startvar
), t
);
7149 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7150 false, GSI_CONTINUE_LINKING
);
7153 assign_stmt
= gimple_build_assign (endvar
, e
);
7154 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7155 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
7156 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
7158 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
7159 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7161 if (fd
->collapse
> 1)
7162 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
7166 /* The code controlling the sequential loop goes in CONT_BB,
7167 replacing the GIMPLE_OMP_CONTINUE. */
7168 gsi
= gsi_last_bb (cont_bb
);
7169 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
7170 vmain
= gimple_omp_continue_control_use (cont_stmt
);
7171 vback
= gimple_omp_continue_control_def (cont_stmt
);
7173 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7175 if (POINTER_TYPE_P (type
))
7176 t
= fold_build_pointer_plus (vmain
, step
);
7178 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
7179 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
7180 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7181 true, GSI_SAME_STMT
);
7182 assign_stmt
= gimple_build_assign (vback
, t
);
7183 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7185 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
7186 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
7188 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
7191 /* Remove GIMPLE_OMP_CONTINUE. */
7192 gsi_remove (&gsi
, true);
7194 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
7195 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
7197 /* Trip update code goes into TRIP_UPDATE_BB. */
7198 gsi
= gsi_start_bb (trip_update_bb
);
7200 t
= build_int_cst (itype
, 1);
7201 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
7202 assign_stmt
= gimple_build_assign (trip_back
, t
);
7203 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7206 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7207 gsi
= gsi_last_bb (exit_bb
);
7208 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
7210 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
7211 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
7212 gcc_checking_assert (t
== NULL_TREE
);
7214 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
7216 gsi_remove (&gsi
, true);
7218 /* Connect the new blocks. */
7219 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
7220 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
7224 se
= find_edge (cont_bb
, body_bb
);
7225 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7230 else if (fd
->collapse
> 1)
7233 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
7236 se
->flags
= EDGE_TRUE_VALUE
;
7237 find_edge (cont_bb
, trip_update_bb
)->flags
7238 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
7240 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
7243 if (gimple_in_ssa_p (cfun
))
7251 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
7253 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7254 remove arguments of the phi nodes in fin_bb. We need to create
7255 appropriate phi nodes in iter_part_bb instead. */
7256 se
= single_pred_edge (fin_bb
);
7257 re
= single_succ_edge (trip_update_bb
);
7258 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
7259 ene
= single_succ_edge (entry_bb
);
7261 psi
= gsi_start_phis (fin_bb
);
7262 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
7263 gsi_next (&psi
), ++i
)
7266 source_location locus
;
7269 t
= gimple_phi_result (phi
);
7270 gcc_assert (t
== redirect_edge_var_map_result (vm
));
7271 nphi
= create_phi_node (t
, iter_part_bb
);
7273 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
7274 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
7276 /* A special case -- fd->loop.v is not yet computed in
7277 iter_part_bb, we need to use vextra instead. */
7278 if (t
== fd
->loop
.v
)
7280 add_phi_arg (nphi
, t
, ene
, locus
);
7281 locus
= redirect_edge_var_map_location (vm
);
7282 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
7284 gcc_assert (gsi_end_p (psi
) && i
== head
->length ());
7285 redirect_edge_var_map_clear (re
);
7288 psi
= gsi_start_phis (fin_bb
);
7289 if (gsi_end_p (psi
))
7291 remove_phi_node (&psi
, false);
7294 /* Make phi node for trip. */
7295 phi
= create_phi_node (trip_main
, iter_part_bb
);
7296 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
7298 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
7303 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
7304 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
7305 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
7306 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
7307 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
7308 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
7309 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
7310 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
7311 recompute_dominator (CDI_DOMINATORS
, body_bb
));
7315 struct loop
*trip_loop
= alloc_loop ();
7316 trip_loop
->header
= iter_part_bb
;
7317 trip_loop
->latch
= trip_update_bb
;
7318 add_loop (trip_loop
, iter_part_bb
->loop_father
);
7320 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7322 struct loop
*loop
= alloc_loop ();
7323 loop
->header
= body_bb
;
7324 if (collapse_bb
== NULL
)
7325 loop
->latch
= cont_bb
;
7326 add_loop (loop
, trip_loop
);
7331 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7333 for (V = N1; V cond N2; V += STEP) BODY;
7335 where COND is "<" or ">" or "!=", we generate pseudocode
7337 for (ind_var = low; ind_var < high; ind_var++)
7339 V = n1 + (ind_var * STEP)
7344 In the above pseudocode, low and high are function parameters of the
7345 child function. In the function below, we are inserting a temp.
7346 variable that will be making a call to two OMP functions that will not be
7347 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7348 with _Cilk_for). These functions are replaced with low and high
7349 by the function that handles taskreg. */
7353 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
7355 bool broken_loop
= region
->cont
== NULL
;
7356 basic_block entry_bb
= region
->entry
;
7357 basic_block cont_bb
= region
->cont
;
7359 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7360 gcc_assert (broken_loop
7361 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7362 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7363 basic_block l1_bb
, l2_bb
;
7367 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7368 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7369 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7370 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7374 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7375 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7376 l2_bb
= single_succ (l1_bb
);
7378 basic_block exit_bb
= region
->exit
;
7379 basic_block l2_dom_bb
= NULL
;
7381 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
7383 /* Below statements until the "tree high_val = ..." are pseudo statements
7384 used to pass information to be used by expand_omp_taskreg.
7385 low_val and high_val will be replaced by the __low and __high
7386 parameter from the child function.
7388 The call_exprs part is a place-holder, it is mainly used
7389 to distinctly identify to the top-level part that this is
7390 where we should put low and high (reasoning given in header
7394 = gimple_omp_parallel_child_fn (
7395 as_a
<gomp_parallel
*> (last_stmt (region
->outer
->entry
)));
7396 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
7397 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
7399 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
7401 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
7404 gcc_assert (low_val
&& high_val
);
7406 tree type
= TREE_TYPE (low_val
);
7407 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
7408 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7410 /* Not needed in SSA form right now. */
7411 gcc_assert (!gimple_in_ssa_p (cfun
));
7412 if (l2_dom_bb
== NULL
)
7418 gimple stmt
= gimple_build_assign (ind_var
, n1
);
7420 /* Replace the GIMPLE_OMP_FOR statement. */
7421 gsi_replace (&gsi
, stmt
, true);
7425 /* Code to control the increment goes in the CONT_BB. */
7426 gsi
= gsi_last_bb (cont_bb
);
7427 stmt
= gsi_stmt (gsi
);
7428 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7429 stmt
= gimple_build_assign (ind_var
, PLUS_EXPR
, ind_var
,
7430 build_one_cst (type
));
7432 /* Replace GIMPLE_OMP_CONTINUE. */
7433 gsi_replace (&gsi
, stmt
, true);
7436 /* Emit the condition in L1_BB. */
7437 gsi
= gsi_after_labels (l1_bb
);
7438 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
7439 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
7441 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
7442 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7443 fd
->loop
.n1
, fold_convert (sizetype
, t
));
7445 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7446 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
7447 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
7448 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7450 /* The condition is always '<' since the runtime will fill in the low
7452 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
7453 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
7455 /* Remove GIMPLE_OMP_RETURN. */
7456 gsi
= gsi_last_bb (exit_bb
);
7457 gsi_remove (&gsi
, true);
7459 /* Connect the new blocks. */
7460 remove_edge (FALLTHRU_EDGE (entry_bb
));
7465 remove_edge (BRANCH_EDGE (entry_bb
));
7466 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7468 e
= BRANCH_EDGE (l1_bb
);
7469 ne
= FALLTHRU_EDGE (l1_bb
);
7470 e
->flags
= EDGE_TRUE_VALUE
;
7474 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7476 ne
= single_succ_edge (l1_bb
);
7477 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7480 ne
->flags
= EDGE_FALSE_VALUE
;
7481 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7482 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7484 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7485 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7486 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7490 struct loop
*loop
= alloc_loop ();
7491 loop
->header
= l1_bb
;
7492 loop
->latch
= cont_bb
;
7493 add_loop (loop
, l1_bb
->loop_father
);
7494 loop
->safelen
= INT_MAX
;
7497 /* Pick the correct library function based on the precision of the
7498 induction variable type. */
7499 tree lib_fun
= NULL_TREE
;
7500 if (TYPE_PRECISION (type
) == 32)
7501 lib_fun
= cilk_for_32_fndecl
;
7502 else if (TYPE_PRECISION (type
) == 64)
7503 lib_fun
= cilk_for_64_fndecl
;
7507 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
7509 /* WS_ARGS contains the library function flavor to call:
7510 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7511 user-defined grain value. If the user does not define one, then zero
7512 is passed in by the parser. */
7513 vec_alloc (region
->ws_args
, 2);
7514 region
->ws_args
->quick_push (lib_fun
);
7515 region
->ws_args
->quick_push (fd
->chunk_size
);
7518 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7519 loop. Given parameters:
7521 for (V = N1; V cond N2; V += STEP) BODY;
7523 where COND is "<" or ">", we generate pseudocode
7531 if (V cond N2) goto L0; else goto L2;
7534 For collapsed loops, given parameters:
7536 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7537 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7538 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7541 we generate pseudocode
7547 count3 = (adj + N32 - N31) / STEP3;
7552 count2 = (adj + N22 - N21) / STEP2;
7557 count1 = (adj + N12 - N11) / STEP1;
7558 count = count1 * count2 * count3;
7568 V2 += (V3 cond3 N32) ? 0 : STEP2;
7569 V3 = (V3 cond3 N32) ? V3 : N31;
7570 V1 += (V2 cond2 N22) ? 0 : STEP1;
7571 V2 = (V2 cond2 N22) ? V2 : N21;
7573 if (V < count) goto L0; else goto L2;
7579 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
7582 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
7583 gimple_stmt_iterator gsi
;
7586 bool broken_loop
= region
->cont
== NULL
;
7588 tree
*counts
= NULL
;
7590 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7591 OMP_CLAUSE_SAFELEN
);
7592 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7593 OMP_CLAUSE__SIMDUID_
);
7596 type
= TREE_TYPE (fd
->loop
.v
);
7597 entry_bb
= region
->entry
;
7598 cont_bb
= region
->cont
;
7599 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7600 gcc_assert (broken_loop
7601 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7602 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7605 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7606 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7607 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7608 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7612 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7613 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7614 l2_bb
= single_succ (l1_bb
);
7616 exit_bb
= region
->exit
;
7619 gsi
= gsi_last_bb (entry_bb
);
7621 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7622 /* Not needed in SSA form right now. */
7623 gcc_assert (!gimple_in_ssa_p (cfun
));
7624 if (fd
->collapse
> 1)
7626 int first_zero_iter
= -1;
7627 basic_block zero_iter_bb
= l2_bb
;
7629 counts
= XALLOCAVEC (tree
, fd
->collapse
);
7630 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7631 zero_iter_bb
, first_zero_iter
,
7634 if (l2_dom_bb
== NULL
)
7639 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7641 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7642 OMP_CLAUSE__LOOPTEMP_
);
7643 gcc_assert (innerc
);
7644 n1
= OMP_CLAUSE_DECL (innerc
);
7645 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7646 OMP_CLAUSE__LOOPTEMP_
);
7647 gcc_assert (innerc
);
7648 n2
= OMP_CLAUSE_DECL (innerc
);
7649 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7650 fold_convert (type
, n1
));
7651 if (fd
->collapse
> 1)
7654 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
7660 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7661 fold_convert (type
, fd
->loop
.n1
));
7662 if (fd
->collapse
> 1)
7663 for (i
= 0; i
< fd
->collapse
; i
++)
7665 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7666 if (POINTER_TYPE_P (itype
))
7667 itype
= signed_type_for (itype
);
7668 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
7669 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7673 /* Remove the GIMPLE_OMP_FOR statement. */
7674 gsi_remove (&gsi
, true);
7678 /* Code to control the increment goes in the CONT_BB. */
7679 gsi
= gsi_last_bb (cont_bb
);
7680 stmt
= gsi_stmt (gsi
);
7681 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7683 if (POINTER_TYPE_P (type
))
7684 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
7686 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
7687 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7689 if (fd
->collapse
> 1)
7691 i
= fd
->collapse
- 1;
7692 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7694 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
7695 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
7699 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
7701 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7704 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7706 for (i
= fd
->collapse
- 1; i
> 0; i
--)
7708 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7709 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
7710 if (POINTER_TYPE_P (itype2
))
7711 itype2
= signed_type_for (itype2
);
7712 t
= build3 (COND_EXPR
, itype2
,
7713 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7715 fold_convert (itype
, fd
->loops
[i
].n2
)),
7716 build_int_cst (itype2
, 0),
7717 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
7718 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
7719 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
7721 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
7722 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
7724 t
= build3 (COND_EXPR
, itype
,
7725 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7727 fold_convert (itype
, fd
->loops
[i
].n2
)),
7729 fold_convert (itype
, fd
->loops
[i
].n1
));
7730 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7734 /* Remove GIMPLE_OMP_CONTINUE. */
7735 gsi_remove (&gsi
, true);
7738 /* Emit the condition in L1_BB. */
7739 gsi
= gsi_start_bb (l1_bb
);
7741 t
= fold_convert (type
, n2
);
7742 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7743 false, GSI_CONTINUE_LINKING
);
7744 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
7745 cond_stmt
= gimple_build_cond_empty (t
);
7746 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
7747 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7749 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7752 gsi
= gsi_for_stmt (cond_stmt
);
7753 gimple_regimplify_operands (cond_stmt
, &gsi
);
7756 /* Remove GIMPLE_OMP_RETURN. */
7757 gsi
= gsi_last_bb (exit_bb
);
7758 gsi_remove (&gsi
, true);
7760 /* Connect the new blocks. */
7761 remove_edge (FALLTHRU_EDGE (entry_bb
));
7765 remove_edge (BRANCH_EDGE (entry_bb
));
7766 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7768 e
= BRANCH_EDGE (l1_bb
);
7769 ne
= FALLTHRU_EDGE (l1_bb
);
7770 e
->flags
= EDGE_TRUE_VALUE
;
7774 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7776 ne
= single_succ_edge (l1_bb
);
7777 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7780 ne
->flags
= EDGE_FALSE_VALUE
;
7781 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7782 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7784 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7785 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7786 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7790 struct loop
*loop
= alloc_loop ();
7791 loop
->header
= l1_bb
;
7792 loop
->latch
= cont_bb
;
7793 add_loop (loop
, l1_bb
->loop_father
);
7794 if (safelen
== NULL_TREE
)
7795 loop
->safelen
= INT_MAX
;
7798 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
7799 if (TREE_CODE (safelen
) != INTEGER_CST
)
7801 else if (!tree_fits_uhwi_p (safelen
)
7802 || tree_to_uhwi (safelen
) > INT_MAX
)
7803 loop
->safelen
= INT_MAX
;
7805 loop
->safelen
= tree_to_uhwi (safelen
);
7806 if (loop
->safelen
== 1)
7811 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
7812 cfun
->has_simduid_loops
= true;
7814 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7816 if ((flag_tree_loop_vectorize
7817 || (!global_options_set
.x_flag_tree_loop_vectorize
7818 && !global_options_set
.x_flag_tree_vectorize
))
7819 && flag_tree_loop_optimize
7820 && loop
->safelen
> 1)
7822 loop
->force_vectorize
= true;
7823 cfun
->has_force_vectorize_loops
= true;
7827 cfun
->has_simduid_loops
= true;
7831 /* Expand the OMP loop defined by REGION. */
7834 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
7836 struct omp_for_data fd
;
7837 struct omp_for_data_loop
*loops
;
7840 = (struct omp_for_data_loop
*)
7841 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
7842 * sizeof (struct omp_for_data_loop
));
7843 extract_omp_for_data (as_a
<gomp_for
*> (last_stmt (region
->entry
)),
7845 region
->sched_kind
= fd
.sched_kind
;
7847 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
7848 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7849 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7852 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
7853 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7854 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7857 /* If there isn't a continue then this is a degerate case where
7858 the introduction of abnormal edges during lowering will prevent
7859 original loops from being detected. Fix that up. */
7860 loops_state_set (LOOPS_NEED_FIXUP
);
7862 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
7863 expand_omp_simd (region
, &fd
);
7864 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
7865 expand_cilk_for (region
, &fd
);
7866 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
7867 && !fd
.have_ordered
)
7869 if (fd
.chunk_size
== NULL
)
7870 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
7872 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
7876 int fn_index
, start_ix
, next_ix
;
7878 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
7879 == GF_OMP_FOR_KIND_FOR
);
7880 if (fd
.chunk_size
== NULL
7881 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
7882 fd
.chunk_size
= integer_zero_node
;
7883 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
7884 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
7885 ? 3 : fd
.sched_kind
;
7886 fn_index
+= fd
.have_ordered
* 4;
7887 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
7888 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
7889 if (fd
.iter_type
== long_long_unsigned_type_node
)
7891 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7892 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
7893 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7894 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7896 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7897 (enum built_in_function
) next_ix
, inner_stmt
);
7900 if (gimple_in_ssa_p (cfun
))
7901 update_ssa (TODO_update_ssa_only_virtuals
);
7905 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7907 v = GOMP_sections_start (n);
7924 v = GOMP_sections_next ();
7929 If this is a combined parallel sections, replace the call to
7930 GOMP_sections_start with call to GOMP_sections_next. */
7933 expand_omp_sections (struct omp_region
*region
)
7935 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7937 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7938 gimple_stmt_iterator si
, switch_si
;
7939 gomp_sections
*sections_stmt
;
7941 gomp_continue
*cont
;
7944 struct omp_region
*inner
;
7946 bool exit_reachable
= region
->cont
!= NULL
;
7948 gcc_assert (region
->exit
!= NULL
);
7949 entry_bb
= region
->entry
;
7950 l0_bb
= single_succ (entry_bb
);
7951 l1_bb
= region
->cont
;
7952 l2_bb
= region
->exit
;
7953 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7954 l2
= gimple_block_label (l2_bb
);
7957 /* This can happen if there are reductions. */
7958 len
= EDGE_COUNT (l0_bb
->succs
);
7959 gcc_assert (len
> 0);
7960 e
= EDGE_SUCC (l0_bb
, len
- 1);
7961 si
= gsi_last_bb (e
->dest
);
7964 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7965 l2
= gimple_block_label (e
->dest
);
7967 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7969 si
= gsi_last_bb (e
->dest
);
7971 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7973 l2
= gimple_block_label (e
->dest
);
7979 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7981 default_bb
= create_empty_bb (l0_bb
);
7983 /* We will build a switch() with enough cases for all the
7984 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7985 and a default case to abort if something goes wrong. */
7986 len
= EDGE_COUNT (l0_bb
->succs
);
7988 /* Use vec::quick_push on label_vec throughout, since we know the size
7990 auto_vec
<tree
> label_vec (len
);
7992 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7993 GIMPLE_OMP_SECTIONS statement. */
7994 si
= gsi_last_bb (entry_bb
);
7995 sections_stmt
= as_a
<gomp_sections
*> (gsi_stmt (si
));
7996 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
7997 vin
= gimple_omp_sections_control (sections_stmt
);
7998 if (!is_combined_parallel (region
))
8000 /* If we are not inside a combined parallel+sections region,
8001 call GOMP_sections_start. */
8002 t
= build_int_cst (unsigned_type_node
, len
- 1);
8003 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
8004 stmt
= gimple_build_call (u
, 1, t
);
8008 /* Otherwise, call GOMP_sections_next. */
8009 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8010 stmt
= gimple_build_call (u
, 0);
8012 gimple_call_set_lhs (stmt
, vin
);
8013 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8014 gsi_remove (&si
, true);
8016 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8018 switch_si
= gsi_last_bb (l0_bb
);
8019 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
8022 cont
= as_a
<gomp_continue
*> (last_stmt (l1_bb
));
8023 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
8024 vmain
= gimple_omp_continue_control_use (cont
);
8025 vnext
= gimple_omp_continue_control_def (cont
);
8033 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
8034 label_vec
.quick_push (t
);
8037 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8038 for (inner
= region
->inner
, casei
= 1;
8040 inner
= inner
->next
, i
++, casei
++)
8042 basic_block s_entry_bb
, s_exit_bb
;
8044 /* Skip optional reduction region. */
8045 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
8052 s_entry_bb
= inner
->entry
;
8053 s_exit_bb
= inner
->exit
;
8055 t
= gimple_block_label (s_entry_bb
);
8056 u
= build_int_cst (unsigned_type_node
, casei
);
8057 u
= build_case_label (u
, NULL
, t
);
8058 label_vec
.quick_push (u
);
8060 si
= gsi_last_bb (s_entry_bb
);
8061 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
8062 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
8063 gsi_remove (&si
, true);
8064 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
8066 if (s_exit_bb
== NULL
)
8069 si
= gsi_last_bb (s_exit_bb
);
8070 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8071 gsi_remove (&si
, true);
8073 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
8076 /* Error handling code goes in DEFAULT_BB. */
8077 t
= gimple_block_label (default_bb
);
8078 u
= build_case_label (NULL
, NULL
, t
);
8079 make_edge (l0_bb
, default_bb
, 0);
8080 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
8082 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
8083 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
8084 gsi_remove (&switch_si
, true);
8086 si
= gsi_start_bb (default_bb
);
8087 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
8088 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
8094 /* Code to get the next section goes in L1_BB. */
8095 si
= gsi_last_bb (l1_bb
);
8096 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
8098 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8099 stmt
= gimple_build_call (bfn_decl
, 0);
8100 gimple_call_set_lhs (stmt
, vnext
);
8101 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8102 gsi_remove (&si
, true);
8104 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
8107 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8108 si
= gsi_last_bb (l2_bb
);
8109 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
8110 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
8111 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
8112 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
8114 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
8115 stmt
= gimple_build_call (t
, 0);
8116 if (gimple_omp_return_lhs (gsi_stmt (si
)))
8117 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
8118 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8119 gsi_remove (&si
, true);
8121 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
8125 /* Expand code for an OpenMP single directive. We've already expanded
8126 much of the code, here we simply place the GOMP_barrier call. */
8129 expand_omp_single (struct omp_region
*region
)
8131 basic_block entry_bb
, exit_bb
;
8132 gimple_stmt_iterator si
;
8134 entry_bb
= region
->entry
;
8135 exit_bb
= region
->exit
;
8137 si
= gsi_last_bb (entry_bb
);
8138 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
8139 gsi_remove (&si
, true);
8140 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8142 si
= gsi_last_bb (exit_bb
);
8143 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
8145 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
8146 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
8148 gsi_remove (&si
, true);
8149 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8153 /* Generic expansion for OpenMP synchronization directives: master,
8154 ordered and critical. All we need to do here is remove the entry
8155 and exit markers for REGION. */
8158 expand_omp_synch (struct omp_region
*region
)
8160 basic_block entry_bb
, exit_bb
;
8161 gimple_stmt_iterator si
;
8163 entry_bb
= region
->entry
;
8164 exit_bb
= region
->exit
;
8166 si
= gsi_last_bb (entry_bb
);
8167 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
8168 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
8169 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
8170 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
8171 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
8172 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
8173 gsi_remove (&si
, true);
8174 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8178 si
= gsi_last_bb (exit_bb
);
8179 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8180 gsi_remove (&si
, true);
8181 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8185 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8186 operation as a normal volatile load. */
8189 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
8190 tree loaded_val
, int index
)
8192 enum built_in_function tmpbase
;
8193 gimple_stmt_iterator gsi
;
8194 basic_block store_bb
;
8197 tree decl
, call
, type
, itype
;
8199 gsi
= gsi_last_bb (load_bb
);
8200 stmt
= gsi_stmt (gsi
);
8201 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8202 loc
= gimple_location (stmt
);
8204 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8205 is smaller than word size, then expand_atomic_load assumes that the load
8206 is atomic. We could avoid the builtin entirely in this case. */
8208 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8209 decl
= builtin_decl_explicit (tmpbase
);
8210 if (decl
== NULL_TREE
)
8213 type
= TREE_TYPE (loaded_val
);
8214 itype
= TREE_TYPE (TREE_TYPE (decl
));
8216 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
8217 build_int_cst (NULL
,
8218 gimple_omp_atomic_seq_cst_p (stmt
)
8220 : MEMMODEL_RELAXED
));
8221 if (!useless_type_conversion_p (type
, itype
))
8222 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8223 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8225 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8226 gsi_remove (&gsi
, true);
8228 store_bb
= single_succ (load_bb
);
8229 gsi
= gsi_last_bb (store_bb
);
8230 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8231 gsi_remove (&gsi
, true);
8233 if (gimple_in_ssa_p (cfun
))
8234 update_ssa (TODO_update_ssa_no_phi
);
8239 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8240 operation as a normal volatile store. */
8243 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
8244 tree loaded_val
, tree stored_val
, int index
)
8246 enum built_in_function tmpbase
;
8247 gimple_stmt_iterator gsi
;
8248 basic_block store_bb
= single_succ (load_bb
);
8251 tree decl
, call
, type
, itype
;
8255 gsi
= gsi_last_bb (load_bb
);
8256 stmt
= gsi_stmt (gsi
);
8257 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8259 /* If the load value is needed, then this isn't a store but an exchange. */
8260 exchange
= gimple_omp_atomic_need_value_p (stmt
);
8262 gsi
= gsi_last_bb (store_bb
);
8263 stmt
= gsi_stmt (gsi
);
8264 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
8265 loc
= gimple_location (stmt
);
8267 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8268 is smaller than word size, then expand_atomic_store assumes that the store
8269 is atomic. We could avoid the builtin entirely in this case. */
8271 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
8272 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
8273 decl
= builtin_decl_explicit (tmpbase
);
8274 if (decl
== NULL_TREE
)
8277 type
= TREE_TYPE (stored_val
);
8279 /* Dig out the type of the function's second argument. */
8280 itype
= TREE_TYPE (decl
);
8281 itype
= TYPE_ARG_TYPES (itype
);
8282 itype
= TREE_CHAIN (itype
);
8283 itype
= TREE_VALUE (itype
);
8284 imode
= TYPE_MODE (itype
);
8286 if (exchange
&& !can_atomic_exchange_p (imode
, true))
8289 if (!useless_type_conversion_p (itype
, type
))
8290 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
8291 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
8292 build_int_cst (NULL
,
8293 gimple_omp_atomic_seq_cst_p (stmt
)
8295 : MEMMODEL_RELAXED
));
8298 if (!useless_type_conversion_p (type
, itype
))
8299 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8300 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8303 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8304 gsi_remove (&gsi
, true);
8306 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8307 gsi
= gsi_last_bb (load_bb
);
8308 gsi_remove (&gsi
, true);
8310 if (gimple_in_ssa_p (cfun
))
8311 update_ssa (TODO_update_ssa_no_phi
);
8316 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8317 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8318 size of the data type, and thus usable to find the index of the builtin
8319 decl. Returns false if the expression is not of the proper form. */
8322 expand_omp_atomic_fetch_op (basic_block load_bb
,
8323 tree addr
, tree loaded_val
,
8324 tree stored_val
, int index
)
8326 enum built_in_function oldbase
, newbase
, tmpbase
;
8327 tree decl
, itype
, call
;
8329 basic_block store_bb
= single_succ (load_bb
);
8330 gimple_stmt_iterator gsi
;
8333 enum tree_code code
;
8334 bool need_old
, need_new
;
8338 /* We expect to find the following sequences:
8341 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8344 val = tmp OP something; (or: something OP tmp)
8345 GIMPLE_OMP_STORE (val)
8347 ???FIXME: Allow a more flexible sequence.
8348 Perhaps use data flow to pick the statements.
8352 gsi
= gsi_after_labels (store_bb
);
8353 stmt
= gsi_stmt (gsi
);
8354 loc
= gimple_location (stmt
);
8355 if (!is_gimple_assign (stmt
))
8358 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
8360 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
8361 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
8362 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
8363 gcc_checking_assert (!need_old
|| !need_new
);
8365 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
8368 /* Check for one of the supported fetch-op operations. */
8369 code
= gimple_assign_rhs_code (stmt
);
8373 case POINTER_PLUS_EXPR
:
8374 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
8375 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
8378 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
8379 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
8382 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
8383 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
8386 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
8387 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
8390 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
8391 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
8397 /* Make sure the expression is of the proper form. */
8398 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
8399 rhs
= gimple_assign_rhs2 (stmt
);
8400 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
8401 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
8402 rhs
= gimple_assign_rhs1 (stmt
);
8406 tmpbase
= ((enum built_in_function
)
8407 ((need_new
? newbase
: oldbase
) + index
+ 1));
8408 decl
= builtin_decl_explicit (tmpbase
);
8409 if (decl
== NULL_TREE
)
8411 itype
= TREE_TYPE (TREE_TYPE (decl
));
8412 imode
= TYPE_MODE (itype
);
8414 /* We could test all of the various optabs involved, but the fact of the
8415 matter is that (with the exception of i486 vs i586 and xadd) all targets
8416 that support any atomic operaton optab also implements compare-and-swap.
8417 Let optabs.c take care of expanding any compare-and-swap loop. */
8418 if (!can_compare_and_swap_p (imode
, true))
8421 gsi
= gsi_last_bb (load_bb
);
8422 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8424 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8425 It only requires that the operation happen atomically. Thus we can
8426 use the RELAXED memory model. */
8427 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
8428 fold_convert_loc (loc
, itype
, rhs
),
8429 build_int_cst (NULL
,
8430 seq_cst
? MEMMODEL_SEQ_CST
8431 : MEMMODEL_RELAXED
));
8433 if (need_old
|| need_new
)
8435 lhs
= need_old
? loaded_val
: stored_val
;
8436 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
8437 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
8440 call
= fold_convert_loc (loc
, void_type_node
, call
);
8441 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8442 gsi_remove (&gsi
, true);
8444 gsi
= gsi_last_bb (store_bb
);
8445 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8446 gsi_remove (&gsi
, true);
8447 gsi
= gsi_last_bb (store_bb
);
8448 gsi_remove (&gsi
, true);
8450 if (gimple_in_ssa_p (cfun
))
8451 update_ssa (TODO_update_ssa_no_phi
);
8456 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8460 newval = rhs; // with oldval replacing *addr in rhs
8461 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8462 if (oldval != newval)
8465 INDEX is log2 of the size of the data type, and thus usable to find the
8466 index of the builtin decl. */
8469 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
8470 tree addr
, tree loaded_val
, tree stored_val
,
8473 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
8474 tree type
, itype
, cmpxchg
, iaddr
;
8475 gimple_stmt_iterator si
;
8476 basic_block loop_header
= single_succ (load_bb
);
8479 enum built_in_function fncode
;
8481 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8482 order to use the RELAXED memory model effectively. */
8483 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8485 cmpxchg
= builtin_decl_explicit (fncode
);
8486 if (cmpxchg
== NULL_TREE
)
8488 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8489 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
8491 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
8494 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8495 si
= gsi_last_bb (load_bb
);
8496 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8498 /* For floating-point values, we'll need to view-convert them to integers
8499 so that we can perform the atomic compare and swap. Simplify the
8500 following code by always setting up the "i"ntegral variables. */
8501 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
8505 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
8508 = force_gimple_operand_gsi (&si
,
8509 fold_convert (TREE_TYPE (iaddr
), addr
),
8510 false, NULL_TREE
, true, GSI_SAME_STMT
);
8511 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
8512 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8513 loadedi
= create_tmp_var (itype
);
8514 if (gimple_in_ssa_p (cfun
))
8515 loadedi
= make_ssa_name (loadedi
);
8520 loadedi
= loaded_val
;
8523 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8524 tree loaddecl
= builtin_decl_explicit (fncode
);
8527 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
8528 build_call_expr (loaddecl
, 2, iaddr
,
8529 build_int_cst (NULL_TREE
,
8530 MEMMODEL_RELAXED
)));
8532 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
8533 build_int_cst (TREE_TYPE (iaddr
), 0));
8536 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
8539 /* Move the value to the LOADEDI temporary. */
8540 if (gimple_in_ssa_p (cfun
))
8542 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
8543 phi
= create_phi_node (loadedi
, loop_header
);
8544 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
8548 gsi_insert_before (&si
,
8549 gimple_build_assign (loadedi
, initial
),
8551 if (loadedi
!= loaded_val
)
8553 gimple_stmt_iterator gsi2
;
8556 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
8557 gsi2
= gsi_start_bb (loop_header
);
8558 if (gimple_in_ssa_p (cfun
))
8561 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8562 true, GSI_SAME_STMT
);
8563 stmt
= gimple_build_assign (loaded_val
, x
);
8564 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
8568 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
8569 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8570 true, GSI_SAME_STMT
);
8573 gsi_remove (&si
, true);
8575 si
= gsi_last_bb (store_bb
);
8576 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8579 storedi
= stored_val
;
8582 force_gimple_operand_gsi (&si
,
8583 build1 (VIEW_CONVERT_EXPR
, itype
,
8584 stored_val
), true, NULL_TREE
, true,
8587 /* Build the compare&swap statement. */
8588 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
8589 new_storedi
= force_gimple_operand_gsi (&si
,
8590 fold_convert (TREE_TYPE (loadedi
),
8593 true, GSI_SAME_STMT
);
8595 if (gimple_in_ssa_p (cfun
))
8599 old_vali
= create_tmp_var (TREE_TYPE (loadedi
));
8600 stmt
= gimple_build_assign (old_vali
, loadedi
);
8601 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8603 stmt
= gimple_build_assign (loadedi
, new_storedi
);
8604 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8607 /* Note that we always perform the comparison as an integer, even for
8608 floating point. This allows the atomic operation to properly
8609 succeed even with NaNs and -0.0. */
8610 stmt
= gimple_build_cond_empty
8611 (build2 (NE_EXPR
, boolean_type_node
,
8612 new_storedi
, old_vali
));
8613 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8616 e
= single_succ_edge (store_bb
);
8617 e
->flags
&= ~EDGE_FALLTHRU
;
8618 e
->flags
|= EDGE_FALSE_VALUE
;
8620 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
8622 /* Copy the new value to loadedi (we already did that before the condition
8623 if we are not in SSA). */
8624 if (gimple_in_ssa_p (cfun
))
8626 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
8627 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
8630 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8631 gsi_remove (&si
, true);
8633 struct loop
*loop
= alloc_loop ();
8634 loop
->header
= loop_header
;
8635 loop
->latch
= store_bb
;
8636 add_loop (loop
, loop_header
->loop_father
);
8638 if (gimple_in_ssa_p (cfun
))
8639 update_ssa (TODO_update_ssa_no_phi
);
8644 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8646 GOMP_atomic_start ();
8650 The result is not globally atomic, but works so long as all parallel
8651 references are within #pragma omp atomic directives. According to
8652 responses received from omp@openmp.org, appears to be within spec.
8653 Which makes sense, since that's how several other compilers handle
8654 this situation as well.
8655 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8656 expanding. STORED_VAL is the operand of the matching
8657 GIMPLE_OMP_ATOMIC_STORE.
8660 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8664 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8669 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
8670 tree addr
, tree loaded_val
, tree stored_val
)
8672 gimple_stmt_iterator si
;
8676 si
= gsi_last_bb (load_bb
);
8677 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8679 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
8680 t
= build_call_expr (t
, 0);
8681 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8683 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
8684 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8685 gsi_remove (&si
, true);
8687 si
= gsi_last_bb (store_bb
);
8688 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8690 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
8692 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8694 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
8695 t
= build_call_expr (t
, 0);
8696 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8697 gsi_remove (&si
, true);
8699 if (gimple_in_ssa_p (cfun
))
8700 update_ssa (TODO_update_ssa_no_phi
);
8704 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8705 using expand_omp_atomic_fetch_op. If it failed, we try to
8706 call expand_omp_atomic_pipeline, and if it fails too, the
8707 ultimate fallback is wrapping the operation in a mutex
8708 (expand_omp_atomic_mutex). REGION is the atomic region built
8709 by build_omp_regions_1(). */
8712 expand_omp_atomic (struct omp_region
*region
)
8714 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
8715 gomp_atomic_load
*load
= as_a
<gomp_atomic_load
*> (last_stmt (load_bb
));
8716 gomp_atomic_store
*store
= as_a
<gomp_atomic_store
*> (last_stmt (store_bb
));
8717 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
8718 tree addr
= gimple_omp_atomic_load_rhs (load
);
8719 tree stored_val
= gimple_omp_atomic_store_val (store
);
8720 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8721 HOST_WIDE_INT index
;
8723 /* Make sure the type is one of the supported sizes. */
8724 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
8725 index
= exact_log2 (index
);
8726 if (index
>= 0 && index
<= 4)
8728 unsigned int align
= TYPE_ALIGN_UNIT (type
);
8730 /* __sync builtins require strict data alignment. */
8731 if (exact_log2 (align
) >= index
)
8734 if (loaded_val
== stored_val
8735 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8736 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8737 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8738 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
8742 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8743 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8744 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8745 && store_bb
== single_succ (load_bb
)
8746 && first_stmt (store_bb
) == store
8747 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
8751 /* When possible, use specialized atomic update functions. */
8752 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
8753 && store_bb
== single_succ (load_bb
)
8754 && expand_omp_atomic_fetch_op (load_bb
, addr
,
8755 loaded_val
, stored_val
, index
))
8758 /* If we don't have specialized __sync builtins, try and implement
8759 as a compare and swap loop. */
8760 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
8761 loaded_val
, stored_val
, index
))
8766 /* The ultimate fallback is wrapping the operation in a mutex. */
8767 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
8771 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8774 expand_omp_target (struct omp_region
*region
)
8776 basic_block entry_bb
, exit_bb
, new_bb
;
8777 struct function
*child_cfun
;
8778 tree child_fn
, block
, t
;
8779 gimple_stmt_iterator gsi
;
8780 gomp_target
*entry_stmt
;
8783 bool offloaded
, data_region
;
8785 entry_stmt
= as_a
<gomp_target
*> (last_stmt (region
->entry
));
8786 new_bb
= region
->entry
;
8788 offloaded
= is_gimple_omp_offloaded (entry_stmt
);
8789 switch (gimple_omp_target_kind (entry_stmt
))
8791 case GF_OMP_TARGET_KIND_REGION
:
8792 case GF_OMP_TARGET_KIND_UPDATE
:
8793 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
8794 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
8795 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
8796 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
8797 data_region
= false;
8799 case GF_OMP_TARGET_KIND_DATA
:
8800 case GF_OMP_TARGET_KIND_OACC_DATA
:
8807 child_fn
= NULL_TREE
;
8811 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
8812 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
8815 /* Supported by expand_omp_taskreg, but not here. */
8816 if (child_cfun
!= NULL
)
8817 gcc_checking_assert (!child_cfun
->cfg
);
8818 gcc_checking_assert (!gimple_in_ssa_p (cfun
));
8820 entry_bb
= region
->entry
;
8821 exit_bb
= region
->exit
;
8825 unsigned srcidx
, dstidx
, num
;
8827 /* If the offloading region needs data sent from the parent
8828 function, then the very first statement (except possible
8829 tree profile counter updates) of the offloading body
8830 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8831 &.OMP_DATA_O is passed as an argument to the child function,
8832 we need to replace it with the argument as seen by the child
8835 In most cases, this will end up being the identity assignment
8836 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8837 a function call that has been inlined, the original PARM_DECL
8838 .OMP_DATA_I may have been converted into a different local
8839 variable. In which case, we need to keep the assignment. */
8840 tree data_arg
= gimple_omp_target_data_arg (entry_stmt
);
8843 basic_block entry_succ_bb
= single_succ (entry_bb
);
8844 gimple_stmt_iterator gsi
;
8846 gimple tgtcopy_stmt
= NULL
;
8847 tree sender
= TREE_VEC_ELT (data_arg
, 0);
8849 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
8851 gcc_assert (!gsi_end_p (gsi
));
8852 stmt
= gsi_stmt (gsi
);
8853 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
8856 if (gimple_num_ops (stmt
) == 2)
8858 tree arg
= gimple_assign_rhs1 (stmt
);
8860 /* We're ignoring the subcode because we're
8861 effectively doing a STRIP_NOPS. */
8863 if (TREE_CODE (arg
) == ADDR_EXPR
8864 && TREE_OPERAND (arg
, 0) == sender
)
8866 tgtcopy_stmt
= stmt
;
8872 gcc_assert (tgtcopy_stmt
!= NULL
);
8873 arg
= DECL_ARGUMENTS (child_fn
);
8875 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
8876 gsi_remove (&gsi
, true);
8879 /* Declare local variables needed in CHILD_CFUN. */
8880 block
= DECL_INITIAL (child_fn
);
8881 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
8882 /* The gimplifier could record temporaries in the offloading block
8883 rather than in containing function's local_decls chain,
8884 which would mean cgraph missed finalizing them. Do it now. */
8885 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
8886 if (TREE_CODE (t
) == VAR_DECL
8888 && !DECL_EXTERNAL (t
))
8889 varpool_node::finalize_decl (t
);
8890 DECL_SAVED_TREE (child_fn
) = NULL
;
8891 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8892 gimple_set_body (child_fn
, NULL
);
8893 TREE_USED (block
) = 1;
8895 /* Reset DECL_CONTEXT on function arguments. */
8896 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
8897 DECL_CONTEXT (t
) = child_fn
;
8899 /* Split ENTRY_BB at GIMPLE_*,
8900 so that it can be moved to the child function. */
8901 gsi
= gsi_last_bb (entry_bb
);
8902 stmt
= gsi_stmt (gsi
);
8904 && gimple_code (stmt
) == gimple_code (entry_stmt
));
8905 e
= split_block (entry_bb
, stmt
);
8906 gsi_remove (&gsi
, true);
8908 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8910 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8913 gsi
= gsi_last_bb (exit_bb
);
8914 gcc_assert (!gsi_end_p (gsi
)
8915 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
8916 stmt
= gimple_build_return (NULL
);
8917 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
8918 gsi_remove (&gsi
, true);
8921 /* Move the offloading region into CHILD_CFUN. */
8923 block
= gimple_block (entry_stmt
);
8925 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
8927 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
8928 /* When the OMP expansion process cannot guarantee an up-to-date
8929 loop tree arrange for the child function to fixup loops. */
8930 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
8931 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
8933 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8934 num
= vec_safe_length (child_cfun
->local_decls
);
8935 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
8937 t
= (*child_cfun
->local_decls
)[srcidx
];
8938 if (DECL_CONTEXT (t
) == cfun
->decl
)
8940 if (srcidx
!= dstidx
)
8941 (*child_cfun
->local_decls
)[dstidx
] = t
;
8945 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
8947 /* Inform the callgraph about the new function. */
8948 child_cfun
->curr_properties
= cfun
->curr_properties
;
8949 child_cfun
->has_simduid_loops
|= cfun
->has_simduid_loops
;
8950 child_cfun
->has_force_vectorize_loops
|= cfun
->has_force_vectorize_loops
;
8951 cgraph_node
*node
= cgraph_node::get_create (child_fn
);
8952 node
->parallelized_function
= 1;
8953 cgraph_node::add_new_function (child_fn
, true);
8955 #ifdef ENABLE_OFFLOADING
8956 /* Add the new function to the offload table. */
8957 vec_safe_push (offload_funcs
, child_fn
);
8960 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8961 fixed in a following pass. */
8962 push_cfun (child_cfun
);
8963 cgraph_edge::rebuild_edges ();
8965 #ifdef ENABLE_OFFLOADING
8966 /* Prevent IPA from removing child_fn as unreachable, since there are no
8967 refs from the parent function to child_fn in offload LTO mode. */
8968 cgraph_node::get (child_fn
)->mark_force_output ();
8971 /* Some EH regions might become dead, see PR34608. If
8972 pass_cleanup_cfg isn't the first pass to happen with the
8973 new child, these dead EH edges might cause problems.
8974 Clean them up now. */
8975 if (flag_exceptions
)
8978 bool changed
= false;
8980 FOR_EACH_BB_FN (bb
, cfun
)
8981 changed
|= gimple_purge_dead_eh_edges (bb
);
8983 cleanup_tree_cfg ();
8988 /* Emit a library call to launch the offloading region, or do data
8990 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
8991 enum built_in_function start_ix
;
8992 location_t clause_loc
;
8994 switch (gimple_omp_target_kind (entry_stmt
))
8996 case GF_OMP_TARGET_KIND_REGION
:
8997 start_ix
= BUILT_IN_GOMP_TARGET
;
8999 case GF_OMP_TARGET_KIND_DATA
:
9000 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
9002 case GF_OMP_TARGET_KIND_UPDATE
:
9003 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
9005 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
9006 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
9007 start_ix
= BUILT_IN_GOACC_PARALLEL
;
9009 case GF_OMP_TARGET_KIND_OACC_DATA
:
9010 start_ix
= BUILT_IN_GOACC_DATA_START
;
9012 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9013 start_ix
= BUILT_IN_GOACC_UPDATE
;
9015 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9016 start_ix
= BUILT_IN_GOACC_ENTER_EXIT_DATA
;
9022 clauses
= gimple_omp_target_clauses (entry_stmt
);
9024 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9025 library choose) and there is no conditional. */
9027 device
= build_int_cst (integer_type_node
, GOMP_DEVICE_ICV
);
9029 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
9031 cond
= OMP_CLAUSE_IF_EXPR (c
);
9033 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
9036 /* Even if we pass it to all library function calls, it is currently only
9037 defined/used for the OpenMP target ones. */
9038 gcc_checking_assert (start_ix
== BUILT_IN_GOMP_TARGET
9039 || start_ix
== BUILT_IN_GOMP_TARGET_DATA
9040 || start_ix
== BUILT_IN_GOMP_TARGET_UPDATE
);
9042 device
= OMP_CLAUSE_DEVICE_ID (c
);
9043 clause_loc
= OMP_CLAUSE_LOCATION (c
);
9046 clause_loc
= gimple_location (entry_stmt
);
9048 /* Ensure 'device' is of the correct type. */
9049 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
9051 /* If we found the clause 'if (cond)', build
9052 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9055 cond
= gimple_boolify (cond
);
9057 basic_block cond_bb
, then_bb
, else_bb
;
9061 tmp_var
= create_tmp_var (TREE_TYPE (device
));
9063 e
= split_block_after_labels (new_bb
);
9066 gsi
= gsi_last_bb (new_bb
);
9068 e
= split_block (new_bb
, gsi_stmt (gsi
));
9074 then_bb
= create_empty_bb (cond_bb
);
9075 else_bb
= create_empty_bb (then_bb
);
9076 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
9077 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
9079 stmt
= gimple_build_cond_empty (cond
);
9080 gsi
= gsi_last_bb (cond_bb
);
9081 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9083 gsi
= gsi_start_bb (then_bb
);
9084 stmt
= gimple_build_assign (tmp_var
, device
);
9085 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9087 gsi
= gsi_start_bb (else_bb
);
9088 stmt
= gimple_build_assign (tmp_var
,
9089 build_int_cst (integer_type_node
,
9090 GOMP_DEVICE_HOST_FALLBACK
));
9091 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9093 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
9094 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
9095 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
9096 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
9097 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
9098 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
9103 gsi
= gsi_last_bb (new_bb
);
9104 t
= gimple_omp_target_data_arg (entry_stmt
);
9107 t1
= size_zero_node
;
9108 t2
= build_zero_cst (ptr_type_node
);
9114 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
9115 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
9116 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
9117 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
9118 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
9122 /* The maximum number used by any start_ix, without varargs. */
9123 auto_vec
<tree
, 11> args
;
9124 args
.quick_push (device
);
9126 args
.quick_push (build_fold_addr_expr (child_fn
));
9129 case BUILT_IN_GOMP_TARGET
:
9130 case BUILT_IN_GOMP_TARGET_DATA
:
9131 case BUILT_IN_GOMP_TARGET_UPDATE
:
9132 /* This const void * is part of the current ABI, but we're not actually
9134 args
.quick_push (build_zero_cst (ptr_type_node
));
9136 case BUILT_IN_GOACC_DATA_START
:
9137 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9138 case BUILT_IN_GOACC_PARALLEL
:
9139 case BUILT_IN_GOACC_UPDATE
:
9144 args
.quick_push (t1
);
9145 args
.quick_push (t2
);
9146 args
.quick_push (t3
);
9147 args
.quick_push (t4
);
9150 case BUILT_IN_GOACC_DATA_START
:
9151 case BUILT_IN_GOMP_TARGET
:
9152 case BUILT_IN_GOMP_TARGET_DATA
:
9153 case BUILT_IN_GOMP_TARGET_UPDATE
:
9155 case BUILT_IN_GOACC_PARALLEL
:
9157 tree t_num_gangs
, t_num_workers
, t_vector_length
;
9159 /* Default values for num_gangs, num_workers, and vector_length. */
9160 t_num_gangs
= t_num_workers
= t_vector_length
9161 = fold_convert_loc (gimple_location (entry_stmt
),
9162 integer_type_node
, integer_one_node
);
9163 /* ..., but if present, use the value specified by the respective
9164 clause, making sure that are of the correct type. */
9165 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
9167 t_num_gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9169 OMP_CLAUSE_NUM_GANGS_EXPR (c
));
9170 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_WORKERS
);
9172 t_num_workers
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9174 OMP_CLAUSE_NUM_WORKERS_EXPR (c
));
9175 c
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
9177 t_vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9179 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c
));
9180 args
.quick_push (t_num_gangs
);
9181 args
.quick_push (t_num_workers
);
9182 args
.quick_push (t_vector_length
);
9185 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9186 case BUILT_IN_GOACC_UPDATE
:
9191 /* Default values for t_async. */
9192 t_async
= fold_convert_loc (gimple_location (entry_stmt
),
9194 build_int_cst (integer_type_node
,
9196 /* ..., but if present, use the value specified by the respective
9197 clause, making sure that is of the correct type. */
9198 c
= find_omp_clause (clauses
, OMP_CLAUSE_ASYNC
);
9200 t_async
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9202 OMP_CLAUSE_ASYNC_EXPR (c
));
9204 args
.quick_push (t_async
);
9205 /* Save the index, and... */
9206 t_wait_idx
= args
.length ();
9207 /* ... push a default value. */
9208 args
.quick_push (fold_convert_loc (gimple_location (entry_stmt
),
9210 integer_zero_node
));
9211 c
= find_omp_clause (clauses
, OMP_CLAUSE_WAIT
);
9216 for (; c
; c
= OMP_CLAUSE_CHAIN (c
))
9218 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WAIT
)
9220 args
.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9222 OMP_CLAUSE_WAIT_EXPR (c
)));
9227 /* Now that we know the number, replace the default value. */
9228 args
.ordered_remove (t_wait_idx
);
9229 args
.quick_insert (t_wait_idx
,
9230 fold_convert_loc (gimple_location (entry_stmt
),
9232 build_int_cst (integer_type_node
, n
)));
9240 g
= gimple_build_call_vec (builtin_decl_explicit (start_ix
), args
);
9241 gimple_set_location (g
, gimple_location (entry_stmt
));
9242 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
9246 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
9247 gsi_remove (&gsi
, true);
9252 gsi
= gsi_last_bb (region
->exit
);
9254 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
9255 gsi_remove (&gsi
, true);
9260 /* Expand the parallel region tree rooted at REGION. Expansion
9261 proceeds in depth-first order. Innermost regions are expanded
9262 first. This way, parallel regions that require a new function to
9263 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9264 internal dependencies in their body. */
9267 expand_omp (struct omp_region
*region
)
9271 location_t saved_location
;
9272 gimple inner_stmt
= NULL
;
9274 /* First, determine whether this is a combined parallel+workshare
9276 if (region
->type
== GIMPLE_OMP_PARALLEL
)
9277 determine_parallel_type (region
);
9279 if (region
->type
== GIMPLE_OMP_FOR
9280 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
9281 inner_stmt
= last_stmt (region
->inner
->entry
);
9284 expand_omp (region
->inner
);
9286 saved_location
= input_location
;
9287 if (gimple_has_location (last_stmt (region
->entry
)))
9288 input_location
= gimple_location (last_stmt (region
->entry
));
9290 switch (region
->type
)
9292 case GIMPLE_OMP_PARALLEL
:
9293 case GIMPLE_OMP_TASK
:
9294 expand_omp_taskreg (region
);
9297 case GIMPLE_OMP_FOR
:
9298 expand_omp_for (region
, inner_stmt
);
9301 case GIMPLE_OMP_SECTIONS
:
9302 expand_omp_sections (region
);
9305 case GIMPLE_OMP_SECTION
:
9306 /* Individual omp sections are handled together with their
9307 parent GIMPLE_OMP_SECTIONS region. */
9310 case GIMPLE_OMP_SINGLE
:
9311 expand_omp_single (region
);
9314 case GIMPLE_OMP_MASTER
:
9315 case GIMPLE_OMP_TASKGROUP
:
9316 case GIMPLE_OMP_ORDERED
:
9317 case GIMPLE_OMP_CRITICAL
:
9318 case GIMPLE_OMP_TEAMS
:
9319 expand_omp_synch (region
);
9322 case GIMPLE_OMP_ATOMIC_LOAD
:
9323 expand_omp_atomic (region
);
9326 case GIMPLE_OMP_TARGET
:
9327 expand_omp_target (region
);
9334 input_location
= saved_location
;
9335 region
= region
->next
;
9340 /* Helper for build_omp_regions. Scan the dominator tree starting at
9341 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9342 true, the function ends once a single tree is built (otherwise, whole
9343 forest of OMP constructs may be built). */
9346 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
9349 gimple_stmt_iterator gsi
;
9353 gsi
= gsi_last_bb (bb
);
9354 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
9356 struct omp_region
*region
;
9357 enum gimple_code code
;
9359 stmt
= gsi_stmt (gsi
);
9360 code
= gimple_code (stmt
);
9361 if (code
== GIMPLE_OMP_RETURN
)
9363 /* STMT is the return point out of region PARENT. Mark it
9364 as the exit point and make PARENT the immediately
9365 enclosing region. */
9366 gcc_assert (parent
);
9369 parent
= parent
->outer
;
9371 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
9373 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9374 GIMPLE_OMP_RETURN, but matches with
9375 GIMPLE_OMP_ATOMIC_LOAD. */
9376 gcc_assert (parent
);
9377 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
9380 parent
= parent
->outer
;
9382 else if (code
== GIMPLE_OMP_CONTINUE
)
9384 gcc_assert (parent
);
9387 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
9389 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9390 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9394 region
= new_omp_region (bb
, code
, parent
);
9396 if (code
== GIMPLE_OMP_TARGET
)
9398 switch (gimple_omp_target_kind (stmt
))
9400 case GF_OMP_TARGET_KIND_REGION
:
9401 case GF_OMP_TARGET_KIND_DATA
:
9402 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
9403 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
9404 case GF_OMP_TARGET_KIND_OACC_DATA
:
9406 case GF_OMP_TARGET_KIND_UPDATE
:
9407 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9408 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9409 /* ..., other than for those stand-alone directives... */
9416 /* ..., this directive becomes the parent for a new region. */
9422 if (single_tree
&& !parent
)
9425 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
9427 son
= next_dom_son (CDI_DOMINATORS
, son
))
9428 build_omp_regions_1 (son
, parent
, single_tree
);
9431 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9435 build_omp_regions_root (basic_block root
)
9437 gcc_assert (root_omp_region
== NULL
);
9438 build_omp_regions_1 (root
, NULL
, true);
9439 gcc_assert (root_omp_region
!= NULL
);
9442 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9445 omp_expand_local (basic_block head
)
9447 build_omp_regions_root (head
);
9448 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
9450 fprintf (dump_file
, "\nOMP region tree\n\n");
9451 dump_omp_region (dump_file
, root_omp_region
, 0);
9452 fprintf (dump_file
, "\n");
9455 remove_exit_barriers (root_omp_region
);
9456 expand_omp (root_omp_region
);
9458 free_omp_regions ();
9461 /* Scan the CFG and build a tree of OMP regions. Return the root of
9462 the OMP region tree. */
9465 build_omp_regions (void)
9467 gcc_assert (root_omp_region
== NULL
);
9468 calculate_dominance_info (CDI_DOMINATORS
);
9469 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
9472 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9475 execute_expand_omp (void)
9477 build_omp_regions ();
9479 if (!root_omp_region
)
9484 fprintf (dump_file
, "\nOMP region tree\n\n");
9485 dump_omp_region (dump_file
, root_omp_region
, 0);
9486 fprintf (dump_file
, "\n");
9489 remove_exit_barriers (root_omp_region
);
9491 expand_omp (root_omp_region
);
9493 cleanup_tree_cfg ();
9495 free_omp_regions ();
9500 /* OMP expansion -- the default pass, run before creation of SSA form. */
9504 const pass_data pass_data_expand_omp
=
9506 GIMPLE_PASS
, /* type */
9507 "ompexp", /* name */
9508 OPTGROUP_NONE
, /* optinfo_flags */
9509 TV_NONE
, /* tv_id */
9510 PROP_gimple_any
, /* properties_required */
9511 PROP_gimple_eomp
, /* properties_provided */
9512 0, /* properties_destroyed */
9513 0, /* todo_flags_start */
9514 0, /* todo_flags_finish */
9517 class pass_expand_omp
: public gimple_opt_pass
9520 pass_expand_omp (gcc::context
*ctxt
)
9521 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
9524 /* opt_pass methods: */
9525 virtual unsigned int execute (function
*)
9527 bool gate
= ((flag_cilkplus
!= 0 || flag_openacc
!= 0 || flag_openmp
!= 0
9528 || flag_openmp_simd
!= 0)
9531 /* This pass always runs, to provide PROP_gimple_eomp.
9532 But often, there is nothing to do. */
9536 return execute_expand_omp ();
9539 }; // class pass_expand_omp
9544 make_pass_expand_omp (gcc::context
*ctxt
)
9546 return new pass_expand_omp (ctxt
);
9551 const pass_data pass_data_expand_omp_ssa
=
9553 GIMPLE_PASS
, /* type */
9554 "ompexpssa", /* name */
9555 OPTGROUP_NONE
, /* optinfo_flags */
9556 TV_NONE
, /* tv_id */
9557 PROP_cfg
| PROP_ssa
, /* properties_required */
9558 PROP_gimple_eomp
, /* properties_provided */
9559 0, /* properties_destroyed */
9560 0, /* todo_flags_start */
9561 TODO_cleanup_cfg
| TODO_rebuild_alias
, /* todo_flags_finish */
9564 class pass_expand_omp_ssa
: public gimple_opt_pass
9567 pass_expand_omp_ssa (gcc::context
*ctxt
)
9568 : gimple_opt_pass (pass_data_expand_omp_ssa
, ctxt
)
9571 /* opt_pass methods: */
9572 virtual bool gate (function
*fun
)
9574 return !(fun
->curr_properties
& PROP_gimple_eomp
);
9576 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
9578 }; // class pass_expand_omp_ssa
9583 make_pass_expand_omp_ssa (gcc::context
*ctxt
)
9585 return new pass_expand_omp_ssa (ctxt
);
9588 /* Routines to lower OMP directives into OMP-GIMPLE. */
9590 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9591 convert it to gimple. */
9593 oacc_gimple_assign (tree dest
, tree_code op
, tree src
, gimple_seq
*seq
)
9597 if (TREE_CODE (TREE_TYPE (dest
)) != COMPLEX_TYPE
)
9599 stmt
= gimple_build_assign (dest
, op
, dest
, src
);
9600 gimple_seq_add_stmt (seq
, stmt
);
9604 tree t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9605 tree rdest
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9606 gimplify_assign (t
, rdest
, seq
);
9609 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9610 tree idest
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9611 gimplify_assign (t
, idest
, seq
);
9614 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9615 tree rsrc
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9616 gimplify_assign (t
, rsrc
, seq
);
9619 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9620 tree isrc
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9621 gimplify_assign (t
, isrc
, seq
);
9624 tree r
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9625 tree i
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9628 if (op
== PLUS_EXPR
)
9630 stmt
= gimple_build_assign (r
, op
, rdest
, rsrc
);
9631 gimple_seq_add_stmt (seq
, stmt
);
9633 stmt
= gimple_build_assign (i
, op
, idest
, isrc
);
9634 gimple_seq_add_stmt (seq
, stmt
);
9636 else if (op
== MULT_EXPR
)
9638 /* Let x = a + ib = dest, y = c + id = src.
9639 x * y = (ac - bd) + i(ad + bc) */
9640 tree ac
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9641 tree bd
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9642 tree ad
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9643 tree bc
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9645 stmt
= gimple_build_assign (ac
, MULT_EXPR
, rdest
, rsrc
);
9646 gimple_seq_add_stmt (seq
, stmt
);
9648 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, isrc
);
9649 gimple_seq_add_stmt (seq
, stmt
);
9651 stmt
= gimple_build_assign (r
, MINUS_EXPR
, ac
, bd
);
9652 gimple_seq_add_stmt (seq
, stmt
);
9654 stmt
= gimple_build_assign (ad
, MULT_EXPR
, rdest
, isrc
);
9655 gimple_seq_add_stmt (seq
, stmt
);
9657 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, rsrc
);
9658 gimple_seq_add_stmt (seq
, stmt
);
9660 stmt
= gimple_build_assign (i
, PLUS_EXPR
, ad
, bc
);
9661 gimple_seq_add_stmt (seq
, stmt
);
9666 result
= build2 (COMPLEX_EXPR
, TREE_TYPE (dest
), r
, i
);
9667 gimplify_assign (dest
, result
, seq
);
9670 /* Helper function to initialize local data for the reduction arrays.
9671 The reduction arrays need to be placed inside the calling function
9672 for accelerators, or else the host won't be able to preform the final
9676 oacc_initialize_reduction_data (tree clauses
, tree nthreads
,
9677 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9683 /* Find the innermost OpenACC parallel context. */
9684 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
9685 && (gimple_omp_target_kind (ctx
->stmt
)
9686 == GF_OMP_TARGET_KIND_OACC_PARALLEL
))
9690 gcc_checking_assert (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
9691 && (gimple_omp_target_kind (octx
->stmt
)
9692 == GF_OMP_TARGET_KIND_OACC_PARALLEL
));
9694 /* Extract the clauses. */
9695 oc
= gimple_omp_target_clauses (octx
->stmt
);
9697 /* Find the last outer clause. */
9698 for (; oc
&& OMP_CLAUSE_CHAIN (oc
); oc
= OMP_CLAUSE_CHAIN (oc
))
9701 /* Allocate arrays for each reduction variable. */
9702 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9704 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9707 tree var
= OMP_CLAUSE_DECL (c
);
9708 tree type
= get_base_type (var
);
9709 tree array
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
),
9713 /* Calculate size of the reduction array. */
9714 t
= create_tmp_var (TREE_TYPE (nthreads
));
9715 stmt
= gimple_build_assign (t
, MULT_EXPR
, nthreads
,
9716 fold_convert (TREE_TYPE (nthreads
),
9717 TYPE_SIZE_UNIT (type
)));
9718 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9720 size
= create_tmp_var (sizetype
);
9721 gimplify_assign (size
, fold_build1 (NOP_EXPR
, sizetype
, t
), stmt_seqp
);
9723 /* Now allocate memory for it. */
9724 call
= unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA
));
9725 stmt
= gimple_build_call (call
, 1, size
);
9726 gimple_call_set_lhs (stmt
, array
);
9727 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9729 /* Map this array into the accelerator. */
9731 /* Add the reduction array to the list of clauses. */
9733 t
= build_omp_clause (gimple_location (ctx
->stmt
), OMP_CLAUSE_MAP
);
9734 OMP_CLAUSE_SET_MAP_KIND (t
, GOMP_MAP_FORCE_FROM
);
9735 OMP_CLAUSE_DECL (t
) = x
;
9736 OMP_CLAUSE_CHAIN (t
) = NULL
;
9738 OMP_CLAUSE_CHAIN (oc
) = t
;
9740 gimple_omp_target_set_clauses (as_a
<gomp_target
*> (octx
->stmt
), t
);
9741 OMP_CLAUSE_SIZE (t
) = size
;
9746 /* Helper function to process the array of partial reductions. Nthreads
9747 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9748 cannot be used here, because nthreads on the host may be different than
9749 on the accelerator. */
9752 oacc_finalize_reduction_data (tree clauses
, tree nthreads
,
9753 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9755 tree c
, x
, var
, array
, loop_header
, loop_body
, loop_exit
, type
;
9760 let var = the original reduction variable
9761 let array = reduction variable array
9763 for (i = 0; i < nthreads; i++)
9767 loop_header
= create_artificial_label (UNKNOWN_LOCATION
);
9768 loop_body
= create_artificial_label (UNKNOWN_LOCATION
);
9769 loop_exit
= create_artificial_label (UNKNOWN_LOCATION
);
9771 /* Create and initialize an index variable. */
9772 tree ix
= create_tmp_var (sizetype
);
9773 gimplify_assign (ix
, fold_build1 (NOP_EXPR
, sizetype
, integer_zero_node
),
9776 /* Insert the loop header label here. */
9777 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_header
));
9779 /* Exit loop if ix >= nthreads. */
9780 x
= create_tmp_var (sizetype
);
9781 gimplify_assign (x
, fold_build1 (NOP_EXPR
, sizetype
, nthreads
), stmt_seqp
);
9782 stmt
= gimple_build_cond (GE_EXPR
, ix
, x
, loop_exit
, loop_body
);
9783 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9785 /* Insert the loop body label here. */
9786 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_body
));
9788 /* Collapse each reduction array, one element at a time. */
9789 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9791 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9794 tree_code reduction_code
= OMP_CLAUSE_REDUCTION_CODE (c
);
9796 /* reduction(-:var) sums up the partial results, so it acts
9797 identically to reduction(+:var). */
9798 if (reduction_code
== MINUS_EXPR
)
9799 reduction_code
= PLUS_EXPR
;
9801 /* Set up reduction variable var. */
9802 var
= OMP_CLAUSE_DECL (c
);
9803 type
= get_base_type (var
);
9804 array
= lookup_oacc_reduction (oacc_get_reduction_array_id
9805 (OMP_CLAUSE_DECL (c
)), ctx
);
9807 /* Calculate the array offset. */
9808 tree offset
= create_tmp_var (sizetype
);
9809 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
), stmt_seqp
);
9810 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, ix
);
9811 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9813 tree ptr
= create_tmp_var (TREE_TYPE (array
));
9814 stmt
= gimple_build_assign (ptr
, POINTER_PLUS_EXPR
, array
, offset
);
9815 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9817 /* Extract array[ix] into mem. */
9818 tree mem
= create_tmp_var (type
);
9819 gimplify_assign (mem
, build_simple_mem_ref (ptr
), stmt_seqp
);
9821 /* Find the original reduction variable. */
9822 if (is_reference (var
))
9823 var
= build_simple_mem_ref (var
);
9825 tree t
= create_tmp_var (type
);
9827 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, t
, var
);
9828 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9830 /* var = var op mem */
9831 switch (OMP_CLAUSE_REDUCTION_CODE (c
))
9833 case TRUTH_ANDIF_EXPR
:
9834 case TRUTH_ORIF_EXPR
:
9835 t
= fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c
), integer_type_node
,
9837 gimplify_and_add (t
, stmt_seqp
);
9840 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9841 oacc_gimple_assign (t
, OMP_CLAUSE_REDUCTION_CODE (c
), mem
,
9845 t
= fold_build1 (NOP_EXPR
, TREE_TYPE (var
), t
);
9846 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, var
, t
);
9847 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9850 /* Increment the induction variable. */
9851 tree one
= fold_build1 (NOP_EXPR
, sizetype
, integer_one_node
);
9852 stmt
= gimple_build_assign (ix
, PLUS_EXPR
, ix
, one
);
9853 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9855 /* Go back to the top of the loop. */
9856 gimple_seq_add_stmt (stmt_seqp
, gimple_build_goto (loop_header
));
9858 /* Place the loop exit label here. */
9859 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_exit
));
9862 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9863 scan that for reductions. */
9866 oacc_process_reduction_data (gimple_seq
*body
, gimple_seq
*in_stmt_seqp
,
9867 gimple_seq
*out_stmt_seqp
, omp_context
*ctx
)
9869 gimple_stmt_iterator gsi
;
9870 gimple_seq inner
= NULL
;
9872 /* A collapse clause may have inserted a new bind block. */
9873 gsi
= gsi_start (*body
);
9874 while (!gsi_end_p (gsi
))
9876 gimple stmt
= gsi_stmt (gsi
);
9877 if (gbind
*bind_stmt
= dyn_cast
<gbind
*> (stmt
))
9879 inner
= gimple_bind_body (bind_stmt
);
9881 gsi
= gsi_start (*body
);
9883 else if (dyn_cast
<gomp_for
*> (stmt
))
9889 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
9891 tree clauses
, nthreads
, t
, c
, acc_device
, acc_device_host
, call
,
9893 bool reduction_found
= false;
9895 gimple stmt
= gsi_stmt (gsi
);
9897 switch (gimple_code (stmt
))
9899 case GIMPLE_OMP_FOR
:
9900 clauses
= gimple_omp_for_clauses (stmt
);
9902 /* Search for a reduction clause. */
9903 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9904 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
9906 reduction_found
= true;
9910 if (!reduction_found
)
9913 ctx
= maybe_lookup_ctx (stmt
);
9916 /* Extract the number of threads. */
9917 nthreads
= create_tmp_var (sizetype
);
9918 t
= oacc_max_threads (ctx
);
9919 gimplify_assign (nthreads
, t
, in_stmt_seqp
);
9921 /* Determine if this is kernel will be executed on the host. */
9922 call
= builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE
);
9923 acc_device
= create_tmp_var (integer_type_node
, ".acc_device_type");
9924 stmt
= gimple_build_call (call
, 0);
9925 gimple_call_set_lhs (stmt
, acc_device
);
9926 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9928 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9929 acc_device_host
= create_tmp_var (integer_type_node
,
9930 ".acc_device_host");
9931 gimplify_assign (acc_device_host
,
9932 build_int_cst (integer_type_node
,
9936 enter
= create_artificial_label (UNKNOWN_LOCATION
);
9937 exit
= create_artificial_label (UNKNOWN_LOCATION
);
9939 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
9941 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9942 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
9943 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
9946 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
9948 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9949 gimplify_assign (acc_device_host
,
9950 build_int_cst (integer_type_node
,
9951 GOMP_DEVICE_HOST_NONSHM
),
9954 enter
= create_artificial_label (UNKNOWN_LOCATION
);
9955 exit
= create_artificial_label (UNKNOWN_LOCATION
);
9957 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
9959 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9960 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
9961 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
9964 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
9966 oacc_initialize_reduction_data (clauses
, nthreads
, in_stmt_seqp
,
9968 oacc_finalize_reduction_data (clauses
, nthreads
, out_stmt_seqp
, ctx
);
9971 // Scan for other directives which support reduction here.
9977 /* If ctx is a worksharing context inside of a cancellable parallel
9978 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9979 and conditional branch to parallel's cancel_label to handle
9980 cancellation in the implicit barrier. */
9983 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
9985 gimple omp_return
= gimple_seq_last_stmt (*body
);
9986 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
9987 if (gimple_omp_return_nowait_p (omp_return
))
9990 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
9991 && ctx
->outer
->cancellable
)
9993 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
9994 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
9995 tree lhs
= create_tmp_var (c_bool_type
);
9996 gimple_omp_return_set_lhs (omp_return
, lhs
);
9997 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
9998 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
9999 fold_convert (c_bool_type
,
10000 boolean_false_node
),
10001 ctx
->outer
->cancel_label
, fallthru_label
);
10002 gimple_seq_add_stmt (body
, g
);
10003 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
10007 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10008 CTX is the enclosing OMP context for the current statement. */
10011 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10013 tree block
, control
;
10014 gimple_stmt_iterator tgsi
;
10015 gomp_sections
*stmt
;
10017 gbind
*new_stmt
, *bind
;
10018 gimple_seq ilist
, dlist
, olist
, new_body
;
10020 stmt
= as_a
<gomp_sections
*> (gsi_stmt (*gsi_p
));
10022 push_gimplify_context ();
10026 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
10027 &ilist
, &dlist
, ctx
, NULL
);
10029 new_body
= gimple_omp_body (stmt
);
10030 gimple_omp_set_body (stmt
, NULL
);
10031 tgsi
= gsi_start (new_body
);
10032 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
10037 sec_start
= gsi_stmt (tgsi
);
10038 sctx
= maybe_lookup_ctx (sec_start
);
10041 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
10042 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
10043 GSI_CONTINUE_LINKING
);
10044 gimple_omp_set_body (sec_start
, NULL
);
10046 if (gsi_one_before_end_p (tgsi
))
10048 gimple_seq l
= NULL
;
10049 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
10051 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
10052 gimple_omp_section_set_last (sec_start
);
10055 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
10056 GSI_CONTINUE_LINKING
);
10059 block
= make_node (BLOCK
);
10060 bind
= gimple_build_bind (NULL
, new_body
, block
);
10063 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
10065 block
= make_node (BLOCK
);
10066 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10067 gsi_replace (gsi_p
, new_stmt
, true);
10069 pop_gimplify_context (new_stmt
);
10070 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10071 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10072 if (BLOCK_VARS (block
))
10073 TREE_USED (block
) = 1;
10076 gimple_seq_add_seq (&new_body
, ilist
);
10077 gimple_seq_add_stmt (&new_body
, stmt
);
10078 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
10079 gimple_seq_add_stmt (&new_body
, bind
);
10081 control
= create_tmp_var (unsigned_type_node
, ".section");
10082 t
= gimple_build_omp_continue (control
, control
);
10083 gimple_omp_sections_set_control (stmt
, control
);
10084 gimple_seq_add_stmt (&new_body
, t
);
10086 gimple_seq_add_seq (&new_body
, olist
);
10087 if (ctx
->cancellable
)
10088 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
10089 gimple_seq_add_seq (&new_body
, dlist
);
10091 new_body
= maybe_catch_exception (new_body
);
10093 t
= gimple_build_omp_return
10094 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
10095 OMP_CLAUSE_NOWAIT
));
10096 gimple_seq_add_stmt (&new_body
, t
);
10097 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
10099 gimple_bind_set_body (new_stmt
, new_body
);
10103 /* A subroutine of lower_omp_single. Expand the simple form of
10104 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10106 if (GOMP_single_start ())
10108 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10110 FIXME. It may be better to delay expanding the logic of this until
10111 pass_expand_omp. The expanded logic may make the job more difficult
10112 to a synchronization analysis pass. */
10115 lower_omp_single_simple (gomp_single
*single_stmt
, gimple_seq
*pre_p
)
10117 location_t loc
= gimple_location (single_stmt
);
10118 tree tlabel
= create_artificial_label (loc
);
10119 tree flabel
= create_artificial_label (loc
);
10123 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
10124 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)));
10125 call
= gimple_build_call (decl
, 0);
10126 gimple_call_set_lhs (call
, lhs
);
10127 gimple_seq_add_stmt (pre_p
, call
);
10129 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
10130 fold_convert_loc (loc
, TREE_TYPE (lhs
),
10131 boolean_true_node
),
10133 gimple_seq_add_stmt (pre_p
, cond
);
10134 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
10135 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10136 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
10140 /* A subroutine of lower_omp_single. Expand the simple form of
10141 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10143 #pragma omp single copyprivate (a, b, c)
10145 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10148 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10154 GOMP_single_copy_end (©out);
10165 FIXME. It may be better to delay expanding the logic of this until
10166 pass_expand_omp. The expanded logic may make the job more difficult
10167 to a synchronization analysis pass. */
10170 lower_omp_single_copy (gomp_single
*single_stmt
, gimple_seq
*pre_p
,
10173 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
10174 gimple_seq copyin_seq
;
10175 location_t loc
= gimple_location (single_stmt
);
10177 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
10179 ptr_type
= build_pointer_type (ctx
->record_type
);
10180 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
10182 l0
= create_artificial_label (loc
);
10183 l1
= create_artificial_label (loc
);
10184 l2
= create_artificial_label (loc
);
10186 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
10187 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
10188 t
= fold_convert_loc (loc
, ptr_type
, t
);
10189 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
10191 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
10192 build_int_cst (ptr_type
, 0));
10193 t
= build3 (COND_EXPR
, void_type_node
, t
,
10194 build_and_jump (&l0
), build_and_jump (&l1
));
10195 gimplify_and_add (t
, pre_p
);
10197 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
10199 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10202 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
10205 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10206 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
10207 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
10208 gimplify_and_add (t
, pre_p
);
10210 t
= build_and_jump (&l2
);
10211 gimplify_and_add (t
, pre_p
);
10213 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
10215 gimple_seq_add_seq (pre_p
, copyin_seq
);
10217 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
10221 /* Expand code for an OpenMP single directive. */
10224 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10228 gomp_single
*single_stmt
= as_a
<gomp_single
*> (gsi_stmt (*gsi_p
));
10230 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
10232 push_gimplify_context ();
10234 block
= make_node (BLOCK
);
10235 bind
= gimple_build_bind (NULL
, NULL
, block
);
10236 gsi_replace (gsi_p
, bind
, true);
10239 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
10240 &bind_body
, &dlist
, ctx
, NULL
);
10241 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
10243 gimple_seq_add_stmt (&bind_body
, single_stmt
);
10245 if (ctx
->record_type
)
10246 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
10248 lower_omp_single_simple (single_stmt
, &bind_body
);
10250 gimple_omp_set_body (single_stmt
, NULL
);
10252 gimple_seq_add_seq (&bind_body
, dlist
);
10254 bind_body
= maybe_catch_exception (bind_body
);
10256 t
= gimple_build_omp_return
10257 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
10258 OMP_CLAUSE_NOWAIT
));
10259 gimple_seq_add_stmt (&bind_body_tail
, t
);
10260 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
10261 if (ctx
->record_type
)
10263 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
10264 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
10265 TREE_THIS_VOLATILE (clobber
) = 1;
10266 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
10267 clobber
), GSI_SAME_STMT
);
10269 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
10270 gimple_bind_set_body (bind
, bind_body
);
10272 pop_gimplify_context (bind
);
10274 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10275 BLOCK_VARS (block
) = ctx
->block_vars
;
10276 if (BLOCK_VARS (block
))
10277 TREE_USED (block
) = 1;
10281 /* Expand code for an OpenMP master directive. */
10284 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10286 tree block
, lab
= NULL
, x
, bfn_decl
;
10287 gimple stmt
= gsi_stmt (*gsi_p
);
10289 location_t loc
= gimple_location (stmt
);
10292 push_gimplify_context ();
10294 block
= make_node (BLOCK
);
10295 bind
= gimple_build_bind (NULL
, NULL
, block
);
10296 gsi_replace (gsi_p
, bind
, true);
10297 gimple_bind_add_stmt (bind
, stmt
);
10299 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
10300 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
10301 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
10302 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
10304 gimplify_and_add (x
, &tseq
);
10305 gimple_bind_add_seq (bind
, tseq
);
10307 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10308 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10309 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10310 gimple_omp_set_body (stmt
, NULL
);
10312 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
10314 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10316 pop_gimplify_context (bind
);
10318 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10319 BLOCK_VARS (block
) = ctx
->block_vars
;
10323 /* Expand code for an OpenMP taskgroup directive. */
10326 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10328 gimple stmt
= gsi_stmt (*gsi_p
);
10331 tree block
= make_node (BLOCK
);
10333 bind
= gimple_build_bind (NULL
, NULL
, block
);
10334 gsi_replace (gsi_p
, bind
, true);
10335 gimple_bind_add_stmt (bind
, stmt
);
10337 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
10339 gimple_bind_add_stmt (bind
, x
);
10341 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10342 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10343 gimple_omp_set_body (stmt
, NULL
);
10345 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10347 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10348 BLOCK_VARS (block
) = ctx
->block_vars
;
10352 /* Expand code for an OpenMP ordered directive. */
10355 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10358 gimple stmt
= gsi_stmt (*gsi_p
);
10362 push_gimplify_context ();
10364 block
= make_node (BLOCK
);
10365 bind
= gimple_build_bind (NULL
, NULL
, block
);
10366 gsi_replace (gsi_p
, bind
, true);
10367 gimple_bind_add_stmt (bind
, stmt
);
10369 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
10371 gimple_bind_add_stmt (bind
, x
);
10373 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10374 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10375 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10376 gimple_omp_set_body (stmt
, NULL
);
10378 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
10379 gimple_bind_add_stmt (bind
, x
);
10381 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10383 pop_gimplify_context (bind
);
10385 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10386 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10390 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10391 substitution of a couple of function calls. But in the NAMED case,
10392 requires that languages coordinate a symbol name. It is therefore
10393 best put here in common code. */
10395 static GTY(()) hash_map
<tree
, tree
> *critical_name_mutexes
;
10398 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10401 tree name
, lock
, unlock
;
10402 gomp_critical
*stmt
= as_a
<gomp_critical
*> (gsi_stmt (*gsi_p
));
10404 location_t loc
= gimple_location (stmt
);
10407 name
= gimple_omp_critical_name (stmt
);
10412 if (!critical_name_mutexes
)
10413 critical_name_mutexes
= hash_map
<tree
, tree
>::create_ggc (10);
10415 tree
*n
= critical_name_mutexes
->get (name
);
10420 decl
= create_tmp_var_raw (ptr_type_node
);
10422 new_str
= ACONCAT ((".gomp_critical_user_",
10423 IDENTIFIER_POINTER (name
), NULL
));
10424 DECL_NAME (decl
) = get_identifier (new_str
);
10425 TREE_PUBLIC (decl
) = 1;
10426 TREE_STATIC (decl
) = 1;
10427 DECL_COMMON (decl
) = 1;
10428 DECL_ARTIFICIAL (decl
) = 1;
10429 DECL_IGNORED_P (decl
) = 1;
10431 varpool_node::finalize_decl (decl
);
10433 critical_name_mutexes
->put (name
, decl
);
10438 /* If '#pragma omp critical' is inside offloaded region or
10439 inside function marked as offloadable, the symbol must be
10440 marked as offloadable too. */
10442 if (cgraph_node::get (current_function_decl
)->offloadable
)
10443 varpool_node::get_create (decl
)->offloadable
= 1;
10445 for (octx
= ctx
->outer
; octx
; octx
= octx
->outer
)
10446 if (is_gimple_omp_offloaded (octx
->stmt
))
10448 varpool_node::get_create (decl
)->offloadable
= 1;
10452 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
10453 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
10455 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
10456 unlock
= build_call_expr_loc (loc
, unlock
, 1,
10457 build_fold_addr_expr_loc (loc
, decl
));
10461 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
10462 lock
= build_call_expr_loc (loc
, lock
, 0);
10464 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
10465 unlock
= build_call_expr_loc (loc
, unlock
, 0);
10468 push_gimplify_context ();
10470 block
= make_node (BLOCK
);
10471 bind
= gimple_build_bind (NULL
, NULL
, block
);
10472 gsi_replace (gsi_p
, bind
, true);
10473 gimple_bind_add_stmt (bind
, stmt
);
10475 tbody
= gimple_bind_body (bind
);
10476 gimplify_and_add (lock
, &tbody
);
10477 gimple_bind_set_body (bind
, tbody
);
10479 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10480 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10481 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10482 gimple_omp_set_body (stmt
, NULL
);
10484 tbody
= gimple_bind_body (bind
);
10485 gimplify_and_add (unlock
, &tbody
);
10486 gimple_bind_set_body (bind
, tbody
);
10488 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10490 pop_gimplify_context (bind
);
10491 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10492 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10496 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10497 for a lastprivate clause. Given a loop control predicate of (V
10498 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10499 is appended to *DLIST, iterator initialization is appended to
10503 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
10504 gimple_seq
*dlist
, struct omp_context
*ctx
)
10506 tree clauses
, cond
, vinit
;
10507 enum tree_code cond_code
;
10510 cond_code
= fd
->loop
.cond_code
;
10511 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
10513 /* When possible, use a strict equality expression. This can let VRP
10514 type optimizations deduce the value and remove a copy. */
10515 if (tree_fits_shwi_p (fd
->loop
.step
))
10517 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
10518 if (step
== 1 || step
== -1)
10519 cond_code
= EQ_EXPR
;
10522 tree n2
= fd
->loop
.n2
;
10523 if (fd
->collapse
> 1
10524 && TREE_CODE (n2
) != INTEGER_CST
10525 && gimple_omp_for_combined_into_p (fd
->for_stmt
)
10526 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_FOR
)
10528 gomp_for
*gfor
= as_a
<gomp_for
*> (ctx
->outer
->stmt
);
10529 if (gimple_omp_for_kind (gfor
) == GF_OMP_FOR_KIND_FOR
)
10531 struct omp_for_data outer_fd
;
10532 extract_omp_for_data (gfor
, &outer_fd
, NULL
);
10533 n2
= fold_convert (TREE_TYPE (n2
), outer_fd
.loop
.n2
);
10536 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, n2
);
10538 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
10540 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
10541 if (!gimple_seq_empty_p (stmts
))
10543 gimple_seq_add_seq (&stmts
, *dlist
);
10546 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10547 vinit
= fd
->loop
.n1
;
10548 if (cond_code
== EQ_EXPR
10549 && tree_fits_shwi_p (fd
->loop
.n2
)
10550 && ! integer_zerop (fd
->loop
.n2
))
10551 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
10553 vinit
= unshare_expr (vinit
);
10555 /* Initialize the iterator variable, so that threads that don't execute
10556 any iterations don't execute the lastprivate clauses by accident. */
10557 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
10562 /* Lower code for an OMP loop directive. */
10565 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10567 tree
*rhs_p
, block
;
10568 struct omp_for_data fd
, *fdp
= NULL
;
10569 gomp_for
*stmt
= as_a
<gomp_for
*> (gsi_stmt (*gsi_p
));
10571 gimple_seq omp_for_body
, body
, dlist
;
10574 push_gimplify_context ();
10576 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
10578 block
= make_node (BLOCK
);
10579 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10580 /* Replace at gsi right away, so that 'stmt' is no member
10581 of a sequence anymore as we're going to add to to a different
10583 gsi_replace (gsi_p
, new_stmt
, true);
10585 /* Move declaration of temporaries in the loop body before we make
10587 omp_for_body
= gimple_omp_body (stmt
);
10588 if (!gimple_seq_empty_p (omp_for_body
)
10589 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
10592 = as_a
<gbind
*> (gimple_seq_first_stmt (omp_for_body
));
10593 tree vars
= gimple_bind_vars (inner_bind
);
10594 gimple_bind_append_vars (new_stmt
, vars
);
10595 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10596 keep them on the inner_bind and it's block. */
10597 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
10598 if (gimple_bind_block (inner_bind
))
10599 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
10602 if (gimple_omp_for_combined_into_p (stmt
))
10604 extract_omp_for_data (stmt
, &fd
, NULL
);
10607 /* We need two temporaries with fd.loop.v type (istart/iend)
10608 and then (fd.collapse - 1) temporaries with the same
10609 type for count2 ... countN-1 vars if not constant. */
10611 tree type
= fd
.iter_type
;
10612 if (fd
.collapse
> 1
10613 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
10614 count
+= fd
.collapse
- 1;
10615 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
10616 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
10617 tree clauses
= *pc
;
10620 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
10621 OMP_CLAUSE__LOOPTEMP_
);
10622 for (i
= 0; i
< count
; i
++)
10627 gcc_assert (outerc
);
10628 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
10629 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
10630 OMP_CLAUSE__LOOPTEMP_
);
10634 temp
= create_tmp_var (type
);
10635 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
10637 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
10638 OMP_CLAUSE_DECL (*pc
) = temp
;
10639 pc
= &OMP_CLAUSE_CHAIN (*pc
);
10644 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10647 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
10649 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
10651 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10653 /* Lower the header expressions. At this point, we can assume that
10654 the header is of the form:
10656 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10658 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10659 using the .omp_data_s mapping, if needed. */
10660 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
10662 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
10663 if (!is_gimple_min_invariant (*rhs_p
))
10664 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10666 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
10667 if (!is_gimple_min_invariant (*rhs_p
))
10668 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10670 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
10671 if (!is_gimple_min_invariant (*rhs_p
))
10672 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10675 /* Once lowered, extract the bounds and clauses. */
10676 extract_omp_for_data (stmt
, &fd
, NULL
);
10678 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
10680 gimple_seq_add_stmt (&body
, stmt
);
10681 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
10683 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
10686 /* After the loop, add exit clauses. */
10687 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
10689 if (ctx
->cancellable
)
10690 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
10692 gimple_seq_add_seq (&body
, dlist
);
10694 body
= maybe_catch_exception (body
);
10696 /* Region exit marker goes at the end of the loop body. */
10697 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
10698 maybe_add_implicit_barrier_cancel (ctx
, &body
);
10699 pop_gimplify_context (new_stmt
);
10701 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10702 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
10703 if (BLOCK_VARS (block
))
10704 TREE_USED (block
) = 1;
10706 gimple_bind_set_body (new_stmt
, body
);
10707 gimple_omp_set_body (stmt
, NULL
);
10708 gimple_omp_for_set_pre_body (stmt
, NULL
);
10711 /* Callback for walk_stmts. Check if the current statement only contains
10712 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10715 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
10716 bool *handled_ops_p
,
10717 struct walk_stmt_info
*wi
)
10719 int *info
= (int *) wi
->info
;
10720 gimple stmt
= gsi_stmt (*gsi_p
);
10722 *handled_ops_p
= true;
10723 switch (gimple_code (stmt
))
10727 case GIMPLE_OMP_FOR
:
10728 case GIMPLE_OMP_SECTIONS
:
10729 *info
= *info
== 0 ? 1 : -1;
10738 struct omp_taskcopy_context
10740 /* This field must be at the beginning, as we do "inheritance": Some
10741 callback functions for tree-inline.c (e.g., omp_copy_decl)
10742 receive a copy_body_data pointer that is up-casted to an
10743 omp_context pointer. */
10749 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
10751 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
10753 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
10754 return create_tmp_var (TREE_TYPE (var
));
10760 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
10762 tree name
, new_fields
= NULL
, type
, f
;
10764 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
10765 name
= DECL_NAME (TYPE_NAME (orig_type
));
10766 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
10767 TYPE_DECL
, name
, type
);
10768 TYPE_NAME (type
) = name
;
10770 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
10772 tree new_f
= copy_node (f
);
10773 DECL_CONTEXT (new_f
) = type
;
10774 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
10775 TREE_CHAIN (new_f
) = new_fields
;
10776 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10777 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10778 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
10780 new_fields
= new_f
;
10781 tcctx
->cb
.decl_map
->put (f
, new_f
);
10783 TYPE_FIELDS (type
) = nreverse (new_fields
);
10784 layout_type (type
);
10788 /* Create task copyfn. */
10791 create_task_copyfn (gomp_task
*task_stmt
, omp_context
*ctx
)
10793 struct function
*child_cfun
;
10794 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
10795 tree record_type
, srecord_type
, bind
, list
;
10796 bool record_needs_remap
= false, srecord_needs_remap
= false;
10798 struct omp_taskcopy_context tcctx
;
10799 location_t loc
= gimple_location (task_stmt
);
10801 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
10802 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
10803 gcc_assert (child_cfun
->cfg
== NULL
);
10804 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
10806 /* Reset DECL_CONTEXT on function arguments. */
10807 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
10808 DECL_CONTEXT (t
) = child_fn
;
10810 /* Populate the function. */
10811 push_gimplify_context ();
10812 push_cfun (child_cfun
);
10814 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
10815 TREE_SIDE_EFFECTS (bind
) = 1;
10817 DECL_SAVED_TREE (child_fn
) = bind
;
10818 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
10820 /* Remap src and dst argument types if needed. */
10821 record_type
= ctx
->record_type
;
10822 srecord_type
= ctx
->srecord_type
;
10823 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
10824 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10826 record_needs_remap
= true;
10829 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
10830 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10832 srecord_needs_remap
= true;
10836 if (record_needs_remap
|| srecord_needs_remap
)
10838 memset (&tcctx
, '\0', sizeof (tcctx
));
10839 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
10840 tcctx
.cb
.dst_fn
= child_fn
;
10841 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
10842 gcc_checking_assert (tcctx
.cb
.src_node
);
10843 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
10844 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
10845 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
10846 tcctx
.cb
.eh_lp_nr
= 0;
10847 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
10848 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
10851 if (record_needs_remap
)
10852 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
10853 if (srecord_needs_remap
)
10854 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
10857 tcctx
.cb
.decl_map
= NULL
;
10859 arg
= DECL_ARGUMENTS (child_fn
);
10860 TREE_TYPE (arg
) = build_pointer_type (record_type
);
10861 sarg
= DECL_CHAIN (arg
);
10862 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
10864 /* First pass: initialize temporaries used in record_type and srecord_type
10865 sizes and field offsets. */
10866 if (tcctx
.cb
.decl_map
)
10867 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10868 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
10872 decl
= OMP_CLAUSE_DECL (c
);
10873 p
= tcctx
.cb
.decl_map
->get (decl
);
10876 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10877 sf
= (tree
) n
->value
;
10878 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10879 src
= build_simple_mem_ref_loc (loc
, sarg
);
10880 src
= omp_build_component_ref (src
, sf
);
10881 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
10882 append_to_statement_list (t
, &list
);
10885 /* Second pass: copy shared var pointers and copy construct non-VLA
10886 firstprivate vars. */
10887 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10888 switch (OMP_CLAUSE_CODE (c
))
10890 case OMP_CLAUSE_SHARED
:
10891 decl
= OMP_CLAUSE_DECL (c
);
10892 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10895 f
= (tree
) n
->value
;
10896 if (tcctx
.cb
.decl_map
)
10897 f
= *tcctx
.cb
.decl_map
->get (f
);
10898 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10899 sf
= (tree
) n
->value
;
10900 if (tcctx
.cb
.decl_map
)
10901 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10902 src
= build_simple_mem_ref_loc (loc
, sarg
);
10903 src
= omp_build_component_ref (src
, sf
);
10904 dst
= build_simple_mem_ref_loc (loc
, arg
);
10905 dst
= omp_build_component_ref (dst
, f
);
10906 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
10907 append_to_statement_list (t
, &list
);
10909 case OMP_CLAUSE_FIRSTPRIVATE
:
10910 decl
= OMP_CLAUSE_DECL (c
);
10911 if (is_variable_sized (decl
))
10913 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10916 f
= (tree
) n
->value
;
10917 if (tcctx
.cb
.decl_map
)
10918 f
= *tcctx
.cb
.decl_map
->get (f
);
10919 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10922 sf
= (tree
) n
->value
;
10923 if (tcctx
.cb
.decl_map
)
10924 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10925 src
= build_simple_mem_ref_loc (loc
, sarg
);
10926 src
= omp_build_component_ref (src
, sf
);
10927 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
10928 src
= build_simple_mem_ref_loc (loc
, src
);
10932 dst
= build_simple_mem_ref_loc (loc
, arg
);
10933 dst
= omp_build_component_ref (dst
, f
);
10934 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
10935 append_to_statement_list (t
, &list
);
10937 case OMP_CLAUSE_PRIVATE
:
10938 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
10940 decl
= OMP_CLAUSE_DECL (c
);
10941 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10942 f
= (tree
) n
->value
;
10943 if (tcctx
.cb
.decl_map
)
10944 f
= *tcctx
.cb
.decl_map
->get (f
);
10945 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10948 sf
= (tree
) n
->value
;
10949 if (tcctx
.cb
.decl_map
)
10950 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10951 src
= build_simple_mem_ref_loc (loc
, sarg
);
10952 src
= omp_build_component_ref (src
, sf
);
10953 if (use_pointer_for_field (decl
, NULL
))
10954 src
= build_simple_mem_ref_loc (loc
, src
);
10958 dst
= build_simple_mem_ref_loc (loc
, arg
);
10959 dst
= omp_build_component_ref (dst
, f
);
10960 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
10961 append_to_statement_list (t
, &list
);
10967 /* Last pass: handle VLA firstprivates. */
10968 if (tcctx
.cb
.decl_map
)
10969 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10970 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
10974 decl
= OMP_CLAUSE_DECL (c
);
10975 if (!is_variable_sized (decl
))
10977 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10980 f
= (tree
) n
->value
;
10981 f
= *tcctx
.cb
.decl_map
->get (f
);
10982 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
10983 ind
= DECL_VALUE_EXPR (decl
);
10984 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
10985 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
10986 n
= splay_tree_lookup (ctx
->sfield_map
,
10987 (splay_tree_key
) TREE_OPERAND (ind
, 0));
10988 sf
= (tree
) n
->value
;
10989 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10990 src
= build_simple_mem_ref_loc (loc
, sarg
);
10991 src
= omp_build_component_ref (src
, sf
);
10992 src
= build_simple_mem_ref_loc (loc
, src
);
10993 dst
= build_simple_mem_ref_loc (loc
, arg
);
10994 dst
= omp_build_component_ref (dst
, f
);
10995 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
10996 append_to_statement_list (t
, &list
);
10997 n
= splay_tree_lookup (ctx
->field_map
,
10998 (splay_tree_key
) TREE_OPERAND (ind
, 0));
10999 df
= (tree
) n
->value
;
11000 df
= *tcctx
.cb
.decl_map
->get (df
);
11001 ptr
= build_simple_mem_ref_loc (loc
, arg
);
11002 ptr
= omp_build_component_ref (ptr
, df
);
11003 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
11004 build_fold_addr_expr_loc (loc
, dst
));
11005 append_to_statement_list (t
, &list
);
11008 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
11009 append_to_statement_list (t
, &list
);
11011 if (tcctx
.cb
.decl_map
)
11012 delete tcctx
.cb
.decl_map
;
11013 pop_gimplify_context (NULL
);
11014 BIND_EXPR_BODY (bind
) = list
;
11019 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
11023 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
11025 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
11026 OMP_CLAUSE_DEPEND
);
11027 gcc_assert (clauses
);
11028 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11029 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
11030 switch (OMP_CLAUSE_DEPEND_KIND (c
))
11032 case OMP_CLAUSE_DEPEND_IN
:
11035 case OMP_CLAUSE_DEPEND_OUT
:
11036 case OMP_CLAUSE_DEPEND_INOUT
:
11040 gcc_unreachable ();
11042 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
11043 tree array
= create_tmp_var (type
);
11044 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
11046 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
11047 gimple_seq_add_stmt (iseq
, g
);
11048 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
11050 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
11051 gimple_seq_add_stmt (iseq
, g
);
11052 for (i
= 0; i
< 2; i
++)
11054 if ((i
? n_in
: n_out
) == 0)
11056 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11057 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
11058 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
11060 tree t
= OMP_CLAUSE_DECL (c
);
11061 t
= fold_convert (ptr_type_node
, t
);
11062 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
11063 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
11064 NULL_TREE
, NULL_TREE
);
11065 g
= gimple_build_assign (r
, t
);
11066 gimple_seq_add_stmt (iseq
, g
);
11069 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
11070 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
11071 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
11072 OMP_CLAUSE_CHAIN (c
) = *p
;
11074 tree clobber
= build_constructor (type
, NULL
);
11075 TREE_THIS_VOLATILE (clobber
) = 1;
11076 g
= gimple_build_assign (array
, clobber
);
11077 gimple_seq_add_stmt (oseq
, g
);
11080 /* Lower the OpenMP parallel or task directive in the current statement
11081 in GSI_P. CTX holds context information for the directive. */
11084 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11088 gimple stmt
= gsi_stmt (*gsi_p
);
11089 gbind
*par_bind
, *bind
, *dep_bind
= NULL
;
11090 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
11091 location_t loc
= gimple_location (stmt
);
11093 clauses
= gimple_omp_taskreg_clauses (stmt
);
11095 = as_a
<gbind
*> (gimple_seq_first_stmt (gimple_omp_body (stmt
)));
11096 par_body
= gimple_bind_body (par_bind
);
11097 child_fn
= ctx
->cb
.dst_fn
;
11098 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
11099 && !gimple_omp_parallel_combined_p (stmt
))
11101 struct walk_stmt_info wi
;
11104 memset (&wi
, 0, sizeof (wi
));
11106 wi
.val_only
= true;
11107 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
11109 gimple_omp_parallel_set_combined_p (stmt
, true);
11111 gimple_seq dep_ilist
= NULL
;
11112 gimple_seq dep_olist
= NULL
;
11113 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
11114 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
11116 push_gimplify_context ();
11117 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
11118 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
11121 if (ctx
->srecord_type
)
11122 create_task_copyfn (as_a
<gomp_task
*> (stmt
), ctx
);
11124 push_gimplify_context ();
11129 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
11130 lower_omp (&par_body
, ctx
);
11131 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
11132 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
11134 /* Declare all the variables created by mapping and the variables
11135 declared in the scope of the parallel body. */
11136 record_vars_into (ctx
->block_vars
, child_fn
);
11137 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
11139 if (ctx
->record_type
)
11142 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
11143 : ctx
->record_type
, ".omp_data_o");
11144 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11145 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11146 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
11151 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
11152 lower_send_shared_vars (&ilist
, &olist
, ctx
);
11154 if (ctx
->record_type
)
11156 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
11157 TREE_THIS_VOLATILE (clobber
) = 1;
11158 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11162 /* Once all the expansions are done, sequence all the different
11163 fragments inside gimple_omp_body. */
11167 if (ctx
->record_type
)
11169 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11170 /* fixup_child_record_type might have changed receiver_decl's type. */
11171 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11172 gimple_seq_add_stmt (&new_body
,
11173 gimple_build_assign (ctx
->receiver_decl
, t
));
11176 gimple_seq_add_seq (&new_body
, par_ilist
);
11177 gimple_seq_add_seq (&new_body
, par_body
);
11178 gimple_seq_add_seq (&new_body
, par_rlist
);
11179 if (ctx
->cancellable
)
11180 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
11181 gimple_seq_add_seq (&new_body
, par_olist
);
11182 new_body
= maybe_catch_exception (new_body
);
11183 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
)
11184 gimple_seq_add_stmt (&new_body
,
11185 gimple_build_omp_continue (integer_zero_node
,
11186 integer_zero_node
));
11187 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11188 gimple_omp_set_body (stmt
, new_body
);
11190 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
11191 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
11192 gimple_bind_add_seq (bind
, ilist
);
11193 gimple_bind_add_stmt (bind
, stmt
);
11194 gimple_bind_add_seq (bind
, olist
);
11196 pop_gimplify_context (NULL
);
11200 gimple_bind_add_seq (dep_bind
, dep_ilist
);
11201 gimple_bind_add_stmt (dep_bind
, bind
);
11202 gimple_bind_add_seq (dep_bind
, dep_olist
);
11203 pop_gimplify_context (dep_bind
);
11207 /* Lower the GIMPLE_OMP_TARGET in the current statement
11208 in GSI_P. CTX holds context information for the directive. */
11211 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11214 tree child_fn
, t
, c
;
11215 gomp_target
*stmt
= as_a
<gomp_target
*> (gsi_stmt (*gsi_p
));
11216 gbind
*tgt_bind
, *bind
;
11217 gimple_seq tgt_body
, olist
, ilist
, orlist
, irlist
, new_body
;
11218 location_t loc
= gimple_location (stmt
);
11219 bool offloaded
, data_region
;
11220 unsigned int map_cnt
= 0;
11222 offloaded
= is_gimple_omp_offloaded (stmt
);
11223 switch (gimple_omp_target_kind (stmt
))
11225 case GF_OMP_TARGET_KIND_REGION
:
11226 case GF_OMP_TARGET_KIND_UPDATE
:
11227 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
11228 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
11229 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
11230 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
11231 data_region
= false;
11233 case GF_OMP_TARGET_KIND_DATA
:
11234 case GF_OMP_TARGET_KIND_OACC_DATA
:
11235 data_region
= true;
11238 gcc_unreachable ();
11241 clauses
= gimple_omp_target_clauses (stmt
);
11247 tgt_bind
= gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt
));
11248 tgt_body
= gimple_bind_body (tgt_bind
);
11250 else if (data_region
)
11251 tgt_body
= gimple_omp_body (stmt
);
11252 child_fn
= ctx
->cb
.dst_fn
;
11254 push_gimplify_context ();
11259 && is_gimple_omp_oacc (stmt
))
11260 oacc_process_reduction_data (&tgt_body
, &irlist
, &orlist
, ctx
);
11262 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11263 switch (OMP_CLAUSE_CODE (c
))
11269 case OMP_CLAUSE_MAP
:
11270 #ifdef ENABLE_CHECKING
11271 /* First check what we're prepared to handle in the following. */
11272 switch (OMP_CLAUSE_MAP_KIND (c
))
11274 case GOMP_MAP_ALLOC
:
11276 case GOMP_MAP_FROM
:
11277 case GOMP_MAP_TOFROM
:
11278 case GOMP_MAP_POINTER
:
11279 case GOMP_MAP_TO_PSET
:
11281 case GOMP_MAP_FORCE_ALLOC
:
11282 case GOMP_MAP_FORCE_TO
:
11283 case GOMP_MAP_FORCE_FROM
:
11284 case GOMP_MAP_FORCE_TOFROM
:
11285 case GOMP_MAP_FORCE_PRESENT
:
11286 case GOMP_MAP_FORCE_DEALLOC
:
11287 case GOMP_MAP_FORCE_DEVICEPTR
:
11288 gcc_assert (is_gimple_omp_oacc (stmt
));
11291 gcc_unreachable ();
11295 case OMP_CLAUSE_TO
:
11296 case OMP_CLAUSE_FROM
:
11297 var
= OMP_CLAUSE_DECL (c
);
11300 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
11301 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11306 if (DECL_SIZE (var
)
11307 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
11309 tree var2
= DECL_VALUE_EXPR (var
);
11310 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
11311 var2
= TREE_OPERAND (var2
, 0);
11312 gcc_assert (DECL_P (var2
));
11316 if (!maybe_lookup_field (var
, ctx
))
11321 x
= build_receiver_ref (var
, true, ctx
);
11322 tree new_var
= lookup_decl (var
, ctx
);
11323 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11324 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11325 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
11326 x
= build_simple_mem_ref (x
);
11327 SET_DECL_VALUE_EXPR (new_var
, x
);
11328 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
11335 target_nesting_level
++;
11336 lower_omp (&tgt_body
, ctx
);
11337 target_nesting_level
--;
11339 else if (data_region
)
11340 lower_omp (&tgt_body
, ctx
);
11344 /* Declare all the variables created by mapping and the variables
11345 declared in the scope of the target body. */
11346 record_vars_into (ctx
->block_vars
, child_fn
);
11347 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
11352 if (ctx
->record_type
)
11355 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
11356 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11357 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11358 t
= make_tree_vec (3);
11359 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
11360 TREE_VEC_ELT (t
, 1)
11361 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
11362 ".omp_data_sizes");
11363 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
11364 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
11365 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
11368 if (is_gimple_omp_oacc (stmt
))
11370 tkind_type
= short_unsigned_type_node
;
11375 tkind_type
= unsigned_char_type_node
;
11378 TREE_VEC_ELT (t
, 2)
11379 = create_tmp_var (build_array_type_nelts (tkind_type
, map_cnt
),
11380 ".omp_data_kinds");
11381 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
11382 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
11383 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
11384 gimple_omp_target_set_data_arg (stmt
, t
);
11386 vec
<constructor_elt
, va_gc
> *vsize
;
11387 vec
<constructor_elt
, va_gc
> *vkind
;
11388 vec_alloc (vsize
, map_cnt
);
11389 vec_alloc (vkind
, map_cnt
);
11390 unsigned int map_idx
= 0;
11392 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11393 switch (OMP_CLAUSE_CODE (c
))
11399 case OMP_CLAUSE_MAP
:
11400 case OMP_CLAUSE_TO
:
11401 case OMP_CLAUSE_FROM
:
11403 ovar
= OMP_CLAUSE_DECL (c
);
11404 if (!DECL_P (ovar
))
11406 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11407 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11409 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
11410 == get_base_address (ovar
));
11411 nc
= OMP_CLAUSE_CHAIN (c
);
11412 ovar
= OMP_CLAUSE_DECL (nc
);
11416 tree x
= build_sender_ref (ovar
, ctx
);
11418 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
11419 gimplify_assign (x
, v
, &ilist
);
11425 if (DECL_SIZE (ovar
)
11426 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
11428 tree ovar2
= DECL_VALUE_EXPR (ovar
);
11429 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
11430 ovar2
= TREE_OPERAND (ovar2
, 0);
11431 gcc_assert (DECL_P (ovar2
));
11434 if (!maybe_lookup_field (ovar
, ctx
))
11438 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
11439 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
11440 talign
= DECL_ALIGN_UNIT (ovar
);
11443 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
11444 tree x
= build_sender_ref (ovar
, ctx
);
11445 if (maybe_lookup_oacc_reduction (var
, ctx
))
11447 gcc_checking_assert (offloaded
11448 && is_gimple_omp_oacc (stmt
));
11449 gimplify_assign (x
, var
, &ilist
);
11451 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11452 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11453 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11454 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
11456 gcc_assert (offloaded
);
11458 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)));
11459 mark_addressable (avar
);
11460 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
11461 talign
= DECL_ALIGN_UNIT (avar
);
11462 avar
= build_fold_addr_expr (avar
);
11463 gimplify_assign (x
, avar
, &ilist
);
11465 else if (is_gimple_reg (var
))
11467 gcc_assert (offloaded
);
11468 tree avar
= create_tmp_var (TREE_TYPE (var
));
11469 mark_addressable (avar
);
11470 enum gomp_map_kind map_kind
= OMP_CLAUSE_MAP_KIND (c
);
11471 if (GOMP_MAP_COPY_TO_P (map_kind
)
11472 || map_kind
== GOMP_MAP_POINTER
11473 || map_kind
== GOMP_MAP_TO_PSET
11474 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11475 gimplify_assign (avar
, var
, &ilist
);
11476 avar
= build_fold_addr_expr (avar
);
11477 gimplify_assign (x
, avar
, &ilist
);
11478 if ((GOMP_MAP_COPY_FROM_P (map_kind
)
11479 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11480 && !TYPE_READONLY (TREE_TYPE (var
)))
11482 x
= build_sender_ref (ovar
, ctx
);
11483 x
= build_simple_mem_ref (x
);
11484 gimplify_assign (var
, x
, &olist
);
11489 var
= build_fold_addr_expr (var
);
11490 gimplify_assign (x
, var
, &ilist
);
11493 tree s
= OMP_CLAUSE_SIZE (c
);
11494 if (s
== NULL_TREE
)
11495 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
11496 s
= fold_convert (size_type_node
, s
);
11497 tree purpose
= size_int (map_idx
++);
11498 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
11499 if (TREE_CODE (s
) != INTEGER_CST
)
11500 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
11502 unsigned HOST_WIDE_INT tkind
;
11503 switch (OMP_CLAUSE_CODE (c
))
11505 case OMP_CLAUSE_MAP
:
11506 tkind
= OMP_CLAUSE_MAP_KIND (c
);
11508 case OMP_CLAUSE_TO
:
11509 tkind
= GOMP_MAP_TO
;
11511 case OMP_CLAUSE_FROM
:
11512 tkind
= GOMP_MAP_FROM
;
11515 gcc_unreachable ();
11517 gcc_checking_assert (tkind
11518 < (HOST_WIDE_INT_C (1U) << talign_shift
));
11519 talign
= ceil_log2 (talign
);
11520 tkind
|= talign
<< talign_shift
;
11521 gcc_checking_assert (tkind
11522 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
11523 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
11524 build_int_cstu (tkind_type
, tkind
));
11529 gcc_assert (map_idx
== map_cnt
);
11531 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
11532 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
11533 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
11534 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
11535 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
11537 gimple_seq initlist
= NULL
;
11538 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
11539 TREE_VEC_ELT (t
, 1)),
11540 &initlist
, true, NULL_TREE
);
11541 gimple_seq_add_seq (&ilist
, initlist
);
11543 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
11545 TREE_THIS_VOLATILE (clobber
) = 1;
11546 gimple_seq_add_stmt (&olist
,
11547 gimple_build_assign (TREE_VEC_ELT (t
, 1),
11551 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
11552 TREE_THIS_VOLATILE (clobber
) = 1;
11553 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11557 /* Once all the expansions are done, sequence all the different
11558 fragments inside gimple_omp_body. */
11563 && ctx
->record_type
)
11565 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11566 /* fixup_child_record_type might have changed receiver_decl's type. */
11567 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11568 gimple_seq_add_stmt (&new_body
,
11569 gimple_build_assign (ctx
->receiver_decl
, t
));
11574 gimple_seq_add_seq (&new_body
, tgt_body
);
11575 new_body
= maybe_catch_exception (new_body
);
11577 else if (data_region
)
11578 new_body
= tgt_body
;
11579 if (offloaded
|| data_region
)
11581 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11582 gimple_omp_set_body (stmt
, new_body
);
11585 bind
= gimple_build_bind (NULL
, NULL
,
11586 tgt_bind
? gimple_bind_block (tgt_bind
)
11588 gsi_replace (gsi_p
, bind
, true);
11589 gimple_bind_add_seq (bind
, irlist
);
11590 gimple_bind_add_seq (bind
, ilist
);
11591 gimple_bind_add_stmt (bind
, stmt
);
11592 gimple_bind_add_seq (bind
, olist
);
11593 gimple_bind_add_seq (bind
, orlist
);
11595 pop_gimplify_context (NULL
);
11598 /* Expand code for an OpenMP teams directive. */
11601 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11603 gomp_teams
*teams_stmt
= as_a
<gomp_teams
*> (gsi_stmt (*gsi_p
));
11604 push_gimplify_context ();
11606 tree block
= make_node (BLOCK
);
11607 gbind
*bind
= gimple_build_bind (NULL
, NULL
, block
);
11608 gsi_replace (gsi_p
, bind
, true);
11609 gimple_seq bind_body
= NULL
;
11610 gimple_seq dlist
= NULL
;
11611 gimple_seq olist
= NULL
;
11613 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11614 OMP_CLAUSE_NUM_TEAMS
);
11615 if (num_teams
== NULL_TREE
)
11616 num_teams
= build_int_cst (unsigned_type_node
, 0);
11619 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
11620 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
11621 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
11623 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11624 OMP_CLAUSE_THREAD_LIMIT
);
11625 if (thread_limit
== NULL_TREE
)
11626 thread_limit
= build_int_cst (unsigned_type_node
, 0);
11629 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
11630 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
11631 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
11635 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
11636 &bind_body
, &dlist
, ctx
, NULL
);
11637 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
11638 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
11639 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
11641 location_t loc
= gimple_location (teams_stmt
);
11642 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
11643 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
11644 gimple_set_location (call
, loc
);
11645 gimple_seq_add_stmt (&bind_body
, call
);
11647 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
11648 gimple_omp_set_body (teams_stmt
, NULL
);
11649 gimple_seq_add_seq (&bind_body
, olist
);
11650 gimple_seq_add_seq (&bind_body
, dlist
);
11651 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
11652 gimple_bind_set_body (bind
, bind_body
);
11654 pop_gimplify_context (bind
);
11656 gimple_bind_append_vars (bind
, ctx
->block_vars
);
11657 BLOCK_VARS (block
) = ctx
->block_vars
;
11658 if (BLOCK_VARS (block
))
11659 TREE_USED (block
) = 1;
11663 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11664 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11665 of OMP context, but with task_shared_vars set. */
11668 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
11673 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11674 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
11677 if (task_shared_vars
11679 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
11682 /* If a global variable has been privatized, TREE_CONSTANT on
11683 ADDR_EXPR might be wrong. */
11684 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
11685 recompute_tree_invariant_for_addr_expr (t
);
11687 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
11692 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11694 gimple stmt
= gsi_stmt (*gsi_p
);
11695 struct walk_stmt_info wi
;
11698 if (gimple_has_location (stmt
))
11699 input_location
= gimple_location (stmt
);
11701 if (task_shared_vars
)
11702 memset (&wi
, '\0', sizeof (wi
));
11704 /* If we have issued syntax errors, avoid doing any heavy lifting.
11705 Just replace the OMP directives with a NOP to avoid
11706 confusing RTL expansion. */
11707 if (seen_error () && is_gimple_omp (stmt
))
11709 gsi_replace (gsi_p
, gimple_build_nop (), true);
11713 switch (gimple_code (stmt
))
11717 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
11718 if ((ctx
|| task_shared_vars
)
11719 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
11720 lower_omp_regimplify_p
,
11721 ctx
? NULL
: &wi
, NULL
)
11722 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
11723 lower_omp_regimplify_p
,
11724 ctx
? NULL
: &wi
, NULL
)))
11725 gimple_regimplify_operands (cond_stmt
, gsi_p
);
11729 lower_omp (gimple_catch_handler_ptr (as_a
<gcatch
*> (stmt
)), ctx
);
11731 case GIMPLE_EH_FILTER
:
11732 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
11735 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
11736 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
11738 case GIMPLE_TRANSACTION
:
11739 lower_omp (gimple_transaction_body_ptr (
11740 as_a
<gtransaction
*> (stmt
)),
11744 lower_omp (gimple_bind_body_ptr (as_a
<gbind
*> (stmt
)), ctx
);
11746 case GIMPLE_OMP_PARALLEL
:
11747 case GIMPLE_OMP_TASK
:
11748 ctx
= maybe_lookup_ctx (stmt
);
11750 if (ctx
->cancellable
)
11751 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11752 lower_omp_taskreg (gsi_p
, ctx
);
11754 case GIMPLE_OMP_FOR
:
11755 ctx
= maybe_lookup_ctx (stmt
);
11757 if (ctx
->cancellable
)
11758 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11759 lower_omp_for (gsi_p
, ctx
);
11761 case GIMPLE_OMP_SECTIONS
:
11762 ctx
= maybe_lookup_ctx (stmt
);
11764 if (ctx
->cancellable
)
11765 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11766 lower_omp_sections (gsi_p
, ctx
);
11768 case GIMPLE_OMP_SINGLE
:
11769 ctx
= maybe_lookup_ctx (stmt
);
11771 lower_omp_single (gsi_p
, ctx
);
11773 case GIMPLE_OMP_MASTER
:
11774 ctx
= maybe_lookup_ctx (stmt
);
11776 lower_omp_master (gsi_p
, ctx
);
11778 case GIMPLE_OMP_TASKGROUP
:
11779 ctx
= maybe_lookup_ctx (stmt
);
11781 lower_omp_taskgroup (gsi_p
, ctx
);
11783 case GIMPLE_OMP_ORDERED
:
11784 ctx
= maybe_lookup_ctx (stmt
);
11786 lower_omp_ordered (gsi_p
, ctx
);
11788 case GIMPLE_OMP_CRITICAL
:
11789 ctx
= maybe_lookup_ctx (stmt
);
11791 lower_omp_critical (gsi_p
, ctx
);
11793 case GIMPLE_OMP_ATOMIC_LOAD
:
11794 if ((ctx
|| task_shared_vars
)
11795 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11796 as_a
<gomp_atomic_load
*> (stmt
)),
11797 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
11798 gimple_regimplify_operands (stmt
, gsi_p
);
11800 case GIMPLE_OMP_TARGET
:
11801 ctx
= maybe_lookup_ctx (stmt
);
11803 lower_omp_target (gsi_p
, ctx
);
11805 case GIMPLE_OMP_TEAMS
:
11806 ctx
= maybe_lookup_ctx (stmt
);
11808 lower_omp_teams (gsi_p
, ctx
);
11812 call_stmt
= as_a
<gcall
*> (stmt
);
11813 fndecl
= gimple_call_fndecl (call_stmt
);
11815 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
11816 switch (DECL_FUNCTION_CODE (fndecl
))
11818 case BUILT_IN_GOMP_BARRIER
:
11822 case BUILT_IN_GOMP_CANCEL
:
11823 case BUILT_IN_GOMP_CANCELLATION_POINT
:
11826 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
11827 cctx
= cctx
->outer
;
11828 gcc_assert (gimple_call_lhs (call_stmt
) == NULL_TREE
);
11829 if (!cctx
->cancellable
)
11831 if (DECL_FUNCTION_CODE (fndecl
)
11832 == BUILT_IN_GOMP_CANCELLATION_POINT
)
11834 stmt
= gimple_build_nop ();
11835 gsi_replace (gsi_p
, stmt
, false);
11839 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
11841 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
11842 gimple_call_set_fndecl (call_stmt
, fndecl
);
11843 gimple_call_set_fntype (call_stmt
, TREE_TYPE (fndecl
));
11846 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)));
11847 gimple_call_set_lhs (call_stmt
, lhs
);
11848 tree fallthru_label
;
11849 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
11851 g
= gimple_build_label (fallthru_label
);
11852 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11853 g
= gimple_build_cond (NE_EXPR
, lhs
,
11854 fold_convert (TREE_TYPE (lhs
),
11855 boolean_false_node
),
11856 cctx
->cancel_label
, fallthru_label
);
11857 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11864 if ((ctx
|| task_shared_vars
)
11865 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
11868 /* Just remove clobbers, this should happen only if we have
11869 "privatized" local addressable variables in SIMD regions,
11870 the clobber isn't needed in that case and gimplifying address
11871 of the ARRAY_REF into a pointer and creating MEM_REF based
11872 clobber would create worse code than we get with the clobber
11874 if (gimple_clobber_p (stmt
))
11876 gsi_replace (gsi_p
, gimple_build_nop (), true);
11879 gimple_regimplify_operands (stmt
, gsi_p
);
11886 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
11888 location_t saved_location
= input_location
;
11889 gimple_stmt_iterator gsi
;
11890 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11891 lower_omp_1 (&gsi
, ctx
);
11892 /* During gimplification, we haven't folded statments inside offloading
11893 regions (gimplify.c:maybe_fold_stmt); do that now. */
11894 if (target_nesting_level
)
11895 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11897 input_location
= saved_location
;
11900 /* Main entry point. */
11902 static unsigned int
11903 execute_lower_omp (void)
11909 /* This pass always runs, to provide PROP_gimple_lomp.
11910 But often, there is nothing to do. */
11911 if (flag_cilkplus
== 0 && flag_openacc
== 0 && flag_openmp
== 0
11912 && flag_openmp_simd
== 0)
11915 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
11916 delete_omp_context
);
11918 body
= gimple_body (current_function_decl
);
11919 scan_omp (&body
, NULL
);
11920 gcc_assert (taskreg_nesting_level
== 0);
11921 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
11922 finish_taskreg_scan (ctx
);
11923 taskreg_contexts
.release ();
11925 if (all_contexts
->root
)
11927 if (task_shared_vars
)
11928 push_gimplify_context ();
11929 lower_omp (&body
, NULL
);
11930 if (task_shared_vars
)
11931 pop_gimplify_context (NULL
);
11936 splay_tree_delete (all_contexts
);
11937 all_contexts
= NULL
;
11939 BITMAP_FREE (task_shared_vars
);
11945 const pass_data pass_data_lower_omp
=
11947 GIMPLE_PASS
, /* type */
11948 "omplower", /* name */
11949 OPTGROUP_NONE
, /* optinfo_flags */
11950 TV_NONE
, /* tv_id */
11951 PROP_gimple_any
, /* properties_required */
11952 PROP_gimple_lomp
, /* properties_provided */
11953 0, /* properties_destroyed */
11954 0, /* todo_flags_start */
11955 0, /* todo_flags_finish */
11958 class pass_lower_omp
: public gimple_opt_pass
11961 pass_lower_omp (gcc::context
*ctxt
)
11962 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
11965 /* opt_pass methods: */
11966 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
11968 }; // class pass_lower_omp
11970 } // anon namespace
11973 make_pass_lower_omp (gcc::context
*ctxt
)
11975 return new pass_lower_omp (ctxt
);
11978 /* The following is a utility to diagnose structured block violations.
11979 It is not part of the "omplower" pass, as that's invoked too late. It
11980 should be invoked by the respective front ends after gimplification. */
11982 static splay_tree all_labels
;
11984 /* Check for mismatched contexts and generate an error if needed. Return
11985 true if an error is detected. */
11988 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
11989 gimple branch_ctx
, gimple label_ctx
)
11991 gcc_checking_assert (!branch_ctx
|| is_gimple_omp (branch_ctx
));
11992 gcc_checking_assert (!label_ctx
|| is_gimple_omp (label_ctx
));
11994 if (label_ctx
== branch_ctx
)
11997 const char* kind
= NULL
;
12002 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
12003 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
12005 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
12006 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
12007 kind
= "Cilk Plus";
12011 if ((branch_ctx
&& is_gimple_omp_oacc (branch_ctx
))
12012 || (label_ctx
&& is_gimple_omp_oacc (label_ctx
)))
12014 gcc_checking_assert (kind
== NULL
);
12020 gcc_checking_assert (flag_openmp
);
12025 Previously we kept track of the label's entire context in diagnose_sb_[12]
12026 so we could traverse it and issue a correct "exit" or "enter" error
12027 message upon a structured block violation.
12029 We built the context by building a list with tree_cons'ing, but there is
12030 no easy counterpart in gimple tuples. It seems like far too much work
12031 for issuing exit/enter error messages. If someone really misses the
12032 distinct error message... patches welcome.
12036 /* Try to avoid confusing the user by producing and error message
12037 with correct "exit" or "enter" verbiage. We prefer "exit"
12038 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12039 if (branch_ctx
== NULL
)
12045 if (TREE_VALUE (label_ctx
) == branch_ctx
)
12050 label_ctx
= TREE_CHAIN (label_ctx
);
12055 error ("invalid exit from %s structured block", kind
);
12057 error ("invalid entry to %s structured block", kind
);
12060 /* If it's obvious we have an invalid entry, be specific about the error. */
12061 if (branch_ctx
== NULL
)
12062 error ("invalid entry to %s structured block", kind
);
12065 /* Otherwise, be vague and lazy, but efficient. */
12066 error ("invalid branch to/from %s structured block", kind
);
12069 gsi_replace (gsi_p
, gimple_build_nop (), false);
12073 /* Pass 1: Create a minimal tree of structured blocks, and record
12074 where each label is found. */
12077 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12078 struct walk_stmt_info
*wi
)
12080 gimple context
= (gimple
) wi
->info
;
12081 gimple inner_context
;
12082 gimple stmt
= gsi_stmt (*gsi_p
);
12084 *handled_ops_p
= true;
12086 switch (gimple_code (stmt
))
12090 case GIMPLE_OMP_PARALLEL
:
12091 case GIMPLE_OMP_TASK
:
12092 case GIMPLE_OMP_SECTIONS
:
12093 case GIMPLE_OMP_SINGLE
:
12094 case GIMPLE_OMP_SECTION
:
12095 case GIMPLE_OMP_MASTER
:
12096 case GIMPLE_OMP_ORDERED
:
12097 case GIMPLE_OMP_CRITICAL
:
12098 case GIMPLE_OMP_TARGET
:
12099 case GIMPLE_OMP_TEAMS
:
12100 case GIMPLE_OMP_TASKGROUP
:
12101 /* The minimal context here is just the current OMP construct. */
12102 inner_context
= stmt
;
12103 wi
->info
= inner_context
;
12104 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12105 wi
->info
= context
;
12108 case GIMPLE_OMP_FOR
:
12109 inner_context
= stmt
;
12110 wi
->info
= inner_context
;
12111 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12113 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
12114 diagnose_sb_1
, NULL
, wi
);
12115 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12116 wi
->info
= context
;
12120 splay_tree_insert (all_labels
,
12121 (splay_tree_key
) gimple_label_label (
12122 as_a
<glabel
*> (stmt
)),
12123 (splay_tree_value
) context
);
12133 /* Pass 2: Check each branch and see if its context differs from that of
12134 the destination label's context. */
12137 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12138 struct walk_stmt_info
*wi
)
12140 gimple context
= (gimple
) wi
->info
;
12142 gimple stmt
= gsi_stmt (*gsi_p
);
12144 *handled_ops_p
= true;
12146 switch (gimple_code (stmt
))
12150 case GIMPLE_OMP_PARALLEL
:
12151 case GIMPLE_OMP_TASK
:
12152 case GIMPLE_OMP_SECTIONS
:
12153 case GIMPLE_OMP_SINGLE
:
12154 case GIMPLE_OMP_SECTION
:
12155 case GIMPLE_OMP_MASTER
:
12156 case GIMPLE_OMP_ORDERED
:
12157 case GIMPLE_OMP_CRITICAL
:
12158 case GIMPLE_OMP_TARGET
:
12159 case GIMPLE_OMP_TEAMS
:
12160 case GIMPLE_OMP_TASKGROUP
:
12162 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12163 wi
->info
= context
;
12166 case GIMPLE_OMP_FOR
:
12168 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12170 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
12171 diagnose_sb_2
, NULL
, wi
);
12172 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12173 wi
->info
= context
;
12178 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
12179 tree lab
= gimple_cond_true_label (cond_stmt
);
12182 n
= splay_tree_lookup (all_labels
,
12183 (splay_tree_key
) lab
);
12184 diagnose_sb_0 (gsi_p
, context
,
12185 n
? (gimple
) n
->value
: NULL
);
12187 lab
= gimple_cond_false_label (cond_stmt
);
12190 n
= splay_tree_lookup (all_labels
,
12191 (splay_tree_key
) lab
);
12192 diagnose_sb_0 (gsi_p
, context
,
12193 n
? (gimple
) n
->value
: NULL
);
12200 tree lab
= gimple_goto_dest (stmt
);
12201 if (TREE_CODE (lab
) != LABEL_DECL
)
12204 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12205 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
12209 case GIMPLE_SWITCH
:
12211 gswitch
*switch_stmt
= as_a
<gswitch
*> (stmt
);
12213 for (i
= 0; i
< gimple_switch_num_labels (switch_stmt
); ++i
)
12215 tree lab
= CASE_LABEL (gimple_switch_label (switch_stmt
, i
));
12216 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12217 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
12223 case GIMPLE_RETURN
:
12224 diagnose_sb_0 (gsi_p
, context
, NULL
);
12234 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12237 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
12240 gimple last
= last_stmt (bb
);
12241 enum gimple_code code
= gimple_code (last
);
12242 struct omp_region
*cur_region
= *region
;
12243 bool fallthru
= false;
12247 case GIMPLE_OMP_PARALLEL
:
12248 case GIMPLE_OMP_TASK
:
12249 case GIMPLE_OMP_FOR
:
12250 case GIMPLE_OMP_SINGLE
:
12251 case GIMPLE_OMP_TEAMS
:
12252 case GIMPLE_OMP_MASTER
:
12253 case GIMPLE_OMP_TASKGROUP
:
12254 case GIMPLE_OMP_ORDERED
:
12255 case GIMPLE_OMP_CRITICAL
:
12256 case GIMPLE_OMP_SECTION
:
12257 cur_region
= new_omp_region (bb
, code
, cur_region
);
12261 case GIMPLE_OMP_TARGET
:
12262 cur_region
= new_omp_region (bb
, code
, cur_region
);
12264 switch (gimple_omp_target_kind (last
))
12266 case GF_OMP_TARGET_KIND_REGION
:
12267 case GF_OMP_TARGET_KIND_DATA
:
12268 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
12269 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
12270 case GF_OMP_TARGET_KIND_OACC_DATA
:
12272 case GF_OMP_TARGET_KIND_UPDATE
:
12273 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
12274 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
12275 cur_region
= cur_region
->outer
;
12278 gcc_unreachable ();
12282 case GIMPLE_OMP_SECTIONS
:
12283 cur_region
= new_omp_region (bb
, code
, cur_region
);
12287 case GIMPLE_OMP_SECTIONS_SWITCH
:
12291 case GIMPLE_OMP_ATOMIC_LOAD
:
12292 case GIMPLE_OMP_ATOMIC_STORE
:
12296 case GIMPLE_OMP_RETURN
:
12297 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12298 somewhere other than the next block. This will be
12300 cur_region
->exit
= bb
;
12301 if (cur_region
->type
== GIMPLE_OMP_TASK
)
12302 /* Add an edge corresponding to not scheduling the task
12304 make_edge (cur_region
->entry
, bb
, EDGE_ABNORMAL
);
12305 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
12306 cur_region
= cur_region
->outer
;
12309 case GIMPLE_OMP_CONTINUE
:
12310 cur_region
->cont
= bb
;
12311 switch (cur_region
->type
)
12313 case GIMPLE_OMP_FOR
:
12314 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12315 succs edges as abnormal to prevent splitting
12317 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
12318 /* Make the loopback edge. */
12319 make_edge (bb
, single_succ (cur_region
->entry
),
12322 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12323 corresponds to the case that the body of the loop
12324 is not executed at all. */
12325 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
12326 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
12330 case GIMPLE_OMP_SECTIONS
:
12331 /* Wire up the edges into and out of the nested sections. */
12333 basic_block switch_bb
= single_succ (cur_region
->entry
);
12335 struct omp_region
*i
;
12336 for (i
= cur_region
->inner
; i
; i
= i
->next
)
12338 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
12339 make_edge (switch_bb
, i
->entry
, 0);
12340 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
12343 /* Make the loopback edge to the block with
12344 GIMPLE_OMP_SECTIONS_SWITCH. */
12345 make_edge (bb
, switch_bb
, 0);
12347 /* Make the edge from the switch to exit. */
12348 make_edge (switch_bb
, bb
->next_bb
, 0);
12353 case GIMPLE_OMP_TASK
:
12358 gcc_unreachable ();
12363 gcc_unreachable ();
12366 if (*region
!= cur_region
)
12368 *region
= cur_region
;
12370 *region_idx
= cur_region
->entry
->index
;
12378 static unsigned int
12379 diagnose_omp_structured_block_errors (void)
12381 struct walk_stmt_info wi
;
12382 gimple_seq body
= gimple_body (current_function_decl
);
12384 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
12386 memset (&wi
, 0, sizeof (wi
));
12387 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
12389 memset (&wi
, 0, sizeof (wi
));
12390 wi
.want_locations
= true;
12391 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
12393 gimple_set_body (current_function_decl
, body
);
12395 splay_tree_delete (all_labels
);
12403 const pass_data pass_data_diagnose_omp_blocks
=
12405 GIMPLE_PASS
, /* type */
12406 "*diagnose_omp_blocks", /* name */
12407 OPTGROUP_NONE
, /* optinfo_flags */
12408 TV_NONE
, /* tv_id */
12409 PROP_gimple_any
, /* properties_required */
12410 0, /* properties_provided */
12411 0, /* properties_destroyed */
12412 0, /* todo_flags_start */
12413 0, /* todo_flags_finish */
12416 class pass_diagnose_omp_blocks
: public gimple_opt_pass
12419 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12420 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
12423 /* opt_pass methods: */
12424 virtual bool gate (function
*)
12426 return flag_cilkplus
|| flag_openacc
|| flag_openmp
;
12428 virtual unsigned int execute (function
*)
12430 return diagnose_omp_structured_block_errors ();
12433 }; // class pass_diagnose_omp_blocks
12435 } // anon namespace
12438 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12440 return new pass_diagnose_omp_blocks (ctxt
);
12443 /* SIMD clone supporting code. */
12445 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12446 of arguments to reserve space for. */
12448 static struct cgraph_simd_clone
*
12449 simd_clone_struct_alloc (int nargs
)
12451 struct cgraph_simd_clone
*clone_info
;
12452 size_t len
= (sizeof (struct cgraph_simd_clone
)
12453 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
12454 clone_info
= (struct cgraph_simd_clone
*)
12455 ggc_internal_cleared_alloc (len
);
12459 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12462 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
12463 struct cgraph_simd_clone
*from
)
12465 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
12466 + ((from
->nargs
- from
->inbranch
)
12467 * sizeof (struct cgraph_simd_clone_arg
))));
12470 /* Return vector of parameter types of function FNDECL. This uses
12471 TYPE_ARG_TYPES if available, otherwise falls back to types of
12472 DECL_ARGUMENTS types. */
12475 simd_clone_vector_of_formal_parm_types (tree fndecl
)
12477 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
12478 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
12479 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
12482 FOR_EACH_VEC_ELT (args
, i
, arg
)
12483 args
[i
] = TREE_TYPE (args
[i
]);
12487 /* Given a simd function in NODE, extract the simd specific
12488 information from the OMP clauses passed in CLAUSES, and return
12489 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12490 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12491 otherwise set to FALSE. */
12493 static struct cgraph_simd_clone
*
12494 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
12495 bool *inbranch_specified
)
12497 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12500 *inbranch_specified
= false;
12502 n
= args
.length ();
12503 if (n
> 0 && args
.last () == void_type_node
)
12506 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12507 be cloned have a distinctive artificial label in addition to "omp
12511 && lookup_attribute ("cilk simd function",
12512 DECL_ATTRIBUTES (node
->decl
)));
12514 /* Allocate one more than needed just in case this is an in-branch
12515 clone which will require a mask argument. */
12516 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
12517 clone_info
->nargs
= n
;
12518 clone_info
->cilk_elemental
= cilk_clone
;
12525 clauses
= TREE_VALUE (clauses
);
12526 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
12529 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
12531 switch (OMP_CLAUSE_CODE (t
))
12533 case OMP_CLAUSE_INBRANCH
:
12534 clone_info
->inbranch
= 1;
12535 *inbranch_specified
= true;
12537 case OMP_CLAUSE_NOTINBRANCH
:
12538 clone_info
->inbranch
= 0;
12539 *inbranch_specified
= true;
12541 case OMP_CLAUSE_SIMDLEN
:
12542 clone_info
->simdlen
12543 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
12545 case OMP_CLAUSE_LINEAR
:
12547 tree decl
= OMP_CLAUSE_DECL (t
);
12548 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
12549 int argno
= TREE_INT_CST_LOW (decl
);
12550 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
12552 clone_info
->args
[argno
].arg_type
12553 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
12554 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12555 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
12556 && clone_info
->args
[argno
].linear_step
< n
);
12560 if (POINTER_TYPE_P (args
[argno
]))
12561 step
= fold_convert (ssizetype
, step
);
12562 if (!tree_fits_shwi_p (step
))
12564 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12565 "ignoring large linear step");
12569 else if (integer_zerop (step
))
12571 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12572 "ignoring zero linear step");
12578 clone_info
->args
[argno
].arg_type
12579 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
12580 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12585 case OMP_CLAUSE_UNIFORM
:
12587 tree decl
= OMP_CLAUSE_DECL (t
);
12588 int argno
= tree_to_uhwi (decl
);
12589 clone_info
->args
[argno
].arg_type
12590 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
12593 case OMP_CLAUSE_ALIGNED
:
12595 tree decl
= OMP_CLAUSE_DECL (t
);
12596 int argno
= tree_to_uhwi (decl
);
12597 clone_info
->args
[argno
].alignment
12598 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
12609 /* Given a SIMD clone in NODE, calculate the characteristic data
12610 type and return the coresponding type. The characteristic data
12611 type is computed as described in the Intel Vector ABI. */
12614 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
12615 struct cgraph_simd_clone
*clone_info
)
12617 tree type
= integer_type_node
;
12618 tree fndecl
= node
->decl
;
12620 /* a) For non-void function, the characteristic data type is the
12622 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
12623 type
= TREE_TYPE (TREE_TYPE (fndecl
));
12625 /* b) If the function has any non-uniform, non-linear parameters,
12626 then the characteristic data type is the type of the first
12630 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
12631 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
12632 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
12640 /* c) If the characteristic data type determined by a) or b) above
12641 is struct, union, or class type which is pass-by-value (except
12642 for the type that maps to the built-in complex data type), the
12643 characteristic data type is int. */
12644 if (RECORD_OR_UNION_TYPE_P (type
)
12645 && !aggregate_value_p (type
, NULL
)
12646 && TREE_CODE (type
) != COMPLEX_TYPE
)
12647 return integer_type_node
;
12649 /* d) If none of the above three classes is applicable, the
12650 characteristic data type is int. */
12654 /* e) For Intel Xeon Phi native and offload compilation, if the
12655 resulting characteristic data type is 8-bit or 16-bit integer
12656 data type, the characteristic data type is int. */
12657 /* Well, we don't handle Xeon Phi yet. */
12661 simd_clone_mangle (struct cgraph_node
*node
,
12662 struct cgraph_simd_clone
*clone_info
)
12664 char vecsize_mangle
= clone_info
->vecsize_mangle
;
12665 char mask
= clone_info
->inbranch
? 'M' : 'N';
12666 unsigned int simdlen
= clone_info
->simdlen
;
12670 gcc_assert (vecsize_mangle
&& simdlen
);
12672 pp_string (&pp
, "_ZGV");
12673 pp_character (&pp
, vecsize_mangle
);
12674 pp_character (&pp
, mask
);
12675 pp_decimal_int (&pp
, simdlen
);
12677 for (n
= 0; n
< clone_info
->nargs
; ++n
)
12679 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
12681 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
12682 pp_character (&pp
, 'u');
12683 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
12685 gcc_assert (arg
.linear_step
!= 0);
12686 pp_character (&pp
, 'l');
12687 if (arg
.linear_step
> 1)
12688 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12689 else if (arg
.linear_step
< 0)
12691 pp_character (&pp
, 'n');
12692 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
12696 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
12698 pp_character (&pp
, 's');
12699 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12702 pp_character (&pp
, 'v');
12705 pp_character (&pp
, 'a');
12706 pp_decimal_int (&pp
, arg
.alignment
);
12710 pp_underscore (&pp
);
12711 const char *str
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
));
12714 pp_string (&pp
, str
);
12715 str
= pp_formatted_text (&pp
);
12717 /* If there already is a SIMD clone with the same mangled name, don't
12718 add another one. This can happen e.g. for
12719 #pragma omp declare simd
12720 #pragma omp declare simd simdlen(8)
12721 int foo (int, int);
12722 if the simdlen is assumed to be 8 for the first one, etc. */
12723 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
12724 clone
= clone
->simdclone
->next_clone
)
12725 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
12729 return get_identifier (str
);
12732 /* Create a simd clone of OLD_NODE and return it. */
12734 static struct cgraph_node
*
12735 simd_clone_create (struct cgraph_node
*old_node
)
12737 struct cgraph_node
*new_node
;
12738 if (old_node
->definition
)
12740 if (!old_node
->has_gimple_body_p ())
12742 old_node
->get_body ();
12743 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
12749 tree old_decl
= old_node
->decl
;
12750 tree new_decl
= copy_node (old_node
->decl
);
12751 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
12752 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
12753 SET_DECL_RTL (new_decl
, NULL
);
12754 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
12755 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
12756 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
12757 symtab
->call_cgraph_insertion_hooks (new_node
);
12759 if (new_node
== NULL
)
12762 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
12764 /* The function cgraph_function_versioning () will force the new
12765 symbol local. Undo this, and inherit external visability from
12767 new_node
->local
.local
= old_node
->local
.local
;
12768 new_node
->externally_visible
= old_node
->externally_visible
;
12773 /* Adjust the return type of the given function to its appropriate
12774 vector counterpart. Returns a simd array to be used throughout the
12775 function as a return value. */
12778 simd_clone_adjust_return_type (struct cgraph_node
*node
)
12780 tree fndecl
= node
->decl
;
12781 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
12782 unsigned int veclen
;
12785 /* Adjust the function return type. */
12786 if (orig_rettype
== void_type_node
)
12788 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
12789 t
= TREE_TYPE (TREE_TYPE (fndecl
));
12790 if (INTEGRAL_TYPE_P (t
) || POINTER_TYPE_P (t
))
12791 veclen
= node
->simdclone
->vecsize_int
;
12793 veclen
= node
->simdclone
->vecsize_float
;
12794 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (t
));
12795 if (veclen
> node
->simdclone
->simdlen
)
12796 veclen
= node
->simdclone
->simdlen
;
12797 if (POINTER_TYPE_P (t
))
12798 t
= pointer_sized_int_node
;
12799 if (veclen
== node
->simdclone
->simdlen
)
12800 t
= build_vector_type (t
, node
->simdclone
->simdlen
);
12803 t
= build_vector_type (t
, veclen
);
12804 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
12806 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
12807 if (!node
->definition
)
12810 t
= DECL_RESULT (fndecl
);
12811 /* Adjust the DECL_RESULT. */
12812 gcc_assert (TREE_TYPE (t
) != void_type_node
);
12813 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
12816 tree atype
= build_array_type_nelts (orig_rettype
,
12817 node
->simdclone
->simdlen
);
12818 if (veclen
!= node
->simdclone
->simdlen
)
12819 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
12821 /* Set up a SIMD array to use as the return value. */
12822 tree retval
= create_tmp_var_raw (atype
, "retval");
12823 gimple_add_tmp_var (retval
);
12827 /* Each vector argument has a corresponding array to be used locally
12828 as part of the eventual loop. Create such temporary array and
12831 PREFIX is the prefix to be used for the temporary.
12833 TYPE is the inner element type.
12835 SIMDLEN is the number of elements. */
12838 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
12840 tree atype
= build_array_type_nelts (type
, simdlen
);
12841 tree avar
= create_tmp_var_raw (atype
, prefix
);
12842 gimple_add_tmp_var (avar
);
12846 /* Modify the function argument types to their corresponding vector
12847 counterparts if appropriate. Also, create one array for each simd
12848 argument to be used locally when using the function arguments as
12851 NODE is the function whose arguments are to be adjusted.
12853 Returns an adjustment vector that will be filled describing how the
12854 argument types will be adjusted. */
12856 static ipa_parm_adjustment_vec
12857 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
12860 ipa_parm_adjustment_vec adjustments
;
12862 if (node
->definition
)
12863 args
= ipa_get_vector_of_formal_parms (node
->decl
);
12865 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12866 adjustments
.create (args
.length ());
12867 unsigned i
, j
, veclen
;
12868 struct ipa_parm_adjustment adj
;
12869 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
12871 memset (&adj
, 0, sizeof (adj
));
12872 tree parm
= args
[i
];
12873 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
12874 adj
.base_index
= i
;
12877 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
12878 node
->simdclone
->args
[i
].orig_type
= parm_type
;
12880 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
12882 /* No adjustment necessary for scalar arguments. */
12883 adj
.op
= IPA_PARM_OP_COPY
;
12887 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
12888 veclen
= node
->simdclone
->vecsize_int
;
12890 veclen
= node
->simdclone
->vecsize_float
;
12891 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
12892 if (veclen
> node
->simdclone
->simdlen
)
12893 veclen
= node
->simdclone
->simdlen
;
12894 adj
.arg_prefix
= "simd";
12895 if (POINTER_TYPE_P (parm_type
))
12896 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
12898 adj
.type
= build_vector_type (parm_type
, veclen
);
12899 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
12900 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
12902 adjustments
.safe_push (adj
);
12905 memset (&adj
, 0, sizeof (adj
));
12906 adj
.op
= IPA_PARM_OP_NEW
;
12907 adj
.arg_prefix
= "simd";
12908 adj
.base_index
= i
;
12909 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
12913 if (node
->definition
)
12914 node
->simdclone
->args
[i
].simd_array
12915 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
12916 parm_type
, node
->simdclone
->simdlen
);
12918 adjustments
.safe_push (adj
);
12921 if (node
->simdclone
->inbranch
)
12924 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
12927 memset (&adj
, 0, sizeof (adj
));
12928 adj
.op
= IPA_PARM_OP_NEW
;
12929 adj
.arg_prefix
= "mask";
12931 adj
.base_index
= i
;
12932 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
12933 veclen
= node
->simdclone
->vecsize_int
;
12935 veclen
= node
->simdclone
->vecsize_float
;
12936 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
12937 if (veclen
> node
->simdclone
->simdlen
)
12938 veclen
= node
->simdclone
->simdlen
;
12939 if (POINTER_TYPE_P (base_type
))
12940 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
12942 adj
.type
= build_vector_type (base_type
, veclen
);
12943 adjustments
.safe_push (adj
);
12945 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
12946 adjustments
.safe_push (adj
);
12948 /* We have previously allocated one extra entry for the mask. Use
12950 struct cgraph_simd_clone
*sc
= node
->simdclone
;
12952 if (node
->definition
)
12954 sc
->args
[i
].orig_arg
12955 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
12956 sc
->args
[i
].simd_array
12957 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
12959 sc
->args
[i
].orig_type
= base_type
;
12960 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
12963 if (node
->definition
)
12964 ipa_modify_formal_parameters (node
->decl
, adjustments
);
12967 tree new_arg_types
= NULL_TREE
, new_reversed
;
12968 bool last_parm_void
= false;
12969 if (args
.length () > 0 && args
.last () == void_type_node
)
12970 last_parm_void
= true;
12972 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
12973 j
= adjustments
.length ();
12974 for (i
= 0; i
< j
; i
++)
12976 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
12978 if (adj
->op
== IPA_PARM_OP_COPY
)
12979 ptype
= args
[adj
->base_index
];
12982 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
12984 new_reversed
= nreverse (new_arg_types
);
12985 if (last_parm_void
)
12988 TREE_CHAIN (new_arg_types
) = void_list_node
;
12990 new_reversed
= void_list_node
;
12993 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
12994 TYPE_ARG_TYPES (new_type
) = new_reversed
;
12995 TREE_TYPE (node
->decl
) = new_type
;
12997 adjustments
.release ();
13000 return adjustments
;
13003 /* Initialize and copy the function arguments in NODE to their
13004 corresponding local simd arrays. Returns a fresh gimple_seq with
13005 the instruction sequence generated. */
13008 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
13009 ipa_parm_adjustment_vec adjustments
)
13011 gimple_seq seq
= NULL
;
13012 unsigned i
= 0, j
= 0, k
;
13014 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
13016 arg
= DECL_CHAIN (arg
), i
++, j
++)
13018 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
13021 node
->simdclone
->args
[i
].vector_arg
= arg
;
13023 tree array
= node
->simdclone
->args
[i
].simd_array
;
13024 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
13026 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
13027 tree ptr
= build_fold_addr_expr (array
);
13028 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
13029 build_int_cst (ptype
, 0));
13030 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
13031 gimplify_and_add (t
, &seq
);
13035 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
13036 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
13037 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
13039 tree ptr
= build_fold_addr_expr (array
);
13043 arg
= DECL_CHAIN (arg
);
13047 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
13048 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
13049 build_int_cst (ptype
, k
* elemsize
));
13050 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
13051 gimplify_and_add (t
, &seq
);
13058 /* Callback info for ipa_simd_modify_stmt_ops below. */
13060 struct modify_stmt_info
{
13061 ipa_parm_adjustment_vec adjustments
;
13063 /* True if the parent statement was modified by
13064 ipa_simd_modify_stmt_ops. */
13068 /* Callback for walk_gimple_op.
13070 Adjust operands from a given statement as specified in the
13071 adjustments vector in the callback data. */
13074 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
13076 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
13077 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
13078 tree
*orig_tp
= tp
;
13079 if (TREE_CODE (*tp
) == ADDR_EXPR
)
13080 tp
= &TREE_OPERAND (*tp
, 0);
13081 struct ipa_parm_adjustment
*cand
= NULL
;
13082 if (TREE_CODE (*tp
) == PARM_DECL
)
13083 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
13087 *walk_subtrees
= 0;
13090 tree repl
= NULL_TREE
;
13092 repl
= unshare_expr (cand
->new_decl
);
13097 *walk_subtrees
= 0;
13098 bool modified
= info
->modified
;
13099 info
->modified
= false;
13100 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
13101 if (!info
->modified
)
13103 info
->modified
= modified
;
13106 info
->modified
= modified
;
13115 repl
= build_fold_addr_expr (repl
);
13117 if (is_gimple_debug (info
->stmt
))
13119 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
13120 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
13121 DECL_ARTIFICIAL (vexpr
) = 1;
13122 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
13123 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
13128 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
)), repl
);
13129 repl
= gimple_assign_lhs (stmt
);
13131 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
13132 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13135 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
13137 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
13143 info
->modified
= true;
13147 /* Traverse the function body and perform all modifications as
13148 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13149 modified such that the replacement/reduction value will now be an
13150 offset into the corresponding simd_array.
13152 This function will replace all function argument uses with their
13153 corresponding simd array elements, and ajust the return values
13157 ipa_simd_modify_function_body (struct cgraph_node
*node
,
13158 ipa_parm_adjustment_vec adjustments
,
13159 tree retval_array
, tree iter
)
13162 unsigned int i
, j
, l
;
13164 /* Re-use the adjustments array, but this time use it to replace
13165 every function argument use to an offset into the corresponding
13167 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
13169 if (!node
->simdclone
->args
[i
].vector_arg
)
13172 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
13173 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
13174 adjustments
[j
].new_decl
13175 = build4 (ARRAY_REF
,
13177 node
->simdclone
->args
[i
].simd_array
,
13179 NULL_TREE
, NULL_TREE
);
13180 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
13181 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
13182 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
13185 l
= adjustments
.length ();
13186 for (i
= 1; i
< num_ssa_names
; i
++)
13188 tree name
= ssa_name (i
);
13190 && SSA_NAME_VAR (name
)
13191 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
13193 for (j
= 0; j
< l
; j
++)
13194 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
13195 && adjustments
[j
].new_decl
)
13198 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
13201 = copy_var_decl (adjustments
[j
].base
,
13202 DECL_NAME (adjustments
[j
].base
),
13203 TREE_TYPE (adjustments
[j
].base
));
13204 adjustments
[j
].new_ssa_base
= base_var
;
13207 base_var
= adjustments
[j
].new_ssa_base
;
13208 if (SSA_NAME_IS_DEFAULT_DEF (name
))
13210 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13211 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
13212 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
13213 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
13214 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13215 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
13216 gimple stmt
= gimple_build_assign (name
, new_decl
);
13217 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13220 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13225 struct modify_stmt_info info
;
13226 info
.adjustments
= adjustments
;
13228 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
13230 gimple_stmt_iterator gsi
;
13232 gsi
= gsi_start_bb (bb
);
13233 while (!gsi_end_p (gsi
))
13235 gimple stmt
= gsi_stmt (gsi
);
13237 struct walk_stmt_info wi
;
13239 memset (&wi
, 0, sizeof (wi
));
13240 info
.modified
= false;
13242 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
13244 if (greturn
*return_stmt
= dyn_cast
<greturn
*> (stmt
))
13246 tree retval
= gimple_return_retval (return_stmt
);
13249 gsi_remove (&gsi
, true);
13253 /* Replace `return foo' with `retval_array[iter] = foo'. */
13254 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
13255 retval_array
, iter
, NULL
, NULL
);
13256 stmt
= gimple_build_assign (ref
, retval
);
13257 gsi_replace (&gsi
, stmt
, true);
13258 info
.modified
= true;
13263 update_stmt (stmt
);
13264 if (maybe_clean_eh_stmt (stmt
))
13265 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
13272 /* Adjust the argument types in NODE to their appropriate vector
13276 simd_clone_adjust (struct cgraph_node
*node
)
13278 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
13280 targetm
.simd_clone
.adjust (node
);
13282 tree retval
= simd_clone_adjust_return_type (node
);
13283 ipa_parm_adjustment_vec adjustments
13284 = simd_clone_adjust_argument_types (node
);
13286 push_gimplify_context ();
13288 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
13290 /* Adjust all uses of vector arguments accordingly. Adjust all
13291 return values accordingly. */
13292 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
13293 tree iter1
= make_ssa_name (iter
);
13294 tree iter2
= make_ssa_name (iter
);
13295 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
13297 /* Initialize the iteration variable. */
13298 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13299 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
13300 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
13301 /* Insert the SIMD array and iv initialization at function
13303 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
13305 pop_gimplify_context (NULL
);
13307 /* Create a new BB right before the original exit BB, to hold the
13308 iteration increment and the condition/branch. */
13309 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
13310 basic_block incr_bb
= create_empty_bb (orig_exit
);
13311 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
13312 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13313 flag. Set it now to be a FALLTHRU_EDGE. */
13314 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
13315 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
13316 for (unsigned i
= 0;
13317 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
13319 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
13320 redirect_edge_succ (e
, incr_bb
);
13322 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
13323 e
->probability
= REG_BR_PROB_BASE
;
13324 gsi
= gsi_last_bb (incr_bb
);
13325 gimple g
= gimple_build_assign (iter2
, PLUS_EXPR
, iter1
,
13326 build_int_cst (unsigned_type_node
, 1));
13327 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13329 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13330 struct loop
*loop
= alloc_loop ();
13331 cfun
->has_force_vectorize_loops
= true;
13332 loop
->safelen
= node
->simdclone
->simdlen
;
13333 loop
->force_vectorize
= true;
13334 loop
->header
= body_bb
;
13336 /* Branch around the body if the mask applies. */
13337 if (node
->simdclone
->inbranch
)
13339 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
13341 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
13342 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)));
13343 tree aref
= build4 (ARRAY_REF
,
13344 TREE_TYPE (TREE_TYPE (mask_array
)),
13347 g
= gimple_build_assign (mask
, aref
);
13348 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13349 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
13350 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
13352 aref
= build1 (VIEW_CONVERT_EXPR
,
13353 build_nonstandard_integer_type (bitsize
, 0), mask
);
13354 mask
= make_ssa_name (TREE_TYPE (aref
));
13355 g
= gimple_build_assign (mask
, aref
);
13356 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13359 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
13361 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13362 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
13363 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
13366 /* Generate the condition. */
13367 g
= gimple_build_cond (LT_EXPR
,
13369 build_int_cst (unsigned_type_node
,
13370 node
->simdclone
->simdlen
),
13372 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13373 e
= split_block (incr_bb
, gsi_stmt (gsi
));
13374 basic_block latch_bb
= e
->dest
;
13375 basic_block new_exit_bb
;
13376 new_exit_bb
= split_block_after_labels (latch_bb
)->dest
;
13377 loop
->latch
= latch_bb
;
13379 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
13381 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
13382 /* The successor of incr_bb is already pointing to latch_bb; just
13384 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13385 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
13387 gphi
*phi
= create_phi_node (iter1
, body_bb
);
13388 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
13389 edge latch_edge
= single_succ_edge (latch_bb
);
13390 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
13392 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13394 /* Generate the new return. */
13395 gsi
= gsi_last_bb (new_exit_bb
);
13397 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
13398 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
13399 retval
= TREE_OPERAND (retval
, 0);
13402 retval
= build1 (VIEW_CONVERT_EXPR
,
13403 TREE_TYPE (TREE_TYPE (node
->decl
)),
13405 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
13406 false, GSI_CONTINUE_LINKING
);
13408 g
= gimple_build_return (retval
);
13409 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13411 /* Handle aligned clauses by replacing default defs of the aligned
13412 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13413 lhs. Handle linear by adding PHIs. */
13414 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
13415 if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
13416 && (TREE_ADDRESSABLE (node
->simdclone
->args
[i
].orig_arg
)
13417 || !is_gimple_reg_type
13418 (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
13420 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13421 if (is_gimple_reg_type (TREE_TYPE (orig_arg
)))
13422 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
13425 iter1
= create_tmp_var_raw (TREE_TYPE (orig_arg
));
13426 gimple_add_tmp_var (iter1
);
13428 gsi
= gsi_after_labels (entry_bb
);
13429 g
= gimple_build_assign (iter1
, orig_arg
);
13430 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13431 gsi
= gsi_after_labels (body_bb
);
13432 g
= gimple_build_assign (orig_arg
, iter1
);
13433 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13435 else if (node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
13436 && DECL_BY_REFERENCE (node
->simdclone
->args
[i
].orig_arg
)
13437 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
13439 && TREE_ADDRESSABLE
13440 (TREE_TYPE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))))
13442 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13443 tree def
= ssa_default_def (cfun
, orig_arg
);
13444 if (def
&& !has_zero_uses (def
))
13446 iter1
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg
)));
13447 gimple_add_tmp_var (iter1
);
13448 gsi
= gsi_after_labels (entry_bb
);
13449 g
= gimple_build_assign (iter1
, build_simple_mem_ref (def
));
13450 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13451 gsi
= gsi_after_labels (body_bb
);
13452 g
= gimple_build_assign (build_simple_mem_ref (def
), iter1
);
13453 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13456 else if (node
->simdclone
->args
[i
].alignment
13457 && node
->simdclone
->args
[i
].arg_type
13458 == SIMD_CLONE_ARG_TYPE_UNIFORM
13459 && (node
->simdclone
->args
[i
].alignment
13460 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
13461 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
13464 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
13465 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13466 tree def
= ssa_default_def (cfun
, orig_arg
);
13467 if (def
&& !has_zero_uses (def
))
13469 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
13470 gimple_seq seq
= NULL
;
13471 bool need_cvt
= false;
13473 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
13475 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
13478 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
);
13479 gimple_call_set_lhs (g
, t
);
13480 gimple_seq_add_stmt_without_update (&seq
, g
);
13483 t
= make_ssa_name (orig_arg
);
13484 g
= gimple_build_assign (t
, NOP_EXPR
, gimple_call_lhs (g
));
13485 gimple_seq_add_stmt_without_update (&seq
, g
);
13487 gsi_insert_seq_on_edge_immediate
13488 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
13490 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13491 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
13493 node
->create_edge (cgraph_node::get_create (fn
),
13494 call
, entry_bb
->count
, freq
);
13496 imm_use_iterator iter
;
13497 use_operand_p use_p
;
13499 tree repl
= gimple_get_lhs (g
);
13500 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13501 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
13504 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13505 SET_USE (use_p
, repl
);
13508 else if (node
->simdclone
->args
[i
].arg_type
13509 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
13511 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13512 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13513 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
13514 tree def
= NULL_TREE
;
13515 if (TREE_ADDRESSABLE (orig_arg
))
13517 def
= make_ssa_name (TREE_TYPE (orig_arg
));
13518 iter1
= make_ssa_name (TREE_TYPE (orig_arg
));
13519 iter2
= make_ssa_name (TREE_TYPE (orig_arg
));
13520 gsi
= gsi_after_labels (entry_bb
);
13521 g
= gimple_build_assign (def
, orig_arg
);
13522 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13526 def
= ssa_default_def (cfun
, orig_arg
);
13527 if (!def
|| has_zero_uses (def
))
13531 iter1
= make_ssa_name (orig_arg
);
13532 iter2
= make_ssa_name (orig_arg
);
13537 phi
= create_phi_node (iter1
, body_bb
);
13538 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
13539 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13540 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13541 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
13542 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13543 ? TREE_TYPE (orig_arg
) : sizetype
;
13545 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
13546 g
= gimple_build_assign (iter2
, code
, iter1
, addcst
);
13547 gsi
= gsi_last_bb (incr_bb
);
13548 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
13550 imm_use_iterator iter
;
13551 use_operand_p use_p
;
13553 if (TREE_ADDRESSABLE (orig_arg
))
13555 gsi
= gsi_after_labels (body_bb
);
13556 g
= gimple_build_assign (orig_arg
, iter1
);
13557 gsi_insert_before (&gsi
, g
, GSI_NEW_STMT
);
13560 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13561 if (use_stmt
== phi
)
13564 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13565 SET_USE (use_p
, iter1
);
13569 calculate_dominance_info (CDI_DOMINATORS
);
13570 add_loop (loop
, loop
->header
->loop_father
);
13571 update_ssa (TODO_update_ssa
);
13576 /* If the function in NODE is tagged as an elemental SIMD function,
13577 create the appropriate SIMD clones. */
13580 expand_simd_clones (struct cgraph_node
*node
)
13582 tree attr
= lookup_attribute ("omp declare simd",
13583 DECL_ATTRIBUTES (node
->decl
));
13584 if (attr
== NULL_TREE
13585 || node
->global
.inlined_to
13586 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
13590 #pragma omp declare simd
13592 in C, there we don't know the argument types at all. */
13593 if (!node
->definition
13594 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
13599 /* Start with parsing the "omp declare simd" attribute(s). */
13600 bool inbranch_clause_specified
;
13601 struct cgraph_simd_clone
*clone_info
13602 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
13603 &inbranch_clause_specified
);
13604 if (clone_info
== NULL
)
13607 int orig_simdlen
= clone_info
->simdlen
;
13608 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
13609 /* The target can return 0 (no simd clones should be created),
13610 1 (just one ISA of simd clones should be created) or higher
13611 count of ISA variants. In that case, clone_info is initialized
13612 for the first ISA variant. */
13614 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
13619 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13620 also create one inbranch and one !inbranch clone of it. */
13621 for (int i
= 0; i
< count
* 2; i
++)
13623 struct cgraph_simd_clone
*clone
= clone_info
;
13624 if (inbranch_clause_specified
&& (i
& 1) != 0)
13629 clone
= simd_clone_struct_alloc (clone_info
->nargs
13631 simd_clone_struct_copy (clone
, clone_info
);
13632 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13633 and simd_clone_adjust_argument_types did to the first
13635 clone
->nargs
-= clone_info
->inbranch
;
13636 clone
->simdlen
= orig_simdlen
;
13637 /* And call the target hook again to get the right ISA. */
13638 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
13642 clone
->inbranch
= 1;
13645 /* simd_clone_mangle might fail if such a clone has been created
13647 tree id
= simd_clone_mangle (node
, clone
);
13648 if (id
== NULL_TREE
)
13651 /* Only when we are sure we want to create the clone actually
13652 clone the function (or definitions) or create another
13653 extern FUNCTION_DECL (for prototypes without definitions). */
13654 struct cgraph_node
*n
= simd_clone_create (node
);
13658 n
->simdclone
= clone
;
13659 clone
->origin
= node
;
13660 clone
->next_clone
= NULL
;
13661 if (node
->simd_clones
== NULL
)
13663 clone
->prev_clone
= n
;
13664 node
->simd_clones
= n
;
13668 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
13669 clone
->prev_clone
->simdclone
->next_clone
= n
;
13670 node
->simd_clones
->simdclone
->prev_clone
= n
;
13672 symtab
->change_decl_assembler_name (n
->decl
, id
);
13673 /* And finally adjust the return type, parameters and for
13674 definitions also function body. */
13675 if (node
->definition
)
13676 simd_clone_adjust (n
);
13679 simd_clone_adjust_return_type (n
);
13680 simd_clone_adjust_argument_types (n
);
13684 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
13687 /* Entry point for IPA simd clone creation pass. */
13689 static unsigned int
13690 ipa_omp_simd_clone (void)
13692 struct cgraph_node
*node
;
13693 FOR_EACH_FUNCTION (node
)
13694 expand_simd_clones (node
);
13700 const pass_data pass_data_omp_simd_clone
=
13702 SIMPLE_IPA_PASS
, /* type */
13703 "simdclone", /* name */
13704 OPTGROUP_NONE
, /* optinfo_flags */
13705 TV_NONE
, /* tv_id */
13706 ( PROP_ssa
| PROP_cfg
), /* properties_required */
13707 0, /* properties_provided */
13708 0, /* properties_destroyed */
13709 0, /* todo_flags_start */
13710 0, /* todo_flags_finish */
13713 class pass_omp_simd_clone
: public simple_ipa_opt_pass
13716 pass_omp_simd_clone(gcc::context
*ctxt
)
13717 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
13720 /* opt_pass methods: */
13721 virtual bool gate (function
*);
13722 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
13726 pass_omp_simd_clone::gate (function
*)
13728 return ((flag_openmp
|| flag_openmp_simd
13730 || (in_lto_p
&& !flag_wpa
))
13731 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
13734 } // anon namespace
13736 simple_ipa_opt_pass
*
13737 make_pass_omp_simd_clone (gcc::context
*ctxt
)
13739 return new pass_omp_simd_clone (ctxt
);
13742 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13743 adds their addresses and sizes to constructor-vector V_CTOR. */
13745 add_decls_addresses_to_decl_constructor (vec
<tree
, va_gc
> *v_decls
,
13746 vec
<constructor_elt
, va_gc
> *v_ctor
)
13748 unsigned len
= vec_safe_length (v_decls
);
13749 for (unsigned i
= 0; i
< len
; i
++)
13751 tree it
= (*v_decls
)[i
];
13752 bool is_function
= TREE_CODE (it
) != VAR_DECL
;
13754 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, build_fold_addr_expr (it
));
13756 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
,
13757 fold_convert (const_ptr_type_node
,
13758 DECL_SIZE_UNIT (it
)));
13762 /* Create new symbols containing (address, size) pairs for global variables,
13763 marked with "omp declare target" attribute, as well as addresses for the
13764 functions, which are outlined offloading regions. */
13766 omp_finish_file (void)
13768 unsigned num_funcs
= vec_safe_length (offload_funcs
);
13769 unsigned num_vars
= vec_safe_length (offload_vars
);
13771 if (num_funcs
== 0 && num_vars
== 0)
13774 if (targetm_common
.have_named_sections
)
13776 vec
<constructor_elt
, va_gc
> *v_f
, *v_v
;
13777 vec_alloc (v_f
, num_funcs
);
13778 vec_alloc (v_v
, num_vars
* 2);
13780 add_decls_addresses_to_decl_constructor (offload_funcs
, v_f
);
13781 add_decls_addresses_to_decl_constructor (offload_vars
, v_v
);
13783 tree vars_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13785 tree funcs_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13787 TYPE_ALIGN (vars_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13788 TYPE_ALIGN (funcs_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13789 tree ctor_v
= build_constructor (vars_decl_type
, v_v
);
13790 tree ctor_f
= build_constructor (funcs_decl_type
, v_f
);
13791 TREE_CONSTANT (ctor_v
) = TREE_CONSTANT (ctor_f
) = 1;
13792 TREE_STATIC (ctor_v
) = TREE_STATIC (ctor_f
) = 1;
13793 tree funcs_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13794 get_identifier (".offload_func_table"),
13796 tree vars_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13797 get_identifier (".offload_var_table"),
13799 TREE_STATIC (funcs_decl
) = TREE_STATIC (vars_decl
) = 1;
13800 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13801 otherwise a joint table in a binary will contain padding between
13802 tables from multiple object files. */
13803 DECL_USER_ALIGN (funcs_decl
) = DECL_USER_ALIGN (vars_decl
) = 1;
13804 DECL_ALIGN (funcs_decl
) = TYPE_ALIGN (funcs_decl_type
);
13805 DECL_ALIGN (vars_decl
) = TYPE_ALIGN (vars_decl_type
);
13806 DECL_INITIAL (funcs_decl
) = ctor_f
;
13807 DECL_INITIAL (vars_decl
) = ctor_v
;
13808 set_decl_section_name (funcs_decl
, OFFLOAD_FUNC_TABLE_SECTION_NAME
);
13809 set_decl_section_name (vars_decl
, OFFLOAD_VAR_TABLE_SECTION_NAME
);
13811 varpool_node::finalize_decl (vars_decl
);
13812 varpool_node::finalize_decl (funcs_decl
);
13816 for (unsigned i
= 0; i
< num_funcs
; i
++)
13818 tree it
= (*offload_funcs
)[i
];
13819 targetm
.record_offload_symbol (it
);
13821 for (unsigned i
= 0; i
< num_vars
; i
++)
13823 tree it
= (*offload_vars
)[i
];
13824 targetm
.record_offload_symbol (it
);
13829 #include "gt-omp-low.h"