1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
27 #include "coretypes.h"
32 #include "double-int.h"
39 #include "fold-const.h"
40 #include "stringpool.h"
41 #include "stor-layout.h"
44 #include "hard-reg-set.h"
46 #include "dominance.h"
49 #include "basic-block.h"
50 #include "tree-ssa-alias.h"
51 #include "internal-fn.h"
52 #include "gimple-fold.h"
53 #include "gimple-expr.h"
57 #include "gimple-iterator.h"
58 #include "gimplify-me.h"
59 #include "gimple-walk.h"
60 #include "tree-iterator.h"
61 #include "tree-inline.h"
62 #include "langhooks.h"
63 #include "diagnostic-core.h"
64 #include "gimple-ssa.h"
66 #include "plugin-api.h"
70 #include "tree-phinodes.h"
71 #include "ssa-iterators.h"
72 #include "tree-ssanames.h"
73 #include "tree-into-ssa.h"
76 #include "statistics.h"
78 #include "fixed-value.h"
79 #include "insn-config.h"
90 #include "tree-pass.h"
92 #include "splay-tree.h"
93 #include "insn-codes.h"
97 #include "common/common-target.h"
99 #include "gimple-low.h"
100 #include "tree-cfgcleanup.h"
101 #include "pretty-print.h"
102 #include "alloc-pool.h"
103 #include "symbol-summary.h"
104 #include "ipa-prop.h"
105 #include "tree-nested.h"
109 #include "lto-section-names.h"
110 #include "gomp-constants.h"
113 /* Lowering of OMP parallel and workshare constructs proceeds in two
114 phases. The first phase scans the function looking for OMP statements
115 and then for variables that must be replaced to satisfy data sharing
116 clauses. The second phase expands code for the constructs, as well as
117 re-gimplifying things when variables have been replaced with complex
120 Final code generation is done by pass_expand_omp. The flowgraph is
121 scanned for regions which are then moved to a new
122 function, to be invoked by the thread library, or offloaded. */
124 /* OMP region information. Every parallel and workshare
125 directive is enclosed between two markers, the OMP_* directive
126 and a corresponding OMP_RETURN statement. */
130 /* The enclosing region. */
131 struct omp_region
*outer
;
133 /* First child region. */
134 struct omp_region
*inner
;
136 /* Next peer region. */
137 struct omp_region
*next
;
139 /* Block containing the omp directive as its last stmt. */
142 /* Block containing the OMP_RETURN as its last stmt. */
145 /* Block containing the OMP_CONTINUE as its last stmt. */
148 /* If this is a combined parallel+workshare region, this is a list
149 of additional arguments needed by the combined parallel+workshare
151 vec
<tree
, va_gc
> *ws_args
;
153 /* The code for the omp directive of this region. */
154 enum gimple_code type
;
156 /* Schedule kind, only used for OMP_FOR type regions. */
157 enum omp_clause_schedule_kind sched_kind
;
159 /* True if this is a combined parallel+workshare region. */
160 bool is_combined_parallel
;
163 /* Levels of parallelism as defined by OpenACC. Increasing numbers
164 correspond to deeper loop nesting levels. */
166 #define MASK_WORKER 2
167 #define MASK_VECTOR 4
169 /* Context structure. Used to store information about each parallel
170 directive in the code. */
172 typedef struct omp_context
174 /* This field must be at the beginning, as we do "inheritance": Some
175 callback functions for tree-inline.c (e.g., omp_copy_decl)
176 receive a copy_body_data pointer that is up-casted to an
177 omp_context pointer. */
180 /* The tree of contexts corresponding to the encountered constructs. */
181 struct omp_context
*outer
;
184 /* Map variables to fields in a structure that allows communication
185 between sending and receiving threads. */
186 splay_tree field_map
;
191 /* These are used just by task contexts, if task firstprivate fn is
192 needed. srecord_type is used to communicate from the thread
193 that encountered the task construct to task firstprivate fn,
194 record_type is allocated by GOMP_task, initialized by task firstprivate
195 fn and passed to the task body fn. */
196 splay_tree sfield_map
;
199 /* A chain of variables to add to the top-level block surrounding the
200 construct. In the case of a parallel, this is in the child function. */
203 /* A map of reduction pointer variables. For accelerators, each
204 reduction variable is replaced with an array. Each thread, in turn,
205 is assigned to a slot on that array. */
206 splay_tree reduction_map
;
208 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
209 barriers should jump to during omplower pass. */
212 /* What to do with variables with implicitly determined sharing
214 enum omp_clause_default_kind default_kind
;
216 /* Nesting depth of this context. Used to beautify error messages re
217 invalid gotos. The outermost ctx is depth 1, with depth 0 being
218 reserved for the main body of the function. */
221 /* True if this parallel directive is nested within another. */
224 /* True if this construct can be cancelled. */
227 /* For OpenACC loops, a mask of gang, worker and vector used at
228 levels below this one. */
230 /* For OpenACC loops, a mask of gang, worker and vector used at
231 this level and above. For parallel and kernels clauses, a mask
232 indicating which of num_gangs/num_workers/num_vectors was used. */
236 /* A structure holding the elements of:
237 for (V = N1; V cond N2; V += STEP) [...] */
239 struct omp_for_data_loop
241 tree v
, n1
, n2
, step
;
242 enum tree_code cond_code
;
245 /* A structure describing the main elements of a parallel loop. */
249 struct omp_for_data_loop loop
;
254 bool have_nowait
, have_ordered
;
255 enum omp_clause_schedule_kind sched_kind
;
256 struct omp_for_data_loop
*loops
;
260 static splay_tree all_contexts
;
261 static int taskreg_nesting_level
;
262 static int target_nesting_level
;
263 static struct omp_region
*root_omp_region
;
264 static bitmap task_shared_vars
;
265 static vec
<omp_context
*> taskreg_contexts
;
267 static void scan_omp (gimple_seq
*, omp_context
*);
268 static tree
scan_omp_1_op (tree
*, int *, void *);
270 #define WALK_SUBSTMTS \
274 case GIMPLE_EH_FILTER: \
275 case GIMPLE_TRANSACTION: \
276 /* The sub-statements for these should be walked. */ \
277 *handled_ops_p = false; \
280 /* Helper function to get the name of the array containing the partial
281 reductions for OpenACC reductions. */
283 oacc_get_reduction_array_id (tree node
)
285 const char *id
= IDENTIFIER_POINTER (DECL_NAME (node
));
286 int len
= strlen ("OACC") + strlen (id
);
287 char *temp_name
= XALLOCAVEC (char, len
+ 1);
288 snprintf (temp_name
, len
+ 1, "OACC%s", id
);
289 return IDENTIFIER_POINTER (get_identifier (temp_name
));
292 /* Determine the number of threads OpenACC threads used to determine the
293 size of the array of partial reductions. Currently, this is num_gangs
294 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
295 because it is independed of the device used. */
298 oacc_max_threads (omp_context
*ctx
)
300 tree nthreads
, vector_length
, gangs
, clauses
;
302 gangs
= fold_convert (sizetype
, integer_one_node
);
303 vector_length
= gangs
;
305 /* The reduction clause may be nested inside a loop directive.
306 Scan for the innermost vector_length clause. */
307 for (omp_context
*oc
= ctx
; oc
; oc
= oc
->outer
)
309 if (gimple_code (oc
->stmt
) != GIMPLE_OMP_TARGET
310 || (gimple_omp_target_kind (oc
->stmt
)
311 != GF_OMP_TARGET_KIND_OACC_PARALLEL
))
314 clauses
= gimple_omp_target_clauses (oc
->stmt
);
316 vector_length
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
318 vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length
),
320 OMP_CLAUSE_VECTOR_LENGTH_EXPR
323 vector_length
= fold_convert (sizetype
, integer_one_node
);
325 gangs
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
327 gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (gangs
), sizetype
,
328 OMP_CLAUSE_NUM_GANGS_EXPR (gangs
));
330 gangs
= fold_convert (sizetype
, integer_one_node
);
335 nthreads
= fold_build2 (MULT_EXPR
, sizetype
, gangs
, vector_length
);
340 /* Holds offload tables with decls. */
341 vec
<tree
, va_gc
> *offload_funcs
, *offload_vars
;
343 /* Convenience function for calling scan_omp_1_op on tree operands. */
346 scan_omp_op (tree
*tp
, omp_context
*ctx
)
348 struct walk_stmt_info wi
;
350 memset (&wi
, 0, sizeof (wi
));
352 wi
.want_locations
= true;
354 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
357 static void lower_omp (gimple_seq
*, omp_context
*);
358 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
359 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
361 /* Find an OMP clause of type KIND within CLAUSES. */
364 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
366 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
367 if (OMP_CLAUSE_CODE (clauses
) == kind
)
373 /* Return true if CTX is for an omp parallel. */
376 is_parallel_ctx (omp_context
*ctx
)
378 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
382 /* Return true if CTX is for an omp task. */
385 is_task_ctx (omp_context
*ctx
)
387 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
391 /* Return true if CTX is for an omp parallel or omp task. */
394 is_taskreg_ctx (omp_context
*ctx
)
396 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
397 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
401 /* Return true if REGION is a combined parallel+workshare region. */
404 is_combined_parallel (struct omp_region
*region
)
406 return region
->is_combined_parallel
;
410 /* Extract the header elements of parallel loop FOR_STMT and store
414 extract_omp_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
415 struct omp_for_data_loop
*loops
)
417 tree t
, var
, *collapse_iter
, *collapse_count
;
418 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
419 struct omp_for_data_loop
*loop
;
421 struct omp_for_data_loop dummy_loop
;
422 location_t loc
= gimple_location (for_stmt
);
423 bool simd
= gimple_omp_for_kind (for_stmt
) & GF_OMP_FOR_SIMD
;
424 bool distribute
= gimple_omp_for_kind (for_stmt
)
425 == GF_OMP_FOR_KIND_DISTRIBUTE
;
427 fd
->for_stmt
= for_stmt
;
429 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
430 if (fd
->collapse
> 1)
433 fd
->loops
= &fd
->loop
;
435 fd
->have_nowait
= distribute
|| simd
;
436 fd
->have_ordered
= false;
437 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
438 fd
->chunk_size
= NULL_TREE
;
439 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
440 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_CILKFOR
;
441 collapse_iter
= NULL
;
442 collapse_count
= NULL
;
444 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
445 switch (OMP_CLAUSE_CODE (t
))
447 case OMP_CLAUSE_NOWAIT
:
448 fd
->have_nowait
= true;
450 case OMP_CLAUSE_ORDERED
:
451 fd
->have_ordered
= true;
453 case OMP_CLAUSE_SCHEDULE
:
454 gcc_assert (!distribute
);
455 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
456 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
458 case OMP_CLAUSE_DIST_SCHEDULE
:
459 gcc_assert (distribute
);
460 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
462 case OMP_CLAUSE_COLLAPSE
:
463 if (fd
->collapse
> 1)
465 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
466 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
473 /* FIXME: for now map schedule(auto) to schedule(static).
474 There should be analysis to determine whether all iterations
475 are approximately the same amount of work (then schedule(static)
476 is best) or if it varies (then schedule(dynamic,N) is better). */
477 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
479 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
480 gcc_assert (fd
->chunk_size
== NULL
);
482 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
483 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
484 gcc_assert (fd
->chunk_size
== NULL
);
485 else if (fd
->chunk_size
== NULL
)
487 /* We only need to compute a default chunk size for ordered
488 static loops and dynamic loops. */
489 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
491 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
492 ? integer_zero_node
: integer_one_node
;
495 for (i
= 0; i
< fd
->collapse
; i
++)
497 if (fd
->collapse
== 1)
499 else if (loops
!= NULL
)
504 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
505 gcc_assert (SSA_VAR_P (loop
->v
));
506 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
507 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
508 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
509 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
511 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
512 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
513 switch (loop
->cond_code
)
519 gcc_assert (gimple_omp_for_kind (for_stmt
)
520 == GF_OMP_FOR_KIND_CILKSIMD
521 || (gimple_omp_for_kind (for_stmt
)
522 == GF_OMP_FOR_KIND_CILKFOR
));
525 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
526 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
528 loop
->n2
= fold_build2_loc (loc
,
529 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
530 build_int_cst (TREE_TYPE (loop
->n2
), 1));
531 loop
->cond_code
= LT_EXPR
;
534 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
535 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
537 loop
->n2
= fold_build2_loc (loc
,
538 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
539 build_int_cst (TREE_TYPE (loop
->n2
), 1));
540 loop
->cond_code
= GT_EXPR
;
546 t
= gimple_omp_for_incr (for_stmt
, i
);
547 gcc_assert (TREE_OPERAND (t
, 0) == var
);
548 switch (TREE_CODE (t
))
551 loop
->step
= TREE_OPERAND (t
, 1);
553 case POINTER_PLUS_EXPR
:
554 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
557 loop
->step
= TREE_OPERAND (t
, 1);
558 loop
->step
= fold_build1_loc (loc
,
559 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
567 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
568 && !fd
->have_ordered
))
570 if (fd
->collapse
== 1)
571 iter_type
= TREE_TYPE (loop
->v
);
573 || TYPE_PRECISION (iter_type
)
574 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
576 = build_nonstandard_integer_type
577 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
579 else if (iter_type
!= long_long_unsigned_type_node
)
581 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
582 iter_type
= long_long_unsigned_type_node
;
583 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
584 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
585 >= TYPE_PRECISION (iter_type
))
589 if (loop
->cond_code
== LT_EXPR
)
590 n
= fold_build2_loc (loc
,
591 PLUS_EXPR
, TREE_TYPE (loop
->v
),
592 loop
->n2
, loop
->step
);
595 if (TREE_CODE (n
) != INTEGER_CST
596 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
597 iter_type
= long_long_unsigned_type_node
;
599 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
600 > TYPE_PRECISION (iter_type
))
604 if (loop
->cond_code
== LT_EXPR
)
607 n2
= fold_build2_loc (loc
,
608 PLUS_EXPR
, TREE_TYPE (loop
->v
),
609 loop
->n2
, loop
->step
);
613 n1
= fold_build2_loc (loc
,
614 MINUS_EXPR
, TREE_TYPE (loop
->v
),
615 loop
->n2
, loop
->step
);
618 if (TREE_CODE (n1
) != INTEGER_CST
619 || TREE_CODE (n2
) != INTEGER_CST
620 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
621 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
622 iter_type
= long_long_unsigned_type_node
;
626 if (collapse_count
&& *collapse_count
== NULL
)
628 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
629 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
630 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
631 if (t
&& integer_zerop (t
))
632 count
= build_zero_cst (long_long_unsigned_type_node
);
633 else if ((i
== 0 || count
!= NULL_TREE
)
634 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
635 && TREE_CONSTANT (loop
->n1
)
636 && TREE_CONSTANT (loop
->n2
)
637 && TREE_CODE (loop
->step
) == INTEGER_CST
)
639 tree itype
= TREE_TYPE (loop
->v
);
641 if (POINTER_TYPE_P (itype
))
642 itype
= signed_type_for (itype
);
643 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
644 t
= fold_build2_loc (loc
,
646 fold_convert_loc (loc
, itype
, loop
->step
), t
);
647 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
648 fold_convert_loc (loc
, itype
, loop
->n2
));
649 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
650 fold_convert_loc (loc
, itype
, loop
->n1
));
651 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
652 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
653 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
654 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
655 fold_convert_loc (loc
, itype
,
658 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
659 fold_convert_loc (loc
, itype
, loop
->step
));
660 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
661 if (count
!= NULL_TREE
)
662 count
= fold_build2_loc (loc
,
663 MULT_EXPR
, long_long_unsigned_type_node
,
667 if (TREE_CODE (count
) != INTEGER_CST
)
670 else if (count
&& !integer_zerop (count
))
677 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
678 || fd
->have_ordered
))
680 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
681 iter_type
= long_long_unsigned_type_node
;
683 iter_type
= long_integer_type_node
;
685 else if (collapse_iter
&& *collapse_iter
!= NULL
)
686 iter_type
= TREE_TYPE (*collapse_iter
);
687 fd
->iter_type
= iter_type
;
688 if (collapse_iter
&& *collapse_iter
== NULL
)
689 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
690 if (collapse_count
&& *collapse_count
== NULL
)
693 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
695 *collapse_count
= create_tmp_var (iter_type
, ".count");
698 if (fd
->collapse
> 1)
700 fd
->loop
.v
= *collapse_iter
;
701 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
702 fd
->loop
.n2
= *collapse_count
;
703 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
704 fd
->loop
.cond_code
= LT_EXPR
;
707 /* For OpenACC loops, force a chunk size of one, as this avoids the default
708 scheduling where several subsequent iterations are being executed by the
710 if (gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
712 gcc_assert (fd
->chunk_size
== NULL_TREE
);
713 fd
->chunk_size
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
718 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
719 is the immediate dominator of PAR_ENTRY_BB, return true if there
720 are no data dependencies that would prevent expanding the parallel
721 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
723 When expanding a combined parallel+workshare region, the call to
724 the child function may need additional arguments in the case of
725 GIMPLE_OMP_FOR regions. In some cases, these arguments are
726 computed out of variables passed in from the parent to the child
727 via 'struct .omp_data_s'. For instance:
729 #pragma omp parallel for schedule (guided, i * 4)
734 # BLOCK 2 (PAR_ENTRY_BB)
736 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
738 # BLOCK 3 (WS_ENTRY_BB)
739 .omp_data_i = &.omp_data_o;
740 D.1667 = .omp_data_i->i;
742 #pragma omp for schedule (guided, D.1598)
744 When we outline the parallel region, the call to the child function
745 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
746 that value is computed *after* the call site. So, in principle we
747 cannot do the transformation.
749 To see whether the code in WS_ENTRY_BB blocks the combined
750 parallel+workshare call, we collect all the variables used in the
751 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
752 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
755 FIXME. If we had the SSA form built at this point, we could merely
756 hoist the code in block 3 into block 2 and be done with it. But at
757 this point we don't have dataflow information and though we could
758 hack something up here, it is really not worth the aggravation. */
761 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
763 struct omp_for_data fd
;
764 gimple ws_stmt
= last_stmt (ws_entry_bb
);
766 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
769 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
771 extract_omp_for_data (as_a
<gomp_for
*> (ws_stmt
), &fd
, NULL
);
773 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
775 if (fd
.iter_type
!= long_integer_type_node
)
778 /* FIXME. We give up too easily here. If any of these arguments
779 are not constants, they will likely involve variables that have
780 been mapped into fields of .omp_data_s for sharing with the child
781 function. With appropriate data flow, it would be possible to
783 if (!is_gimple_min_invariant (fd
.loop
.n1
)
784 || !is_gimple_min_invariant (fd
.loop
.n2
)
785 || !is_gimple_min_invariant (fd
.loop
.step
)
786 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
793 /* Collect additional arguments needed to emit a combined
794 parallel+workshare call. WS_STMT is the workshare directive being
797 static vec
<tree
, va_gc
> *
798 get_ws_args_for (gimple par_stmt
, gimple ws_stmt
)
801 location_t loc
= gimple_location (ws_stmt
);
802 vec
<tree
, va_gc
> *ws_args
;
804 if (gomp_for
*for_stmt
= dyn_cast
<gomp_for
*> (ws_stmt
))
806 struct omp_for_data fd
;
809 extract_omp_for_data (for_stmt
, &fd
, NULL
);
813 if (gimple_omp_for_combined_into_p (for_stmt
))
816 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt
),
817 OMP_CLAUSE__LOOPTEMP_
);
819 n1
= OMP_CLAUSE_DECL (innerc
);
820 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
821 OMP_CLAUSE__LOOPTEMP_
);
823 n2
= OMP_CLAUSE_DECL (innerc
);
826 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
828 t
= fold_convert_loc (loc
, long_integer_type_node
, n1
);
829 ws_args
->quick_push (t
);
831 t
= fold_convert_loc (loc
, long_integer_type_node
, n2
);
832 ws_args
->quick_push (t
);
834 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
835 ws_args
->quick_push (t
);
839 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
840 ws_args
->quick_push (t
);
845 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
847 /* Number of sections is equal to the number of edges from the
848 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
849 the exit of the sections region. */
850 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
851 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
852 vec_alloc (ws_args
, 1);
853 ws_args
->quick_push (t
);
861 /* Discover whether REGION is a combined parallel+workshare region. */
864 determine_parallel_type (struct omp_region
*region
)
866 basic_block par_entry_bb
, par_exit_bb
;
867 basic_block ws_entry_bb
, ws_exit_bb
;
869 if (region
== NULL
|| region
->inner
== NULL
870 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
871 || region
->inner
->cont
== NULL
)
874 /* We only support parallel+for and parallel+sections. */
875 if (region
->type
!= GIMPLE_OMP_PARALLEL
876 || (region
->inner
->type
!= GIMPLE_OMP_FOR
877 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
880 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
881 WS_EXIT_BB -> PAR_EXIT_BB. */
882 par_entry_bb
= region
->entry
;
883 par_exit_bb
= region
->exit
;
884 ws_entry_bb
= region
->inner
->entry
;
885 ws_exit_bb
= region
->inner
->exit
;
887 if (single_succ (par_entry_bb
) == ws_entry_bb
888 && single_succ (ws_exit_bb
) == par_exit_bb
889 && workshare_safe_to_combine_p (ws_entry_bb
)
890 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
891 || (last_and_only_stmt (ws_entry_bb
)
892 && last_and_only_stmt (par_exit_bb
))))
894 gimple par_stmt
= last_stmt (par_entry_bb
);
895 gimple ws_stmt
= last_stmt (ws_entry_bb
);
897 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
899 /* If this is a combined parallel loop, we need to determine
900 whether or not to use the combined library calls. There
901 are two cases where we do not apply the transformation:
902 static loops and any kind of ordered loop. In the first
903 case, we already open code the loop so there is no need
904 to do anything else. In the latter case, the combined
905 parallel loop call would still need extra synchronization
906 to implement ordered semantics, so there would not be any
907 gain in using the combined call. */
908 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
909 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
911 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
912 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
914 region
->is_combined_parallel
= false;
915 region
->inner
->is_combined_parallel
= false;
920 region
->is_combined_parallel
= true;
921 region
->inner
->is_combined_parallel
= true;
922 region
->ws_args
= get_ws_args_for (par_stmt
, ws_stmt
);
927 /* Return true if EXPR is variable sized. */
930 is_variable_sized (const_tree expr
)
932 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
935 /* Return true if DECL is a reference type. */
938 is_reference (tree decl
)
940 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
943 /* Return the type of a decl. If the decl is reference type,
944 return its base type. */
946 get_base_type (tree decl
)
948 tree type
= TREE_TYPE (decl
);
949 if (is_reference (decl
))
950 type
= TREE_TYPE (type
);
954 /* Lookup variables. The "maybe" form
955 allows for the variable form to not have been entered, otherwise we
956 assert that the variable must have been entered. */
959 lookup_decl (tree var
, omp_context
*ctx
)
961 tree
*n
= ctx
->cb
.decl_map
->get (var
);
966 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
968 tree
*n
= ctx
->cb
.decl_map
->get (const_cast<tree
> (var
));
969 return n
? *n
: NULL_TREE
;
973 lookup_field (tree var
, omp_context
*ctx
)
976 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
977 return (tree
) n
->value
;
981 lookup_sfield (tree var
, omp_context
*ctx
)
984 n
= splay_tree_lookup (ctx
->sfield_map
985 ? ctx
->sfield_map
: ctx
->field_map
,
986 (splay_tree_key
) var
);
987 return (tree
) n
->value
;
991 maybe_lookup_field (tree var
, omp_context
*ctx
)
994 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
995 return n
? (tree
) n
->value
: NULL_TREE
;
999 lookup_oacc_reduction (const char *id
, omp_context
*ctx
)
1002 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) id
);
1003 return (tree
) n
->value
;
1007 maybe_lookup_oacc_reduction (tree var
, omp_context
*ctx
)
1009 splay_tree_node n
= NULL
;
1010 if (ctx
->reduction_map
)
1011 n
= splay_tree_lookup (ctx
->reduction_map
, (splay_tree_key
) var
);
1012 return n
? (tree
) n
->value
: NULL_TREE
;
1015 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1016 the parallel context if DECL is to be shared. */
1019 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
1021 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
1024 /* We can only use copy-in/copy-out semantics for shared variables
1025 when we know the value is not accessible from an outer scope. */
1028 gcc_assert (!is_gimple_omp_oacc (shared_ctx
->stmt
));
1030 /* ??? Trivially accessible from anywhere. But why would we even
1031 be passing an address in this case? Should we simply assert
1032 this to be false, or should we have a cleanup pass that removes
1033 these from the list of mappings? */
1034 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
1037 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1038 without analyzing the expression whether or not its location
1039 is accessible to anyone else. In the case of nested parallel
1040 regions it certainly may be. */
1041 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
1044 /* Do not use copy-in/copy-out for variables that have their
1046 if (TREE_ADDRESSABLE (decl
))
1049 /* lower_send_shared_vars only uses copy-in, but not copy-out
1051 if (TREE_READONLY (decl
)
1052 || ((TREE_CODE (decl
) == RESULT_DECL
1053 || TREE_CODE (decl
) == PARM_DECL
)
1054 && DECL_BY_REFERENCE (decl
)))
1057 /* Disallow copy-in/out in nested parallel if
1058 decl is shared in outer parallel, otherwise
1059 each thread could store the shared variable
1060 in its own copy-in location, making the
1061 variable no longer really shared. */
1062 if (shared_ctx
->is_nested
)
1066 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
1067 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
1074 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
1075 c
; c
= OMP_CLAUSE_CHAIN (c
))
1076 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1077 && OMP_CLAUSE_DECL (c
) == decl
)
1081 goto maybe_mark_addressable_and_ret
;
1085 /* For tasks avoid using copy-in/out. As tasks can be
1086 deferred or executed in different thread, when GOMP_task
1087 returns, the task hasn't necessarily terminated. */
1088 if (is_task_ctx (shared_ctx
))
1091 maybe_mark_addressable_and_ret
:
1092 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
1093 if (is_gimple_reg (outer
))
1095 /* Taking address of OUTER in lower_send_shared_vars
1096 might need regimplification of everything that uses the
1098 if (!task_shared_vars
)
1099 task_shared_vars
= BITMAP_ALLOC (NULL
);
1100 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
1101 TREE_ADDRESSABLE (outer
) = 1;
1110 /* Construct a new automatic decl similar to VAR. */
1113 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
1115 tree copy
= copy_var_decl (var
, name
, type
);
1117 DECL_CONTEXT (copy
) = current_function_decl
;
1118 DECL_CHAIN (copy
) = ctx
->block_vars
;
1119 ctx
->block_vars
= copy
;
1125 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
1127 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
1130 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1133 omp_build_component_ref (tree obj
, tree field
)
1135 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
1136 if (TREE_THIS_VOLATILE (field
))
1137 TREE_THIS_VOLATILE (ret
) |= 1;
1138 if (TREE_READONLY (field
))
1139 TREE_READONLY (ret
) |= 1;
1143 /* Build tree nodes to access the field for VAR on the receiver side. */
1146 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
1148 tree x
, field
= lookup_field (var
, ctx
);
1150 /* If the receiver record type was remapped in the child function,
1151 remap the field into the new record type. */
1152 x
= maybe_lookup_field (field
, ctx
);
1156 x
= build_simple_mem_ref (ctx
->receiver_decl
);
1157 x
= omp_build_component_ref (x
, field
);
1159 x
= build_simple_mem_ref (x
);
1164 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1165 of a parallel, this is a component reference; for workshare constructs
1166 this is some variable. */
1169 build_outer_var_ref (tree var
, omp_context
*ctx
)
1173 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
1175 else if (is_variable_sized (var
))
1177 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
1178 x
= build_outer_var_ref (x
, ctx
);
1179 x
= build_simple_mem_ref (x
);
1181 else if (is_taskreg_ctx (ctx
))
1183 bool by_ref
= use_pointer_for_field (var
, NULL
);
1184 x
= build_receiver_ref (var
, by_ref
, ctx
);
1186 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1187 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
1189 /* #pragma omp simd isn't a worksharing construct, and can reference even
1190 private vars in its linear etc. clauses. */
1192 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
1193 x
= lookup_decl (var
, ctx
->outer
);
1194 else if (ctx
->outer
)
1195 x
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
1199 else if (ctx
->outer
)
1200 x
= lookup_decl (var
, ctx
->outer
);
1201 else if (is_reference (var
))
1202 /* This can happen with orphaned constructs. If var is reference, it is
1203 possible it is shared and as such valid. */
1208 if (is_reference (var
))
1209 x
= build_simple_mem_ref (x
);
1214 /* Build tree nodes to access the field for VAR on the sender side. */
1217 build_sender_ref (tree var
, omp_context
*ctx
)
1219 tree field
= lookup_sfield (var
, ctx
);
1220 return omp_build_component_ref (ctx
->sender_decl
, field
);
1223 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1226 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
1228 tree field
, type
, sfield
= NULL_TREE
;
1230 gcc_assert ((mask
& 1) == 0
1231 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
1232 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
1233 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
1234 gcc_assert ((mask
& 3) == 3
1235 || !is_gimple_omp_oacc (ctx
->stmt
));
1237 type
= TREE_TYPE (var
);
1240 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
1241 type
= build_pointer_type (build_pointer_type (type
));
1244 type
= build_pointer_type (type
);
1245 else if ((mask
& 3) == 1 && is_reference (var
))
1246 type
= TREE_TYPE (type
);
1248 field
= build_decl (DECL_SOURCE_LOCATION (var
),
1249 FIELD_DECL
, DECL_NAME (var
), type
);
1251 /* Remember what variable this field was created for. This does have a
1252 side effect of making dwarf2out ignore this member, so for helpful
1253 debugging we clear it later in delete_omp_context. */
1254 DECL_ABSTRACT_ORIGIN (field
) = var
;
1255 if (type
== TREE_TYPE (var
))
1257 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1258 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1259 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1262 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1264 if ((mask
& 3) == 3)
1266 insert_field_into_struct (ctx
->record_type
, field
);
1267 if (ctx
->srecord_type
)
1269 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1270 FIELD_DECL
, DECL_NAME (var
), type
);
1271 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1272 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1273 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1274 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1275 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1280 if (ctx
->srecord_type
== NULL_TREE
)
1284 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1285 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1286 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1288 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1289 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1290 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1291 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1292 splay_tree_insert (ctx
->sfield_map
,
1293 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1294 (splay_tree_value
) sfield
);
1298 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1299 : ctx
->srecord_type
, field
);
1303 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1304 (splay_tree_value
) field
);
1305 if ((mask
& 2) && ctx
->sfield_map
)
1306 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1307 (splay_tree_value
) sfield
);
1311 install_var_local (tree var
, omp_context
*ctx
)
1313 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1314 insert_decl_map (&ctx
->cb
, var
, new_var
);
1318 /* Adjust the replacement for DECL in CTX for the new context. This means
1319 copying the DECL_VALUE_EXPR, and fixing up the type. */
1322 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1324 tree new_decl
, size
;
1326 new_decl
= lookup_decl (decl
, ctx
);
1328 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1330 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1331 && DECL_HAS_VALUE_EXPR_P (decl
))
1333 tree ve
= DECL_VALUE_EXPR (decl
);
1334 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1335 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1336 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1339 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1341 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1342 if (size
== error_mark_node
)
1343 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1344 DECL_SIZE (new_decl
) = size
;
1346 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1347 if (size
== error_mark_node
)
1348 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1349 DECL_SIZE_UNIT (new_decl
) = size
;
1353 /* The callback for remap_decl. Search all containing contexts for a
1354 mapping of the variable; this avoids having to duplicate the splay
1355 tree ahead of time. We know a mapping doesn't already exist in the
1356 given context. Create new mappings to implement default semantics. */
1359 omp_copy_decl (tree var
, copy_body_data
*cb
)
1361 omp_context
*ctx
= (omp_context
*) cb
;
1364 if (TREE_CODE (var
) == LABEL_DECL
)
1366 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1367 DECL_CONTEXT (new_var
) = current_function_decl
;
1368 insert_decl_map (&ctx
->cb
, var
, new_var
);
1372 while (!is_taskreg_ctx (ctx
))
1377 new_var
= maybe_lookup_decl (var
, ctx
);
1382 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1385 return error_mark_node
;
1389 /* Debugging dumps for parallel regions. */
1390 void dump_omp_region (FILE *, struct omp_region
*, int);
1391 void debug_omp_region (struct omp_region
*);
1392 void debug_all_omp_regions (void);
1394 /* Dump the parallel region tree rooted at REGION. */
1397 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1399 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1400 gimple_code_name
[region
->type
]);
1403 dump_omp_region (file
, region
->inner
, indent
+ 4);
1407 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1408 region
->cont
->index
);
1412 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1413 region
->exit
->index
);
1415 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1418 dump_omp_region (file
, region
->next
, indent
);
1422 debug_omp_region (struct omp_region
*region
)
1424 dump_omp_region (stderr
, region
, 0);
1428 debug_all_omp_regions (void)
1430 dump_omp_region (stderr
, root_omp_region
, 0);
1434 /* Create a new parallel region starting at STMT inside region PARENT. */
1436 static struct omp_region
*
1437 new_omp_region (basic_block bb
, enum gimple_code type
,
1438 struct omp_region
*parent
)
1440 struct omp_region
*region
= XCNEW (struct omp_region
);
1442 region
->outer
= parent
;
1444 region
->type
= type
;
1448 /* This is a nested region. Add it to the list of inner
1449 regions in PARENT. */
1450 region
->next
= parent
->inner
;
1451 parent
->inner
= region
;
1455 /* This is a toplevel region. Add it to the list of toplevel
1456 regions in ROOT_OMP_REGION. */
1457 region
->next
= root_omp_region
;
1458 root_omp_region
= region
;
1464 /* Release the memory associated with the region tree rooted at REGION. */
1467 free_omp_region_1 (struct omp_region
*region
)
1469 struct omp_region
*i
, *n
;
1471 for (i
= region
->inner
; i
; i
= n
)
1474 free_omp_region_1 (i
);
1480 /* Release the memory for the entire omp region tree. */
1483 free_omp_regions (void)
1485 struct omp_region
*r
, *n
;
1486 for (r
= root_omp_region
; r
; r
= n
)
1489 free_omp_region_1 (r
);
1491 root_omp_region
= NULL
;
1495 /* Create a new context, with OUTER_CTX being the surrounding context. */
1497 static omp_context
*
1498 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1500 omp_context
*ctx
= XCNEW (omp_context
);
1502 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1503 (splay_tree_value
) ctx
);
1508 ctx
->outer
= outer_ctx
;
1509 ctx
->cb
= outer_ctx
->cb
;
1510 ctx
->cb
.block
= NULL
;
1511 ctx
->depth
= outer_ctx
->depth
+ 1;
1512 ctx
->reduction_map
= outer_ctx
->reduction_map
;
1516 ctx
->cb
.src_fn
= current_function_decl
;
1517 ctx
->cb
.dst_fn
= current_function_decl
;
1518 ctx
->cb
.src_node
= cgraph_node::get (current_function_decl
);
1519 gcc_checking_assert (ctx
->cb
.src_node
);
1520 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1521 ctx
->cb
.src_cfun
= cfun
;
1522 ctx
->cb
.copy_decl
= omp_copy_decl
;
1523 ctx
->cb
.eh_lp_nr
= 0;
1524 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1528 ctx
->cb
.decl_map
= new hash_map
<tree
, tree
>;
1533 static gimple_seq
maybe_catch_exception (gimple_seq
);
1535 /* Finalize task copyfn. */
1538 finalize_task_copyfn (gomp_task
*task_stmt
)
1540 struct function
*child_cfun
;
1542 gimple_seq seq
= NULL
, new_seq
;
1545 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1546 if (child_fn
== NULL_TREE
)
1549 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1550 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1552 push_cfun (child_cfun
);
1553 bind
= gimplify_body (child_fn
, false);
1554 gimple_seq_add_stmt (&seq
, bind
);
1555 new_seq
= maybe_catch_exception (seq
);
1558 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1560 gimple_seq_add_stmt (&seq
, bind
);
1562 gimple_set_body (child_fn
, seq
);
1565 /* Inform the callgraph about the new function. */
1566 cgraph_node::add_new_function (child_fn
, false);
1567 cgraph_node::get (child_fn
)->parallelized_function
= 1;
1570 /* Destroy a omp_context data structures. Called through the splay tree
1571 value delete callback. */
1574 delete_omp_context (splay_tree_value value
)
1576 omp_context
*ctx
= (omp_context
*) value
;
1578 delete ctx
->cb
.decl_map
;
1581 splay_tree_delete (ctx
->field_map
);
1582 if (ctx
->sfield_map
)
1583 splay_tree_delete (ctx
->sfield_map
);
1584 /* Reduction map is copied to nested contexts, so only delete it in the
1586 if (ctx
->reduction_map
1587 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
1588 && is_gimple_omp_offloaded (ctx
->stmt
)
1589 && is_gimple_omp_oacc (ctx
->stmt
))
1590 splay_tree_delete (ctx
->reduction_map
);
1592 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1593 it produces corrupt debug information. */
1594 if (ctx
->record_type
)
1597 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1598 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1600 if (ctx
->srecord_type
)
1603 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1604 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1607 if (is_task_ctx (ctx
))
1608 finalize_task_copyfn (as_a
<gomp_task
*> (ctx
->stmt
));
1613 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1617 fixup_child_record_type (omp_context
*ctx
)
1619 tree f
, type
= ctx
->record_type
;
1621 /* ??? It isn't sufficient to just call remap_type here, because
1622 variably_modified_type_p doesn't work the way we expect for
1623 record types. Testing each field for whether it needs remapping
1624 and creating a new record by hand works, however. */
1625 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1626 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1630 tree name
, new_fields
= NULL
;
1632 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1633 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1634 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1635 TYPE_DECL
, name
, type
);
1636 TYPE_NAME (type
) = name
;
1638 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1640 tree new_f
= copy_node (f
);
1641 DECL_CONTEXT (new_f
) = type
;
1642 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1643 DECL_CHAIN (new_f
) = new_fields
;
1644 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1645 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1647 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1651 /* Arrange to be able to look up the receiver field
1652 given the sender field. */
1653 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1654 (splay_tree_value
) new_f
);
1656 TYPE_FIELDS (type
) = nreverse (new_fields
);
1660 TREE_TYPE (ctx
->receiver_decl
)
1661 = build_qualified_type (build_reference_type (type
), TYPE_QUAL_RESTRICT
);
1664 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1665 specified by CLAUSES. */
1668 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1671 bool scan_array_reductions
= false;
1673 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1677 switch (OMP_CLAUSE_CODE (c
))
1679 case OMP_CLAUSE_PRIVATE
:
1680 decl
= OMP_CLAUSE_DECL (c
);
1681 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1683 else if (!is_variable_sized (decl
))
1684 install_var_local (decl
, ctx
);
1687 case OMP_CLAUSE_SHARED
:
1688 decl
= OMP_CLAUSE_DECL (c
);
1689 /* Ignore shared directives in teams construct. */
1690 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1692 /* Global variables don't need to be copied,
1693 the receiver side will use them directly. */
1694 tree odecl
= maybe_lookup_decl_in_outer_ctx (decl
, ctx
);
1695 if (is_global_var (odecl
))
1697 insert_decl_map (&ctx
->cb
, decl
, odecl
);
1700 gcc_assert (is_taskreg_ctx (ctx
));
1701 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1702 || !is_variable_sized (decl
));
1703 /* Global variables don't need to be copied,
1704 the receiver side will use them directly. */
1705 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1707 by_ref
= use_pointer_for_field (decl
, ctx
);
1708 if (! TREE_READONLY (decl
)
1709 || TREE_ADDRESSABLE (decl
)
1711 || is_reference (decl
))
1713 install_var_field (decl
, by_ref
, 3, ctx
);
1714 install_var_local (decl
, ctx
);
1717 /* We don't need to copy const scalar vars back. */
1718 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1721 case OMP_CLAUSE_LASTPRIVATE
:
1722 /* Let the corresponding firstprivate clause create
1724 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1728 case OMP_CLAUSE_FIRSTPRIVATE
:
1729 if (is_gimple_omp_oacc (ctx
->stmt
))
1731 sorry ("clause not supported yet");
1735 case OMP_CLAUSE_REDUCTION
:
1736 case OMP_CLAUSE_LINEAR
:
1737 decl
= OMP_CLAUSE_DECL (c
);
1739 if (is_variable_sized (decl
))
1741 if (is_task_ctx (ctx
))
1742 install_var_field (decl
, false, 1, ctx
);
1745 else if (is_taskreg_ctx (ctx
))
1748 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1749 by_ref
= use_pointer_for_field (decl
, NULL
);
1751 if (is_task_ctx (ctx
)
1752 && (global
|| by_ref
|| is_reference (decl
)))
1754 install_var_field (decl
, false, 1, ctx
);
1756 install_var_field (decl
, by_ref
, 2, ctx
);
1759 install_var_field (decl
, by_ref
, 3, ctx
);
1761 install_var_local (decl
, ctx
);
1762 if (is_gimple_omp_oacc (ctx
->stmt
)
1763 && OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
1765 /* Create a decl for the reduction array. */
1766 tree var
= OMP_CLAUSE_DECL (c
);
1767 tree type
= get_base_type (var
);
1768 tree ptype
= build_pointer_type (type
);
1769 tree array
= create_tmp_var (ptype
,
1770 oacc_get_reduction_array_id (var
));
1771 omp_context
*c
= (ctx
->field_map
? ctx
: ctx
->outer
);
1772 install_var_field (array
, true, 3, c
);
1773 install_var_local (array
, c
);
1775 /* Insert it into the current context. */
1776 splay_tree_insert (ctx
->reduction_map
, (splay_tree_key
)
1777 oacc_get_reduction_array_id (var
),
1778 (splay_tree_value
) array
);
1779 splay_tree_insert (ctx
->reduction_map
,
1780 (splay_tree_key
) array
,
1781 (splay_tree_value
) array
);
1785 case OMP_CLAUSE__LOOPTEMP_
:
1786 gcc_assert (is_parallel_ctx (ctx
));
1787 decl
= OMP_CLAUSE_DECL (c
);
1788 install_var_field (decl
, false, 3, ctx
);
1789 install_var_local (decl
, ctx
);
1792 case OMP_CLAUSE_COPYPRIVATE
:
1793 case OMP_CLAUSE_COPYIN
:
1794 decl
= OMP_CLAUSE_DECL (c
);
1795 by_ref
= use_pointer_for_field (decl
, NULL
);
1796 install_var_field (decl
, by_ref
, 3, ctx
);
1799 case OMP_CLAUSE_DEFAULT
:
1800 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1803 case OMP_CLAUSE_FINAL
:
1805 case OMP_CLAUSE_NUM_THREADS
:
1806 case OMP_CLAUSE_NUM_TEAMS
:
1807 case OMP_CLAUSE_THREAD_LIMIT
:
1808 case OMP_CLAUSE_DEVICE
:
1809 case OMP_CLAUSE_SCHEDULE
:
1810 case OMP_CLAUSE_DIST_SCHEDULE
:
1811 case OMP_CLAUSE_DEPEND
:
1812 case OMP_CLAUSE__CILK_FOR_COUNT_
:
1813 case OMP_CLAUSE_NUM_GANGS
:
1814 case OMP_CLAUSE_NUM_WORKERS
:
1815 case OMP_CLAUSE_VECTOR_LENGTH
:
1817 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1821 case OMP_CLAUSE_FROM
:
1822 case OMP_CLAUSE_MAP
:
1824 scan_omp_op (&OMP_CLAUSE_SIZE (c
), ctx
->outer
);
1825 decl
= OMP_CLAUSE_DECL (c
);
1826 /* Global variables with "omp declare target" attribute
1827 don't need to be copied, the receiver side will use them
1829 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1831 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1832 && varpool_node::get_create (decl
)->offloadable
)
1834 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1835 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
)
1837 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1838 not offloaded; there is nothing to map for those. */
1839 if (!is_gimple_omp_offloaded (ctx
->stmt
)
1840 && !POINTER_TYPE_P (TREE_TYPE (decl
))
1841 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
1846 if (DECL_SIZE (decl
)
1847 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
1849 tree decl2
= DECL_VALUE_EXPR (decl
);
1850 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
1851 decl2
= TREE_OPERAND (decl2
, 0);
1852 gcc_assert (DECL_P (decl2
));
1853 install_var_field (decl2
, true, 3, ctx
);
1854 install_var_local (decl2
, ctx
);
1855 install_var_local (decl
, ctx
);
1859 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
1860 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1861 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
1862 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1863 install_var_field (decl
, true, 7, ctx
);
1865 install_var_field (decl
, true, 3, ctx
);
1866 if (is_gimple_omp_offloaded (ctx
->stmt
))
1867 install_var_local (decl
, ctx
);
1872 tree base
= get_base_address (decl
);
1873 tree nc
= OMP_CLAUSE_CHAIN (c
);
1876 && OMP_CLAUSE_CODE (nc
) == OMP_CLAUSE_MAP
1877 && OMP_CLAUSE_DECL (nc
) == base
1878 && OMP_CLAUSE_MAP_KIND (nc
) == GOMP_MAP_POINTER
1879 && integer_zerop (OMP_CLAUSE_SIZE (nc
)))
1881 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
) = 1;
1882 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc
) = 1;
1888 scan_omp_op (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
1889 decl
= OMP_CLAUSE_DECL (c
);
1891 gcc_assert (!splay_tree_lookup (ctx
->field_map
,
1892 (splay_tree_key
) decl
));
1894 = build_decl (OMP_CLAUSE_LOCATION (c
),
1895 FIELD_DECL
, NULL_TREE
, ptr_type_node
);
1896 DECL_ALIGN (field
) = TYPE_ALIGN (ptr_type_node
);
1897 insert_field_into_struct (ctx
->record_type
, field
);
1898 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) decl
,
1899 (splay_tree_value
) field
);
1904 case OMP_CLAUSE_NOWAIT
:
1905 case OMP_CLAUSE_ORDERED
:
1906 case OMP_CLAUSE_COLLAPSE
:
1907 case OMP_CLAUSE_UNTIED
:
1908 case OMP_CLAUSE_MERGEABLE
:
1909 case OMP_CLAUSE_PROC_BIND
:
1910 case OMP_CLAUSE_SAFELEN
:
1911 case OMP_CLAUSE_ASYNC
:
1912 case OMP_CLAUSE_WAIT
:
1913 case OMP_CLAUSE_GANG
:
1914 case OMP_CLAUSE_WORKER
:
1915 case OMP_CLAUSE_VECTOR
:
1918 case OMP_CLAUSE_ALIGNED
:
1919 decl
= OMP_CLAUSE_DECL (c
);
1920 if (is_global_var (decl
)
1921 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
1922 install_var_local (decl
, ctx
);
1925 case OMP_CLAUSE_DEVICE_RESIDENT
:
1926 case OMP_CLAUSE_USE_DEVICE
:
1927 case OMP_CLAUSE__CACHE_
:
1928 case OMP_CLAUSE_INDEPENDENT
:
1929 case OMP_CLAUSE_AUTO
:
1930 case OMP_CLAUSE_SEQ
:
1931 sorry ("Clause not supported yet");
1939 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1941 switch (OMP_CLAUSE_CODE (c
))
1943 case OMP_CLAUSE_LASTPRIVATE
:
1944 /* Let the corresponding firstprivate clause create
1946 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1947 scan_array_reductions
= true;
1948 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1952 case OMP_CLAUSE_FIRSTPRIVATE
:
1953 if (is_gimple_omp_oacc (ctx
->stmt
))
1955 sorry ("clause not supported yet");
1959 case OMP_CLAUSE_PRIVATE
:
1960 case OMP_CLAUSE_REDUCTION
:
1961 case OMP_CLAUSE_LINEAR
:
1962 decl
= OMP_CLAUSE_DECL (c
);
1963 if (is_variable_sized (decl
))
1964 install_var_local (decl
, ctx
);
1965 fixup_remapped_decl (decl
, ctx
,
1966 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1967 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1968 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1969 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1970 scan_array_reductions
= true;
1971 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
1972 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
1973 scan_array_reductions
= true;
1976 case OMP_CLAUSE_SHARED
:
1977 /* Ignore shared directives in teams construct. */
1978 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
1980 decl
= OMP_CLAUSE_DECL (c
);
1981 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1982 fixup_remapped_decl (decl
, ctx
, false);
1985 case OMP_CLAUSE_MAP
:
1986 if (!is_gimple_omp_offloaded (ctx
->stmt
))
1988 decl
= OMP_CLAUSE_DECL (c
);
1990 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
))
1991 && varpool_node::get_create (decl
)->offloadable
)
1995 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
1996 && TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
1997 && !COMPLETE_TYPE_P (TREE_TYPE (decl
)))
1999 tree new_decl
= lookup_decl (decl
, ctx
);
2000 TREE_TYPE (new_decl
)
2001 = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
2003 else if (DECL_SIZE (decl
)
2004 && TREE_CODE (DECL_SIZE (decl
)) != INTEGER_CST
)
2006 tree decl2
= DECL_VALUE_EXPR (decl
);
2007 gcc_assert (TREE_CODE (decl2
) == INDIRECT_REF
);
2008 decl2
= TREE_OPERAND (decl2
, 0);
2009 gcc_assert (DECL_P (decl2
));
2010 fixup_remapped_decl (decl2
, ctx
, false);
2011 fixup_remapped_decl (decl
, ctx
, true);
2014 fixup_remapped_decl (decl
, ctx
, false);
2018 case OMP_CLAUSE_COPYPRIVATE
:
2019 case OMP_CLAUSE_COPYIN
:
2020 case OMP_CLAUSE_DEFAULT
:
2022 case OMP_CLAUSE_NUM_THREADS
:
2023 case OMP_CLAUSE_NUM_TEAMS
:
2024 case OMP_CLAUSE_THREAD_LIMIT
:
2025 case OMP_CLAUSE_DEVICE
:
2026 case OMP_CLAUSE_SCHEDULE
:
2027 case OMP_CLAUSE_DIST_SCHEDULE
:
2028 case OMP_CLAUSE_NOWAIT
:
2029 case OMP_CLAUSE_ORDERED
:
2030 case OMP_CLAUSE_COLLAPSE
:
2031 case OMP_CLAUSE_UNTIED
:
2032 case OMP_CLAUSE_FINAL
:
2033 case OMP_CLAUSE_MERGEABLE
:
2034 case OMP_CLAUSE_PROC_BIND
:
2035 case OMP_CLAUSE_SAFELEN
:
2036 case OMP_CLAUSE_ALIGNED
:
2037 case OMP_CLAUSE_DEPEND
:
2038 case OMP_CLAUSE__LOOPTEMP_
:
2040 case OMP_CLAUSE_FROM
:
2041 case OMP_CLAUSE__CILK_FOR_COUNT_
:
2042 case OMP_CLAUSE_ASYNC
:
2043 case OMP_CLAUSE_WAIT
:
2044 case OMP_CLAUSE_NUM_GANGS
:
2045 case OMP_CLAUSE_NUM_WORKERS
:
2046 case OMP_CLAUSE_VECTOR_LENGTH
:
2047 case OMP_CLAUSE_GANG
:
2048 case OMP_CLAUSE_WORKER
:
2049 case OMP_CLAUSE_VECTOR
:
2052 case OMP_CLAUSE_DEVICE_RESIDENT
:
2053 case OMP_CLAUSE_USE_DEVICE
:
2054 case OMP_CLAUSE__CACHE_
:
2055 case OMP_CLAUSE_INDEPENDENT
:
2056 case OMP_CLAUSE_AUTO
:
2057 case OMP_CLAUSE_SEQ
:
2058 sorry ("Clause not supported yet");
2066 gcc_checking_assert (!scan_array_reductions
2067 || !is_gimple_omp_oacc (ctx
->stmt
));
2068 if (scan_array_reductions
)
2069 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2070 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
2071 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2073 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
2074 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
2076 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2077 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2078 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
2079 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2080 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
2081 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
2084 /* Create a new name for omp child function. Returns an identifier. If
2085 IS_CILK_FOR is true then the suffix for the child function is
2089 create_omp_child_function_name (bool task_copy
, bool is_cilk_for
)
2092 return clone_function_name (current_function_decl
, "_cilk_for_fn");
2093 return clone_function_name (current_function_decl
,
2094 task_copy
? "_omp_cpyfn" : "_omp_fn");
2097 /* Returns the type of the induction variable for the child function for
2098 _Cilk_for and the types for _high and _low variables based on TYPE. */
2101 cilk_for_check_loop_diff_type (tree type
)
2103 if (TYPE_PRECISION (type
) <= TYPE_PRECISION (uint32_type_node
))
2105 if (TYPE_UNSIGNED (type
))
2106 return uint32_type_node
;
2108 return integer_type_node
;
2112 if (TYPE_UNSIGNED (type
))
2113 return uint64_type_node
;
2115 return long_long_integer_type_node
;
2119 /* Build a decl for the omp child function. It'll not contain a body
2120 yet, just the bare decl. */
2123 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
2125 tree decl
, type
, name
, t
;
2128 = (flag_cilkplus
&& gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2129 ? find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2130 OMP_CLAUSE__CILK_FOR_COUNT_
) : NULL_TREE
;
2131 tree cilk_var_type
= NULL_TREE
;
2133 name
= create_omp_child_function_name (task_copy
,
2134 cilk_for_count
!= NULL_TREE
);
2136 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2137 ptr_type_node
, NULL_TREE
);
2138 else if (cilk_for_count
)
2140 type
= TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count
, 0));
2141 cilk_var_type
= cilk_for_check_loop_diff_type (type
);
2142 type
= build_function_type_list (void_type_node
, ptr_type_node
,
2143 cilk_var_type
, cilk_var_type
, NULL_TREE
);
2146 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
2148 decl
= build_decl (gimple_location (ctx
->stmt
), FUNCTION_DECL
, name
, type
);
2150 gcc_checking_assert (!is_gimple_omp_oacc (ctx
->stmt
)
2153 ctx
->cb
.dst_fn
= decl
;
2155 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
2157 TREE_STATIC (decl
) = 1;
2158 TREE_USED (decl
) = 1;
2159 DECL_ARTIFICIAL (decl
) = 1;
2160 DECL_IGNORED_P (decl
) = 0;
2161 TREE_PUBLIC (decl
) = 0;
2162 DECL_UNINLINABLE (decl
) = 1;
2163 DECL_EXTERNAL (decl
) = 0;
2164 DECL_CONTEXT (decl
) = NULL_TREE
;
2165 DECL_INITIAL (decl
) = make_node (BLOCK
);
2166 if (cgraph_node::get (current_function_decl
)->offloadable
)
2167 cgraph_node::get_create (decl
)->offloadable
= 1;
2171 for (octx
= ctx
; octx
; octx
= octx
->outer
)
2172 if (is_gimple_omp_offloaded (octx
->stmt
))
2174 cgraph_node::get_create (decl
)->offloadable
= 1;
2175 #ifdef ENABLE_OFFLOADING
2176 g
->have_offload
= true;
2182 if (cgraph_node::get_create (decl
)->offloadable
2183 && !lookup_attribute ("omp declare target",
2184 DECL_ATTRIBUTES (current_function_decl
)))
2185 DECL_ATTRIBUTES (decl
)
2186 = tree_cons (get_identifier ("omp target entrypoint"),
2187 NULL_TREE
, DECL_ATTRIBUTES (decl
));
2189 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2190 RESULT_DECL
, NULL_TREE
, void_type_node
);
2191 DECL_ARTIFICIAL (t
) = 1;
2192 DECL_IGNORED_P (t
) = 1;
2193 DECL_CONTEXT (t
) = decl
;
2194 DECL_RESULT (decl
) = t
;
2196 /* _Cilk_for's child function requires two extra parameters called
2197 __low and __high that are set the by Cilk runtime when it calls this
2201 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2202 PARM_DECL
, get_identifier ("__high"), cilk_var_type
);
2203 DECL_ARTIFICIAL (t
) = 1;
2204 DECL_NAMELESS (t
) = 1;
2205 DECL_ARG_TYPE (t
) = ptr_type_node
;
2206 DECL_CONTEXT (t
) = current_function_decl
;
2208 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2209 DECL_ARGUMENTS (decl
) = t
;
2211 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2212 PARM_DECL
, get_identifier ("__low"), cilk_var_type
);
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 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2219 DECL_ARGUMENTS (decl
) = t
;
2222 tree data_name
= get_identifier (".omp_data_i");
2223 t
= build_decl (DECL_SOURCE_LOCATION (decl
), PARM_DECL
, data_name
,
2225 DECL_ARTIFICIAL (t
) = 1;
2226 DECL_NAMELESS (t
) = 1;
2227 DECL_ARG_TYPE (t
) = ptr_type_node
;
2228 DECL_CONTEXT (t
) = current_function_decl
;
2231 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2232 DECL_ARGUMENTS (decl
) = t
;
2234 ctx
->receiver_decl
= t
;
2237 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
2238 PARM_DECL
, get_identifier (".omp_data_o"),
2240 DECL_ARTIFICIAL (t
) = 1;
2241 DECL_NAMELESS (t
) = 1;
2242 DECL_ARG_TYPE (t
) = ptr_type_node
;
2243 DECL_CONTEXT (t
) = current_function_decl
;
2245 TREE_ADDRESSABLE (t
) = 1;
2246 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
2247 DECL_ARGUMENTS (decl
) = t
;
2250 /* Allocate memory for the function structure. The call to
2251 allocate_struct_function clobbers CFUN, so we need to restore
2253 push_struct_function (decl
);
2254 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
2258 /* Callback for walk_gimple_seq. Check if combined parallel
2259 contains gimple_omp_for_combined_into_p OMP_FOR. */
2262 find_combined_for (gimple_stmt_iterator
*gsi_p
,
2263 bool *handled_ops_p
,
2264 struct walk_stmt_info
*wi
)
2266 gimple stmt
= gsi_stmt (*gsi_p
);
2268 *handled_ops_p
= true;
2269 switch (gimple_code (stmt
))
2273 case GIMPLE_OMP_FOR
:
2274 if (gimple_omp_for_combined_into_p (stmt
)
2275 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
)
2278 return integer_zero_node
;
2287 /* Scan an OpenMP parallel directive. */
2290 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2294 gomp_parallel
*stmt
= as_a
<gomp_parallel
*> (gsi_stmt (*gsi
));
2296 /* Ignore parallel directives with empty bodies, unless there
2297 are copyin clauses. */
2299 && empty_body_p (gimple_omp_body (stmt
))
2300 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
2301 OMP_CLAUSE_COPYIN
) == NULL
)
2303 gsi_replace (gsi
, gimple_build_nop (), false);
2307 if (gimple_omp_parallel_combined_p (stmt
))
2309 struct walk_stmt_info wi
;
2311 memset (&wi
, 0, sizeof (wi
));
2313 walk_gimple_seq (gimple_omp_body (stmt
),
2314 find_combined_for
, NULL
, &wi
);
2317 gomp_for
*for_stmt
= as_a
<gomp_for
*> ((gimple
) wi
.info
);
2318 struct omp_for_data fd
;
2319 extract_omp_for_data (for_stmt
, &fd
, NULL
);
2320 /* We need two temporaries with fd.loop.v type (istart/iend)
2321 and then (fd.collapse - 1) temporaries with the same
2322 type for count2 ... countN-1 vars if not constant. */
2323 size_t count
= 2, i
;
2324 tree type
= fd
.iter_type
;
2326 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
2327 count
+= fd
.collapse
- 1;
2328 for (i
= 0; i
< count
; i
++)
2330 tree temp
= create_tmp_var (type
);
2331 tree c
= build_omp_clause (UNKNOWN_LOCATION
,
2332 OMP_CLAUSE__LOOPTEMP_
);
2333 insert_decl_map (&outer_ctx
->cb
, temp
, temp
);
2334 OMP_CLAUSE_DECL (c
) = temp
;
2335 OMP_CLAUSE_CHAIN (c
) = gimple_omp_parallel_clauses (stmt
);
2336 gimple_omp_parallel_set_clauses (stmt
, c
);
2341 ctx
= new_omp_context (stmt
, outer_ctx
);
2342 taskreg_contexts
.safe_push (ctx
);
2343 if (taskreg_nesting_level
> 1)
2344 ctx
->is_nested
= true;
2345 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2346 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2347 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2348 name
= create_tmp_var_name (".omp_data_s");
2349 name
= build_decl (gimple_location (stmt
),
2350 TYPE_DECL
, name
, ctx
->record_type
);
2351 DECL_ARTIFICIAL (name
) = 1;
2352 DECL_NAMELESS (name
) = 1;
2353 TYPE_NAME (ctx
->record_type
) = name
;
2354 create_omp_child_function (ctx
, false);
2355 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2357 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
2358 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2360 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2361 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2364 /* Scan an OpenMP task directive. */
2367 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
2371 gomp_task
*stmt
= as_a
<gomp_task
*> (gsi_stmt (*gsi
));
2373 /* Ignore task directives with empty bodies. */
2375 && empty_body_p (gimple_omp_body (stmt
)))
2377 gsi_replace (gsi
, gimple_build_nop (), false);
2381 ctx
= new_omp_context (stmt
, outer_ctx
);
2382 taskreg_contexts
.safe_push (ctx
);
2383 if (taskreg_nesting_level
> 1)
2384 ctx
->is_nested
= true;
2385 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2386 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2387 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2388 name
= create_tmp_var_name (".omp_data_s");
2389 name
= build_decl (gimple_location (stmt
),
2390 TYPE_DECL
, name
, ctx
->record_type
);
2391 DECL_ARTIFICIAL (name
) = 1;
2392 DECL_NAMELESS (name
) = 1;
2393 TYPE_NAME (ctx
->record_type
) = name
;
2394 create_omp_child_function (ctx
, false);
2395 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2397 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
2399 if (ctx
->srecord_type
)
2401 name
= create_tmp_var_name (".omp_data_a");
2402 name
= build_decl (gimple_location (stmt
),
2403 TYPE_DECL
, name
, ctx
->srecord_type
);
2404 DECL_ARTIFICIAL (name
) = 1;
2405 DECL_NAMELESS (name
) = 1;
2406 TYPE_NAME (ctx
->srecord_type
) = name
;
2407 create_omp_child_function (ctx
, true);
2410 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2412 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2414 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2415 t
= build_int_cst (long_integer_type_node
, 0);
2416 gimple_omp_task_set_arg_size (stmt
, t
);
2417 t
= build_int_cst (long_integer_type_node
, 1);
2418 gimple_omp_task_set_arg_align (stmt
, t
);
2423 /* If any decls have been made addressable during scan_omp,
2424 adjust their fields if needed, and layout record types
2425 of parallel/task constructs. */
2428 finish_taskreg_scan (omp_context
*ctx
)
2430 if (ctx
->record_type
== NULL_TREE
)
2433 /* If any task_shared_vars were needed, verify all
2434 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2435 statements if use_pointer_for_field hasn't changed
2436 because of that. If it did, update field types now. */
2437 if (task_shared_vars
)
2441 for (c
= gimple_omp_taskreg_clauses (ctx
->stmt
);
2442 c
; c
= OMP_CLAUSE_CHAIN (c
))
2443 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
)
2445 tree decl
= OMP_CLAUSE_DECL (c
);
2447 /* Global variables don't need to be copied,
2448 the receiver side will use them directly. */
2449 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
2451 if (!bitmap_bit_p (task_shared_vars
, DECL_UID (decl
))
2452 || !use_pointer_for_field (decl
, ctx
))
2454 tree field
= lookup_field (decl
, ctx
);
2455 if (TREE_CODE (TREE_TYPE (field
)) == POINTER_TYPE
2456 && TREE_TYPE (TREE_TYPE (field
)) == TREE_TYPE (decl
))
2458 TREE_TYPE (field
) = build_pointer_type (TREE_TYPE (decl
));
2459 TREE_THIS_VOLATILE (field
) = 0;
2460 DECL_USER_ALIGN (field
) = 0;
2461 DECL_ALIGN (field
) = TYPE_ALIGN (TREE_TYPE (field
));
2462 if (TYPE_ALIGN (ctx
->record_type
) < DECL_ALIGN (field
))
2463 TYPE_ALIGN (ctx
->record_type
) = DECL_ALIGN (field
);
2464 if (ctx
->srecord_type
)
2466 tree sfield
= lookup_sfield (decl
, ctx
);
2467 TREE_TYPE (sfield
) = TREE_TYPE (field
);
2468 TREE_THIS_VOLATILE (sfield
) = 0;
2469 DECL_USER_ALIGN (sfield
) = 0;
2470 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
2471 if (TYPE_ALIGN (ctx
->srecord_type
) < DECL_ALIGN (sfield
))
2472 TYPE_ALIGN (ctx
->srecord_type
) = DECL_ALIGN (sfield
);
2477 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
)
2479 layout_type (ctx
->record_type
);
2480 fixup_child_record_type (ctx
);
2484 location_t loc
= gimple_location (ctx
->stmt
);
2485 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
2486 /* Move VLA fields to the end. */
2487 p
= &TYPE_FIELDS (ctx
->record_type
);
2489 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
2490 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
2493 *p
= TREE_CHAIN (*p
);
2494 TREE_CHAIN (*q
) = NULL_TREE
;
2495 q
= &TREE_CHAIN (*q
);
2498 p
= &DECL_CHAIN (*p
);
2500 layout_type (ctx
->record_type
);
2501 fixup_child_record_type (ctx
);
2502 if (ctx
->srecord_type
)
2503 layout_type (ctx
->srecord_type
);
2504 tree t
= fold_convert_loc (loc
, long_integer_type_node
,
2505 TYPE_SIZE_UNIT (ctx
->record_type
));
2506 gimple_omp_task_set_arg_size (ctx
->stmt
, t
);
2507 t
= build_int_cst (long_integer_type_node
,
2508 TYPE_ALIGN_UNIT (ctx
->record_type
));
2509 gimple_omp_task_set_arg_align (ctx
->stmt
, t
);
2514 static omp_context
*
2515 enclosing_target_ctx (omp_context
*ctx
)
2518 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
2520 gcc_assert (ctx
!= NULL
);
2525 oacc_loop_or_target_p (gimple stmt
)
2527 enum gimple_code outer_type
= gimple_code (stmt
);
2528 return ((outer_type
== GIMPLE_OMP_TARGET
2529 && ((gimple_omp_target_kind (stmt
)
2530 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2531 || (gimple_omp_target_kind (stmt
)
2532 == GF_OMP_TARGET_KIND_OACC_KERNELS
)))
2533 || (outer_type
== GIMPLE_OMP_FOR
2534 && gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
));
2537 /* Scan a GIMPLE_OMP_FOR. */
2540 scan_omp_for (gomp_for
*stmt
, omp_context
*outer_ctx
)
2542 enum gimple_code outer_type
= GIMPLE_ERROR_MARK
;
2545 tree clauses
= gimple_omp_for_clauses (stmt
);
2548 outer_type
= gimple_code (outer_ctx
->stmt
);
2550 ctx
= new_omp_context (stmt
, outer_ctx
);
2552 if (is_gimple_omp_oacc (stmt
))
2554 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2555 ctx
->gwv_this
= outer_ctx
->gwv_this
;
2556 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2559 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_GANG
)
2561 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WORKER
)
2563 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR
)
2567 ctx
->gwv_this
|= val
;
2570 /* Skip; not nested inside a region. */
2573 if (!oacc_loop_or_target_p (outer_ctx
->stmt
))
2575 /* Skip; not nested inside an OpenACC region. */
2578 if (outer_type
== GIMPLE_OMP_FOR
)
2579 outer_ctx
->gwv_below
|= val
;
2580 if (OMP_CLAUSE_OPERAND (c
, 0) != NULL_TREE
)
2582 omp_context
*enclosing
= enclosing_target_ctx (outer_ctx
);
2583 if (gimple_omp_target_kind (enclosing
->stmt
)
2584 == GF_OMP_TARGET_KIND_OACC_PARALLEL
)
2585 error_at (gimple_location (stmt
),
2586 "no arguments allowed to gang, worker and vector clauses inside parallel");
2591 scan_sharing_clauses (clauses
, ctx
);
2593 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
2594 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
2596 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
2597 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
2598 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
2599 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
2601 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2603 if (is_gimple_omp_oacc (stmt
))
2605 if (ctx
->gwv_this
& ctx
->gwv_below
)
2606 error_at (gimple_location (stmt
),
2607 "gang, worker and vector may occur only once in a loop nest");
2608 else if (ctx
->gwv_below
!= 0
2609 && ctx
->gwv_this
> ctx
->gwv_below
)
2610 error_at (gimple_location (stmt
),
2611 "gang, worker and vector must occur in this order in a loop nest");
2612 if (outer_ctx
&& outer_type
== GIMPLE_OMP_FOR
)
2613 outer_ctx
->gwv_below
|= ctx
->gwv_below
;
2617 /* Scan an OpenMP sections directive. */
2620 scan_omp_sections (gomp_sections
*stmt
, omp_context
*outer_ctx
)
2624 ctx
= new_omp_context (stmt
, outer_ctx
);
2625 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
2626 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2629 /* Scan an OpenMP single directive. */
2632 scan_omp_single (gomp_single
*stmt
, omp_context
*outer_ctx
)
2637 ctx
= new_omp_context (stmt
, outer_ctx
);
2638 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2639 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2640 name
= create_tmp_var_name (".omp_copy_s");
2641 name
= build_decl (gimple_location (stmt
),
2642 TYPE_DECL
, name
, ctx
->record_type
);
2643 TYPE_NAME (ctx
->record_type
) = name
;
2645 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
2646 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2648 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2649 ctx
->record_type
= NULL
;
2651 layout_type (ctx
->record_type
);
2654 /* Scan a GIMPLE_OMP_TARGET. */
2657 scan_omp_target (gomp_target
*stmt
, omp_context
*outer_ctx
)
2661 bool offloaded
= is_gimple_omp_offloaded (stmt
);
2662 tree clauses
= gimple_omp_target_clauses (stmt
);
2664 ctx
= new_omp_context (stmt
, outer_ctx
);
2665 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
2666 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
2667 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
2668 name
= create_tmp_var_name (".omp_data_t");
2669 name
= build_decl (gimple_location (stmt
),
2670 TYPE_DECL
, name
, ctx
->record_type
);
2671 DECL_ARTIFICIAL (name
) = 1;
2672 DECL_NAMELESS (name
) = 1;
2673 TYPE_NAME (ctx
->record_type
) = name
;
2676 if (is_gimple_omp_oacc (stmt
))
2677 ctx
->reduction_map
= splay_tree_new (splay_tree_compare_pointers
,
2680 create_omp_child_function (ctx
, false);
2681 gimple_omp_target_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
2684 if (is_gimple_omp_oacc (stmt
))
2686 for (tree c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2688 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_GANGS
)
2689 ctx
->gwv_this
|= MASK_GANG
;
2690 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_NUM_WORKERS
)
2691 ctx
->gwv_this
|= MASK_WORKER
;
2692 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_VECTOR_LENGTH
)
2693 ctx
->gwv_this
|= MASK_VECTOR
;
2697 scan_sharing_clauses (clauses
, ctx
);
2698 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2700 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
2701 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
2704 TYPE_FIELDS (ctx
->record_type
)
2705 = nreverse (TYPE_FIELDS (ctx
->record_type
));
2706 #ifdef ENABLE_CHECKING
2708 unsigned int align
= DECL_ALIGN (TYPE_FIELDS (ctx
->record_type
));
2709 for (field
= TYPE_FIELDS (ctx
->record_type
);
2711 field
= DECL_CHAIN (field
))
2712 gcc_assert (DECL_ALIGN (field
) == align
);
2714 layout_type (ctx
->record_type
);
2716 fixup_child_record_type (ctx
);
2720 /* Scan an OpenMP teams directive. */
2723 scan_omp_teams (gomp_teams
*stmt
, omp_context
*outer_ctx
)
2725 omp_context
*ctx
= new_omp_context (stmt
, outer_ctx
);
2726 scan_sharing_clauses (gimple_omp_teams_clauses (stmt
), ctx
);
2727 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2730 /* Check nesting restrictions. */
2732 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
2734 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2735 inside an OpenACC CTX. */
2736 if (!(is_gimple_omp (stmt
)
2737 && is_gimple_omp_oacc (stmt
)))
2739 for (omp_context
*ctx_
= ctx
; ctx_
!= NULL
; ctx_
= ctx_
->outer
)
2740 if (is_gimple_omp (ctx_
->stmt
)
2741 && is_gimple_omp_oacc (ctx_
->stmt
))
2743 error_at (gimple_location (stmt
),
2744 "non-OpenACC construct inside of OpenACC region");
2751 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2752 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
2754 error_at (gimple_location (stmt
),
2755 "OpenMP constructs may not be nested inside simd region");
2758 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
2760 if ((gimple_code (stmt
) != GIMPLE_OMP_FOR
2761 || (gimple_omp_for_kind (stmt
)
2762 != GF_OMP_FOR_KIND_DISTRIBUTE
))
2763 && gimple_code (stmt
) != GIMPLE_OMP_PARALLEL
)
2765 error_at (gimple_location (stmt
),
2766 "only distribute or parallel constructs are allowed to "
2767 "be closely nested inside teams construct");
2772 switch (gimple_code (stmt
))
2774 case GIMPLE_OMP_FOR
:
2775 if (gimple_omp_for_kind (stmt
) & GF_OMP_FOR_SIMD
)
2777 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_DISTRIBUTE
)
2779 if (ctx
!= NULL
&& gimple_code (ctx
->stmt
) != GIMPLE_OMP_TEAMS
)
2781 error_at (gimple_location (stmt
),
2782 "distribute construct must be closely nested inside "
2790 if (is_gimple_call (stmt
)
2791 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2792 == BUILT_IN_GOMP_CANCEL
2793 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2794 == BUILT_IN_GOMP_CANCELLATION_POINT
))
2796 const char *bad
= NULL
;
2797 const char *kind
= NULL
;
2800 error_at (gimple_location (stmt
), "orphaned %qs construct",
2801 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2802 == BUILT_IN_GOMP_CANCEL
2803 ? "#pragma omp cancel"
2804 : "#pragma omp cancellation point");
2807 switch (tree_fits_shwi_p (gimple_call_arg (stmt
, 0))
2808 ? tree_to_shwi (gimple_call_arg (stmt
, 0))
2812 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_PARALLEL
)
2813 bad
= "#pragma omp parallel";
2814 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2815 == BUILT_IN_GOMP_CANCEL
2816 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2817 ctx
->cancellable
= true;
2821 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2822 || gimple_omp_for_kind (ctx
->stmt
) != GF_OMP_FOR_KIND_FOR
)
2823 bad
= "#pragma omp for";
2824 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2825 == BUILT_IN_GOMP_CANCEL
2826 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2828 ctx
->cancellable
= true;
2829 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2831 warning_at (gimple_location (stmt
), 0,
2832 "%<#pragma omp cancel for%> inside "
2833 "%<nowait%> for construct");
2834 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2835 OMP_CLAUSE_ORDERED
))
2836 warning_at (gimple_location (stmt
), 0,
2837 "%<#pragma omp cancel for%> inside "
2838 "%<ordered%> for construct");
2843 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTIONS
2844 && gimple_code (ctx
->stmt
) != GIMPLE_OMP_SECTION
)
2845 bad
= "#pragma omp sections";
2846 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2847 == BUILT_IN_GOMP_CANCEL
2848 && !integer_zerop (gimple_call_arg (stmt
, 1)))
2850 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_SECTIONS
)
2852 ctx
->cancellable
= true;
2853 if (find_omp_clause (gimple_omp_sections_clauses
2856 warning_at (gimple_location (stmt
), 0,
2857 "%<#pragma omp cancel sections%> inside "
2858 "%<nowait%> sections construct");
2862 gcc_assert (ctx
->outer
2863 && gimple_code (ctx
->outer
->stmt
)
2864 == GIMPLE_OMP_SECTIONS
);
2865 ctx
->outer
->cancellable
= true;
2866 if (find_omp_clause (gimple_omp_sections_clauses
2869 warning_at (gimple_location (stmt
), 0,
2870 "%<#pragma omp cancel sections%> inside "
2871 "%<nowait%> sections construct");
2877 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TASK
)
2878 bad
= "#pragma omp task";
2880 ctx
->cancellable
= true;
2884 error_at (gimple_location (stmt
), "invalid arguments");
2889 error_at (gimple_location (stmt
),
2890 "%<%s %s%> construct not closely nested inside of %qs",
2891 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2892 == BUILT_IN_GOMP_CANCEL
2893 ? "#pragma omp cancel"
2894 : "#pragma omp cancellation point", kind
, bad
);
2899 case GIMPLE_OMP_SECTIONS
:
2900 case GIMPLE_OMP_SINGLE
:
2901 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2902 switch (gimple_code (ctx
->stmt
))
2904 case GIMPLE_OMP_FOR
:
2905 case GIMPLE_OMP_SECTIONS
:
2906 case GIMPLE_OMP_SINGLE
:
2907 case GIMPLE_OMP_ORDERED
:
2908 case GIMPLE_OMP_MASTER
:
2909 case GIMPLE_OMP_TASK
:
2910 case GIMPLE_OMP_CRITICAL
:
2911 if (is_gimple_call (stmt
))
2913 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
))
2914 != BUILT_IN_GOMP_BARRIER
)
2916 error_at (gimple_location (stmt
),
2917 "barrier region may not be closely nested inside "
2918 "of work-sharing, critical, ordered, master or "
2919 "explicit task region");
2922 error_at (gimple_location (stmt
),
2923 "work-sharing region may not be closely nested inside "
2924 "of work-sharing, critical, ordered, master or explicit "
2927 case GIMPLE_OMP_PARALLEL
:
2933 case GIMPLE_OMP_MASTER
:
2934 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2935 switch (gimple_code (ctx
->stmt
))
2937 case GIMPLE_OMP_FOR
:
2938 case GIMPLE_OMP_SECTIONS
:
2939 case GIMPLE_OMP_SINGLE
:
2940 case GIMPLE_OMP_TASK
:
2941 error_at (gimple_location (stmt
),
2942 "master region may not be closely nested inside "
2943 "of work-sharing or explicit task region");
2945 case GIMPLE_OMP_PARALLEL
:
2951 case GIMPLE_OMP_ORDERED
:
2952 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2953 switch (gimple_code (ctx
->stmt
))
2955 case GIMPLE_OMP_CRITICAL
:
2956 case GIMPLE_OMP_TASK
:
2957 error_at (gimple_location (stmt
),
2958 "ordered region may not be closely nested inside "
2959 "of critical or explicit task region");
2961 case GIMPLE_OMP_FOR
:
2962 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2963 OMP_CLAUSE_ORDERED
) == NULL
)
2965 error_at (gimple_location (stmt
),
2966 "ordered region must be closely nested inside "
2967 "a loop region with an ordered clause");
2971 case GIMPLE_OMP_PARALLEL
:
2972 error_at (gimple_location (stmt
),
2973 "ordered region must be closely nested inside "
2974 "a loop region with an ordered clause");
2980 case GIMPLE_OMP_CRITICAL
:
2983 = gimple_omp_critical_name (as_a
<gomp_critical
*> (stmt
));
2984 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
2985 if (gomp_critical
*other_crit
2986 = dyn_cast
<gomp_critical
*> (ctx
->stmt
))
2987 if (this_stmt_name
== gimple_omp_critical_name (other_crit
))
2989 error_at (gimple_location (stmt
),
2990 "critical region may not be nested inside a critical "
2991 "region with the same name");
2996 case GIMPLE_OMP_TEAMS
:
2998 || gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
2999 || gimple_omp_target_kind (ctx
->stmt
) != GF_OMP_TARGET_KIND_REGION
)
3001 error_at (gimple_location (stmt
),
3002 "teams construct not closely nested inside of target "
3007 case GIMPLE_OMP_TARGET
:
3008 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
3010 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_TARGET
)
3012 if (is_gimple_omp (stmt
)
3013 && is_gimple_omp_oacc (stmt
)
3014 && is_gimple_omp (ctx
->stmt
))
3016 error_at (gimple_location (stmt
),
3017 "OpenACC construct inside of non-OpenACC region");
3023 const char *stmt_name
, *ctx_stmt_name
;
3024 switch (gimple_omp_target_kind (stmt
))
3026 case GF_OMP_TARGET_KIND_REGION
: stmt_name
= "target"; break;
3027 case GF_OMP_TARGET_KIND_DATA
: stmt_name
= "target data"; break;
3028 case GF_OMP_TARGET_KIND_UPDATE
: stmt_name
= "target update"; break;
3029 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: stmt_name
= "parallel"; break;
3030 case GF_OMP_TARGET_KIND_OACC_KERNELS
: stmt_name
= "kernels"; break;
3031 case GF_OMP_TARGET_KIND_OACC_DATA
: stmt_name
= "data"; break;
3032 case GF_OMP_TARGET_KIND_OACC_UPDATE
: stmt_name
= "update"; break;
3033 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
: stmt_name
= "enter/exit data"; break;
3034 default: gcc_unreachable ();
3036 switch (gimple_omp_target_kind (ctx
->stmt
))
3038 case GF_OMP_TARGET_KIND_REGION
: ctx_stmt_name
= "target"; break;
3039 case GF_OMP_TARGET_KIND_DATA
: ctx_stmt_name
= "target data"; break;
3040 case GF_OMP_TARGET_KIND_OACC_PARALLEL
: ctx_stmt_name
= "parallel"; break;
3041 case GF_OMP_TARGET_KIND_OACC_KERNELS
: ctx_stmt_name
= "kernels"; break;
3042 case GF_OMP_TARGET_KIND_OACC_DATA
: ctx_stmt_name
= "data"; break;
3043 default: gcc_unreachable ();
3046 /* OpenACC/OpenMP mismatch? */
3047 if (is_gimple_omp_oacc (stmt
)
3048 != is_gimple_omp_oacc (ctx
->stmt
))
3050 error_at (gimple_location (stmt
),
3051 "%s %s construct inside of %s %s region",
3052 (is_gimple_omp_oacc (stmt
)
3053 ? "OpenACC" : "OpenMP"), stmt_name
,
3054 (is_gimple_omp_oacc (ctx
->stmt
)
3055 ? "OpenACC" : "OpenMP"), ctx_stmt_name
);
3058 if (is_gimple_omp_offloaded (ctx
->stmt
))
3060 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3061 if (is_gimple_omp_oacc (ctx
->stmt
))
3063 error_at (gimple_location (stmt
),
3064 "%s construct inside of %s region",
3065 stmt_name
, ctx_stmt_name
);
3070 gcc_checking_assert (!is_gimple_omp_oacc (stmt
));
3071 warning_at (gimple_location (stmt
), 0,
3072 "%s construct inside of %s region",
3073 stmt_name
, ctx_stmt_name
);
3085 /* Helper function scan_omp.
3087 Callback for walk_tree or operators in walk_gimple_stmt used to
3088 scan for OMP directives in TP. */
3091 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
3093 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
3094 omp_context
*ctx
= (omp_context
*) wi
->info
;
3097 switch (TREE_CODE (t
))
3104 *tp
= remap_decl (t
, &ctx
->cb
);
3108 if (ctx
&& TYPE_P (t
))
3109 *tp
= remap_type (t
, &ctx
->cb
);
3110 else if (!DECL_P (t
))
3115 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
3116 if (tem
!= TREE_TYPE (t
))
3118 if (TREE_CODE (t
) == INTEGER_CST
)
3119 *tp
= wide_int_to_tree (tem
, t
);
3121 TREE_TYPE (t
) = tem
;
3131 /* Return true if FNDECL is a setjmp or a longjmp. */
3134 setjmp_or_longjmp_p (const_tree fndecl
)
3136 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
3137 && (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_SETJMP
3138 || DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_LONGJMP
))
3141 tree declname
= DECL_NAME (fndecl
);
3144 const char *name
= IDENTIFIER_POINTER (declname
);
3145 return !strcmp (name
, "setjmp") || !strcmp (name
, "longjmp");
3149 /* Helper function for scan_omp.
3151 Callback for walk_gimple_stmt used to scan for OMP directives in
3152 the current statement in GSI. */
3155 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
3156 struct walk_stmt_info
*wi
)
3158 gimple stmt
= gsi_stmt (*gsi
);
3159 omp_context
*ctx
= (omp_context
*) wi
->info
;
3161 if (gimple_has_location (stmt
))
3162 input_location
= gimple_location (stmt
);
3164 /* Check the nesting restrictions. */
3165 bool remove
= false;
3166 if (is_gimple_omp (stmt
))
3167 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3168 else if (is_gimple_call (stmt
))
3170 tree fndecl
= gimple_call_fndecl (stmt
);
3173 if (setjmp_or_longjmp_p (fndecl
)
3175 && gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3176 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
3179 error_at (gimple_location (stmt
),
3180 "setjmp/longjmp inside simd construct");
3182 else if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
3183 switch (DECL_FUNCTION_CODE (fndecl
))
3185 case BUILT_IN_GOMP_BARRIER
:
3186 case BUILT_IN_GOMP_CANCEL
:
3187 case BUILT_IN_GOMP_CANCELLATION_POINT
:
3188 case BUILT_IN_GOMP_TASKYIELD
:
3189 case BUILT_IN_GOMP_TASKWAIT
:
3190 case BUILT_IN_GOMP_TASKGROUP_START
:
3191 case BUILT_IN_GOMP_TASKGROUP_END
:
3192 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
3201 stmt
= gimple_build_nop ();
3202 gsi_replace (gsi
, stmt
, false);
3205 *handled_ops_p
= true;
3207 switch (gimple_code (stmt
))
3209 case GIMPLE_OMP_PARALLEL
:
3210 taskreg_nesting_level
++;
3211 scan_omp_parallel (gsi
, ctx
);
3212 taskreg_nesting_level
--;
3215 case GIMPLE_OMP_TASK
:
3216 taskreg_nesting_level
++;
3217 scan_omp_task (gsi
, ctx
);
3218 taskreg_nesting_level
--;
3221 case GIMPLE_OMP_FOR
:
3222 scan_omp_for (as_a
<gomp_for
*> (stmt
), ctx
);
3225 case GIMPLE_OMP_SECTIONS
:
3226 scan_omp_sections (as_a
<gomp_sections
*> (stmt
), ctx
);
3229 case GIMPLE_OMP_SINGLE
:
3230 scan_omp_single (as_a
<gomp_single
*> (stmt
), ctx
);
3233 case GIMPLE_OMP_SECTION
:
3234 case GIMPLE_OMP_MASTER
:
3235 case GIMPLE_OMP_TASKGROUP
:
3236 case GIMPLE_OMP_ORDERED
:
3237 case GIMPLE_OMP_CRITICAL
:
3238 ctx
= new_omp_context (stmt
, ctx
);
3239 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
3242 case GIMPLE_OMP_TARGET
:
3243 scan_omp_target (as_a
<gomp_target
*> (stmt
), ctx
);
3246 case GIMPLE_OMP_TEAMS
:
3247 scan_omp_teams (as_a
<gomp_teams
*> (stmt
), ctx
);
3254 *handled_ops_p
= false;
3256 for (var
= gimple_bind_vars (as_a
<gbind
*> (stmt
));
3258 var
= DECL_CHAIN (var
))
3259 insert_decl_map (&ctx
->cb
, var
, var
);
3263 *handled_ops_p
= false;
3271 /* Scan all the statements starting at the current statement. CTX
3272 contains context information about the OMP directives and
3273 clauses found during the scan. */
3276 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
3278 location_t saved_location
;
3279 struct walk_stmt_info wi
;
3281 memset (&wi
, 0, sizeof (wi
));
3283 wi
.want_locations
= true;
3285 saved_location
= input_location
;
3286 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
3287 input_location
= saved_location
;
3290 /* Re-gimplification and code generation routines. */
3292 /* Build a call to GOMP_barrier. */
3295 build_omp_barrier (tree lhs
)
3297 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
3298 : BUILT_IN_GOMP_BARRIER
);
3299 gcall
*g
= gimple_build_call (fndecl
, 0);
3301 gimple_call_set_lhs (g
, lhs
);
3305 /* If a context was created for STMT when it was scanned, return it. */
3307 static omp_context
*
3308 maybe_lookup_ctx (gimple stmt
)
3311 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
3312 return n
? (omp_context
*) n
->value
: NULL
;
3316 /* Find the mapping for DECL in CTX or the immediately enclosing
3317 context that has a mapping for DECL.
3319 If CTX is a nested parallel directive, we may have to use the decl
3320 mappings created in CTX's parent context. Suppose that we have the
3321 following parallel nesting (variable UIDs showed for clarity):
3324 #omp parallel shared(iD.1562) -> outer parallel
3325 iD.1562 = iD.1562 + 1;
3327 #omp parallel shared (iD.1562) -> inner parallel
3328 iD.1562 = iD.1562 - 1;
3330 Each parallel structure will create a distinct .omp_data_s structure
3331 for copying iD.1562 in/out of the directive:
3333 outer parallel .omp_data_s.1.i -> iD.1562
3334 inner parallel .omp_data_s.2.i -> iD.1562
3336 A shared variable mapping will produce a copy-out operation before
3337 the parallel directive and a copy-in operation after it. So, in
3338 this case we would have:
3341 .omp_data_o.1.i = iD.1562;
3342 #omp parallel shared(iD.1562) -> outer parallel
3343 .omp_data_i.1 = &.omp_data_o.1
3344 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3346 .omp_data_o.2.i = iD.1562; -> **
3347 #omp parallel shared(iD.1562) -> inner parallel
3348 .omp_data_i.2 = &.omp_data_o.2
3349 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3352 ** This is a problem. The symbol iD.1562 cannot be referenced
3353 inside the body of the outer parallel region. But since we are
3354 emitting this copy operation while expanding the inner parallel
3355 directive, we need to access the CTX structure of the outer
3356 parallel directive to get the correct mapping:
3358 .omp_data_o.2.i = .omp_data_i.1->i
3360 Since there may be other workshare or parallel directives enclosing
3361 the parallel directive, it may be necessary to walk up the context
3362 parent chain. This is not a problem in general because nested
3363 parallelism happens only rarely. */
3366 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3371 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3372 t
= maybe_lookup_decl (decl
, up
);
3374 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
3376 return t
? t
: decl
;
3380 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3381 in outer contexts. */
3384 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
3389 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
3390 t
= maybe_lookup_decl (decl
, up
);
3392 return t
? t
: decl
;
3396 /* Construct the initialization value for reduction CLAUSE. */
3399 omp_reduction_init (tree clause
, tree type
)
3401 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
3402 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
3409 case TRUTH_ORIF_EXPR
:
3410 case TRUTH_XOR_EXPR
:
3412 return build_zero_cst (type
);
3415 case TRUTH_AND_EXPR
:
3416 case TRUTH_ANDIF_EXPR
:
3418 return fold_convert_loc (loc
, type
, integer_one_node
);
3421 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
3424 if (SCALAR_FLOAT_TYPE_P (type
))
3426 REAL_VALUE_TYPE max
, min
;
3427 if (HONOR_INFINITIES (type
))
3430 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
3433 real_maxval (&min
, 1, TYPE_MODE (type
));
3434 return build_real (type
, min
);
3438 gcc_assert (INTEGRAL_TYPE_P (type
));
3439 return TYPE_MIN_VALUE (type
);
3443 if (SCALAR_FLOAT_TYPE_P (type
))
3445 REAL_VALUE_TYPE max
;
3446 if (HONOR_INFINITIES (type
))
3449 real_maxval (&max
, 0, TYPE_MODE (type
));
3450 return build_real (type
, max
);
3454 gcc_assert (INTEGRAL_TYPE_P (type
));
3455 return TYPE_MAX_VALUE (type
);
3463 /* Return alignment to be assumed for var in CLAUSE, which should be
3464 OMP_CLAUSE_ALIGNED. */
3467 omp_clause_aligned_alignment (tree clause
)
3469 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
))
3470 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause
);
3472 /* Otherwise return implementation defined alignment. */
3473 unsigned int al
= 1;
3474 machine_mode mode
, vmode
;
3475 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3477 vs
= 1 << floor_log2 (vs
);
3478 static enum mode_class classes
[]
3479 = { MODE_INT
, MODE_VECTOR_INT
, MODE_FLOAT
, MODE_VECTOR_FLOAT
};
3480 for (int i
= 0; i
< 4; i
+= 2)
3481 for (mode
= GET_CLASS_NARROWEST_MODE (classes
[i
]);
3483 mode
= GET_MODE_WIDER_MODE (mode
))
3485 vmode
= targetm
.vectorize
.preferred_simd_mode (mode
);
3486 if (GET_MODE_CLASS (vmode
) != classes
[i
+ 1])
3489 && GET_MODE_SIZE (vmode
) < vs
3490 && GET_MODE_2XWIDER_MODE (vmode
) != VOIDmode
)
3491 vmode
= GET_MODE_2XWIDER_MODE (vmode
);
3493 tree type
= lang_hooks
.types
.type_for_mode (mode
, 1);
3494 if (type
== NULL_TREE
|| TYPE_MODE (type
) != mode
)
3496 type
= build_vector_type (type
, GET_MODE_SIZE (vmode
)
3497 / GET_MODE_SIZE (mode
));
3498 if (TYPE_MODE (type
) != vmode
)
3500 if (TYPE_ALIGN_UNIT (type
) > al
)
3501 al
= TYPE_ALIGN_UNIT (type
);
3503 return build_int_cst (integer_type_node
, al
);
3506 /* Return maximum possible vectorization factor for the target. */
3513 || !flag_tree_loop_optimize
3514 || (!flag_tree_loop_vectorize
3515 && (global_options_set
.x_flag_tree_loop_vectorize
3516 || global_options_set
.x_flag_tree_vectorize
)))
3519 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
3522 vs
= 1 << floor_log2 (vs
);
3525 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
3526 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
3527 return GET_MODE_NUNITS (vqimode
);
3531 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3535 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
3536 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
3540 max_vf
= omp_max_vf ();
3543 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
3544 OMP_CLAUSE_SAFELEN
);
3545 if (c
&& TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) != INTEGER_CST
)
3547 else if (c
&& compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
3549 max_vf
= tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c
));
3553 idx
= create_tmp_var (unsigned_type_node
);
3554 lane
= create_tmp_var (unsigned_type_node
);
3560 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
3561 tree avar
= create_tmp_var_raw (atype
);
3562 if (TREE_ADDRESSABLE (new_var
))
3563 TREE_ADDRESSABLE (avar
) = 1;
3564 DECL_ATTRIBUTES (avar
)
3565 = tree_cons (get_identifier ("omp simd array"), NULL
,
3566 DECL_ATTRIBUTES (avar
));
3567 gimple_add_tmp_var (avar
);
3568 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
3569 NULL_TREE
, NULL_TREE
);
3570 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
3571 NULL_TREE
, NULL_TREE
);
3572 if (DECL_P (new_var
))
3574 SET_DECL_VALUE_EXPR (new_var
, lvar
);
3575 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3580 /* Helper function of lower_rec_input_clauses. For a reference
3581 in simd reduction, add an underlying variable it will reference. */
3584 handle_simd_reference (location_t loc
, tree new_vard
, gimple_seq
*ilist
)
3586 tree z
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard
)));
3587 if (TREE_CONSTANT (z
))
3589 const char *name
= NULL
;
3590 if (DECL_NAME (new_vard
))
3591 name
= IDENTIFIER_POINTER (DECL_NAME (new_vard
));
3593 z
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard
)), name
);
3594 gimple_add_tmp_var (z
);
3595 TREE_ADDRESSABLE (z
) = 1;
3596 z
= build_fold_addr_expr_loc (loc
, z
);
3597 gimplify_assign (new_vard
, z
, ilist
);
3601 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3602 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3603 private variables. Initialization statements go in ILIST, while calls
3604 to destructors go in DLIST. */
3607 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
3608 omp_context
*ctx
, struct omp_for_data
*fd
)
3610 tree c
, dtor
, copyin_seq
, x
, ptr
;
3611 bool copyin_by_ref
= false;
3612 bool lastprivate_firstprivate
= false;
3613 bool reduction_omp_orig_ref
= false;
3615 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3616 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
);
3618 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
3619 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
3620 gimple_seq llist
[2] = { NULL
, NULL
};
3624 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3625 with data sharing clauses referencing variable sized vars. That
3626 is unnecessarily hard to support and very unlikely to result in
3627 vectorized code anyway. */
3629 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3630 switch (OMP_CLAUSE_CODE (c
))
3632 case OMP_CLAUSE_LINEAR
:
3633 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3636 case OMP_CLAUSE_REDUCTION
:
3637 case OMP_CLAUSE_PRIVATE
:
3638 case OMP_CLAUSE_FIRSTPRIVATE
:
3639 case OMP_CLAUSE_LASTPRIVATE
:
3640 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
3647 /* Do all the fixed sized types in the first pass, and the variable sized
3648 types in the second pass. This makes sure that the scalar arguments to
3649 the variable sized types are processed before we use them in the
3650 variable sized operations. */
3651 for (pass
= 0; pass
< 2; ++pass
)
3653 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3655 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
3658 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3662 case OMP_CLAUSE_PRIVATE
:
3663 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
3666 case OMP_CLAUSE_SHARED
:
3667 /* Ignore shared directives in teams construct. */
3668 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3670 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
3672 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
3675 case OMP_CLAUSE_FIRSTPRIVATE
:
3676 case OMP_CLAUSE_COPYIN
:
3677 case OMP_CLAUSE_LINEAR
:
3679 case OMP_CLAUSE_REDUCTION
:
3680 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c
))
3681 reduction_omp_orig_ref
= true;
3683 case OMP_CLAUSE__LOOPTEMP_
:
3684 /* Handle _looptemp_ clauses only on parallel. */
3688 case OMP_CLAUSE_LASTPRIVATE
:
3689 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3691 lastprivate_firstprivate
= true;
3695 /* Even without corresponding firstprivate, if
3696 decl is Fortran allocatable, it needs outer var
3699 && lang_hooks
.decls
.omp_private_outer_ref
3700 (OMP_CLAUSE_DECL (c
)))
3701 lastprivate_firstprivate
= true;
3703 case OMP_CLAUSE_ALIGNED
:
3706 var
= OMP_CLAUSE_DECL (c
);
3707 if (TREE_CODE (TREE_TYPE (var
)) == POINTER_TYPE
3708 && !is_global_var (var
))
3710 new_var
= maybe_lookup_decl (var
, ctx
);
3711 if (new_var
== NULL_TREE
)
3712 new_var
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3713 x
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3714 x
= build_call_expr_loc (clause_loc
, x
, 2, new_var
,
3715 omp_clause_aligned_alignment (c
));
3716 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3717 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
3718 gimplify_and_add (x
, ilist
);
3720 else if (TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
3721 && is_global_var (var
))
3723 tree ptype
= build_pointer_type (TREE_TYPE (var
)), t
, t2
;
3724 new_var
= lookup_decl (var
, ctx
);
3725 t
= maybe_lookup_decl_in_outer_ctx (var
, ctx
);
3726 t
= build_fold_addr_expr_loc (clause_loc
, t
);
3727 t2
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
3728 t
= build_call_expr_loc (clause_loc
, t2
, 2, t
,
3729 omp_clause_aligned_alignment (c
));
3730 t
= fold_convert_loc (clause_loc
, ptype
, t
);
3731 x
= create_tmp_var (ptype
);
3732 t
= build2 (MODIFY_EXPR
, ptype
, x
, t
);
3733 gimplify_and_add (t
, ilist
);
3734 t
= build_simple_mem_ref_loc (clause_loc
, x
);
3735 SET_DECL_VALUE_EXPR (new_var
, t
);
3736 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3743 new_var
= var
= OMP_CLAUSE_DECL (c
);
3744 if (c_kind
!= OMP_CLAUSE_COPYIN
)
3745 new_var
= lookup_decl (var
, ctx
);
3747 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
3752 else if (is_variable_sized (var
))
3754 /* For variable sized types, we need to allocate the
3755 actual storage here. Call alloca and store the
3756 result in the pointer decl that we created elsewhere. */
3760 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
3765 ptr
= DECL_VALUE_EXPR (new_var
);
3766 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
3767 ptr
= TREE_OPERAND (ptr
, 0);
3768 gcc_assert (DECL_P (ptr
));
3769 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
3771 /* void *tmp = __builtin_alloca */
3772 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3773 stmt
= gimple_build_call (atmp
, 1, x
);
3774 tmp
= create_tmp_var_raw (ptr_type_node
);
3775 gimple_add_tmp_var (tmp
);
3776 gimple_call_set_lhs (stmt
, tmp
);
3778 gimple_seq_add_stmt (ilist
, stmt
);
3780 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
3781 gimplify_assign (ptr
, x
, ilist
);
3784 else if (is_reference (var
))
3786 /* For references that are being privatized for Fortran,
3787 allocate new backing storage for the new pointer
3788 variable. This allows us to avoid changing all the
3789 code that expects a pointer to something that expects
3790 a direct variable. */
3794 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
3795 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
3797 x
= build_receiver_ref (var
, false, ctx
);
3798 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3800 else if (TREE_CONSTANT (x
))
3802 /* For reduction in SIMD loop, defer adding the
3803 initialization of the reference, because if we decide
3804 to use SIMD array for it, the initilization could cause
3806 if (c_kind
== OMP_CLAUSE_REDUCTION
&& is_simd
)
3810 const char *name
= NULL
;
3811 if (DECL_NAME (var
))
3812 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
3814 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
3816 gimple_add_tmp_var (x
);
3817 TREE_ADDRESSABLE (x
) = 1;
3818 x
= build_fold_addr_expr_loc (clause_loc
, x
);
3823 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
3824 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
3829 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
3830 gimplify_assign (new_var
, x
, ilist
);
3833 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3835 else if (c_kind
== OMP_CLAUSE_REDUCTION
3836 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3844 switch (OMP_CLAUSE_CODE (c
))
3846 case OMP_CLAUSE_SHARED
:
3847 /* Ignore shared directives in teams construct. */
3848 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TEAMS
)
3850 /* Shared global vars are just accessed directly. */
3851 if (is_global_var (new_var
))
3853 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3854 needs to be delayed until after fixup_child_record_type so
3855 that we get the correct type during the dereference. */
3856 by_ref
= use_pointer_for_field (var
, ctx
);
3857 x
= build_receiver_ref (var
, by_ref
, ctx
);
3858 SET_DECL_VALUE_EXPR (new_var
, x
);
3859 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3861 /* ??? If VAR is not passed by reference, and the variable
3862 hasn't been initialized yet, then we'll get a warning for
3863 the store into the omp_data_s structure. Ideally, we'd be
3864 able to notice this and not store anything at all, but
3865 we're generating code too early. Suppress the warning. */
3867 TREE_NO_WARNING (var
) = 1;
3870 case OMP_CLAUSE_LASTPRIVATE
:
3871 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3875 case OMP_CLAUSE_PRIVATE
:
3876 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
3877 x
= build_outer_var_ref (var
, ctx
);
3878 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3880 if (is_task_ctx (ctx
))
3881 x
= build_receiver_ref (var
, false, ctx
);
3883 x
= build_outer_var_ref (var
, ctx
);
3889 nx
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
3892 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3893 if ((TREE_ADDRESSABLE (new_var
) || nx
|| y
3894 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
3895 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
3896 idx
, lane
, ivar
, lvar
))
3899 x
= lang_hooks
.decls
.omp_clause_default_ctor
3900 (c
, unshare_expr (ivar
), x
);
3902 gimplify_and_add (x
, &llist
[0]);
3905 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
3908 gimple_seq tseq
= NULL
;
3911 gimplify_stmt (&dtor
, &tseq
);
3912 gimple_seq_add_seq (&llist
[1], tseq
);
3919 gimplify_and_add (nx
, ilist
);
3923 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
3926 gimple_seq tseq
= NULL
;
3929 gimplify_stmt (&dtor
, &tseq
);
3930 gimple_seq_add_seq (dlist
, tseq
);
3934 case OMP_CLAUSE_LINEAR
:
3935 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
3936 goto do_firstprivate
;
3937 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
3940 x
= build_outer_var_ref (var
, ctx
);
3943 case OMP_CLAUSE_FIRSTPRIVATE
:
3944 if (is_task_ctx (ctx
))
3946 if (is_reference (var
) || is_variable_sized (var
))
3948 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
3950 || use_pointer_for_field (var
, NULL
))
3952 x
= build_receiver_ref (var
, false, ctx
);
3953 SET_DECL_VALUE_EXPR (new_var
, x
);
3954 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
3959 x
= build_outer_var_ref (var
, ctx
);
3962 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
3963 && gimple_omp_for_combined_into_p (ctx
->stmt
))
3965 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
3966 tree stept
= TREE_TYPE (t
);
3967 tree ct
= find_omp_clause (clauses
,
3968 OMP_CLAUSE__LOOPTEMP_
);
3970 tree l
= OMP_CLAUSE_DECL (ct
);
3971 tree n1
= fd
->loop
.n1
;
3972 tree step
= fd
->loop
.step
;
3973 tree itype
= TREE_TYPE (l
);
3974 if (POINTER_TYPE_P (itype
))
3975 itype
= signed_type_for (itype
);
3976 l
= fold_build2 (MINUS_EXPR
, itype
, l
, n1
);
3977 if (TYPE_UNSIGNED (itype
)
3978 && fd
->loop
.cond_code
== GT_EXPR
)
3979 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
3980 fold_build1 (NEGATE_EXPR
, itype
, l
),
3981 fold_build1 (NEGATE_EXPR
,
3984 l
= fold_build2 (TRUNC_DIV_EXPR
, itype
, l
, step
);
3985 t
= fold_build2 (MULT_EXPR
, stept
,
3986 fold_convert (stept
, l
), t
);
3988 if (OMP_CLAUSE_LINEAR_ARRAY (c
))
3990 x
= lang_hooks
.decls
.omp_clause_linear_ctor
3992 gimplify_and_add (x
, ilist
);
3996 if (POINTER_TYPE_P (TREE_TYPE (x
)))
3997 x
= fold_build2 (POINTER_PLUS_EXPR
,
3998 TREE_TYPE (x
), x
, t
);
4000 x
= fold_build2 (PLUS_EXPR
, TREE_TYPE (x
), x
, t
);
4003 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
4004 || TREE_ADDRESSABLE (new_var
))
4005 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4006 idx
, lane
, ivar
, lvar
))
4008 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
4010 tree iv
= create_tmp_var (TREE_TYPE (new_var
));
4011 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
4012 gimplify_and_add (x
, ilist
);
4013 gimple_stmt_iterator gsi
4014 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4016 = gimple_build_assign (unshare_expr (lvar
), iv
);
4017 gsi_insert_before_without_update (&gsi
, g
,
4019 tree t
= OMP_CLAUSE_LINEAR_STEP (c
);
4020 enum tree_code code
= PLUS_EXPR
;
4021 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
4022 code
= POINTER_PLUS_EXPR
;
4023 g
= gimple_build_assign (iv
, code
, iv
, t
);
4024 gsi_insert_before_without_update (&gsi
, g
,
4028 x
= lang_hooks
.decls
.omp_clause_copy_ctor
4029 (c
, unshare_expr (ivar
), x
);
4030 gimplify_and_add (x
, &llist
[0]);
4031 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4034 gimple_seq tseq
= NULL
;
4037 gimplify_stmt (&dtor
, &tseq
);
4038 gimple_seq_add_seq (&llist
[1], tseq
);
4043 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
4044 gimplify_and_add (x
, ilist
);
4047 case OMP_CLAUSE__LOOPTEMP_
:
4048 gcc_assert (is_parallel_ctx (ctx
));
4049 x
= build_outer_var_ref (var
, ctx
);
4050 x
= build2 (MODIFY_EXPR
, TREE_TYPE (new_var
), new_var
, x
);
4051 gimplify_and_add (x
, ilist
);
4054 case OMP_CLAUSE_COPYIN
:
4055 by_ref
= use_pointer_for_field (var
, NULL
);
4056 x
= build_receiver_ref (var
, by_ref
, ctx
);
4057 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
4058 append_to_statement_list (x
, ©in_seq
);
4059 copyin_by_ref
|= by_ref
;
4062 case OMP_CLAUSE_REDUCTION
:
4063 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4065 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4067 x
= build_outer_var_ref (var
, ctx
);
4069 if (is_reference (var
)
4070 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4072 x
= build_fold_addr_expr_loc (clause_loc
, x
);
4073 SET_DECL_VALUE_EXPR (placeholder
, x
);
4074 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4075 tree new_vard
= new_var
;
4076 if (is_reference (var
))
4078 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4079 new_vard
= TREE_OPERAND (new_var
, 0);
4080 gcc_assert (DECL_P (new_vard
));
4083 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4084 idx
, lane
, ivar
, lvar
))
4086 if (new_vard
== new_var
)
4088 gcc_assert (DECL_VALUE_EXPR (new_var
) == lvar
);
4089 SET_DECL_VALUE_EXPR (new_var
, ivar
);
4093 SET_DECL_VALUE_EXPR (new_vard
,
4094 build_fold_addr_expr (ivar
));
4095 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4097 x
= lang_hooks
.decls
.omp_clause_default_ctor
4098 (c
, unshare_expr (ivar
),
4099 build_outer_var_ref (var
, ctx
));
4101 gimplify_and_add (x
, &llist
[0]);
4102 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4104 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4105 lower_omp (&tseq
, ctx
);
4106 gimple_seq_add_seq (&llist
[0], tseq
);
4108 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4109 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4110 lower_omp (&tseq
, ctx
);
4111 gimple_seq_add_seq (&llist
[1], tseq
);
4112 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4113 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4114 if (new_vard
== new_var
)
4115 SET_DECL_VALUE_EXPR (new_var
, lvar
);
4117 SET_DECL_VALUE_EXPR (new_vard
,
4118 build_fold_addr_expr (lvar
));
4119 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
4124 gimplify_stmt (&dtor
, &tseq
);
4125 gimple_seq_add_seq (&llist
[1], tseq
);
4129 /* If this is a reference to constant size reduction var
4130 with placeholder, we haven't emitted the initializer
4131 for it because it is undesirable if SIMD arrays are used.
4132 But if they aren't used, we need to emit the deferred
4133 initialization now. */
4134 else if (is_reference (var
) && is_simd
)
4135 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4136 x
= lang_hooks
.decls
.omp_clause_default_ctor
4137 (c
, unshare_expr (new_var
),
4138 build_outer_var_ref (var
, ctx
));
4140 gimplify_and_add (x
, ilist
);
4141 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
))
4143 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
);
4144 lower_omp (&tseq
, ctx
);
4145 gimple_seq_add_seq (ilist
, tseq
);
4147 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
4150 tseq
= OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
);
4151 lower_omp (&tseq
, ctx
);
4152 gimple_seq_add_seq (dlist
, tseq
);
4153 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4155 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
4160 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
4161 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
4162 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4164 /* reduction(-:var) sums up the partial results, so it
4165 acts identically to reduction(+:var). */
4166 if (code
== MINUS_EXPR
)
4169 tree new_vard
= new_var
;
4170 if (is_simd
&& is_reference (var
))
4172 gcc_assert (TREE_CODE (new_var
) == MEM_REF
);
4173 new_vard
= TREE_OPERAND (new_var
, 0);
4174 gcc_assert (DECL_P (new_vard
));
4177 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
4178 idx
, lane
, ivar
, lvar
))
4180 tree ref
= build_outer_var_ref (var
, ctx
);
4182 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
4184 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
4185 ref
= build_outer_var_ref (var
, ctx
);
4186 gimplify_assign (ref
, x
, &llist
[1]);
4188 if (new_vard
!= new_var
)
4190 SET_DECL_VALUE_EXPR (new_vard
,
4191 build_fold_addr_expr (lvar
));
4192 DECL_HAS_VALUE_EXPR_P (new_vard
) = 1;
4197 if (is_reference (var
) && is_simd
)
4198 handle_simd_reference (clause_loc
, new_vard
, ilist
);
4199 gimplify_assign (new_var
, x
, ilist
);
4202 tree ref
= build_outer_var_ref (var
, ctx
);
4204 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4205 ref
= build_outer_var_ref (var
, ctx
);
4206 gimplify_assign (ref
, x
, dlist
);
4220 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
4221 /* Don't want uninit warnings on simduid, it is always uninitialized,
4222 but we use it not for the value, but for the DECL_UID only. */
4223 TREE_NO_WARNING (uid
) = 1;
4225 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
4226 gimple_call_set_lhs (g
, lane
);
4227 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
4228 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
4229 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
4230 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
4231 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4232 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4233 g
= gimple_build_assign (lane
, INTEGER_CST
,
4234 build_int_cst (unsigned_type_node
, 0));
4235 gimple_seq_add_stmt (ilist
, g
);
4236 for (int i
= 0; i
< 2; i
++)
4239 tree vf
= create_tmp_var (unsigned_type_node
);
4240 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
4241 gimple_call_set_lhs (g
, vf
);
4242 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
4243 gimple_seq_add_stmt (seq
, g
);
4244 tree t
= build_int_cst (unsigned_type_node
, 0);
4245 g
= gimple_build_assign (idx
, INTEGER_CST
, t
);
4246 gimple_seq_add_stmt (seq
, g
);
4247 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
4248 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
4249 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
4250 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
4251 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
4252 gimple_seq_add_seq (seq
, llist
[i
]);
4253 t
= build_int_cst (unsigned_type_node
, 1);
4254 g
= gimple_build_assign (idx
, PLUS_EXPR
, idx
, t
);
4255 gimple_seq_add_stmt (seq
, g
);
4256 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
4257 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
4258 gimple_seq_add_stmt (seq
, g
);
4259 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
4263 /* The copyin sequence is not to be executed by the main thread, since
4264 that would result in self-copies. Perhaps not visible to scalars,
4265 but it certainly is to C++ operator=. */
4268 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
4270 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
4271 build_int_cst (TREE_TYPE (x
), 0));
4272 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
4273 gimplify_and_add (x
, ilist
);
4276 /* If any copyin variable is passed by reference, we must ensure the
4277 master thread doesn't modify it before it is copied over in all
4278 threads. Similarly for variables in both firstprivate and
4279 lastprivate clauses we need to ensure the lastprivate copying
4280 happens after firstprivate copying in all threads. And similarly
4281 for UDRs if initializer expression refers to omp_orig. */
4282 if (copyin_by_ref
|| lastprivate_firstprivate
|| reduction_omp_orig_ref
)
4284 /* Don't add any barrier for #pragma omp simd or
4285 #pragma omp distribute. */
4286 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
4287 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
4288 gimple_seq_add_stmt (ilist
, build_omp_barrier (NULL_TREE
));
4291 /* If max_vf is non-zero, then we can use only a vectorization factor
4292 up to the max_vf we chose. So stick it into the safelen clause. */
4295 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
4296 OMP_CLAUSE_SAFELEN
);
4298 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c
)) == INTEGER_CST
4299 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
4302 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
4303 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
4305 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
4306 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
4312 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4313 both parallel and workshare constructs. PREDICATE may be NULL if it's
4317 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
4320 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
4321 bool par_clauses
= false;
4322 tree simduid
= NULL
, lastlane
= NULL
;
4324 /* Early exit if there are no lastprivate or linear clauses. */
4325 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
4326 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
4327 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
4328 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
4330 if (clauses
== NULL
)
4332 /* If this was a workshare clause, see if it had been combined
4333 with its parallel. In that case, look for the clauses on the
4334 parallel statement itself. */
4335 if (is_parallel_ctx (ctx
))
4339 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4342 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4343 OMP_CLAUSE_LASTPRIVATE
);
4344 if (clauses
== NULL
)
4352 tree label_true
, arm1
, arm2
;
4354 label
= create_artificial_label (UNKNOWN_LOCATION
);
4355 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
4356 arm1
= TREE_OPERAND (predicate
, 0);
4357 arm2
= TREE_OPERAND (predicate
, 1);
4358 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4359 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
4360 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
4362 gimple_seq_add_stmt (stmt_list
, stmt
);
4363 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
4366 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4367 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4369 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
4371 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
4374 for (c
= clauses
; c
;)
4377 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4379 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4380 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4381 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
4383 var
= OMP_CLAUSE_DECL (c
);
4384 new_var
= lookup_decl (var
, ctx
);
4386 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
4388 tree val
= DECL_VALUE_EXPR (new_var
);
4389 if (TREE_CODE (val
) == ARRAY_REF
4390 && VAR_P (TREE_OPERAND (val
, 0))
4391 && lookup_attribute ("omp simd array",
4392 DECL_ATTRIBUTES (TREE_OPERAND (val
,
4395 if (lastlane
== NULL
)
4397 lastlane
= create_tmp_var (unsigned_type_node
);
4399 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
4401 TREE_OPERAND (val
, 1));
4402 gimple_call_set_lhs (g
, lastlane
);
4403 gimple_seq_add_stmt (stmt_list
, g
);
4405 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
4406 TREE_OPERAND (val
, 0), lastlane
,
4407 NULL_TREE
, NULL_TREE
);
4411 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
4412 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
4414 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
4415 gimple_seq_add_seq (stmt_list
,
4416 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
4417 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
4419 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
4420 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
))
4422 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
), ctx
);
4423 gimple_seq_add_seq (stmt_list
,
4424 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
));
4425 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c
) = NULL
;
4428 x
= build_outer_var_ref (var
, ctx
);
4429 if (is_reference (var
))
4430 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4431 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
4432 gimplify_and_add (x
, stmt_list
);
4434 c
= OMP_CLAUSE_CHAIN (c
);
4435 if (c
== NULL
&& !par_clauses
)
4437 /* If this was a workshare clause, see if it had been combined
4438 with its parallel. In that case, continue looking for the
4439 clauses also on the parallel statement itself. */
4440 if (is_parallel_ctx (ctx
))
4444 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
4447 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
4448 OMP_CLAUSE_LASTPRIVATE
);
4454 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
4458 oacc_lower_reduction_var_helper (gimple_seq
*stmt_seqp
, omp_context
*ctx
,
4459 tree tid
, tree var
, tree new_var
)
4461 /* The atomic add at the end of the sum creates unnecessary
4462 write contention on accelerators. To work around this,
4463 create an array to store the partial reductions. Later, in
4464 lower_omp_for (for openacc), the values of array will be
4467 tree t
= NULL_TREE
, array
, x
;
4468 tree type
= get_base_type (var
);
4471 /* Now insert the partial reductions into the array. */
4473 /* Find the reduction array. */
4475 tree ptype
= build_pointer_type (type
);
4477 t
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
), ctx
);
4478 t
= build_receiver_ref (t
, false, ctx
->outer
);
4480 array
= create_tmp_var (ptype
);
4481 gimplify_assign (array
, t
, stmt_seqp
);
4483 tree ptr
= create_tmp_var (TREE_TYPE (array
));
4485 /* Find the reduction array. */
4487 /* testing a unary conversion. */
4488 tree offset
= create_tmp_var (sizetype
);
4489 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
),
4491 t
= create_tmp_var (sizetype
);
4492 gimplify_assign (t
, unshare_expr (fold_build1 (NOP_EXPR
, sizetype
, tid
)),
4494 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, t
);
4495 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4497 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4498 of adding sizeof(var) to the array? */
4499 ptr
= create_tmp_var (ptype
);
4500 stmt
= gimple_build_assign (unshare_expr (ptr
), POINTER_PLUS_EXPR
, array
,
4502 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4504 /* Move the local sum to gfc$sum[i]. */
4505 x
= unshare_expr (build_simple_mem_ref (ptr
));
4506 stmt
= gimplify_assign (x
, new_var
, stmt_seqp
);
4509 /* Generate code to implement the REDUCTION clauses. */
4512 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
4514 gimple_seq sub_seq
= NULL
;
4516 tree x
, c
, tid
= NULL_TREE
;
4519 /* SIMD reductions are handled in lower_rec_input_clauses. */
4520 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
4521 && gimple_omp_for_kind (ctx
->stmt
) & GF_OMP_FOR_SIMD
)
4524 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4525 update in that case, otherwise use a lock. */
4526 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
4527 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
4529 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4531 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4541 /* Initialize thread info for OpenACC. */
4542 if (is_gimple_omp_oacc (ctx
->stmt
))
4544 /* Get the current thread id. */
4545 tree call
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
4546 tid
= create_tmp_var (TREE_TYPE (TREE_TYPE (call
)));
4547 gimple stmt
= gimple_build_call (call
, 0);
4548 gimple_call_set_lhs (stmt
, tid
);
4549 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4552 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4554 tree var
, ref
, new_var
;
4555 enum tree_code code
;
4556 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4558 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
4561 var
= OMP_CLAUSE_DECL (c
);
4562 new_var
= lookup_decl (var
, ctx
);
4563 if (is_reference (var
))
4564 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4565 ref
= build_outer_var_ref (var
, ctx
);
4566 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
4568 /* reduction(-:var) sums up the partial results, so it acts
4569 identically to reduction(+:var). */
4570 if (code
== MINUS_EXPR
)
4573 if (is_gimple_omp_oacc (ctx
->stmt
))
4575 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
));
4577 oacc_lower_reduction_var_helper (stmt_seqp
, ctx
, tid
, var
, new_var
);
4579 else if (count
== 1)
4581 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
4583 addr
= save_expr (addr
);
4584 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
4585 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
4586 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
4587 gimplify_and_add (x
, stmt_seqp
);
4590 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
4592 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
4594 if (is_reference (var
)
4595 && !useless_type_conversion_p (TREE_TYPE (placeholder
),
4597 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
4598 SET_DECL_VALUE_EXPR (placeholder
, ref
);
4599 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
4600 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
4601 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
4602 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
4603 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
4607 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
4608 ref
= build_outer_var_ref (var
, ctx
);
4609 gimplify_assign (ref
, x
, &sub_seq
);
4613 if (is_gimple_omp_oacc (ctx
->stmt
))
4616 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
4618 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4620 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
4622 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
4624 gimple_seq_add_stmt (stmt_seqp
, stmt
);
4628 /* Generate code to implement the COPYPRIVATE clauses. */
4631 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
4636 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4638 tree var
, new_var
, ref
, x
;
4640 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4642 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
4645 var
= OMP_CLAUSE_DECL (c
);
4646 by_ref
= use_pointer_for_field (var
, NULL
);
4648 ref
= build_sender_ref (var
, ctx
);
4649 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
4652 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
4653 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
4655 gimplify_assign (ref
, x
, slist
);
4657 ref
= build_receiver_ref (var
, false, ctx
);
4660 ref
= fold_convert_loc (clause_loc
,
4661 build_pointer_type (TREE_TYPE (new_var
)),
4663 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
4665 if (is_reference (var
))
4667 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
4668 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
4669 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
4671 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
4672 gimplify_and_add (x
, rlist
);
4677 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4678 and REDUCTION from the sender (aka parent) side. */
4681 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
4686 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
4688 tree val
, ref
, x
, var
;
4689 bool by_ref
, do_in
= false, do_out
= false;
4690 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
4692 switch (OMP_CLAUSE_CODE (c
))
4694 case OMP_CLAUSE_PRIVATE
:
4695 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
4698 case OMP_CLAUSE_FIRSTPRIVATE
:
4699 case OMP_CLAUSE_COPYIN
:
4700 case OMP_CLAUSE_LASTPRIVATE
:
4701 case OMP_CLAUSE_REDUCTION
:
4702 case OMP_CLAUSE__LOOPTEMP_
:
4708 val
= OMP_CLAUSE_DECL (c
);
4709 var
= lookup_decl_in_outer_ctx (val
, ctx
);
4711 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
4712 && is_global_var (var
))
4714 if (is_variable_sized (val
))
4716 by_ref
= use_pointer_for_field (val
, NULL
);
4718 switch (OMP_CLAUSE_CODE (c
))
4720 case OMP_CLAUSE_PRIVATE
:
4721 case OMP_CLAUSE_FIRSTPRIVATE
:
4722 case OMP_CLAUSE_COPYIN
:
4723 case OMP_CLAUSE__LOOPTEMP_
:
4727 case OMP_CLAUSE_LASTPRIVATE
:
4728 if (by_ref
|| is_reference (val
))
4730 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
4737 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
4742 case OMP_CLAUSE_REDUCTION
:
4744 do_out
= !(by_ref
|| is_reference (val
));
4753 ref
= build_sender_ref (val
, ctx
);
4754 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
4755 gimplify_assign (ref
, x
, ilist
);
4756 if (is_task_ctx (ctx
))
4757 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
4762 ref
= build_sender_ref (val
, ctx
);
4763 gimplify_assign (var
, ref
, olist
);
4768 /* Generate code to implement SHARED from the sender (aka parent)
4769 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4770 list things that got automatically shared. */
4773 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
4775 tree var
, ovar
, nvar
, f
, x
, record_type
;
4777 if (ctx
->record_type
== NULL
)
4780 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
4781 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
4783 ovar
= DECL_ABSTRACT_ORIGIN (f
);
4784 nvar
= maybe_lookup_decl (ovar
, ctx
);
4785 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
4788 /* If CTX is a nested parallel directive. Find the immediately
4789 enclosing parallel or workshare construct that contains a
4790 mapping for OVAR. */
4791 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
4793 if (use_pointer_for_field (ovar
, ctx
))
4795 x
= build_sender_ref (ovar
, ctx
);
4796 var
= build_fold_addr_expr (var
);
4797 gimplify_assign (x
, var
, ilist
);
4801 x
= build_sender_ref (ovar
, ctx
);
4802 gimplify_assign (x
, var
, ilist
);
4804 if (!TREE_READONLY (var
)
4805 /* We don't need to receive a new reference to a result
4806 or parm decl. In fact we may not store to it as we will
4807 invalidate any pending RSO and generate wrong gimple
4809 && !((TREE_CODE (var
) == RESULT_DECL
4810 || TREE_CODE (var
) == PARM_DECL
)
4811 && DECL_BY_REFERENCE (var
)))
4813 x
= build_sender_ref (ovar
, ctx
);
4814 gimplify_assign (var
, x
, olist
);
4821 /* A convenience function to build an empty GIMPLE_COND with just the
4825 gimple_build_cond_empty (tree cond
)
4827 enum tree_code pred_code
;
4830 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
4831 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
4835 /* Build the function calls to GOMP_parallel_start etc to actually
4836 generate the parallel operation. REGION is the parallel region
4837 being expanded. BB is the block where to insert the code. WS_ARGS
4838 will be set if this is a call to a combined parallel+workshare
4839 construct, it contains the list of additional arguments needed by
4840 the workshare construct. */
4843 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
4844 gomp_parallel
*entry_stmt
,
4845 vec
<tree
, va_gc
> *ws_args
)
4847 tree t
, t1
, t2
, val
, cond
, c
, clauses
, flags
;
4848 gimple_stmt_iterator gsi
;
4850 enum built_in_function start_ix
;
4852 location_t clause_loc
;
4853 vec
<tree
, va_gc
> *args
;
4855 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
4857 /* Determine what flavor of GOMP_parallel we will be
4859 start_ix
= BUILT_IN_GOMP_PARALLEL
;
4860 if (is_combined_parallel (region
))
4862 switch (region
->inner
->type
)
4864 case GIMPLE_OMP_FOR
:
4865 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
4866 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4867 + (region
->inner
->sched_kind
4868 == OMP_CLAUSE_SCHEDULE_RUNTIME
4869 ? 3 : region
->inner
->sched_kind
));
4870 start_ix
= (enum built_in_function
)start_ix2
;
4872 case GIMPLE_OMP_SECTIONS
:
4873 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS
;
4880 /* By default, the value of NUM_THREADS is zero (selected at run time)
4881 and there is no conditional. */
4883 val
= build_int_cst (unsigned_type_node
, 0);
4884 flags
= build_int_cst (unsigned_type_node
, 0);
4886 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
4888 cond
= OMP_CLAUSE_IF_EXPR (c
);
4890 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
4893 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
4894 clause_loc
= OMP_CLAUSE_LOCATION (c
);
4897 clause_loc
= gimple_location (entry_stmt
);
4899 c
= find_omp_clause (clauses
, OMP_CLAUSE_PROC_BIND
);
4901 flags
= build_int_cst (unsigned_type_node
, OMP_CLAUSE_PROC_BIND_KIND (c
));
4903 /* Ensure 'val' is of the correct type. */
4904 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
4906 /* If we found the clause 'if (cond)', build either
4907 (cond != 0) or (cond ? val : 1u). */
4910 cond
= gimple_boolify (cond
);
4912 if (integer_zerop (val
))
4913 val
= fold_build2_loc (clause_loc
,
4914 EQ_EXPR
, unsigned_type_node
, cond
,
4915 build_int_cst (TREE_TYPE (cond
), 0));
4918 basic_block cond_bb
, then_bb
, else_bb
;
4919 edge e
, e_then
, e_else
;
4920 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
4922 tmp_var
= create_tmp_var (TREE_TYPE (val
));
4923 if (gimple_in_ssa_p (cfun
))
4925 tmp_then
= make_ssa_name (tmp_var
);
4926 tmp_else
= make_ssa_name (tmp_var
);
4927 tmp_join
= make_ssa_name (tmp_var
);
4936 e
= split_block (bb
, NULL
);
4941 then_bb
= create_empty_bb (cond_bb
);
4942 else_bb
= create_empty_bb (then_bb
);
4943 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
4944 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
4946 stmt
= gimple_build_cond_empty (cond
);
4947 gsi
= gsi_start_bb (cond_bb
);
4948 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4950 gsi
= gsi_start_bb (then_bb
);
4951 stmt
= gimple_build_assign (tmp_then
, val
);
4952 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4954 gsi
= gsi_start_bb (else_bb
);
4955 stmt
= gimple_build_assign
4956 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
4957 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4959 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
4960 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
4961 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
4962 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
4963 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
4964 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
4966 if (gimple_in_ssa_p (cfun
))
4968 gphi
*phi
= create_phi_node (tmp_join
, bb
);
4969 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
4970 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
4976 gsi
= gsi_start_bb (bb
);
4977 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
4978 false, GSI_CONTINUE_LINKING
);
4981 gsi
= gsi_last_bb (bb
);
4982 t
= gimple_omp_parallel_data_arg (entry_stmt
);
4984 t1
= null_pointer_node
;
4986 t1
= build_fold_addr_expr (t
);
4987 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
4989 vec_alloc (args
, 4 + vec_safe_length (ws_args
));
4990 args
->quick_push (t2
);
4991 args
->quick_push (t1
);
4992 args
->quick_push (val
);
4994 args
->splice (*ws_args
);
4995 args
->quick_push (flags
);
4997 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
4998 builtin_decl_explicit (start_ix
), args
);
5000 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5001 false, GSI_CONTINUE_LINKING
);
5004 /* Insert a function call whose name is FUNC_NAME with the information from
5005 ENTRY_STMT into the basic_block BB. */
5008 expand_cilk_for_call (basic_block bb
, gomp_parallel
*entry_stmt
,
5009 vec
<tree
, va_gc
> *ws_args
)
5012 gimple_stmt_iterator gsi
;
5013 vec
<tree
, va_gc
> *args
;
5015 gcc_assert (vec_safe_length (ws_args
) == 2);
5016 tree func_name
= (*ws_args
)[0];
5017 tree grain
= (*ws_args
)[1];
5019 tree clauses
= gimple_omp_parallel_clauses (entry_stmt
);
5020 tree count
= find_omp_clause (clauses
, OMP_CLAUSE__CILK_FOR_COUNT_
);
5021 gcc_assert (count
!= NULL_TREE
);
5022 count
= OMP_CLAUSE_OPERAND (count
, 0);
5024 gsi
= gsi_last_bb (bb
);
5025 t
= gimple_omp_parallel_data_arg (entry_stmt
);
5027 t1
= null_pointer_node
;
5029 t1
= build_fold_addr_expr (t
);
5030 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
5032 vec_alloc (args
, 4);
5033 args
->quick_push (t2
);
5034 args
->quick_push (t1
);
5035 args
->quick_push (count
);
5036 args
->quick_push (grain
);
5037 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
, func_name
, args
);
5039 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, false,
5040 GSI_CONTINUE_LINKING
);
5043 /* Build the function call to GOMP_task to actually
5044 generate the task operation. BB is the block where to insert the code. */
5047 expand_task_call (basic_block bb
, gomp_task
*entry_stmt
)
5049 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
, depend
;
5050 gimple_stmt_iterator gsi
;
5051 location_t loc
= gimple_location (entry_stmt
);
5053 clauses
= gimple_omp_task_clauses (entry_stmt
);
5055 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
5057 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
5059 cond
= boolean_true_node
;
5061 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
5062 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
5063 depend
= find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
);
5064 flags
= build_int_cst (unsigned_type_node
,
5065 (c
? 1 : 0) + (c2
? 4 : 0) + (depend
? 8 : 0));
5067 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
5070 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
5071 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
5072 build_int_cst (unsigned_type_node
, 2),
5073 build_int_cst (unsigned_type_node
, 0));
5074 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
5077 depend
= OMP_CLAUSE_DECL (depend
);
5079 depend
= build_int_cst (ptr_type_node
, 0);
5081 gsi
= gsi_last_bb (bb
);
5082 t
= gimple_omp_task_data_arg (entry_stmt
);
5084 t2
= null_pointer_node
;
5086 t2
= build_fold_addr_expr_loc (loc
, t
);
5087 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
5088 t
= gimple_omp_task_copy_fn (entry_stmt
);
5090 t3
= null_pointer_node
;
5092 t3
= build_fold_addr_expr_loc (loc
, t
);
5094 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
5096 gimple_omp_task_arg_size (entry_stmt
),
5097 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
,
5100 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5101 false, GSI_CONTINUE_LINKING
);
5105 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5106 catch handler and return it. This prevents programs from violating the
5107 structured block semantics with throws. */
5110 maybe_catch_exception (gimple_seq body
)
5115 if (!flag_exceptions
)
5118 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
5119 decl
= lang_hooks
.eh_protect_cleanup_actions ();
5121 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
5123 g
= gimple_build_eh_must_not_throw (decl
);
5124 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
5127 return gimple_seq_alloc_with_stmt (g
);
5130 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5133 vec2chain (vec
<tree
, va_gc
> *v
)
5135 tree chain
= NULL_TREE
, t
;
5138 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
5140 DECL_CHAIN (t
) = chain
;
5148 /* Remove barriers in REGION->EXIT's block. Note that this is only
5149 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5150 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5151 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5155 remove_exit_barrier (struct omp_region
*region
)
5157 gimple_stmt_iterator gsi
;
5158 basic_block exit_bb
;
5162 int any_addressable_vars
= -1;
5164 exit_bb
= region
->exit
;
5166 /* If the parallel region doesn't return, we don't have REGION->EXIT
5171 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5172 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5173 statements that can appear in between are extremely limited -- no
5174 memory operations at all. Here, we allow nothing at all, so the
5175 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5176 gsi
= gsi_last_bb (exit_bb
);
5177 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5179 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
5182 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
5184 gsi
= gsi_last_bb (e
->src
);
5185 if (gsi_end_p (gsi
))
5187 stmt
= gsi_stmt (gsi
);
5188 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
5189 && !gimple_omp_return_nowait_p (stmt
))
5191 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5192 in many cases. If there could be tasks queued, the barrier
5193 might be needed to let the tasks run before some local
5194 variable of the parallel that the task uses as shared
5195 runs out of scope. The task can be spawned either
5196 from within current function (this would be easy to check)
5197 or from some function it calls and gets passed an address
5198 of such a variable. */
5199 if (any_addressable_vars
< 0)
5201 gomp_parallel
*parallel_stmt
5202 = as_a
<gomp_parallel
*> (last_stmt (region
->entry
));
5203 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
5204 tree local_decls
, block
, decl
;
5207 any_addressable_vars
= 0;
5208 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
5209 if (TREE_ADDRESSABLE (decl
))
5211 any_addressable_vars
= 1;
5214 for (block
= gimple_block (stmt
);
5215 !any_addressable_vars
5217 && TREE_CODE (block
) == BLOCK
;
5218 block
= BLOCK_SUPERCONTEXT (block
))
5220 for (local_decls
= BLOCK_VARS (block
);
5222 local_decls
= DECL_CHAIN (local_decls
))
5223 if (TREE_ADDRESSABLE (local_decls
))
5225 any_addressable_vars
= 1;
5228 if (block
== gimple_block (parallel_stmt
))
5232 if (!any_addressable_vars
)
5233 gimple_omp_return_set_nowait (stmt
);
5239 remove_exit_barriers (struct omp_region
*region
)
5241 if (region
->type
== GIMPLE_OMP_PARALLEL
)
5242 remove_exit_barrier (region
);
5246 region
= region
->inner
;
5247 remove_exit_barriers (region
);
5248 while (region
->next
)
5250 region
= region
->next
;
5251 remove_exit_barriers (region
);
5256 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5257 calls. These can't be declared as const functions, but
5258 within one parallel body they are constant, so they can be
5259 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5260 which are declared const. Similarly for task body, except
5261 that in untied task omp_get_thread_num () can change at any task
5262 scheduling point. */
5265 optimize_omp_library_calls (gimple entry_stmt
)
5268 gimple_stmt_iterator gsi
;
5269 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5270 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
5271 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5272 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
5273 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
5274 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
5275 OMP_CLAUSE_UNTIED
) != NULL
);
5277 FOR_EACH_BB_FN (bb
, cfun
)
5278 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
5280 gimple call
= gsi_stmt (gsi
);
5283 if (is_gimple_call (call
)
5284 && (decl
= gimple_call_fndecl (call
))
5285 && DECL_EXTERNAL (decl
)
5286 && TREE_PUBLIC (decl
)
5287 && DECL_INITIAL (decl
) == NULL
)
5291 if (DECL_NAME (decl
) == thr_num_id
)
5293 /* In #pragma omp task untied omp_get_thread_num () can change
5294 during the execution of the task region. */
5297 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
5299 else if (DECL_NAME (decl
) == num_thr_id
)
5300 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
5304 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
5305 || gimple_call_num_args (call
) != 0)
5308 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
5311 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
5312 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
5313 TREE_TYPE (TREE_TYPE (built_in
))))
5316 gimple_call_set_fndecl (call
, built_in
);
5321 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5325 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
5329 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5330 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
5333 if (TREE_CODE (t
) == ADDR_EXPR
)
5334 recompute_tree_invariant_for_addr_expr (t
);
5336 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
5340 /* Prepend TO = FROM assignment before *GSI_P. */
5343 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
5345 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
5346 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
5347 true, GSI_SAME_STMT
);
5348 gimple stmt
= gimple_build_assign (to
, from
);
5349 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
5350 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
5351 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
5353 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
5354 gimple_regimplify_operands (stmt
, &gsi
);
5358 /* Expand the OpenMP parallel or task directive starting at REGION. */
5361 expand_omp_taskreg (struct omp_region
*region
)
5363 basic_block entry_bb
, exit_bb
, new_bb
;
5364 struct function
*child_cfun
;
5365 tree child_fn
, block
, t
;
5366 gimple_stmt_iterator gsi
;
5367 gimple entry_stmt
, stmt
;
5369 vec
<tree
, va_gc
> *ws_args
;
5371 entry_stmt
= last_stmt (region
->entry
);
5372 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
5373 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
5375 entry_bb
= region
->entry
;
5376 exit_bb
= region
->exit
;
5380 && gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
5381 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt
),
5382 OMP_CLAUSE__CILK_FOR_COUNT_
) != NULL_TREE
);
5385 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5386 and the inner statement contains the name of the built-in function
5388 ws_args
= region
->inner
->ws_args
;
5389 else if (is_combined_parallel (region
))
5390 ws_args
= region
->ws_args
;
5394 if (child_cfun
->cfg
)
5396 /* Due to inlining, it may happen that we have already outlined
5397 the region, in which case all we need to do is make the
5398 sub-graph unreachable and emit the parallel call. */
5399 edge entry_succ_e
, exit_succ_e
;
5401 entry_succ_e
= single_succ_edge (entry_bb
);
5403 gsi
= gsi_last_bb (entry_bb
);
5404 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
5405 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
5406 gsi_remove (&gsi
, true);
5411 exit_succ_e
= single_succ_edge (exit_bb
);
5412 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
5414 remove_edge_and_dominated_blocks (entry_succ_e
);
5418 unsigned srcidx
, dstidx
, num
;
5420 /* If the parallel region needs data sent from the parent
5421 function, then the very first statement (except possible
5422 tree profile counter updates) of the parallel body
5423 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5424 &.OMP_DATA_O is passed as an argument to the child function,
5425 we need to replace it with the argument as seen by the child
5428 In most cases, this will end up being the identity assignment
5429 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5430 a function call that has been inlined, the original PARM_DECL
5431 .OMP_DATA_I may have been converted into a different local
5432 variable. In which case, we need to keep the assignment. */
5433 if (gimple_omp_taskreg_data_arg (entry_stmt
))
5435 basic_block entry_succ_bb
= single_succ (entry_bb
);
5437 gimple parcopy_stmt
= NULL
;
5439 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
5443 gcc_assert (!gsi_end_p (gsi
));
5444 stmt
= gsi_stmt (gsi
);
5445 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
5448 if (gimple_num_ops (stmt
) == 2)
5450 tree arg
= gimple_assign_rhs1 (stmt
);
5452 /* We're ignore the subcode because we're
5453 effectively doing a STRIP_NOPS. */
5455 if (TREE_CODE (arg
) == ADDR_EXPR
5456 && TREE_OPERAND (arg
, 0)
5457 == gimple_omp_taskreg_data_arg (entry_stmt
))
5459 parcopy_stmt
= stmt
;
5465 gcc_assert (parcopy_stmt
!= NULL
);
5466 arg
= DECL_ARGUMENTS (child_fn
);
5468 if (!gimple_in_ssa_p (cfun
))
5470 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
5471 gsi_remove (&gsi
, true);
5474 /* ?? Is setting the subcode really necessary ?? */
5475 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
5476 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
5481 /* If we are in ssa form, we must load the value from the default
5482 definition of the argument. That should not be defined now,
5483 since the argument is not used uninitialized. */
5484 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
5485 narg
= make_ssa_name (arg
, gimple_build_nop ());
5486 set_ssa_default_def (cfun
, arg
, narg
);
5487 /* ?? Is setting the subcode really necessary ?? */
5488 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
5489 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
5490 update_stmt (parcopy_stmt
);
5494 /* Declare local variables needed in CHILD_CFUN. */
5495 block
= DECL_INITIAL (child_fn
);
5496 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
5497 /* The gimplifier could record temporaries in parallel/task block
5498 rather than in containing function's local_decls chain,
5499 which would mean cgraph missed finalizing them. Do it now. */
5500 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
5501 if (TREE_CODE (t
) == VAR_DECL
5503 && !DECL_EXTERNAL (t
))
5504 varpool_node::finalize_decl (t
);
5505 DECL_SAVED_TREE (child_fn
) = NULL
;
5506 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5507 gimple_set_body (child_fn
, NULL
);
5508 TREE_USED (block
) = 1;
5510 /* Reset DECL_CONTEXT on function arguments. */
5511 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
5512 DECL_CONTEXT (t
) = child_fn
;
5514 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5515 so that it can be moved to the child function. */
5516 gsi
= gsi_last_bb (entry_bb
);
5517 stmt
= gsi_stmt (gsi
);
5518 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
5519 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
5520 e
= split_block (entry_bb
, stmt
);
5521 gsi_remove (&gsi
, true);
5523 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5525 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5528 gsi
= gsi_last_bb (exit_bb
);
5529 gcc_assert (!gsi_end_p (gsi
)
5530 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
5531 stmt
= gimple_build_return (NULL
);
5532 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
5533 gsi_remove (&gsi
, true);
5536 /* Move the parallel region into CHILD_CFUN. */
5538 if (gimple_in_ssa_p (cfun
))
5540 init_tree_ssa (child_cfun
);
5541 init_ssa_operands (child_cfun
);
5542 child_cfun
->gimple_df
->in_ssa_p
= true;
5546 block
= gimple_block (entry_stmt
);
5548 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
5550 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
5551 /* When the OMP expansion process cannot guarantee an up-to-date
5552 loop tree arrange for the child function to fixup loops. */
5553 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
5554 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
5556 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5557 num
= vec_safe_length (child_cfun
->local_decls
);
5558 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
5560 t
= (*child_cfun
->local_decls
)[srcidx
];
5561 if (DECL_CONTEXT (t
) == cfun
->decl
)
5563 if (srcidx
!= dstidx
)
5564 (*child_cfun
->local_decls
)[dstidx
] = t
;
5568 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
5570 /* Inform the callgraph about the new function. */
5571 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
5572 cgraph_node::add_new_function (child_fn
, true);
5573 cgraph_node::get (child_fn
)->parallelized_function
= 1;
5575 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5576 fixed in a following pass. */
5577 push_cfun (child_cfun
);
5579 optimize_omp_library_calls (entry_stmt
);
5580 cgraph_edge::rebuild_edges ();
5582 /* Some EH regions might become dead, see PR34608. If
5583 pass_cleanup_cfg isn't the first pass to happen with the
5584 new child, these dead EH edges might cause problems.
5585 Clean them up now. */
5586 if (flag_exceptions
)
5589 bool changed
= false;
5591 FOR_EACH_BB_FN (bb
, cfun
)
5592 changed
|= gimple_purge_dead_eh_edges (bb
);
5594 cleanup_tree_cfg ();
5596 if (gimple_in_ssa_p (cfun
))
5597 update_ssa (TODO_update_ssa
);
5601 /* Emit a library call to launch the children threads. */
5603 expand_cilk_for_call (new_bb
,
5604 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5605 else if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
5606 expand_parallel_call (region
, new_bb
,
5607 as_a
<gomp_parallel
*> (entry_stmt
), ws_args
);
5609 expand_task_call (new_bb
, as_a
<gomp_task
*> (entry_stmt
));
5610 if (gimple_in_ssa_p (cfun
))
5611 update_ssa (TODO_update_ssa_only_virtuals
);
5615 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5616 of the combined collapse > 1 loop constructs, generate code like:
5617 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5622 count3 = (adj + N32 - N31) / STEP3;
5623 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5628 count2 = (adj + N22 - N21) / STEP2;
5629 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5634 count1 = (adj + N12 - N11) / STEP1;
5635 count = count1 * count2 * count3;
5636 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5638 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5639 of the combined loop constructs, just initialize COUNTS array
5640 from the _looptemp_ clauses. */
5642 /* NOTE: It *could* be better to moosh all of the BBs together,
5643 creating one larger BB with all the computation and the unexpected
5644 jump at the end. I.e.
5646 bool zero3, zero2, zero1, zero;
5649 count3 = (N32 - N31) /[cl] STEP3;
5651 count2 = (N22 - N21) /[cl] STEP2;
5653 count1 = (N12 - N11) /[cl] STEP1;
5654 zero = zero3 || zero2 || zero1;
5655 count = count1 * count2 * count3;
5656 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5658 After all, we expect the zero=false, and thus we expect to have to
5659 evaluate all of the comparison expressions, so short-circuiting
5660 oughtn't be a win. Since the condition isn't protecting a
5661 denominator, we're not concerned about divide-by-zero, so we can
5662 fully evaluate count even if a numerator turned out to be wrong.
5664 It seems like putting this all together would create much better
5665 scheduling opportunities, and less pressure on the chip's branch
5669 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5670 basic_block
&entry_bb
, tree
*counts
,
5671 basic_block
&zero_iter_bb
, int &first_zero_iter
,
5672 basic_block
&l2_dom_bb
)
5674 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
5678 /* Collapsed loops need work for expansion into SSA form. */
5679 gcc_assert (!gimple_in_ssa_p (cfun
));
5681 if (gimple_omp_for_combined_into_p (fd
->for_stmt
)
5682 && TREE_CODE (fd
->loop
.n2
) != INTEGER_CST
)
5684 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5685 isn't supposed to be handled, as the inner loop doesn't
5687 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5688 OMP_CLAUSE__LOOPTEMP_
);
5689 gcc_assert (innerc
);
5690 for (i
= 0; i
< fd
->collapse
; i
++)
5692 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5693 OMP_CLAUSE__LOOPTEMP_
);
5694 gcc_assert (innerc
);
5696 counts
[i
] = OMP_CLAUSE_DECL (innerc
);
5698 counts
[0] = NULL_TREE
;
5703 for (i
= 0; i
< fd
->collapse
; i
++)
5705 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5707 if (SSA_VAR_P (fd
->loop
.n2
)
5708 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
5709 fold_convert (itype
, fd
->loops
[i
].n1
),
5710 fold_convert (itype
, fd
->loops
[i
].n2
)))
5711 == NULL_TREE
|| !integer_onep (t
)))
5715 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
5716 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
5717 true, GSI_SAME_STMT
);
5718 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
5719 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
5720 true, GSI_SAME_STMT
);
5721 cond_stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
5722 NULL_TREE
, NULL_TREE
);
5723 gsi_insert_before (gsi
, cond_stmt
, GSI_SAME_STMT
);
5724 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
5725 expand_omp_regimplify_p
, NULL
, NULL
)
5726 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
5727 expand_omp_regimplify_p
, NULL
, NULL
))
5729 *gsi
= gsi_for_stmt (cond_stmt
);
5730 gimple_regimplify_operands (cond_stmt
, gsi
);
5732 e
= split_block (entry_bb
, cond_stmt
);
5733 if (zero_iter_bb
== NULL
)
5735 gassign
*assign_stmt
;
5736 first_zero_iter
= i
;
5737 zero_iter_bb
= create_empty_bb (entry_bb
);
5738 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
5739 *gsi
= gsi_after_labels (zero_iter_bb
);
5740 assign_stmt
= gimple_build_assign (fd
->loop
.n2
,
5741 build_zero_cst (type
));
5742 gsi_insert_before (gsi
, assign_stmt
, GSI_SAME_STMT
);
5743 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
5746 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
5747 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5748 e
->flags
= EDGE_TRUE_VALUE
;
5749 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
5750 if (l2_dom_bb
== NULL
)
5751 l2_dom_bb
= entry_bb
;
5753 *gsi
= gsi_last_bb (entry_bb
);
5756 if (POINTER_TYPE_P (itype
))
5757 itype
= signed_type_for (itype
);
5758 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
5760 t
= fold_build2 (PLUS_EXPR
, itype
,
5761 fold_convert (itype
, fd
->loops
[i
].step
), t
);
5762 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
5763 fold_convert (itype
, fd
->loops
[i
].n2
));
5764 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
5765 fold_convert (itype
, fd
->loops
[i
].n1
));
5766 /* ?? We could probably use CEIL_DIV_EXPR instead of
5767 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5768 generate the same code in the end because generically we
5769 don't know that the values involved must be negative for
5771 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
5772 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5773 fold_build1 (NEGATE_EXPR
, itype
, t
),
5774 fold_build1 (NEGATE_EXPR
, itype
,
5775 fold_convert (itype
,
5776 fd
->loops
[i
].step
)));
5778 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
5779 fold_convert (itype
, fd
->loops
[i
].step
));
5780 t
= fold_convert (type
, t
);
5781 if (TREE_CODE (t
) == INTEGER_CST
)
5785 counts
[i
] = create_tmp_reg (type
, ".count");
5786 expand_omp_build_assign (gsi
, counts
[i
], t
);
5788 if (SSA_VAR_P (fd
->loop
.n2
))
5793 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
5794 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
5800 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5802 V3 = N31 + (T % count3) * STEP3;
5804 V2 = N21 + (T % count2) * STEP2;
5806 V1 = N11 + T * STEP1;
5807 if this loop doesn't have an inner loop construct combined with it.
5808 If it does have an inner loop construct combined with it and the
5809 iteration count isn't known constant, store values from counts array
5810 into its _looptemp_ temporaries instead. */
5813 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
5814 tree
*counts
, gimple inner_stmt
, tree startvar
)
5817 if (gimple_omp_for_combined_p (fd
->for_stmt
))
5819 /* If fd->loop.n2 is constant, then no propagation of the counts
5820 is needed, they are constant. */
5821 if (TREE_CODE (fd
->loop
.n2
) == INTEGER_CST
)
5824 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
5825 ? gimple_omp_parallel_clauses (inner_stmt
)
5826 : gimple_omp_for_clauses (inner_stmt
);
5827 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5828 isn't supposed to be handled, as the inner loop doesn't
5830 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
5831 gcc_assert (innerc
);
5832 for (i
= 0; i
< fd
->collapse
; i
++)
5834 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
5835 OMP_CLAUSE__LOOPTEMP_
);
5836 gcc_assert (innerc
);
5839 tree tem
= OMP_CLAUSE_DECL (innerc
);
5840 tree t
= fold_convert (TREE_TYPE (tem
), counts
[i
]);
5841 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5842 false, GSI_CONTINUE_LINKING
);
5843 gassign
*stmt
= gimple_build_assign (tem
, t
);
5844 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5850 tree type
= TREE_TYPE (fd
->loop
.v
);
5851 tree tem
= create_tmp_reg (type
, ".tem");
5852 gassign
*stmt
= gimple_build_assign (tem
, startvar
);
5853 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5855 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5857 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
5859 if (POINTER_TYPE_P (vtype
))
5860 itype
= signed_type_for (vtype
);
5862 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
5865 t
= fold_convert (itype
, t
);
5866 t
= fold_build2 (MULT_EXPR
, itype
, t
,
5867 fold_convert (itype
, fd
->loops
[i
].step
));
5868 if (POINTER_TYPE_P (vtype
))
5869 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
5871 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
5872 t
= force_gimple_operand_gsi (gsi
, t
,
5873 DECL_P (fd
->loops
[i
].v
)
5874 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5876 GSI_CONTINUE_LINKING
);
5877 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5878 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5881 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
5882 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
5883 false, GSI_CONTINUE_LINKING
);
5884 stmt
= gimple_build_assign (tem
, t
);
5885 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
5891 /* Helper function for expand_omp_for_*. Generate code like:
5894 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5898 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5905 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
5906 basic_block body_bb
)
5908 basic_block last_bb
, bb
, collapse_bb
= NULL
;
5910 gimple_stmt_iterator gsi
;
5916 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
5918 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
5920 bb
= create_empty_bb (last_bb
);
5921 add_bb_to_loop (bb
, last_bb
->loop_father
);
5922 gsi
= gsi_start_bb (bb
);
5924 if (i
< fd
->collapse
- 1)
5926 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
5927 e
->probability
= REG_BR_PROB_BASE
/ 8;
5929 t
= fd
->loops
[i
+ 1].n1
;
5930 t
= force_gimple_operand_gsi (&gsi
, t
,
5931 DECL_P (fd
->loops
[i
+ 1].v
)
5932 && TREE_ADDRESSABLE (fd
->loops
[i
5935 GSI_CONTINUE_LINKING
);
5936 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
5937 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5942 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
5944 if (POINTER_TYPE_P (vtype
))
5945 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5947 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
5948 t
= force_gimple_operand_gsi (&gsi
, t
,
5949 DECL_P (fd
->loops
[i
].v
)
5950 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
5951 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5952 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
5953 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5957 t
= fd
->loops
[i
].n2
;
5958 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5959 false, GSI_CONTINUE_LINKING
);
5960 tree v
= fd
->loops
[i
].v
;
5961 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
5962 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
5963 false, GSI_CONTINUE_LINKING
);
5964 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
5965 stmt
= gimple_build_cond_empty (t
);
5966 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5967 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
5968 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5971 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
5979 /* A subroutine of expand_omp_for. Generate code for a parallel
5980 loop with any schedule. Given parameters:
5982 for (V = N1; V cond N2; V += STEP) BODY;
5984 where COND is "<" or ">", we generate pseudocode
5986 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5987 if (more) goto L0; else goto L3;
5994 if (V cond iend) goto L1; else goto L2;
5996 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5999 If this is a combined omp parallel loop, instead of the call to
6000 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6001 If this is gimple_omp_for_combined_p loop, then instead of assigning
6002 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6003 inner GIMPLE_OMP_FOR and V += STEP; and
6004 if (V cond iend) goto L1; else goto L2; are removed.
6006 For collapsed loops, given parameters:
6008 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6009 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6010 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6013 we generate pseudocode
6015 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6020 count3 = (adj + N32 - N31) / STEP3;
6021 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6026 count2 = (adj + N22 - N21) / STEP2;
6027 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6032 count1 = (adj + N12 - N11) / STEP1;
6033 count = count1 * count2 * count3;
6038 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6039 if (more) goto L0; else goto L3;
6043 V3 = N31 + (T % count3) * STEP3;
6045 V2 = N21 + (T % count2) * STEP2;
6047 V1 = N11 + T * STEP1;
6052 if (V < iend) goto L10; else goto L2;
6055 if (V3 cond3 N32) goto L1; else goto L11;
6059 if (V2 cond2 N22) goto L1; else goto L12;
6065 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6071 expand_omp_for_generic (struct omp_region
*region
,
6072 struct omp_for_data
*fd
,
6073 enum built_in_function start_fn
,
6074 enum built_in_function next_fn
,
6077 tree type
, istart0
, iend0
, iend
;
6078 tree t
, vmain
, vback
, bias
= NULL_TREE
;
6079 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
6080 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
6081 gimple_stmt_iterator gsi
;
6082 gassign
*assign_stmt
;
6083 bool in_combined_parallel
= is_combined_parallel (region
);
6084 bool broken_loop
= region
->cont
== NULL
;
6086 tree
*counts
= NULL
;
6089 gcc_assert (!broken_loop
|| !in_combined_parallel
);
6090 gcc_assert (fd
->iter_type
== long_integer_type_node
6091 || !in_combined_parallel
);
6093 type
= TREE_TYPE (fd
->loop
.v
);
6094 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
6095 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
6096 TREE_ADDRESSABLE (istart0
) = 1;
6097 TREE_ADDRESSABLE (iend0
) = 1;
6099 /* See if we need to bias by LLONG_MIN. */
6100 if (fd
->iter_type
== long_long_unsigned_type_node
6101 && TREE_CODE (type
) == INTEGER_TYPE
6102 && !TYPE_UNSIGNED (type
))
6106 if (fd
->loop
.cond_code
== LT_EXPR
)
6109 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6113 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
6116 if (TREE_CODE (n1
) != INTEGER_CST
6117 || TREE_CODE (n2
) != INTEGER_CST
6118 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
6119 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
6122 entry_bb
= region
->entry
;
6123 cont_bb
= region
->cont
;
6125 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6126 gcc_assert (broken_loop
6127 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
6128 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6129 l1_bb
= single_succ (l0_bb
);
6132 l2_bb
= create_empty_bb (cont_bb
);
6133 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
6134 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6138 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6139 exit_bb
= region
->exit
;
6141 gsi
= gsi_last_bb (entry_bb
);
6143 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6144 if (fd
->collapse
> 1)
6146 int first_zero_iter
= -1;
6147 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
6149 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6150 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6151 zero_iter_bb
, first_zero_iter
,
6156 /* Some counts[i] vars might be uninitialized if
6157 some loop has zero iterations. But the body shouldn't
6158 be executed in that case, so just avoid uninit warnings. */
6159 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
6160 if (SSA_VAR_P (counts
[i
]))
6161 TREE_NO_WARNING (counts
[i
]) = 1;
6163 e
= split_block (entry_bb
, gsi_stmt (gsi
));
6165 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
6166 gsi
= gsi_last_bb (entry_bb
);
6167 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
6168 get_immediate_dominator (CDI_DOMINATORS
,
6172 if (in_combined_parallel
)
6174 /* In a combined parallel loop, emit a call to
6175 GOMP_loop_foo_next. */
6176 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6177 build_fold_addr_expr (istart0
),
6178 build_fold_addr_expr (iend0
));
6182 tree t0
, t1
, t2
, t3
, t4
;
6183 /* If this is not a combined parallel loop, emit a call to
6184 GOMP_loop_foo_start in ENTRY_BB. */
6185 t4
= build_fold_addr_expr (iend0
);
6186 t3
= build_fold_addr_expr (istart0
);
6187 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
6190 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6192 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6193 OMP_CLAUSE__LOOPTEMP_
);
6194 gcc_assert (innerc
);
6195 t0
= OMP_CLAUSE_DECL (innerc
);
6196 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6197 OMP_CLAUSE__LOOPTEMP_
);
6198 gcc_assert (innerc
);
6199 t1
= OMP_CLAUSE_DECL (innerc
);
6201 if (POINTER_TYPE_P (TREE_TYPE (t0
))
6202 && TYPE_PRECISION (TREE_TYPE (t0
))
6203 != TYPE_PRECISION (fd
->iter_type
))
6205 /* Avoid casting pointers to integer of a different size. */
6206 tree itype
= signed_type_for (type
);
6207 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
6208 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
6212 t1
= fold_convert (fd
->iter_type
, t1
);
6213 t0
= fold_convert (fd
->iter_type
, t0
);
6217 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
6218 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
6220 if (fd
->iter_type
== long_integer_type_node
)
6224 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6225 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6226 6, t0
, t1
, t2
, t
, t3
, t4
);
6229 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6230 5, t0
, t1
, t2
, t3
, t4
);
6238 /* The GOMP_loop_ull_*start functions have additional boolean
6239 argument, true for < loops and false for > loops.
6240 In Fortran, the C bool type can be different from
6241 boolean_type_node. */
6242 bfn_decl
= builtin_decl_explicit (start_fn
);
6243 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
6244 t5
= build_int_cst (c_bool_type
,
6245 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
6248 tree bfn_decl
= builtin_decl_explicit (start_fn
);
6249 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
6250 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
6253 t
= build_call_expr (builtin_decl_explicit (start_fn
),
6254 6, t5
, t0
, t1
, t2
, t3
, t4
);
6257 if (TREE_TYPE (t
) != boolean_type_node
)
6258 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6259 t
, build_int_cst (TREE_TYPE (t
), 0));
6260 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6261 true, GSI_SAME_STMT
);
6262 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6264 /* Remove the GIMPLE_OMP_FOR statement. */
6265 gsi_remove (&gsi
, true);
6267 /* Iteration setup for sequential loop goes in L0_BB. */
6268 tree startvar
= fd
->loop
.v
;
6269 tree endvar
= NULL_TREE
;
6271 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6273 gcc_assert (gimple_code (inner_stmt
) == GIMPLE_OMP_FOR
6274 && gimple_omp_for_kind (inner_stmt
)
6275 == GF_OMP_FOR_KIND_SIMD
);
6276 tree innerc
= find_omp_clause (gimple_omp_for_clauses (inner_stmt
),
6277 OMP_CLAUSE__LOOPTEMP_
);
6278 gcc_assert (innerc
);
6279 startvar
= OMP_CLAUSE_DECL (innerc
);
6280 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6281 OMP_CLAUSE__LOOPTEMP_
);
6282 gcc_assert (innerc
);
6283 endvar
= OMP_CLAUSE_DECL (innerc
);
6286 gsi
= gsi_start_bb (l0_bb
);
6289 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6290 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6291 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6292 t
= fold_convert (TREE_TYPE (startvar
), t
);
6293 t
= force_gimple_operand_gsi (&gsi
, t
,
6295 && TREE_ADDRESSABLE (startvar
),
6296 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6297 assign_stmt
= gimple_build_assign (startvar
, t
);
6298 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6302 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
6303 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
6304 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
6305 t
= fold_convert (TREE_TYPE (startvar
), t
);
6306 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6307 false, GSI_CONTINUE_LINKING
);
6310 assign_stmt
= gimple_build_assign (endvar
, iend
);
6311 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6312 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (iend
)))
6313 assign_stmt
= gimple_build_assign (fd
->loop
.v
, iend
);
6315 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, iend
);
6316 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6318 if (fd
->collapse
> 1)
6319 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6323 /* Code to control the increment and predicate for the sequential
6324 loop goes in the CONT_BB. */
6325 gsi
= gsi_last_bb (cont_bb
);
6326 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6327 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6328 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6329 vback
= gimple_omp_continue_control_def (cont_stmt
);
6331 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6333 if (POINTER_TYPE_P (type
))
6334 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
6336 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
6337 t
= force_gimple_operand_gsi (&gsi
, t
,
6339 && TREE_ADDRESSABLE (vback
),
6340 NULL_TREE
, true, GSI_SAME_STMT
);
6341 assign_stmt
= gimple_build_assign (vback
, t
);
6342 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6344 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6345 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
6347 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6348 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6351 /* Remove GIMPLE_OMP_CONTINUE. */
6352 gsi_remove (&gsi
, true);
6354 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6355 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
6357 /* Emit code to get the next parallel iteration in L2_BB. */
6358 gsi
= gsi_start_bb (l2_bb
);
6360 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
6361 build_fold_addr_expr (istart0
),
6362 build_fold_addr_expr (iend0
));
6363 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6364 false, GSI_CONTINUE_LINKING
);
6365 if (TREE_TYPE (t
) != boolean_type_node
)
6366 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
6367 t
, build_int_cst (TREE_TYPE (t
), 0));
6368 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6369 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
6372 /* Add the loop cleanup function. */
6373 gsi
= gsi_last_bb (exit_bb
);
6374 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6375 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
6376 else if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6377 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL
);
6379 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
6380 gcall
*call_stmt
= gimple_build_call (t
, 0);
6381 if (gimple_omp_return_lhs (gsi_stmt (gsi
)))
6382 gimple_call_set_lhs (call_stmt
, gimple_omp_return_lhs (gsi_stmt (gsi
)));
6383 gsi_insert_after (&gsi
, call_stmt
, GSI_SAME_STMT
);
6384 gsi_remove (&gsi
, true);
6386 /* Connect the new blocks. */
6387 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
6388 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
6394 e
= find_edge (cont_bb
, l3_bb
);
6395 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
6397 phis
= phi_nodes (l3_bb
);
6398 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
6400 gimple phi
= gsi_stmt (gsi
);
6401 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
6402 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
6406 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
6407 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
6408 e
= find_edge (cont_bb
, l1_bb
);
6409 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6414 else if (fd
->collapse
> 1)
6417 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6420 e
->flags
= EDGE_TRUE_VALUE
;
6423 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
6424 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
6428 e
= find_edge (cont_bb
, l2_bb
);
6429 e
->flags
= EDGE_FALLTHRU
;
6431 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
6433 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
6434 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
6435 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
6436 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
6437 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
6438 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
6439 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
6440 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
6442 struct loop
*outer_loop
= alloc_loop ();
6443 outer_loop
->header
= l0_bb
;
6444 outer_loop
->latch
= l2_bb
;
6445 add_loop (outer_loop
, l0_bb
->loop_father
);
6447 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6449 struct loop
*loop
= alloc_loop ();
6450 loop
->header
= l1_bb
;
6451 /* The loop may have multiple latches. */
6452 add_loop (loop
, outer_loop
);
6458 /* A subroutine of expand_omp_for. Generate code for a parallel
6459 loop with static schedule and no specified chunk size. Given
6462 for (V = N1; V cond N2; V += STEP) BODY;
6464 where COND is "<" or ">", we generate pseudocode
6466 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6471 if ((__typeof (V)) -1 > 0 && cond is >)
6472 n = -(adj + N2 - N1) / -STEP;
6474 n = (adj + N2 - N1) / STEP;
6477 if (threadid < tt) goto L3; else goto L4;
6482 s0 = q * threadid + tt;
6485 if (s0 >= e0) goto L2; else goto L0;
6491 if (V cond e) goto L1;
6496 expand_omp_for_static_nochunk (struct omp_region
*region
,
6497 struct omp_for_data
*fd
,
6500 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
6501 tree type
, itype
, vmain
, vback
;
6502 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
6503 basic_block body_bb
, cont_bb
, collapse_bb
= NULL
;
6505 gimple_stmt_iterator gsi
;
6507 bool broken_loop
= region
->cont
== NULL
;
6508 tree
*counts
= NULL
;
6511 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6512 != GF_OMP_FOR_KIND_OACC_LOOP
)
6515 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6516 if (POINTER_TYPE_P (type
))
6517 itype
= signed_type_for (type
);
6519 entry_bb
= region
->entry
;
6520 cont_bb
= region
->cont
;
6521 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
6522 fin_bb
= BRANCH_EDGE (entry_bb
)->dest
;
6523 gcc_assert (broken_loop
6524 || (fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
));
6525 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
6526 body_bb
= single_succ (seq_start_bb
);
6529 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6530 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6532 exit_bb
= region
->exit
;
6534 /* Iteration space partitioning goes in ENTRY_BB. */
6535 gsi
= gsi_last_bb (entry_bb
);
6536 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6538 if (fd
->collapse
> 1)
6540 int first_zero_iter
= -1;
6541 basic_block l2_dom_bb
= NULL
;
6543 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6544 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6545 fin_bb
, first_zero_iter
,
6549 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6550 t
= integer_one_node
;
6552 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6553 fold_convert (type
, fd
->loop
.n1
),
6554 fold_convert (type
, fd
->loop
.n2
));
6555 if (fd
->collapse
== 1
6556 && TYPE_UNSIGNED (type
)
6557 && (t
== NULL_TREE
|| !integer_onep (t
)))
6559 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6560 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6561 true, GSI_SAME_STMT
);
6562 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6563 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6564 true, GSI_SAME_STMT
);
6565 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6566 NULL_TREE
, NULL_TREE
);
6567 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6568 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6569 expand_omp_regimplify_p
, NULL
, NULL
)
6570 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6571 expand_omp_regimplify_p
, NULL
, NULL
))
6573 gsi
= gsi_for_stmt (cond_stmt
);
6574 gimple_regimplify_operands (cond_stmt
, &gsi
);
6576 ep
= split_block (entry_bb
, cond_stmt
);
6577 ep
->flags
= EDGE_TRUE_VALUE
;
6578 entry_bb
= ep
->dest
;
6579 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6580 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6581 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6582 if (gimple_in_ssa_p (cfun
))
6584 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6585 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6586 !gsi_end_p (gpi
); gsi_next (&gpi
))
6588 gphi
*phi
= gpi
.phi ();
6589 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6590 ep
, UNKNOWN_LOCATION
);
6593 gsi
= gsi_last_bb (entry_bb
);
6596 switch (gimple_omp_for_kind (fd
->for_stmt
))
6598 case GF_OMP_FOR_KIND_FOR
:
6599 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
6600 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
6602 case GF_OMP_FOR_KIND_DISTRIBUTE
:
6603 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
6604 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
6606 case GF_OMP_FOR_KIND_OACC_LOOP
:
6607 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
6608 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
6613 nthreads
= build_call_expr (nthreads
, 0);
6614 nthreads
= fold_convert (itype
, nthreads
);
6615 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
6616 true, GSI_SAME_STMT
);
6617 threadid
= build_call_expr (threadid
, 0);
6618 threadid
= fold_convert (itype
, threadid
);
6619 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
6620 true, GSI_SAME_STMT
);
6624 step
= fd
->loop
.step
;
6625 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6627 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
6628 OMP_CLAUSE__LOOPTEMP_
);
6629 gcc_assert (innerc
);
6630 n1
= OMP_CLAUSE_DECL (innerc
);
6631 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6632 OMP_CLAUSE__LOOPTEMP_
);
6633 gcc_assert (innerc
);
6634 n2
= OMP_CLAUSE_DECL (innerc
);
6636 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
6637 true, NULL_TREE
, true, GSI_SAME_STMT
);
6638 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
6639 true, NULL_TREE
, true, GSI_SAME_STMT
);
6640 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
6641 true, NULL_TREE
, true, GSI_SAME_STMT
);
6643 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
6644 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
6645 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
6646 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
6647 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
6648 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
6649 fold_build1 (NEGATE_EXPR
, itype
, t
),
6650 fold_build1 (NEGATE_EXPR
, itype
, step
));
6652 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
6653 t
= fold_convert (itype
, t
);
6654 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6656 q
= create_tmp_reg (itype
, "q");
6657 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
6658 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6659 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
6661 tt
= create_tmp_reg (itype
, "tt");
6662 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
6663 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
6664 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
6666 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
6667 gcond
*cond_stmt
= gimple_build_cond_empty (t
);
6668 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6670 second_bb
= split_block (entry_bb
, cond_stmt
)->dest
;
6671 gsi
= gsi_last_bb (second_bb
);
6672 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6674 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
6676 gassign
*assign_stmt
6677 = gimple_build_assign (q
, PLUS_EXPR
, q
, build_int_cst (itype
, 1));
6678 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6680 third_bb
= split_block (second_bb
, assign_stmt
)->dest
;
6681 gsi
= gsi_last_bb (third_bb
);
6682 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6684 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
6685 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
6686 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6688 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
6689 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6691 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
6692 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6694 /* Remove the GIMPLE_OMP_FOR statement. */
6695 gsi_remove (&gsi
, true);
6697 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6698 gsi
= gsi_start_bb (seq_start_bb
);
6700 tree startvar
= fd
->loop
.v
;
6701 tree endvar
= NULL_TREE
;
6703 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6705 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
6706 ? gimple_omp_parallel_clauses (inner_stmt
)
6707 : gimple_omp_for_clauses (inner_stmt
);
6708 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
6709 gcc_assert (innerc
);
6710 startvar
= OMP_CLAUSE_DECL (innerc
);
6711 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
6712 OMP_CLAUSE__LOOPTEMP_
);
6713 gcc_assert (innerc
);
6714 endvar
= OMP_CLAUSE_DECL (innerc
);
6716 t
= fold_convert (itype
, s0
);
6717 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6718 if (POINTER_TYPE_P (type
))
6719 t
= fold_build_pointer_plus (n1
, t
);
6721 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6722 t
= fold_convert (TREE_TYPE (startvar
), t
);
6723 t
= force_gimple_operand_gsi (&gsi
, t
,
6725 && TREE_ADDRESSABLE (startvar
),
6726 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
6727 assign_stmt
= gimple_build_assign (startvar
, t
);
6728 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6730 t
= fold_convert (itype
, e0
);
6731 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
6732 if (POINTER_TYPE_P (type
))
6733 t
= fold_build_pointer_plus (n1
, t
);
6735 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
6736 t
= fold_convert (TREE_TYPE (startvar
), t
);
6737 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
6738 false, GSI_CONTINUE_LINKING
);
6741 assign_stmt
= gimple_build_assign (endvar
, e
);
6742 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6743 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
6744 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
6746 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
6747 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
6749 if (fd
->collapse
> 1)
6750 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
6754 /* The code controlling the sequential loop replaces the
6755 GIMPLE_OMP_CONTINUE. */
6756 gsi
= gsi_last_bb (cont_bb
);
6757 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
6758 gcc_assert (gimple_code (cont_stmt
) == GIMPLE_OMP_CONTINUE
);
6759 vmain
= gimple_omp_continue_control_use (cont_stmt
);
6760 vback
= gimple_omp_continue_control_def (cont_stmt
);
6762 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
6764 if (POINTER_TYPE_P (type
))
6765 t
= fold_build_pointer_plus (vmain
, step
);
6767 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
6768 t
= force_gimple_operand_gsi (&gsi
, t
,
6770 && TREE_ADDRESSABLE (vback
),
6771 NULL_TREE
, true, GSI_SAME_STMT
);
6772 assign_stmt
= gimple_build_assign (vback
, t
);
6773 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
6775 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
6776 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
6778 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
6781 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6782 gsi_remove (&gsi
, true);
6784 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
6785 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
6788 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6789 gsi
= gsi_last_bb (exit_bb
);
6790 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
6792 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
6793 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
6794 gcc_checking_assert (t
== NULL_TREE
);
6796 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
6798 gsi_remove (&gsi
, true);
6800 /* Connect all the blocks. */
6801 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
6802 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
6803 ep
= find_edge (entry_bb
, second_bb
);
6804 ep
->flags
= EDGE_TRUE_VALUE
;
6805 ep
->probability
= REG_BR_PROB_BASE
/ 4;
6806 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
6807 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
6811 ep
= find_edge (cont_bb
, body_bb
);
6812 if (gimple_omp_for_combined_p (fd
->for_stmt
))
6817 else if (fd
->collapse
> 1)
6820 ep
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
6823 ep
->flags
= EDGE_TRUE_VALUE
;
6824 find_edge (cont_bb
, fin_bb
)->flags
6825 = ep
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
6828 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
6829 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
6830 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
6832 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
6833 recompute_dominator (CDI_DOMINATORS
, body_bb
));
6834 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
6835 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
6837 if (!broken_loop
&& !gimple_omp_for_combined_p (fd
->for_stmt
))
6839 struct loop
*loop
= alloc_loop ();
6840 loop
->header
= body_bb
;
6841 if (collapse_bb
== NULL
)
6842 loop
->latch
= cont_bb
;
6843 add_loop (loop
, body_bb
->loop_father
);
6848 /* A subroutine of expand_omp_for. Generate code for a parallel
6849 loop with static schedule and a specified chunk size. Given
6852 for (V = N1; V cond N2; V += STEP) BODY;
6854 where COND is "<" or ">", we generate pseudocode
6856 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6861 if ((__typeof (V)) -1 > 0 && cond is >)
6862 n = -(adj + N2 - N1) / -STEP;
6864 n = (adj + N2 - N1) / STEP;
6866 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6867 here so that V is defined
6868 if the loop is not entered
6870 s0 = (trip * nthreads + threadid) * CHUNK;
6871 e0 = min(s0 + CHUNK, n);
6872 if (s0 < n) goto L1; else goto L4;
6879 if (V cond e) goto L2; else goto L3;
6887 expand_omp_for_static_chunk (struct omp_region
*region
,
6888 struct omp_for_data
*fd
, gimple inner_stmt
)
6890 tree n
, s0
, e0
, e
, t
;
6891 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
6892 tree type
, itype
, vmain
, vback
, vextra
;
6893 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
6894 basic_block trip_update_bb
= NULL
, cont_bb
, collapse_bb
= NULL
, fin_bb
;
6895 gimple_stmt_iterator gsi
;
6897 bool broken_loop
= region
->cont
== NULL
;
6898 tree
*counts
= NULL
;
6901 gcc_checking_assert ((gimple_omp_for_kind (fd
->for_stmt
)
6902 != GF_OMP_FOR_KIND_OACC_LOOP
)
6905 itype
= type
= TREE_TYPE (fd
->loop
.v
);
6906 if (POINTER_TYPE_P (type
))
6907 itype
= signed_type_for (type
);
6909 entry_bb
= region
->entry
;
6910 se
= split_block (entry_bb
, last_stmt (entry_bb
));
6912 iter_part_bb
= se
->dest
;
6913 cont_bb
= region
->cont
;
6914 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
6915 fin_bb
= BRANCH_EDGE (iter_part_bb
)->dest
;
6916 gcc_assert (broken_loop
6917 || fin_bb
== FALLTHRU_EDGE (cont_bb
)->dest
);
6918 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
6919 body_bb
= single_succ (seq_start_bb
);
6922 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
6923 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
6924 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
6926 exit_bb
= region
->exit
;
6928 /* Trip and adjustment setup goes in ENTRY_BB. */
6929 gsi
= gsi_last_bb (entry_bb
);
6930 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
6932 if (fd
->collapse
> 1)
6934 int first_zero_iter
= -1;
6935 basic_block l2_dom_bb
= NULL
;
6937 counts
= XALLOCAVEC (tree
, fd
->collapse
);
6938 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
6939 fin_bb
, first_zero_iter
,
6943 else if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
6944 t
= integer_one_node
;
6946 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
6947 fold_convert (type
, fd
->loop
.n1
),
6948 fold_convert (type
, fd
->loop
.n2
));
6949 if (fd
->collapse
== 1
6950 && TYPE_UNSIGNED (type
)
6951 && (t
== NULL_TREE
|| !integer_onep (t
)))
6953 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
6954 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
6955 true, GSI_SAME_STMT
);
6956 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
6957 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
6958 true, GSI_SAME_STMT
);
6959 gcond
*cond_stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
6960 NULL_TREE
, NULL_TREE
);
6961 gsi_insert_before (&gsi
, cond_stmt
, GSI_SAME_STMT
);
6962 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
6963 expand_omp_regimplify_p
, NULL
, NULL
)
6964 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
6965 expand_omp_regimplify_p
, NULL
, NULL
))
6967 gsi
= gsi_for_stmt (cond_stmt
);
6968 gimple_regimplify_operands (cond_stmt
, &gsi
);
6970 se
= split_block (entry_bb
, cond_stmt
);
6971 se
->flags
= EDGE_TRUE_VALUE
;
6972 entry_bb
= se
->dest
;
6973 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
6974 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
6975 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
6976 if (gimple_in_ssa_p (cfun
))
6978 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
6979 for (gphi_iterator gpi
= gsi_start_phis (fin_bb
);
6980 !gsi_end_p (gpi
); gsi_next (&gpi
))
6982 gphi
*phi
= gpi
.phi ();
6983 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
6984 se
, UNKNOWN_LOCATION
);
6987 gsi
= gsi_last_bb (entry_bb
);
6990 switch (gimple_omp_for_kind (fd
->for_stmt
))
6992 case GF_OMP_FOR_KIND_FOR
:
6993 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
6994 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
6996 case GF_OMP_FOR_KIND_DISTRIBUTE
:
6997 nthreads
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS
);
6998 threadid
= builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM
);
7000 case GF_OMP_FOR_KIND_OACC_LOOP
:
7001 nthreads
= builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS
);
7002 threadid
= builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM
);
7007 nthreads
= build_call_expr (nthreads
, 0);
7008 nthreads
= fold_convert (itype
, nthreads
);
7009 nthreads
= force_gimple_operand_gsi (&gsi
, nthreads
, true, NULL_TREE
,
7010 true, GSI_SAME_STMT
);
7011 threadid
= build_call_expr (threadid
, 0);
7012 threadid
= fold_convert (itype
, threadid
);
7013 threadid
= force_gimple_operand_gsi (&gsi
, threadid
, true, NULL_TREE
,
7014 true, GSI_SAME_STMT
);
7018 step
= fd
->loop
.step
;
7019 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7021 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7022 OMP_CLAUSE__LOOPTEMP_
);
7023 gcc_assert (innerc
);
7024 n1
= OMP_CLAUSE_DECL (innerc
);
7025 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7026 OMP_CLAUSE__LOOPTEMP_
);
7027 gcc_assert (innerc
);
7028 n2
= OMP_CLAUSE_DECL (innerc
);
7030 n1
= force_gimple_operand_gsi (&gsi
, fold_convert (type
, n1
),
7031 true, NULL_TREE
, true, GSI_SAME_STMT
);
7032 n2
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, n2
),
7033 true, NULL_TREE
, true, GSI_SAME_STMT
);
7034 step
= force_gimple_operand_gsi (&gsi
, fold_convert (itype
, step
),
7035 true, NULL_TREE
, true, GSI_SAME_STMT
);
7037 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->chunk_size
),
7038 true, NULL_TREE
, true, GSI_SAME_STMT
);
7040 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
7041 t
= fold_build2 (PLUS_EXPR
, itype
, step
, t
);
7042 t
= fold_build2 (PLUS_EXPR
, itype
, t
, n2
);
7043 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
7044 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
7045 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
7046 fold_build1 (NEGATE_EXPR
, itype
, t
),
7047 fold_build1 (NEGATE_EXPR
, itype
, step
));
7049 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
7050 t
= fold_convert (itype
, t
);
7051 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7052 true, GSI_SAME_STMT
);
7054 trip_var
= create_tmp_reg (itype
, ".trip");
7055 if (gimple_in_ssa_p (cfun
))
7057 trip_init
= make_ssa_name (trip_var
);
7058 trip_main
= make_ssa_name (trip_var
);
7059 trip_back
= make_ssa_name (trip_var
);
7063 trip_init
= trip_var
;
7064 trip_main
= trip_var
;
7065 trip_back
= trip_var
;
7068 gassign
*assign_stmt
7069 = gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
7070 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7072 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
7073 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7074 if (POINTER_TYPE_P (type
))
7075 t
= fold_build_pointer_plus (n1
, t
);
7077 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7078 vextra
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7079 true, GSI_SAME_STMT
);
7081 /* Remove the GIMPLE_OMP_FOR. */
7082 gsi_remove (&gsi
, true);
7084 /* Iteration space partitioning goes in ITER_PART_BB. */
7085 gsi
= gsi_last_bb (iter_part_bb
);
7087 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
7088 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
7089 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
7090 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7091 false, GSI_CONTINUE_LINKING
);
7093 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
7094 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
7095 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7096 false, GSI_CONTINUE_LINKING
);
7098 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
7099 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
7101 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7102 gsi
= gsi_start_bb (seq_start_bb
);
7104 tree startvar
= fd
->loop
.v
;
7105 tree endvar
= NULL_TREE
;
7107 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7109 tree clauses
= gimple_code (inner_stmt
) == GIMPLE_OMP_PARALLEL
7110 ? gimple_omp_parallel_clauses (inner_stmt
)
7111 : gimple_omp_for_clauses (inner_stmt
);
7112 tree innerc
= find_omp_clause (clauses
, OMP_CLAUSE__LOOPTEMP_
);
7113 gcc_assert (innerc
);
7114 startvar
= OMP_CLAUSE_DECL (innerc
);
7115 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7116 OMP_CLAUSE__LOOPTEMP_
);
7117 gcc_assert (innerc
);
7118 endvar
= OMP_CLAUSE_DECL (innerc
);
7121 t
= fold_convert (itype
, s0
);
7122 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7123 if (POINTER_TYPE_P (type
))
7124 t
= fold_build_pointer_plus (n1
, t
);
7126 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7127 t
= fold_convert (TREE_TYPE (startvar
), t
);
7128 t
= force_gimple_operand_gsi (&gsi
, t
,
7130 && TREE_ADDRESSABLE (startvar
),
7131 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
7132 assign_stmt
= gimple_build_assign (startvar
, t
);
7133 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7135 t
= fold_convert (itype
, e0
);
7136 t
= fold_build2 (MULT_EXPR
, itype
, t
, step
);
7137 if (POINTER_TYPE_P (type
))
7138 t
= fold_build_pointer_plus (n1
, t
);
7140 t
= fold_build2 (PLUS_EXPR
, type
, t
, n1
);
7141 t
= fold_convert (TREE_TYPE (startvar
), t
);
7142 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7143 false, GSI_CONTINUE_LINKING
);
7146 assign_stmt
= gimple_build_assign (endvar
, e
);
7147 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7148 if (useless_type_conversion_p (TREE_TYPE (fd
->loop
.v
), TREE_TYPE (e
)))
7149 assign_stmt
= gimple_build_assign (fd
->loop
.v
, e
);
7151 assign_stmt
= gimple_build_assign (fd
->loop
.v
, NOP_EXPR
, e
);
7152 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7154 if (fd
->collapse
> 1)
7155 expand_omp_for_init_vars (fd
, &gsi
, counts
, inner_stmt
, startvar
);
7159 /* The code controlling the sequential loop goes in CONT_BB,
7160 replacing the GIMPLE_OMP_CONTINUE. */
7161 gsi
= gsi_last_bb (cont_bb
);
7162 gomp_continue
*cont_stmt
= as_a
<gomp_continue
*> (gsi_stmt (gsi
));
7163 vmain
= gimple_omp_continue_control_use (cont_stmt
);
7164 vback
= gimple_omp_continue_control_def (cont_stmt
);
7166 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7168 if (POINTER_TYPE_P (type
))
7169 t
= fold_build_pointer_plus (vmain
, step
);
7171 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, step
);
7172 if (DECL_P (vback
) && TREE_ADDRESSABLE (vback
))
7173 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7174 true, GSI_SAME_STMT
);
7175 assign_stmt
= gimple_build_assign (vback
, t
);
7176 gsi_insert_before (&gsi
, assign_stmt
, GSI_SAME_STMT
);
7178 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
7179 DECL_P (vback
) && TREE_ADDRESSABLE (vback
)
7181 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
7184 /* Remove GIMPLE_OMP_CONTINUE. */
7185 gsi_remove (&gsi
, true);
7187 if (fd
->collapse
> 1 && !gimple_omp_for_combined_p (fd
->for_stmt
))
7188 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, body_bb
);
7190 /* Trip update code goes into TRIP_UPDATE_BB. */
7191 gsi
= gsi_start_bb (trip_update_bb
);
7193 t
= build_int_cst (itype
, 1);
7194 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
7195 assign_stmt
= gimple_build_assign (trip_back
, t
);
7196 gsi_insert_after (&gsi
, assign_stmt
, GSI_CONTINUE_LINKING
);
7199 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7200 gsi
= gsi_last_bb (exit_bb
);
7201 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
7203 t
= gimple_omp_return_lhs (gsi_stmt (gsi
));
7204 if (gimple_omp_for_kind (fd
->for_stmt
) == GF_OMP_FOR_KIND_OACC_LOOP
)
7205 gcc_checking_assert (t
== NULL_TREE
);
7207 gsi_insert_after (&gsi
, build_omp_barrier (t
), GSI_SAME_STMT
);
7209 gsi_remove (&gsi
, true);
7211 /* Connect the new blocks. */
7212 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
7213 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
7217 se
= find_edge (cont_bb
, body_bb
);
7218 if (gimple_omp_for_combined_p (fd
->for_stmt
))
7223 else if (fd
->collapse
> 1)
7226 se
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
7229 se
->flags
= EDGE_TRUE_VALUE
;
7230 find_edge (cont_bb
, trip_update_bb
)->flags
7231 = se
? EDGE_FALSE_VALUE
: EDGE_FALLTHRU
;
7233 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
7236 if (gimple_in_ssa_p (cfun
))
7244 gcc_assert (fd
->collapse
== 1 && !broken_loop
);
7246 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7247 remove arguments of the phi nodes in fin_bb. We need to create
7248 appropriate phi nodes in iter_part_bb instead. */
7249 se
= single_pred_edge (fin_bb
);
7250 re
= single_succ_edge (trip_update_bb
);
7251 vec
<edge_var_map
> *head
= redirect_edge_var_map_vector (re
);
7252 ene
= single_succ_edge (entry_bb
);
7254 psi
= gsi_start_phis (fin_bb
);
7255 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
7256 gsi_next (&psi
), ++i
)
7259 source_location locus
;
7262 t
= gimple_phi_result (phi
);
7263 gcc_assert (t
== redirect_edge_var_map_result (vm
));
7264 nphi
= create_phi_node (t
, iter_part_bb
);
7266 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
7267 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
7269 /* A special case -- fd->loop.v is not yet computed in
7270 iter_part_bb, we need to use vextra instead. */
7271 if (t
== fd
->loop
.v
)
7273 add_phi_arg (nphi
, t
, ene
, locus
);
7274 locus
= redirect_edge_var_map_location (vm
);
7275 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
7277 gcc_assert (gsi_end_p (psi
) && i
== head
->length ());
7278 redirect_edge_var_map_clear (re
);
7281 psi
= gsi_start_phis (fin_bb
);
7282 if (gsi_end_p (psi
))
7284 remove_phi_node (&psi
, false);
7287 /* Make phi node for trip. */
7288 phi
= create_phi_node (trip_main
, iter_part_bb
);
7289 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
7291 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
7296 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
7297 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
7298 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
7299 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
7300 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
7301 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
7302 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
7303 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
7304 recompute_dominator (CDI_DOMINATORS
, body_bb
));
7308 struct loop
*trip_loop
= alloc_loop ();
7309 trip_loop
->header
= iter_part_bb
;
7310 trip_loop
->latch
= trip_update_bb
;
7311 add_loop (trip_loop
, iter_part_bb
->loop_father
);
7313 if (!gimple_omp_for_combined_p (fd
->for_stmt
))
7315 struct loop
*loop
= alloc_loop ();
7316 loop
->header
= body_bb
;
7317 if (collapse_bb
== NULL
)
7318 loop
->latch
= cont_bb
;
7319 add_loop (loop
, trip_loop
);
7324 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7326 for (V = N1; V cond N2; V += STEP) BODY;
7328 where COND is "<" or ">" or "!=", we generate pseudocode
7330 for (ind_var = low; ind_var < high; ind_var++)
7332 V = n1 + (ind_var * STEP)
7337 In the above pseudocode, low and high are function parameters of the
7338 child function. In the function below, we are inserting a temp.
7339 variable that will be making a call to two OMP functions that will not be
7340 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7341 with _Cilk_for). These functions are replaced with low and high
7342 by the function that handles taskreg. */
7346 expand_cilk_for (struct omp_region
*region
, struct omp_for_data
*fd
)
7348 bool broken_loop
= region
->cont
== NULL
;
7349 basic_block entry_bb
= region
->entry
;
7350 basic_block cont_bb
= region
->cont
;
7352 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7353 gcc_assert (broken_loop
7354 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7355 basic_block l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7356 basic_block l1_bb
, l2_bb
;
7360 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7361 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7362 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7363 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7367 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7368 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7369 l2_bb
= single_succ (l1_bb
);
7371 basic_block exit_bb
= region
->exit
;
7372 basic_block l2_dom_bb
= NULL
;
7374 gimple_stmt_iterator gsi
= gsi_last_bb (entry_bb
);
7376 /* Below statements until the "tree high_val = ..." are pseudo statements
7377 used to pass information to be used by expand_omp_taskreg.
7378 low_val and high_val will be replaced by the __low and __high
7379 parameter from the child function.
7381 The call_exprs part is a place-holder, it is mainly used
7382 to distinctly identify to the top-level part that this is
7383 where we should put low and high (reasoning given in header
7387 = gimple_omp_parallel_child_fn (
7388 as_a
<gomp_parallel
*> (last_stmt (region
->outer
->entry
)));
7389 tree t
, low_val
= NULL_TREE
, high_val
= NULL_TREE
;
7390 for (t
= DECL_ARGUMENTS (child_fndecl
); t
; t
= TREE_CHAIN (t
))
7392 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__high"))
7394 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t
)), "__low"))
7397 gcc_assert (low_val
&& high_val
);
7399 tree type
= TREE_TYPE (low_val
);
7400 tree ind_var
= create_tmp_reg (type
, "__cilk_ind_var");
7401 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7403 /* Not needed in SSA form right now. */
7404 gcc_assert (!gimple_in_ssa_p (cfun
));
7405 if (l2_dom_bb
== NULL
)
7411 gimple stmt
= gimple_build_assign (ind_var
, n1
);
7413 /* Replace the GIMPLE_OMP_FOR statement. */
7414 gsi_replace (&gsi
, stmt
, true);
7418 /* Code to control the increment goes in the CONT_BB. */
7419 gsi
= gsi_last_bb (cont_bb
);
7420 stmt
= gsi_stmt (gsi
);
7421 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7422 stmt
= gimple_build_assign (ind_var
, PLUS_EXPR
, ind_var
,
7423 build_one_cst (type
));
7425 /* Replace GIMPLE_OMP_CONTINUE. */
7426 gsi_replace (&gsi
, stmt
, true);
7429 /* Emit the condition in L1_BB. */
7430 gsi
= gsi_after_labels (l1_bb
);
7431 t
= fold_build2 (MULT_EXPR
, TREE_TYPE (fd
->loop
.step
),
7432 fold_convert (TREE_TYPE (fd
->loop
.step
), ind_var
),
7434 if (POINTER_TYPE_P (TREE_TYPE (fd
->loop
.n1
)))
7435 t
= fold_build2 (POINTER_PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7436 fd
->loop
.n1
, fold_convert (sizetype
, t
));
7438 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loop
.n1
),
7439 fd
->loop
.n1
, fold_convert (TREE_TYPE (fd
->loop
.n1
), t
));
7440 t
= fold_convert (TREE_TYPE (fd
->loop
.v
), t
);
7441 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7443 /* The condition is always '<' since the runtime will fill in the low
7445 stmt
= gimple_build_cond (LT_EXPR
, ind_var
, n2
, NULL_TREE
, NULL_TREE
);
7446 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
7448 /* Remove GIMPLE_OMP_RETURN. */
7449 gsi
= gsi_last_bb (exit_bb
);
7450 gsi_remove (&gsi
, true);
7452 /* Connect the new blocks. */
7453 remove_edge (FALLTHRU_EDGE (entry_bb
));
7458 remove_edge (BRANCH_EDGE (entry_bb
));
7459 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7461 e
= BRANCH_EDGE (l1_bb
);
7462 ne
= FALLTHRU_EDGE (l1_bb
);
7463 e
->flags
= EDGE_TRUE_VALUE
;
7467 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7469 ne
= single_succ_edge (l1_bb
);
7470 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7473 ne
->flags
= EDGE_FALSE_VALUE
;
7474 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7475 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7477 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7478 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7479 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7483 struct loop
*loop
= alloc_loop ();
7484 loop
->header
= l1_bb
;
7485 loop
->latch
= cont_bb
;
7486 add_loop (loop
, l1_bb
->loop_father
);
7487 loop
->safelen
= INT_MAX
;
7490 /* Pick the correct library function based on the precision of the
7491 induction variable type. */
7492 tree lib_fun
= NULL_TREE
;
7493 if (TYPE_PRECISION (type
) == 32)
7494 lib_fun
= cilk_for_32_fndecl
;
7495 else if (TYPE_PRECISION (type
) == 64)
7496 lib_fun
= cilk_for_64_fndecl
;
7500 gcc_assert (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_CILKFOR
);
7502 /* WS_ARGS contains the library function flavor to call:
7503 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7504 user-defined grain value. If the user does not define one, then zero
7505 is passed in by the parser. */
7506 vec_alloc (region
->ws_args
, 2);
7507 region
->ws_args
->quick_push (lib_fun
);
7508 region
->ws_args
->quick_push (fd
->chunk_size
);
7511 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7512 loop. Given parameters:
7514 for (V = N1; V cond N2; V += STEP) BODY;
7516 where COND is "<" or ">", we generate pseudocode
7524 if (V cond N2) goto L0; else goto L2;
7527 For collapsed loops, given parameters:
7529 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7530 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7531 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7534 we generate pseudocode
7540 count3 = (adj + N32 - N31) / STEP3;
7545 count2 = (adj + N22 - N21) / STEP2;
7550 count1 = (adj + N12 - N11) / STEP1;
7551 count = count1 * count2 * count3;
7561 V2 += (V3 cond3 N32) ? 0 : STEP2;
7562 V3 = (V3 cond3 N32) ? V3 : N31;
7563 V1 += (V2 cond2 N22) ? 0 : STEP1;
7564 V2 = (V2 cond2 N22) ? V2 : N21;
7566 if (V < count) goto L0; else goto L2;
7572 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
7575 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
7576 gimple_stmt_iterator gsi
;
7579 bool broken_loop
= region
->cont
== NULL
;
7581 tree
*counts
= NULL
;
7583 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7584 OMP_CLAUSE_SAFELEN
);
7585 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7586 OMP_CLAUSE__SIMDUID_
);
7589 type
= TREE_TYPE (fd
->loop
.v
);
7590 entry_bb
= region
->entry
;
7591 cont_bb
= region
->cont
;
7592 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
7593 gcc_assert (broken_loop
7594 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
7595 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
7598 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
7599 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
7600 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
7601 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
7605 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
7606 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
7607 l2_bb
= single_succ (l1_bb
);
7609 exit_bb
= region
->exit
;
7612 gsi
= gsi_last_bb (entry_bb
);
7614 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
7615 /* Not needed in SSA form right now. */
7616 gcc_assert (!gimple_in_ssa_p (cfun
));
7617 if (fd
->collapse
> 1)
7619 int first_zero_iter
= -1;
7620 basic_block zero_iter_bb
= l2_bb
;
7622 counts
= XALLOCAVEC (tree
, fd
->collapse
);
7623 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
7624 zero_iter_bb
, first_zero_iter
,
7627 if (l2_dom_bb
== NULL
)
7632 if (gimple_omp_for_combined_into_p (fd
->for_stmt
))
7634 tree innerc
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
7635 OMP_CLAUSE__LOOPTEMP_
);
7636 gcc_assert (innerc
);
7637 n1
= OMP_CLAUSE_DECL (innerc
);
7638 innerc
= find_omp_clause (OMP_CLAUSE_CHAIN (innerc
),
7639 OMP_CLAUSE__LOOPTEMP_
);
7640 gcc_assert (innerc
);
7641 n2
= OMP_CLAUSE_DECL (innerc
);
7642 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7643 fold_convert (type
, n1
));
7644 if (fd
->collapse
> 1)
7647 expand_omp_for_init_vars (fd
, &gsi
, counts
, NULL
, n1
);
7653 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
7654 fold_convert (type
, fd
->loop
.n1
));
7655 if (fd
->collapse
> 1)
7656 for (i
= 0; i
< fd
->collapse
; i
++)
7658 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7659 if (POINTER_TYPE_P (itype
))
7660 itype
= signed_type_for (itype
);
7661 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
7662 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7666 /* Remove the GIMPLE_OMP_FOR statement. */
7667 gsi_remove (&gsi
, true);
7671 /* Code to control the increment goes in the CONT_BB. */
7672 gsi
= gsi_last_bb (cont_bb
);
7673 stmt
= gsi_stmt (gsi
);
7674 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
7676 if (POINTER_TYPE_P (type
))
7677 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
7679 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
7680 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
7682 if (fd
->collapse
> 1)
7684 i
= fd
->collapse
- 1;
7685 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
7687 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
7688 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
7692 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
7694 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
7697 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7699 for (i
= fd
->collapse
- 1; i
> 0; i
--)
7701 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
7702 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
7703 if (POINTER_TYPE_P (itype2
))
7704 itype2
= signed_type_for (itype2
);
7705 t
= build3 (COND_EXPR
, itype2
,
7706 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7708 fold_convert (itype
, fd
->loops
[i
].n2
)),
7709 build_int_cst (itype2
, 0),
7710 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
7711 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
7712 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
7714 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
7715 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
7717 t
= build3 (COND_EXPR
, itype
,
7718 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
7720 fold_convert (itype
, fd
->loops
[i
].n2
)),
7722 fold_convert (itype
, fd
->loops
[i
].n1
));
7723 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
7727 /* Remove GIMPLE_OMP_CONTINUE. */
7728 gsi_remove (&gsi
, true);
7731 /* Emit the condition in L1_BB. */
7732 gsi
= gsi_start_bb (l1_bb
);
7734 t
= fold_convert (type
, n2
);
7735 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
7736 false, GSI_CONTINUE_LINKING
);
7737 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
7738 cond_stmt
= gimple_build_cond_empty (t
);
7739 gsi_insert_after (&gsi
, cond_stmt
, GSI_CONTINUE_LINKING
);
7740 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7742 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
), expand_omp_regimplify_p
,
7745 gsi
= gsi_for_stmt (cond_stmt
);
7746 gimple_regimplify_operands (cond_stmt
, &gsi
);
7749 /* Remove GIMPLE_OMP_RETURN. */
7750 gsi
= gsi_last_bb (exit_bb
);
7751 gsi_remove (&gsi
, true);
7753 /* Connect the new blocks. */
7754 remove_edge (FALLTHRU_EDGE (entry_bb
));
7758 remove_edge (BRANCH_EDGE (entry_bb
));
7759 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
7761 e
= BRANCH_EDGE (l1_bb
);
7762 ne
= FALLTHRU_EDGE (l1_bb
);
7763 e
->flags
= EDGE_TRUE_VALUE
;
7767 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
7769 ne
= single_succ_edge (l1_bb
);
7770 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
7773 ne
->flags
= EDGE_FALSE_VALUE
;
7774 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
7775 ne
->probability
= REG_BR_PROB_BASE
/ 8;
7777 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
7778 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
7779 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
7783 struct loop
*loop
= alloc_loop ();
7784 loop
->header
= l1_bb
;
7785 loop
->latch
= cont_bb
;
7786 add_loop (loop
, l1_bb
->loop_father
);
7787 if (safelen
== NULL_TREE
)
7788 loop
->safelen
= INT_MAX
;
7791 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
7792 if (TREE_CODE (safelen
) != INTEGER_CST
)
7794 else if (!tree_fits_uhwi_p (safelen
)
7795 || tree_to_uhwi (safelen
) > INT_MAX
)
7796 loop
->safelen
= INT_MAX
;
7798 loop
->safelen
= tree_to_uhwi (safelen
);
7799 if (loop
->safelen
== 1)
7804 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
7805 cfun
->has_simduid_loops
= true;
7807 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7809 if ((flag_tree_loop_vectorize
7810 || (!global_options_set
.x_flag_tree_loop_vectorize
7811 && !global_options_set
.x_flag_tree_vectorize
))
7812 && flag_tree_loop_optimize
7813 && loop
->safelen
> 1)
7815 loop
->force_vectorize
= true;
7816 cfun
->has_force_vectorize_loops
= true;
7822 /* Expand the OMP loop defined by REGION. */
7825 expand_omp_for (struct omp_region
*region
, gimple inner_stmt
)
7827 struct omp_for_data fd
;
7828 struct omp_for_data_loop
*loops
;
7831 = (struct omp_for_data_loop
*)
7832 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
7833 * sizeof (struct omp_for_data_loop
));
7834 extract_omp_for_data (as_a
<gomp_for
*> (last_stmt (region
->entry
)),
7836 region
->sched_kind
= fd
.sched_kind
;
7838 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
7839 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7840 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
7843 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
7844 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7845 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
7848 /* If there isn't a continue then this is a degerate case where
7849 the introduction of abnormal edges during lowering will prevent
7850 original loops from being detected. Fix that up. */
7851 loops_state_set (LOOPS_NEED_FIXUP
);
7853 if (gimple_omp_for_kind (fd
.for_stmt
) & GF_OMP_FOR_SIMD
)
7854 expand_omp_simd (region
, &fd
);
7855 else if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_CILKFOR
)
7856 expand_cilk_for (region
, &fd
);
7857 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
7858 && !fd
.have_ordered
)
7860 if (fd
.chunk_size
== NULL
)
7861 expand_omp_for_static_nochunk (region
, &fd
, inner_stmt
);
7863 expand_omp_for_static_chunk (region
, &fd
, inner_stmt
);
7867 int fn_index
, start_ix
, next_ix
;
7869 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
7870 == GF_OMP_FOR_KIND_FOR
);
7871 if (fd
.chunk_size
== NULL
7872 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
7873 fd
.chunk_size
= integer_zero_node
;
7874 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
7875 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
7876 ? 3 : fd
.sched_kind
;
7877 fn_index
+= fd
.have_ordered
* 4;
7878 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
7879 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
7880 if (fd
.iter_type
== long_long_unsigned_type_node
)
7882 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7883 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
7884 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7885 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
7887 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
7888 (enum built_in_function
) next_ix
, inner_stmt
);
7891 if (gimple_in_ssa_p (cfun
))
7892 update_ssa (TODO_update_ssa_only_virtuals
);
7896 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7898 v = GOMP_sections_start (n);
7915 v = GOMP_sections_next ();
7920 If this is a combined parallel sections, replace the call to
7921 GOMP_sections_start with call to GOMP_sections_next. */
7924 expand_omp_sections (struct omp_region
*region
)
7926 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
7928 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
7929 gimple_stmt_iterator si
, switch_si
;
7930 gomp_sections
*sections_stmt
;
7932 gomp_continue
*cont
;
7935 struct omp_region
*inner
;
7937 bool exit_reachable
= region
->cont
!= NULL
;
7939 gcc_assert (region
->exit
!= NULL
);
7940 entry_bb
= region
->entry
;
7941 l0_bb
= single_succ (entry_bb
);
7942 l1_bb
= region
->cont
;
7943 l2_bb
= region
->exit
;
7944 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
7945 l2
= gimple_block_label (l2_bb
);
7948 /* This can happen if there are reductions. */
7949 len
= EDGE_COUNT (l0_bb
->succs
);
7950 gcc_assert (len
> 0);
7951 e
= EDGE_SUCC (l0_bb
, len
- 1);
7952 si
= gsi_last_bb (e
->dest
);
7955 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7956 l2
= gimple_block_label (e
->dest
);
7958 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
7960 si
= gsi_last_bb (e
->dest
);
7962 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
7964 l2
= gimple_block_label (e
->dest
);
7970 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
7972 default_bb
= create_empty_bb (l0_bb
);
7974 /* We will build a switch() with enough cases for all the
7975 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7976 and a default case to abort if something goes wrong. */
7977 len
= EDGE_COUNT (l0_bb
->succs
);
7979 /* Use vec::quick_push on label_vec throughout, since we know the size
7981 auto_vec
<tree
> label_vec (len
);
7983 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7984 GIMPLE_OMP_SECTIONS statement. */
7985 si
= gsi_last_bb (entry_bb
);
7986 sections_stmt
= as_a
<gomp_sections
*> (gsi_stmt (si
));
7987 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
7988 vin
= gimple_omp_sections_control (sections_stmt
);
7989 if (!is_combined_parallel (region
))
7991 /* If we are not inside a combined parallel+sections region,
7992 call GOMP_sections_start. */
7993 t
= build_int_cst (unsigned_type_node
, len
- 1);
7994 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
7995 stmt
= gimple_build_call (u
, 1, t
);
7999 /* Otherwise, call GOMP_sections_next. */
8000 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8001 stmt
= gimple_build_call (u
, 0);
8003 gimple_call_set_lhs (stmt
, vin
);
8004 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8005 gsi_remove (&si
, true);
8007 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8009 switch_si
= gsi_last_bb (l0_bb
);
8010 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
8013 cont
= as_a
<gomp_continue
*> (last_stmt (l1_bb
));
8014 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
8015 vmain
= gimple_omp_continue_control_use (cont
);
8016 vnext
= gimple_omp_continue_control_def (cont
);
8024 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
8025 label_vec
.quick_push (t
);
8028 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8029 for (inner
= region
->inner
, casei
= 1;
8031 inner
= inner
->next
, i
++, casei
++)
8033 basic_block s_entry_bb
, s_exit_bb
;
8035 /* Skip optional reduction region. */
8036 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
8043 s_entry_bb
= inner
->entry
;
8044 s_exit_bb
= inner
->exit
;
8046 t
= gimple_block_label (s_entry_bb
);
8047 u
= build_int_cst (unsigned_type_node
, casei
);
8048 u
= build_case_label (u
, NULL
, t
);
8049 label_vec
.quick_push (u
);
8051 si
= gsi_last_bb (s_entry_bb
);
8052 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
8053 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
8054 gsi_remove (&si
, true);
8055 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
8057 if (s_exit_bb
== NULL
)
8060 si
= gsi_last_bb (s_exit_bb
);
8061 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8062 gsi_remove (&si
, true);
8064 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
8067 /* Error handling code goes in DEFAULT_BB. */
8068 t
= gimple_block_label (default_bb
);
8069 u
= build_case_label (NULL
, NULL
, t
);
8070 make_edge (l0_bb
, default_bb
, 0);
8071 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
8073 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
8074 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
8075 gsi_remove (&switch_si
, true);
8077 si
= gsi_start_bb (default_bb
);
8078 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
8079 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
8085 /* Code to get the next section goes in L1_BB. */
8086 si
= gsi_last_bb (l1_bb
);
8087 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
8089 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
8090 stmt
= gimple_build_call (bfn_decl
, 0);
8091 gimple_call_set_lhs (stmt
, vnext
);
8092 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8093 gsi_remove (&si
, true);
8095 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
8098 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8099 si
= gsi_last_bb (l2_bb
);
8100 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
8101 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
8102 else if (gimple_omp_return_lhs (gsi_stmt (si
)))
8103 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL
);
8105 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
8106 stmt
= gimple_build_call (t
, 0);
8107 if (gimple_omp_return_lhs (gsi_stmt (si
)))
8108 gimple_call_set_lhs (stmt
, gimple_omp_return_lhs (gsi_stmt (si
)));
8109 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
8110 gsi_remove (&si
, true);
8112 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
8116 /* Expand code for an OpenMP single directive. We've already expanded
8117 much of the code, here we simply place the GOMP_barrier call. */
8120 expand_omp_single (struct omp_region
*region
)
8122 basic_block entry_bb
, exit_bb
;
8123 gimple_stmt_iterator si
;
8125 entry_bb
= region
->entry
;
8126 exit_bb
= region
->exit
;
8128 si
= gsi_last_bb (entry_bb
);
8129 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
8130 gsi_remove (&si
, true);
8131 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8133 si
= gsi_last_bb (exit_bb
);
8134 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
8136 tree t
= gimple_omp_return_lhs (gsi_stmt (si
));
8137 gsi_insert_after (&si
, build_omp_barrier (t
), GSI_SAME_STMT
);
8139 gsi_remove (&si
, true);
8140 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8144 /* Generic expansion for OpenMP synchronization directives: master,
8145 ordered and critical. All we need to do here is remove the entry
8146 and exit markers for REGION. */
8149 expand_omp_synch (struct omp_region
*region
)
8151 basic_block entry_bb
, exit_bb
;
8152 gimple_stmt_iterator si
;
8154 entry_bb
= region
->entry
;
8155 exit_bb
= region
->exit
;
8157 si
= gsi_last_bb (entry_bb
);
8158 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
8159 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
8160 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TASKGROUP
8161 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
8162 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
8163 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_TEAMS
);
8164 gsi_remove (&si
, true);
8165 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8169 si
= gsi_last_bb (exit_bb
);
8170 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
8171 gsi_remove (&si
, true);
8172 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
8176 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8177 operation as a normal volatile load. */
8180 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
8181 tree loaded_val
, int index
)
8183 enum built_in_function tmpbase
;
8184 gimple_stmt_iterator gsi
;
8185 basic_block store_bb
;
8188 tree decl
, call
, type
, itype
;
8190 gsi
= gsi_last_bb (load_bb
);
8191 stmt
= gsi_stmt (gsi
);
8192 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8193 loc
= gimple_location (stmt
);
8195 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8196 is smaller than word size, then expand_atomic_load assumes that the load
8197 is atomic. We could avoid the builtin entirely in this case. */
8199 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8200 decl
= builtin_decl_explicit (tmpbase
);
8201 if (decl
== NULL_TREE
)
8204 type
= TREE_TYPE (loaded_val
);
8205 itype
= TREE_TYPE (TREE_TYPE (decl
));
8207 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
8208 build_int_cst (NULL
,
8209 gimple_omp_atomic_seq_cst_p (stmt
)
8211 : MEMMODEL_RELAXED
));
8212 if (!useless_type_conversion_p (type
, itype
))
8213 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8214 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8216 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8217 gsi_remove (&gsi
, true);
8219 store_bb
= single_succ (load_bb
);
8220 gsi
= gsi_last_bb (store_bb
);
8221 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8222 gsi_remove (&gsi
, true);
8224 if (gimple_in_ssa_p (cfun
))
8225 update_ssa (TODO_update_ssa_no_phi
);
8230 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8231 operation as a normal volatile store. */
8234 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
8235 tree loaded_val
, tree stored_val
, int index
)
8237 enum built_in_function tmpbase
;
8238 gimple_stmt_iterator gsi
;
8239 basic_block store_bb
= single_succ (load_bb
);
8242 tree decl
, call
, type
, itype
;
8246 gsi
= gsi_last_bb (load_bb
);
8247 stmt
= gsi_stmt (gsi
);
8248 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
8250 /* If the load value is needed, then this isn't a store but an exchange. */
8251 exchange
= gimple_omp_atomic_need_value_p (stmt
);
8253 gsi
= gsi_last_bb (store_bb
);
8254 stmt
= gsi_stmt (gsi
);
8255 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
8256 loc
= gimple_location (stmt
);
8258 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8259 is smaller than word size, then expand_atomic_store assumes that the store
8260 is atomic. We could avoid the builtin entirely in this case. */
8262 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
8263 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
8264 decl
= builtin_decl_explicit (tmpbase
);
8265 if (decl
== NULL_TREE
)
8268 type
= TREE_TYPE (stored_val
);
8270 /* Dig out the type of the function's second argument. */
8271 itype
= TREE_TYPE (decl
);
8272 itype
= TYPE_ARG_TYPES (itype
);
8273 itype
= TREE_CHAIN (itype
);
8274 itype
= TREE_VALUE (itype
);
8275 imode
= TYPE_MODE (itype
);
8277 if (exchange
&& !can_atomic_exchange_p (imode
, true))
8280 if (!useless_type_conversion_p (itype
, type
))
8281 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
8282 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
8283 build_int_cst (NULL
,
8284 gimple_omp_atomic_seq_cst_p (stmt
)
8286 : MEMMODEL_RELAXED
));
8289 if (!useless_type_conversion_p (type
, itype
))
8290 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
8291 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
8294 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8295 gsi_remove (&gsi
, true);
8297 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8298 gsi
= gsi_last_bb (load_bb
);
8299 gsi_remove (&gsi
, true);
8301 if (gimple_in_ssa_p (cfun
))
8302 update_ssa (TODO_update_ssa_no_phi
);
8307 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8308 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8309 size of the data type, and thus usable to find the index of the builtin
8310 decl. Returns false if the expression is not of the proper form. */
8313 expand_omp_atomic_fetch_op (basic_block load_bb
,
8314 tree addr
, tree loaded_val
,
8315 tree stored_val
, int index
)
8317 enum built_in_function oldbase
, newbase
, tmpbase
;
8318 tree decl
, itype
, call
;
8320 basic_block store_bb
= single_succ (load_bb
);
8321 gimple_stmt_iterator gsi
;
8324 enum tree_code code
;
8325 bool need_old
, need_new
;
8329 /* We expect to find the following sequences:
8332 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8335 val = tmp OP something; (or: something OP tmp)
8336 GIMPLE_OMP_STORE (val)
8338 ???FIXME: Allow a more flexible sequence.
8339 Perhaps use data flow to pick the statements.
8343 gsi
= gsi_after_labels (store_bb
);
8344 stmt
= gsi_stmt (gsi
);
8345 loc
= gimple_location (stmt
);
8346 if (!is_gimple_assign (stmt
))
8349 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
8351 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
8352 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
8353 seq_cst
= gimple_omp_atomic_seq_cst_p (last_stmt (load_bb
));
8354 gcc_checking_assert (!need_old
|| !need_new
);
8356 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
8359 /* Check for one of the supported fetch-op operations. */
8360 code
= gimple_assign_rhs_code (stmt
);
8364 case POINTER_PLUS_EXPR
:
8365 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
8366 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
8369 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
8370 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
8373 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
8374 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
8377 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
8378 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
8381 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
8382 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
8388 /* Make sure the expression is of the proper form. */
8389 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
8390 rhs
= gimple_assign_rhs2 (stmt
);
8391 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
8392 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
8393 rhs
= gimple_assign_rhs1 (stmt
);
8397 tmpbase
= ((enum built_in_function
)
8398 ((need_new
? newbase
: oldbase
) + index
+ 1));
8399 decl
= builtin_decl_explicit (tmpbase
);
8400 if (decl
== NULL_TREE
)
8402 itype
= TREE_TYPE (TREE_TYPE (decl
));
8403 imode
= TYPE_MODE (itype
);
8405 /* We could test all of the various optabs involved, but the fact of the
8406 matter is that (with the exception of i486 vs i586 and xadd) all targets
8407 that support any atomic operaton optab also implements compare-and-swap.
8408 Let optabs.c take care of expanding any compare-and-swap loop. */
8409 if (!can_compare_and_swap_p (imode
, true))
8412 gsi
= gsi_last_bb (load_bb
);
8413 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8415 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8416 It only requires that the operation happen atomically. Thus we can
8417 use the RELAXED memory model. */
8418 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
8419 fold_convert_loc (loc
, itype
, rhs
),
8420 build_int_cst (NULL
,
8421 seq_cst
? MEMMODEL_SEQ_CST
8422 : MEMMODEL_RELAXED
));
8424 if (need_old
|| need_new
)
8426 lhs
= need_old
? loaded_val
: stored_val
;
8427 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
8428 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
8431 call
= fold_convert_loc (loc
, void_type_node
, call
);
8432 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8433 gsi_remove (&gsi
, true);
8435 gsi
= gsi_last_bb (store_bb
);
8436 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
8437 gsi_remove (&gsi
, true);
8438 gsi
= gsi_last_bb (store_bb
);
8439 gsi_remove (&gsi
, true);
8441 if (gimple_in_ssa_p (cfun
))
8442 update_ssa (TODO_update_ssa_no_phi
);
8447 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8451 newval = rhs; // with oldval replacing *addr in rhs
8452 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8453 if (oldval != newval)
8456 INDEX is log2 of the size of the data type, and thus usable to find the
8457 index of the builtin decl. */
8460 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
8461 tree addr
, tree loaded_val
, tree stored_val
,
8464 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
8465 tree type
, itype
, cmpxchg
, iaddr
;
8466 gimple_stmt_iterator si
;
8467 basic_block loop_header
= single_succ (load_bb
);
8470 enum built_in_function fncode
;
8472 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8473 order to use the RELAXED memory model effectively. */
8474 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8476 cmpxchg
= builtin_decl_explicit (fncode
);
8477 if (cmpxchg
== NULL_TREE
)
8479 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8480 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
8482 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
8485 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8486 si
= gsi_last_bb (load_bb
);
8487 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8489 /* For floating-point values, we'll need to view-convert them to integers
8490 so that we can perform the atomic compare and swap. Simplify the
8491 following code by always setting up the "i"ntegral variables. */
8492 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
8496 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
8499 = force_gimple_operand_gsi (&si
,
8500 fold_convert (TREE_TYPE (iaddr
), addr
),
8501 false, NULL_TREE
, true, GSI_SAME_STMT
);
8502 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
8503 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8504 loadedi
= create_tmp_var (itype
);
8505 if (gimple_in_ssa_p (cfun
))
8506 loadedi
= make_ssa_name (loadedi
);
8511 loadedi
= loaded_val
;
8514 fncode
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
8515 tree loaddecl
= builtin_decl_explicit (fncode
);
8518 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr
)),
8519 build_call_expr (loaddecl
, 2, iaddr
,
8520 build_int_cst (NULL_TREE
,
8521 MEMMODEL_RELAXED
)));
8523 initial
= build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)), iaddr
,
8524 build_int_cst (TREE_TYPE (iaddr
), 0));
8527 = force_gimple_operand_gsi (&si
, initial
, true, NULL_TREE
, true,
8530 /* Move the value to the LOADEDI temporary. */
8531 if (gimple_in_ssa_p (cfun
))
8533 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
8534 phi
= create_phi_node (loadedi
, loop_header
);
8535 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
8539 gsi_insert_before (&si
,
8540 gimple_build_assign (loadedi
, initial
),
8542 if (loadedi
!= loaded_val
)
8544 gimple_stmt_iterator gsi2
;
8547 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
8548 gsi2
= gsi_start_bb (loop_header
);
8549 if (gimple_in_ssa_p (cfun
))
8552 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8553 true, GSI_SAME_STMT
);
8554 stmt
= gimple_build_assign (loaded_val
, x
);
8555 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
8559 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
8560 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
8561 true, GSI_SAME_STMT
);
8564 gsi_remove (&si
, true);
8566 si
= gsi_last_bb (store_bb
);
8567 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8570 storedi
= stored_val
;
8573 force_gimple_operand_gsi (&si
,
8574 build1 (VIEW_CONVERT_EXPR
, itype
,
8575 stored_val
), true, NULL_TREE
, true,
8578 /* Build the compare&swap statement. */
8579 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
8580 new_storedi
= force_gimple_operand_gsi (&si
,
8581 fold_convert (TREE_TYPE (loadedi
),
8584 true, GSI_SAME_STMT
);
8586 if (gimple_in_ssa_p (cfun
))
8590 old_vali
= create_tmp_var (TREE_TYPE (loadedi
));
8591 stmt
= gimple_build_assign (old_vali
, loadedi
);
8592 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8594 stmt
= gimple_build_assign (loadedi
, new_storedi
);
8595 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8598 /* Note that we always perform the comparison as an integer, even for
8599 floating point. This allows the atomic operation to properly
8600 succeed even with NaNs and -0.0. */
8601 stmt
= gimple_build_cond_empty
8602 (build2 (NE_EXPR
, boolean_type_node
,
8603 new_storedi
, old_vali
));
8604 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8607 e
= single_succ_edge (store_bb
);
8608 e
->flags
&= ~EDGE_FALLTHRU
;
8609 e
->flags
|= EDGE_FALSE_VALUE
;
8611 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
8613 /* Copy the new value to loadedi (we already did that before the condition
8614 if we are not in SSA). */
8615 if (gimple_in_ssa_p (cfun
))
8617 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
8618 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
8621 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8622 gsi_remove (&si
, true);
8624 struct loop
*loop
= alloc_loop ();
8625 loop
->header
= loop_header
;
8626 loop
->latch
= store_bb
;
8627 add_loop (loop
, loop_header
->loop_father
);
8629 if (gimple_in_ssa_p (cfun
))
8630 update_ssa (TODO_update_ssa_no_phi
);
8635 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8637 GOMP_atomic_start ();
8641 The result is not globally atomic, but works so long as all parallel
8642 references are within #pragma omp atomic directives. According to
8643 responses received from omp@openmp.org, appears to be within spec.
8644 Which makes sense, since that's how several other compilers handle
8645 this situation as well.
8646 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8647 expanding. STORED_VAL is the operand of the matching
8648 GIMPLE_OMP_ATOMIC_STORE.
8651 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8655 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8660 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
8661 tree addr
, tree loaded_val
, tree stored_val
)
8663 gimple_stmt_iterator si
;
8667 si
= gsi_last_bb (load_bb
);
8668 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
8670 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
8671 t
= build_call_expr (t
, 0);
8672 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8674 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
8675 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8676 gsi_remove (&si
, true);
8678 si
= gsi_last_bb (store_bb
);
8679 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
8681 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
8683 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
8685 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
8686 t
= build_call_expr (t
, 0);
8687 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
8688 gsi_remove (&si
, true);
8690 if (gimple_in_ssa_p (cfun
))
8691 update_ssa (TODO_update_ssa_no_phi
);
8695 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8696 using expand_omp_atomic_fetch_op. If it failed, we try to
8697 call expand_omp_atomic_pipeline, and if it fails too, the
8698 ultimate fallback is wrapping the operation in a mutex
8699 (expand_omp_atomic_mutex). REGION is the atomic region built
8700 by build_omp_regions_1(). */
8703 expand_omp_atomic (struct omp_region
*region
)
8705 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
8706 gomp_atomic_load
*load
= as_a
<gomp_atomic_load
*> (last_stmt (load_bb
));
8707 gomp_atomic_store
*store
= as_a
<gomp_atomic_store
*> (last_stmt (store_bb
));
8708 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
8709 tree addr
= gimple_omp_atomic_load_rhs (load
);
8710 tree stored_val
= gimple_omp_atomic_store_val (store
);
8711 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
8712 HOST_WIDE_INT index
;
8714 /* Make sure the type is one of the supported sizes. */
8715 index
= tree_to_uhwi (TYPE_SIZE_UNIT (type
));
8716 index
= exact_log2 (index
);
8717 if (index
>= 0 && index
<= 4)
8719 unsigned int align
= TYPE_ALIGN_UNIT (type
);
8721 /* __sync builtins require strict data alignment. */
8722 if (exact_log2 (align
) >= index
)
8725 if (loaded_val
== stored_val
8726 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8727 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8728 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8729 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
8733 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
8734 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
8735 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
8736 && store_bb
== single_succ (load_bb
)
8737 && first_stmt (store_bb
) == store
8738 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
8742 /* When possible, use specialized atomic update functions. */
8743 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
8744 && store_bb
== single_succ (load_bb
)
8745 && expand_omp_atomic_fetch_op (load_bb
, addr
,
8746 loaded_val
, stored_val
, index
))
8749 /* If we don't have specialized __sync builtins, try and implement
8750 as a compare and swap loop. */
8751 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
8752 loaded_val
, stored_val
, index
))
8757 /* The ultimate fallback is wrapping the operation in a mutex. */
8758 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
8762 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8765 expand_omp_target (struct omp_region
*region
)
8767 basic_block entry_bb
, exit_bb
, new_bb
;
8768 struct function
*child_cfun
;
8769 tree child_fn
, block
, t
;
8770 gimple_stmt_iterator gsi
;
8771 gomp_target
*entry_stmt
;
8774 bool offloaded
, data_region
;
8776 entry_stmt
= as_a
<gomp_target
*> (last_stmt (region
->entry
));
8777 new_bb
= region
->entry
;
8779 offloaded
= is_gimple_omp_offloaded (entry_stmt
);
8780 switch (gimple_omp_target_kind (entry_stmt
))
8782 case GF_OMP_TARGET_KIND_REGION
:
8783 case GF_OMP_TARGET_KIND_UPDATE
:
8784 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
8785 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
8786 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
8787 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
8788 data_region
= false;
8790 case GF_OMP_TARGET_KIND_DATA
:
8791 case GF_OMP_TARGET_KIND_OACC_DATA
:
8798 child_fn
= NULL_TREE
;
8802 child_fn
= gimple_omp_target_child_fn (entry_stmt
);
8803 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
8806 /* Supported by expand_omp_taskreg, but not here. */
8807 if (child_cfun
!= NULL
)
8808 gcc_checking_assert (!child_cfun
->cfg
);
8809 gcc_checking_assert (!gimple_in_ssa_p (cfun
));
8811 entry_bb
= region
->entry
;
8812 exit_bb
= region
->exit
;
8816 unsigned srcidx
, dstidx
, num
;
8818 /* If the offloading region needs data sent from the parent
8819 function, then the very first statement (except possible
8820 tree profile counter updates) of the offloading body
8821 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8822 &.OMP_DATA_O is passed as an argument to the child function,
8823 we need to replace it with the argument as seen by the child
8826 In most cases, this will end up being the identity assignment
8827 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8828 a function call that has been inlined, the original PARM_DECL
8829 .OMP_DATA_I may have been converted into a different local
8830 variable. In which case, we need to keep the assignment. */
8831 tree data_arg
= gimple_omp_target_data_arg (entry_stmt
);
8834 basic_block entry_succ_bb
= single_succ (entry_bb
);
8835 gimple_stmt_iterator gsi
;
8837 gimple tgtcopy_stmt
= NULL
;
8838 tree sender
= TREE_VEC_ELT (data_arg
, 0);
8840 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
8842 gcc_assert (!gsi_end_p (gsi
));
8843 stmt
= gsi_stmt (gsi
);
8844 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
8847 if (gimple_num_ops (stmt
) == 2)
8849 tree arg
= gimple_assign_rhs1 (stmt
);
8851 /* We're ignoring the subcode because we're
8852 effectively doing a STRIP_NOPS. */
8854 if (TREE_CODE (arg
) == ADDR_EXPR
8855 && TREE_OPERAND (arg
, 0) == sender
)
8857 tgtcopy_stmt
= stmt
;
8863 gcc_assert (tgtcopy_stmt
!= NULL
);
8864 arg
= DECL_ARGUMENTS (child_fn
);
8866 gcc_assert (gimple_assign_lhs (tgtcopy_stmt
) == arg
);
8867 gsi_remove (&gsi
, true);
8870 /* Declare local variables needed in CHILD_CFUN. */
8871 block
= DECL_INITIAL (child_fn
);
8872 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
8873 /* The gimplifier could record temporaries in the offloading block
8874 rather than in containing function's local_decls chain,
8875 which would mean cgraph missed finalizing them. Do it now. */
8876 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
8877 if (TREE_CODE (t
) == VAR_DECL
8879 && !DECL_EXTERNAL (t
))
8880 varpool_node::finalize_decl (t
);
8881 DECL_SAVED_TREE (child_fn
) = NULL
;
8882 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8883 gimple_set_body (child_fn
, NULL
);
8884 TREE_USED (block
) = 1;
8886 /* Reset DECL_CONTEXT on function arguments. */
8887 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
8888 DECL_CONTEXT (t
) = child_fn
;
8890 /* Split ENTRY_BB at GIMPLE_*,
8891 so that it can be moved to the child function. */
8892 gsi
= gsi_last_bb (entry_bb
);
8893 stmt
= gsi_stmt (gsi
);
8895 && gimple_code (stmt
) == gimple_code (entry_stmt
));
8896 e
= split_block (entry_bb
, stmt
);
8897 gsi_remove (&gsi
, true);
8899 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
8901 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8904 gsi
= gsi_last_bb (exit_bb
);
8905 gcc_assert (!gsi_end_p (gsi
)
8906 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
8907 stmt
= gimple_build_return (NULL
);
8908 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
8909 gsi_remove (&gsi
, true);
8912 /* Move the offloading region into CHILD_CFUN. */
8914 block
= gimple_block (entry_stmt
);
8916 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
8918 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
8919 /* When the OMP expansion process cannot guarantee an up-to-date
8920 loop tree arrange for the child function to fixup loops. */
8921 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
8922 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
8924 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8925 num
= vec_safe_length (child_cfun
->local_decls
);
8926 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
8928 t
= (*child_cfun
->local_decls
)[srcidx
];
8929 if (DECL_CONTEXT (t
) == cfun
->decl
)
8931 if (srcidx
!= dstidx
)
8932 (*child_cfun
->local_decls
)[dstidx
] = t
;
8936 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
8938 /* Inform the callgraph about the new function. */
8939 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
8940 cgraph_node::add_new_function (child_fn
, true);
8942 #ifdef ENABLE_OFFLOADING
8943 /* Add the new function to the offload table. */
8944 vec_safe_push (offload_funcs
, child_fn
);
8947 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8948 fixed in a following pass. */
8949 push_cfun (child_cfun
);
8950 cgraph_edge::rebuild_edges ();
8952 #ifdef ENABLE_OFFLOADING
8953 /* Prevent IPA from removing child_fn as unreachable, since there are no
8954 refs from the parent function to child_fn in offload LTO mode. */
8955 struct cgraph_node
*node
= cgraph_node::get (child_fn
);
8956 node
->mark_force_output ();
8959 /* Some EH regions might become dead, see PR34608. If
8960 pass_cleanup_cfg isn't the first pass to happen with the
8961 new child, these dead EH edges might cause problems.
8962 Clean them up now. */
8963 if (flag_exceptions
)
8966 bool changed
= false;
8968 FOR_EACH_BB_FN (bb
, cfun
)
8969 changed
|= gimple_purge_dead_eh_edges (bb
);
8971 cleanup_tree_cfg ();
8976 /* Emit a library call to launch the offloading region, or do data
8978 tree t1
, t2
, t3
, t4
, device
, cond
, c
, clauses
;
8979 enum built_in_function start_ix
;
8980 location_t clause_loc
;
8982 switch (gimple_omp_target_kind (entry_stmt
))
8984 case GF_OMP_TARGET_KIND_REGION
:
8985 start_ix
= BUILT_IN_GOMP_TARGET
;
8987 case GF_OMP_TARGET_KIND_DATA
:
8988 start_ix
= BUILT_IN_GOMP_TARGET_DATA
;
8990 case GF_OMP_TARGET_KIND_UPDATE
:
8991 start_ix
= BUILT_IN_GOMP_TARGET_UPDATE
;
8993 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
8994 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
8995 start_ix
= BUILT_IN_GOACC_PARALLEL
;
8997 case GF_OMP_TARGET_KIND_OACC_DATA
:
8998 start_ix
= BUILT_IN_GOACC_DATA_START
;
9000 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9001 start_ix
= BUILT_IN_GOACC_UPDATE
;
9003 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9004 start_ix
= BUILT_IN_GOACC_ENTER_EXIT_DATA
;
9010 clauses
= gimple_omp_target_clauses (entry_stmt
);
9012 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9013 library choose) and there is no conditional. */
9015 device
= build_int_cst (integer_type_node
, GOMP_DEVICE_ICV
);
9017 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
9019 cond
= OMP_CLAUSE_IF_EXPR (c
);
9021 c
= find_omp_clause (clauses
, OMP_CLAUSE_DEVICE
);
9024 /* Even if we pass it to all library function calls, it is currently only
9025 defined/used for the OpenMP target ones. */
9026 gcc_checking_assert (start_ix
== BUILT_IN_GOMP_TARGET
9027 || start_ix
== BUILT_IN_GOMP_TARGET_DATA
9028 || start_ix
== BUILT_IN_GOMP_TARGET_UPDATE
);
9030 device
= OMP_CLAUSE_DEVICE_ID (c
);
9031 clause_loc
= OMP_CLAUSE_LOCATION (c
);
9034 clause_loc
= gimple_location (entry_stmt
);
9036 /* Ensure 'device' is of the correct type. */
9037 device
= fold_convert_loc (clause_loc
, integer_type_node
, device
);
9039 /* If we found the clause 'if (cond)', build
9040 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9043 cond
= gimple_boolify (cond
);
9045 basic_block cond_bb
, then_bb
, else_bb
;
9049 tmp_var
= create_tmp_var (TREE_TYPE (device
));
9051 e
= split_block (new_bb
, NULL
);
9054 gsi
= gsi_last_bb (new_bb
);
9056 e
= split_block (new_bb
, gsi_stmt (gsi
));
9062 then_bb
= create_empty_bb (cond_bb
);
9063 else_bb
= create_empty_bb (then_bb
);
9064 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
9065 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
9067 stmt
= gimple_build_cond_empty (cond
);
9068 gsi
= gsi_last_bb (cond_bb
);
9069 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9071 gsi
= gsi_start_bb (then_bb
);
9072 stmt
= gimple_build_assign (tmp_var
, device
);
9073 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9075 gsi
= gsi_start_bb (else_bb
);
9076 stmt
= gimple_build_assign (tmp_var
,
9077 build_int_cst (integer_type_node
,
9078 GOMP_DEVICE_HOST_FALLBACK
));
9079 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
9081 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
9082 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
9083 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
9084 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
9085 make_edge (then_bb
, new_bb
, EDGE_FALLTHRU
);
9086 make_edge (else_bb
, new_bb
, EDGE_FALLTHRU
);
9091 gsi
= gsi_last_bb (new_bb
);
9092 t
= gimple_omp_target_data_arg (entry_stmt
);
9095 t1
= size_zero_node
;
9096 t2
= build_zero_cst (ptr_type_node
);
9102 t1
= TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t
, 1))));
9103 t1
= size_binop (PLUS_EXPR
, t1
, size_int (1));
9104 t2
= build_fold_addr_expr (TREE_VEC_ELT (t
, 0));
9105 t3
= build_fold_addr_expr (TREE_VEC_ELT (t
, 1));
9106 t4
= build_fold_addr_expr (TREE_VEC_ELT (t
, 2));
9110 /* The maximum number used by any start_ix, without varargs. */
9111 auto_vec
<tree
, 11> args
;
9112 args
.quick_push (device
);
9114 args
.quick_push (build_fold_addr_expr (child_fn
));
9117 case BUILT_IN_GOMP_TARGET
:
9118 case BUILT_IN_GOMP_TARGET_DATA
:
9119 case BUILT_IN_GOMP_TARGET_UPDATE
:
9120 /* This const void * is part of the current ABI, but we're not actually
9122 args
.quick_push (build_zero_cst (ptr_type_node
));
9124 case BUILT_IN_GOACC_DATA_START
:
9125 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9126 case BUILT_IN_GOACC_PARALLEL
:
9127 case BUILT_IN_GOACC_UPDATE
:
9132 args
.quick_push (t1
);
9133 args
.quick_push (t2
);
9134 args
.quick_push (t3
);
9135 args
.quick_push (t4
);
9138 case BUILT_IN_GOACC_DATA_START
:
9139 case BUILT_IN_GOMP_TARGET
:
9140 case BUILT_IN_GOMP_TARGET_DATA
:
9141 case BUILT_IN_GOMP_TARGET_UPDATE
:
9143 case BUILT_IN_GOACC_PARALLEL
:
9145 tree t_num_gangs
, t_num_workers
, t_vector_length
;
9147 /* Default values for num_gangs, num_workers, and vector_length. */
9148 t_num_gangs
= t_num_workers
= t_vector_length
9149 = fold_convert_loc (gimple_location (entry_stmt
),
9150 integer_type_node
, integer_one_node
);
9151 /* ..., but if present, use the value specified by the respective
9152 clause, making sure that are of the correct type. */
9153 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_GANGS
);
9155 t_num_gangs
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9157 OMP_CLAUSE_NUM_GANGS_EXPR (c
));
9158 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_WORKERS
);
9160 t_num_workers
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9162 OMP_CLAUSE_NUM_WORKERS_EXPR (c
));
9163 c
= find_omp_clause (clauses
, OMP_CLAUSE_VECTOR_LENGTH
);
9165 t_vector_length
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9167 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c
));
9168 args
.quick_push (t_num_gangs
);
9169 args
.quick_push (t_num_workers
);
9170 args
.quick_push (t_vector_length
);
9173 case BUILT_IN_GOACC_ENTER_EXIT_DATA
:
9174 case BUILT_IN_GOACC_UPDATE
:
9179 /* Default values for t_async. */
9180 t_async
= fold_convert_loc (gimple_location (entry_stmt
),
9182 build_int_cst (integer_type_node
,
9184 /* ..., but if present, use the value specified by the respective
9185 clause, making sure that is of the correct type. */
9186 c
= find_omp_clause (clauses
, OMP_CLAUSE_ASYNC
);
9188 t_async
= fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9190 OMP_CLAUSE_ASYNC_EXPR (c
));
9192 args
.quick_push (t_async
);
9193 /* Save the index, and... */
9194 t_wait_idx
= args
.length ();
9195 /* ... push a default value. */
9196 args
.quick_push (fold_convert_loc (gimple_location (entry_stmt
),
9198 integer_zero_node
));
9199 c
= find_omp_clause (clauses
, OMP_CLAUSE_WAIT
);
9204 for (; c
; c
= OMP_CLAUSE_CHAIN (c
))
9206 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_WAIT
)
9208 args
.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c
),
9210 OMP_CLAUSE_WAIT_EXPR (c
)));
9215 /* Now that we know the number, replace the default value. */
9216 args
.ordered_remove (t_wait_idx
);
9217 args
.quick_insert (t_wait_idx
,
9218 fold_convert_loc (gimple_location (entry_stmt
),
9220 build_int_cst (integer_type_node
, n
)));
9228 g
= gimple_build_call_vec (builtin_decl_explicit (start_ix
), args
);
9229 gimple_set_location (g
, gimple_location (entry_stmt
));
9230 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
9234 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_TARGET
);
9235 gsi_remove (&gsi
, true);
9240 gsi
= gsi_last_bb (region
->exit
);
9242 gcc_assert (g
&& gimple_code (g
) == GIMPLE_OMP_RETURN
);
9243 gsi_remove (&gsi
, true);
9248 /* Expand the parallel region tree rooted at REGION. Expansion
9249 proceeds in depth-first order. Innermost regions are expanded
9250 first. This way, parallel regions that require a new function to
9251 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9252 internal dependencies in their body. */
9255 expand_omp (struct omp_region
*region
)
9259 location_t saved_location
;
9260 gimple inner_stmt
= NULL
;
9262 /* First, determine whether this is a combined parallel+workshare
9264 if (region
->type
== GIMPLE_OMP_PARALLEL
)
9265 determine_parallel_type (region
);
9267 if (region
->type
== GIMPLE_OMP_FOR
9268 && gimple_omp_for_combined_p (last_stmt (region
->entry
)))
9269 inner_stmt
= last_stmt (region
->inner
->entry
);
9272 expand_omp (region
->inner
);
9274 saved_location
= input_location
;
9275 if (gimple_has_location (last_stmt (region
->entry
)))
9276 input_location
= gimple_location (last_stmt (region
->entry
));
9278 switch (region
->type
)
9280 case GIMPLE_OMP_PARALLEL
:
9281 case GIMPLE_OMP_TASK
:
9282 expand_omp_taskreg (region
);
9285 case GIMPLE_OMP_FOR
:
9286 expand_omp_for (region
, inner_stmt
);
9289 case GIMPLE_OMP_SECTIONS
:
9290 expand_omp_sections (region
);
9293 case GIMPLE_OMP_SECTION
:
9294 /* Individual omp sections are handled together with their
9295 parent GIMPLE_OMP_SECTIONS region. */
9298 case GIMPLE_OMP_SINGLE
:
9299 expand_omp_single (region
);
9302 case GIMPLE_OMP_MASTER
:
9303 case GIMPLE_OMP_TASKGROUP
:
9304 case GIMPLE_OMP_ORDERED
:
9305 case GIMPLE_OMP_CRITICAL
:
9306 case GIMPLE_OMP_TEAMS
:
9307 expand_omp_synch (region
);
9310 case GIMPLE_OMP_ATOMIC_LOAD
:
9311 expand_omp_atomic (region
);
9314 case GIMPLE_OMP_TARGET
:
9315 expand_omp_target (region
);
9322 input_location
= saved_location
;
9323 region
= region
->next
;
9328 /* Helper for build_omp_regions. Scan the dominator tree starting at
9329 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9330 true, the function ends once a single tree is built (otherwise, whole
9331 forest of OMP constructs may be built). */
9334 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
9337 gimple_stmt_iterator gsi
;
9341 gsi
= gsi_last_bb (bb
);
9342 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
9344 struct omp_region
*region
;
9345 enum gimple_code code
;
9347 stmt
= gsi_stmt (gsi
);
9348 code
= gimple_code (stmt
);
9349 if (code
== GIMPLE_OMP_RETURN
)
9351 /* STMT is the return point out of region PARENT. Mark it
9352 as the exit point and make PARENT the immediately
9353 enclosing region. */
9354 gcc_assert (parent
);
9357 parent
= parent
->outer
;
9359 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
9361 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9362 GIMPLE_OMP_RETURN, but matches with
9363 GIMPLE_OMP_ATOMIC_LOAD. */
9364 gcc_assert (parent
);
9365 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
9368 parent
= parent
->outer
;
9370 else if (code
== GIMPLE_OMP_CONTINUE
)
9372 gcc_assert (parent
);
9375 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
9377 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9378 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9382 region
= new_omp_region (bb
, code
, parent
);
9384 if (code
== GIMPLE_OMP_TARGET
)
9386 switch (gimple_omp_target_kind (stmt
))
9388 case GF_OMP_TARGET_KIND_REGION
:
9389 case GF_OMP_TARGET_KIND_DATA
:
9390 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
9391 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
9392 case GF_OMP_TARGET_KIND_OACC_DATA
:
9394 case GF_OMP_TARGET_KIND_UPDATE
:
9395 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
9396 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
9397 /* ..., other than for those stand-alone directives... */
9404 /* ..., this directive becomes the parent for a new region. */
9410 if (single_tree
&& !parent
)
9413 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
9415 son
= next_dom_son (CDI_DOMINATORS
, son
))
9416 build_omp_regions_1 (son
, parent
, single_tree
);
9419 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9423 build_omp_regions_root (basic_block root
)
9425 gcc_assert (root_omp_region
== NULL
);
9426 build_omp_regions_1 (root
, NULL
, true);
9427 gcc_assert (root_omp_region
!= NULL
);
9430 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9433 omp_expand_local (basic_block head
)
9435 build_omp_regions_root (head
);
9436 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
9438 fprintf (dump_file
, "\nOMP region tree\n\n");
9439 dump_omp_region (dump_file
, root_omp_region
, 0);
9440 fprintf (dump_file
, "\n");
9443 remove_exit_barriers (root_omp_region
);
9444 expand_omp (root_omp_region
);
9446 free_omp_regions ();
9449 /* Scan the CFG and build a tree of OMP regions. Return the root of
9450 the OMP region tree. */
9453 build_omp_regions (void)
9455 gcc_assert (root_omp_region
== NULL
);
9456 calculate_dominance_info (CDI_DOMINATORS
);
9457 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun
), NULL
, false);
9460 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9463 execute_expand_omp (void)
9465 build_omp_regions ();
9467 if (!root_omp_region
)
9472 fprintf (dump_file
, "\nOMP region tree\n\n");
9473 dump_omp_region (dump_file
, root_omp_region
, 0);
9474 fprintf (dump_file
, "\n");
9477 remove_exit_barriers (root_omp_region
);
9479 expand_omp (root_omp_region
);
9481 cleanup_tree_cfg ();
9483 free_omp_regions ();
9488 /* OMP expansion -- the default pass, run before creation of SSA form. */
9492 const pass_data pass_data_expand_omp
=
9494 GIMPLE_PASS
, /* type */
9495 "ompexp", /* name */
9496 OPTGROUP_NONE
, /* optinfo_flags */
9497 TV_NONE
, /* tv_id */
9498 PROP_gimple_any
, /* properties_required */
9499 PROP_gimple_eomp
, /* properties_provided */
9500 0, /* properties_destroyed */
9501 0, /* todo_flags_start */
9502 0, /* todo_flags_finish */
9505 class pass_expand_omp
: public gimple_opt_pass
9508 pass_expand_omp (gcc::context
*ctxt
)
9509 : gimple_opt_pass (pass_data_expand_omp
, ctxt
)
9512 /* opt_pass methods: */
9513 virtual unsigned int execute (function
*)
9515 bool gate
= ((flag_cilkplus
!= 0 || flag_openacc
!= 0 || flag_openmp
!= 0
9516 || flag_openmp_simd
!= 0)
9519 /* This pass always runs, to provide PROP_gimple_eomp.
9520 But often, there is nothing to do. */
9524 return execute_expand_omp ();
9527 }; // class pass_expand_omp
9532 make_pass_expand_omp (gcc::context
*ctxt
)
9534 return new pass_expand_omp (ctxt
);
9539 const pass_data pass_data_expand_omp_ssa
=
9541 GIMPLE_PASS
, /* type */
9542 "ompexpssa", /* name */
9543 OPTGROUP_NONE
, /* optinfo_flags */
9544 TV_NONE
, /* tv_id */
9545 PROP_cfg
| PROP_ssa
, /* properties_required */
9546 PROP_gimple_eomp
, /* properties_provided */
9547 0, /* properties_destroyed */
9548 0, /* todo_flags_start */
9549 TODO_cleanup_cfg
| TODO_rebuild_alias
, /* todo_flags_finish */
9552 class pass_expand_omp_ssa
: public gimple_opt_pass
9555 pass_expand_omp_ssa (gcc::context
*ctxt
)
9556 : gimple_opt_pass (pass_data_expand_omp_ssa
, ctxt
)
9559 /* opt_pass methods: */
9560 virtual bool gate (function
*fun
)
9562 return !(fun
->curr_properties
& PROP_gimple_eomp
);
9564 virtual unsigned int execute (function
*) { return execute_expand_omp (); }
9566 }; // class pass_expand_omp_ssa
9571 make_pass_expand_omp_ssa (gcc::context
*ctxt
)
9573 return new pass_expand_omp_ssa (ctxt
);
9576 /* Routines to lower OMP directives into OMP-GIMPLE. */
9578 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9579 convert it to gimple. */
9581 oacc_gimple_assign (tree dest
, tree_code op
, tree src
, gimple_seq
*seq
)
9585 if (TREE_CODE (TREE_TYPE (dest
)) != COMPLEX_TYPE
)
9587 stmt
= gimple_build_assign (dest
, op
, dest
, src
);
9588 gimple_seq_add_stmt (seq
, stmt
);
9592 tree t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9593 tree rdest
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9594 gimplify_assign (t
, rdest
, seq
);
9597 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9598 tree idest
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (dest
)), dest
);
9599 gimplify_assign (t
, idest
, seq
);
9602 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9603 tree rsrc
= fold_build1 (REALPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9604 gimplify_assign (t
, rsrc
, seq
);
9607 t
= create_tmp_var (TREE_TYPE (TREE_TYPE (src
)));
9608 tree isrc
= fold_build1 (IMAGPART_EXPR
, TREE_TYPE (TREE_TYPE (src
)), src
);
9609 gimplify_assign (t
, isrc
, seq
);
9612 tree r
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9613 tree i
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9616 if (op
== PLUS_EXPR
)
9618 stmt
= gimple_build_assign (r
, op
, rdest
, rsrc
);
9619 gimple_seq_add_stmt (seq
, stmt
);
9621 stmt
= gimple_build_assign (i
, op
, idest
, isrc
);
9622 gimple_seq_add_stmt (seq
, stmt
);
9624 else if (op
== MULT_EXPR
)
9626 /* Let x = a + ib = dest, y = c + id = src.
9627 x * y = (ac - bd) + i(ad + bc) */
9628 tree ac
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9629 tree bd
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9630 tree ad
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9631 tree bc
= create_tmp_var (TREE_TYPE (TREE_TYPE (dest
)));
9633 stmt
= gimple_build_assign (ac
, MULT_EXPR
, rdest
, rsrc
);
9634 gimple_seq_add_stmt (seq
, stmt
);
9636 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, isrc
);
9637 gimple_seq_add_stmt (seq
, stmt
);
9639 stmt
= gimple_build_assign (r
, MINUS_EXPR
, ac
, bd
);
9640 gimple_seq_add_stmt (seq
, stmt
);
9642 stmt
= gimple_build_assign (ad
, MULT_EXPR
, rdest
, isrc
);
9643 gimple_seq_add_stmt (seq
, stmt
);
9645 stmt
= gimple_build_assign (bd
, MULT_EXPR
, idest
, rsrc
);
9646 gimple_seq_add_stmt (seq
, stmt
);
9648 stmt
= gimple_build_assign (i
, PLUS_EXPR
, ad
, bc
);
9649 gimple_seq_add_stmt (seq
, stmt
);
9654 result
= build2 (COMPLEX_EXPR
, TREE_TYPE (dest
), r
, i
);
9655 gimplify_assign (dest
, result
, seq
);
9658 /* Helper function to initialize local data for the reduction arrays.
9659 The reduction arrays need to be placed inside the calling function
9660 for accelerators, or else the host won't be able to preform the final
9664 oacc_initialize_reduction_data (tree clauses
, tree nthreads
,
9665 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9671 /* Find the innermost OpenACC parallel context. */
9672 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_TARGET
9673 && (gimple_omp_target_kind (ctx
->stmt
)
9674 == GF_OMP_TARGET_KIND_OACC_PARALLEL
))
9678 gcc_checking_assert (gimple_code (octx
->stmt
) == GIMPLE_OMP_TARGET
9679 && (gimple_omp_target_kind (octx
->stmt
)
9680 == GF_OMP_TARGET_KIND_OACC_PARALLEL
));
9682 /* Extract the clauses. */
9683 oc
= gimple_omp_target_clauses (octx
->stmt
);
9685 /* Find the last outer clause. */
9686 for (; oc
&& OMP_CLAUSE_CHAIN (oc
); oc
= OMP_CLAUSE_CHAIN (oc
))
9689 /* Allocate arrays for each reduction variable. */
9690 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9692 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9695 tree var
= OMP_CLAUSE_DECL (c
);
9696 tree type
= get_base_type (var
);
9697 tree array
= lookup_oacc_reduction (oacc_get_reduction_array_id (var
),
9701 /* Calculate size of the reduction array. */
9702 t
= create_tmp_var (TREE_TYPE (nthreads
));
9703 stmt
= gimple_build_assign (t
, MULT_EXPR
, nthreads
,
9704 fold_convert (TREE_TYPE (nthreads
),
9705 TYPE_SIZE_UNIT (type
)));
9706 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9708 size
= create_tmp_var (sizetype
);
9709 gimplify_assign (size
, fold_build1 (NOP_EXPR
, sizetype
, t
), stmt_seqp
);
9711 /* Now allocate memory for it. */
9712 call
= unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA
));
9713 stmt
= gimple_build_call (call
, 1, size
);
9714 gimple_call_set_lhs (stmt
, array
);
9715 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9717 /* Map this array into the accelerator. */
9719 /* Add the reduction array to the list of clauses. */
9721 t
= build_omp_clause (gimple_location (ctx
->stmt
), OMP_CLAUSE_MAP
);
9722 OMP_CLAUSE_SET_MAP_KIND (t
, GOMP_MAP_FORCE_FROM
);
9723 OMP_CLAUSE_DECL (t
) = x
;
9724 OMP_CLAUSE_CHAIN (t
) = NULL
;
9726 OMP_CLAUSE_CHAIN (oc
) = t
;
9728 gimple_omp_target_set_clauses (as_a
<gomp_target
*> (octx
->stmt
), t
);
9729 OMP_CLAUSE_SIZE (t
) = size
;
9734 /* Helper function to process the array of partial reductions. Nthreads
9735 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9736 cannot be used here, because nthreads on the host may be different than
9737 on the accelerator. */
9740 oacc_finalize_reduction_data (tree clauses
, tree nthreads
,
9741 gimple_seq
*stmt_seqp
, omp_context
*ctx
)
9743 tree c
, x
, var
, array
, loop_header
, loop_body
, loop_exit
, type
;
9748 let var = the original reduction variable
9749 let array = reduction variable array
9751 for (i = 0; i < nthreads; i++)
9755 loop_header
= create_artificial_label (UNKNOWN_LOCATION
);
9756 loop_body
= create_artificial_label (UNKNOWN_LOCATION
);
9757 loop_exit
= create_artificial_label (UNKNOWN_LOCATION
);
9759 /* Create and initialize an index variable. */
9760 tree ix
= create_tmp_var (sizetype
);
9761 gimplify_assign (ix
, fold_build1 (NOP_EXPR
, sizetype
, integer_zero_node
),
9764 /* Insert the loop header label here. */
9765 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_header
));
9767 /* Exit loop if ix >= nthreads. */
9768 x
= create_tmp_var (sizetype
);
9769 gimplify_assign (x
, fold_build1 (NOP_EXPR
, sizetype
, nthreads
), stmt_seqp
);
9770 stmt
= gimple_build_cond (GE_EXPR
, ix
, x
, loop_exit
, loop_body
);
9771 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9773 /* Insert the loop body label here. */
9774 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_body
));
9776 /* Collapse each reduction array, one element at a time. */
9777 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9779 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
9782 tree_code reduction_code
= OMP_CLAUSE_REDUCTION_CODE (c
);
9784 /* reduction(-:var) sums up the partial results, so it acts
9785 identically to reduction(+:var). */
9786 if (reduction_code
== MINUS_EXPR
)
9787 reduction_code
= PLUS_EXPR
;
9789 /* Set up reduction variable var. */
9790 var
= OMP_CLAUSE_DECL (c
);
9791 type
= get_base_type (var
);
9792 array
= lookup_oacc_reduction (oacc_get_reduction_array_id
9793 (OMP_CLAUSE_DECL (c
)), ctx
);
9795 /* Calculate the array offset. */
9796 tree offset
= create_tmp_var (sizetype
);
9797 gimplify_assign (offset
, TYPE_SIZE_UNIT (type
), stmt_seqp
);
9798 stmt
= gimple_build_assign (offset
, MULT_EXPR
, offset
, ix
);
9799 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9801 tree ptr
= create_tmp_var (TREE_TYPE (array
));
9802 stmt
= gimple_build_assign (ptr
, POINTER_PLUS_EXPR
, array
, offset
);
9803 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9805 /* Extract array[ix] into mem. */
9806 tree mem
= create_tmp_var (type
);
9807 gimplify_assign (mem
, build_simple_mem_ref (ptr
), stmt_seqp
);
9809 /* Find the original reduction variable. */
9810 if (is_reference (var
))
9811 var
= build_simple_mem_ref (var
);
9813 tree t
= create_tmp_var (type
);
9815 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, t
, var
);
9816 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9818 /* var = var op mem */
9819 switch (OMP_CLAUSE_REDUCTION_CODE (c
))
9821 case TRUTH_ANDIF_EXPR
:
9822 case TRUTH_ORIF_EXPR
:
9823 t
= fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c
), integer_type_node
,
9825 gimplify_and_add (t
, stmt_seqp
);
9828 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9829 oacc_gimple_assign (t
, OMP_CLAUSE_REDUCTION_CODE (c
), mem
,
9833 t
= fold_build1 (NOP_EXPR
, TREE_TYPE (var
), t
);
9834 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, var
, t
);
9835 gimplify_and_add (unshare_expr(x
), stmt_seqp
);
9838 /* Increment the induction variable. */
9839 tree one
= fold_build1 (NOP_EXPR
, sizetype
, integer_one_node
);
9840 stmt
= gimple_build_assign (ix
, PLUS_EXPR
, ix
, one
);
9841 gimple_seq_add_stmt (stmt_seqp
, stmt
);
9843 /* Go back to the top of the loop. */
9844 gimple_seq_add_stmt (stmt_seqp
, gimple_build_goto (loop_header
));
9846 /* Place the loop exit label here. */
9847 gimple_seq_add_stmt (stmt_seqp
, gimple_build_label (loop_exit
));
9850 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9851 scan that for reductions. */
9854 oacc_process_reduction_data (gimple_seq
*body
, gimple_seq
*in_stmt_seqp
,
9855 gimple_seq
*out_stmt_seqp
, omp_context
*ctx
)
9857 gimple_stmt_iterator gsi
;
9858 gimple_seq inner
= NULL
;
9860 /* A collapse clause may have inserted a new bind block. */
9861 gsi
= gsi_start (*body
);
9862 while (!gsi_end_p (gsi
))
9864 gimple stmt
= gsi_stmt (gsi
);
9865 if (gbind
*bind_stmt
= dyn_cast
<gbind
*> (stmt
))
9867 inner
= gimple_bind_body (bind_stmt
);
9869 gsi
= gsi_start (*body
);
9871 else if (dyn_cast
<gomp_for
*> (stmt
))
9877 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
9879 tree clauses
, nthreads
, t
, c
, acc_device
, acc_device_host
, call
,
9881 bool reduction_found
= false;
9883 gimple stmt
= gsi_stmt (gsi
);
9885 switch (gimple_code (stmt
))
9887 case GIMPLE_OMP_FOR
:
9888 clauses
= gimple_omp_for_clauses (stmt
);
9890 /* Search for a reduction clause. */
9891 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
9892 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
9894 reduction_found
= true;
9898 if (!reduction_found
)
9901 ctx
= maybe_lookup_ctx (stmt
);
9904 /* Extract the number of threads. */
9905 nthreads
= create_tmp_var (sizetype
);
9906 t
= oacc_max_threads (ctx
);
9907 gimplify_assign (nthreads
, t
, in_stmt_seqp
);
9909 /* Determine if this is kernel will be executed on the host. */
9910 call
= builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE
);
9911 acc_device
= create_tmp_var (integer_type_node
, ".acc_device_type");
9912 stmt
= gimple_build_call (call
, 0);
9913 gimple_call_set_lhs (stmt
, acc_device
);
9914 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9916 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9917 acc_device_host
= create_tmp_var (integer_type_node
,
9918 ".acc_device_host");
9919 gimplify_assign (acc_device_host
,
9920 build_int_cst (integer_type_node
,
9924 enter
= create_artificial_label (UNKNOWN_LOCATION
);
9925 exit
= create_artificial_label (UNKNOWN_LOCATION
);
9927 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
9929 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9930 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
9931 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
9934 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
9936 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9937 gimplify_assign (acc_device_host
,
9938 build_int_cst (integer_type_node
,
9939 GOMP_DEVICE_HOST_NONSHM
),
9942 enter
= create_artificial_label (UNKNOWN_LOCATION
);
9943 exit
= create_artificial_label (UNKNOWN_LOCATION
);
9945 stmt
= gimple_build_cond (EQ_EXPR
, acc_device
, acc_device_host
,
9947 gimple_seq_add_stmt (in_stmt_seqp
, stmt
);
9948 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (enter
));
9949 gimplify_assign (nthreads
, fold_build1 (NOP_EXPR
, sizetype
,
9952 gimple_seq_add_stmt (in_stmt_seqp
, gimple_build_label (exit
));
9954 oacc_initialize_reduction_data (clauses
, nthreads
, in_stmt_seqp
,
9956 oacc_finalize_reduction_data (clauses
, nthreads
, out_stmt_seqp
, ctx
);
9959 // Scan for other directives which support reduction here.
9965 /* If ctx is a worksharing context inside of a cancellable parallel
9966 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9967 and conditional branch to parallel's cancel_label to handle
9968 cancellation in the implicit barrier. */
9971 maybe_add_implicit_barrier_cancel (omp_context
*ctx
, gimple_seq
*body
)
9973 gimple omp_return
= gimple_seq_last_stmt (*body
);
9974 gcc_assert (gimple_code (omp_return
) == GIMPLE_OMP_RETURN
);
9975 if (gimple_omp_return_nowait_p (omp_return
))
9978 && gimple_code (ctx
->outer
->stmt
) == GIMPLE_OMP_PARALLEL
9979 && ctx
->outer
->cancellable
)
9981 tree fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_CANCEL
);
9982 tree c_bool_type
= TREE_TYPE (TREE_TYPE (fndecl
));
9983 tree lhs
= create_tmp_var (c_bool_type
);
9984 gimple_omp_return_set_lhs (omp_return
, lhs
);
9985 tree fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
9986 gimple g
= gimple_build_cond (NE_EXPR
, lhs
,
9987 fold_convert (c_bool_type
,
9988 boolean_false_node
),
9989 ctx
->outer
->cancel_label
, fallthru_label
);
9990 gimple_seq_add_stmt (body
, g
);
9991 gimple_seq_add_stmt (body
, gimple_build_label (fallthru_label
));
9995 /* Lower the OpenMP sections directive in the current statement in GSI_P.
9996 CTX is the enclosing OMP context for the current statement. */
9999 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10001 tree block
, control
;
10002 gimple_stmt_iterator tgsi
;
10003 gomp_sections
*stmt
;
10005 gbind
*new_stmt
, *bind
;
10006 gimple_seq ilist
, dlist
, olist
, new_body
;
10008 stmt
= as_a
<gomp_sections
*> (gsi_stmt (*gsi_p
));
10010 push_gimplify_context ();
10014 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
10015 &ilist
, &dlist
, ctx
, NULL
);
10017 new_body
= gimple_omp_body (stmt
);
10018 gimple_omp_set_body (stmt
, NULL
);
10019 tgsi
= gsi_start (new_body
);
10020 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
10025 sec_start
= gsi_stmt (tgsi
);
10026 sctx
= maybe_lookup_ctx (sec_start
);
10029 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
10030 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
10031 GSI_CONTINUE_LINKING
);
10032 gimple_omp_set_body (sec_start
, NULL
);
10034 if (gsi_one_before_end_p (tgsi
))
10036 gimple_seq l
= NULL
;
10037 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
10039 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
10040 gimple_omp_section_set_last (sec_start
);
10043 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
10044 GSI_CONTINUE_LINKING
);
10047 block
= make_node (BLOCK
);
10048 bind
= gimple_build_bind (NULL
, new_body
, block
);
10051 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
10053 block
= make_node (BLOCK
);
10054 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10055 gsi_replace (gsi_p
, new_stmt
, true);
10057 pop_gimplify_context (new_stmt
);
10058 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10059 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10060 if (BLOCK_VARS (block
))
10061 TREE_USED (block
) = 1;
10064 gimple_seq_add_seq (&new_body
, ilist
);
10065 gimple_seq_add_stmt (&new_body
, stmt
);
10066 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
10067 gimple_seq_add_stmt (&new_body
, bind
);
10069 control
= create_tmp_var (unsigned_type_node
, ".section");
10070 t
= gimple_build_omp_continue (control
, control
);
10071 gimple_omp_sections_set_control (stmt
, control
);
10072 gimple_seq_add_stmt (&new_body
, t
);
10074 gimple_seq_add_seq (&new_body
, olist
);
10075 if (ctx
->cancellable
)
10076 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
10077 gimple_seq_add_seq (&new_body
, dlist
);
10079 new_body
= maybe_catch_exception (new_body
);
10081 t
= gimple_build_omp_return
10082 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
10083 OMP_CLAUSE_NOWAIT
));
10084 gimple_seq_add_stmt (&new_body
, t
);
10085 maybe_add_implicit_barrier_cancel (ctx
, &new_body
);
10087 gimple_bind_set_body (new_stmt
, new_body
);
10091 /* A subroutine of lower_omp_single. Expand the simple form of
10092 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10094 if (GOMP_single_start ())
10096 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10098 FIXME. It may be better to delay expanding the logic of this until
10099 pass_expand_omp. The expanded logic may make the job more difficult
10100 to a synchronization analysis pass. */
10103 lower_omp_single_simple (gomp_single
*single_stmt
, gimple_seq
*pre_p
)
10105 location_t loc
= gimple_location (single_stmt
);
10106 tree tlabel
= create_artificial_label (loc
);
10107 tree flabel
= create_artificial_label (loc
);
10111 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
10112 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)));
10113 call
= gimple_build_call (decl
, 0);
10114 gimple_call_set_lhs (call
, lhs
);
10115 gimple_seq_add_stmt (pre_p
, call
);
10117 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
10118 fold_convert_loc (loc
, TREE_TYPE (lhs
),
10119 boolean_true_node
),
10121 gimple_seq_add_stmt (pre_p
, cond
);
10122 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
10123 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10124 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
10128 /* A subroutine of lower_omp_single. Expand the simple form of
10129 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10131 #pragma omp single copyprivate (a, b, c)
10133 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10136 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10142 GOMP_single_copy_end (©out);
10153 FIXME. It may be better to delay expanding the logic of this until
10154 pass_expand_omp. The expanded logic may make the job more difficult
10155 to a synchronization analysis pass. */
10158 lower_omp_single_copy (gomp_single
*single_stmt
, gimple_seq
*pre_p
,
10161 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
10162 gimple_seq copyin_seq
;
10163 location_t loc
= gimple_location (single_stmt
);
10165 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
10167 ptr_type
= build_pointer_type (ctx
->record_type
);
10168 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
10170 l0
= create_artificial_label (loc
);
10171 l1
= create_artificial_label (loc
);
10172 l2
= create_artificial_label (loc
);
10174 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
10175 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
10176 t
= fold_convert_loc (loc
, ptr_type
, t
);
10177 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
10179 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
10180 build_int_cst (ptr_type
, 0));
10181 t
= build3 (COND_EXPR
, void_type_node
, t
,
10182 build_and_jump (&l0
), build_and_jump (&l1
));
10183 gimplify_and_add (t
, pre_p
);
10185 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
10187 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
10190 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
10193 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
10194 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
10195 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
10196 gimplify_and_add (t
, pre_p
);
10198 t
= build_and_jump (&l2
);
10199 gimplify_and_add (t
, pre_p
);
10201 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
10203 gimple_seq_add_seq (pre_p
, copyin_seq
);
10205 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
10209 /* Expand code for an OpenMP single directive. */
10212 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10216 gomp_single
*single_stmt
= as_a
<gomp_single
*> (gsi_stmt (*gsi_p
));
10218 gimple_seq bind_body
, bind_body_tail
= NULL
, dlist
;
10220 push_gimplify_context ();
10222 block
= make_node (BLOCK
);
10223 bind
= gimple_build_bind (NULL
, NULL
, block
);
10224 gsi_replace (gsi_p
, bind
, true);
10227 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
10228 &bind_body
, &dlist
, ctx
, NULL
);
10229 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
10231 gimple_seq_add_stmt (&bind_body
, single_stmt
);
10233 if (ctx
->record_type
)
10234 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
10236 lower_omp_single_simple (single_stmt
, &bind_body
);
10238 gimple_omp_set_body (single_stmt
, NULL
);
10240 gimple_seq_add_seq (&bind_body
, dlist
);
10242 bind_body
= maybe_catch_exception (bind_body
);
10244 t
= gimple_build_omp_return
10245 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
10246 OMP_CLAUSE_NOWAIT
));
10247 gimple_seq_add_stmt (&bind_body_tail
, t
);
10248 maybe_add_implicit_barrier_cancel (ctx
, &bind_body_tail
);
10249 if (ctx
->record_type
)
10251 gimple_stmt_iterator gsi
= gsi_start (bind_body_tail
);
10252 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
10253 TREE_THIS_VOLATILE (clobber
) = 1;
10254 gsi_insert_after (&gsi
, gimple_build_assign (ctx
->sender_decl
,
10255 clobber
), GSI_SAME_STMT
);
10257 gimple_seq_add_seq (&bind_body
, bind_body_tail
);
10258 gimple_bind_set_body (bind
, bind_body
);
10260 pop_gimplify_context (bind
);
10262 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10263 BLOCK_VARS (block
) = ctx
->block_vars
;
10264 if (BLOCK_VARS (block
))
10265 TREE_USED (block
) = 1;
10269 /* Expand code for an OpenMP master directive. */
10272 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10274 tree block
, lab
= NULL
, x
, bfn_decl
;
10275 gimple stmt
= gsi_stmt (*gsi_p
);
10277 location_t loc
= gimple_location (stmt
);
10280 push_gimplify_context ();
10282 block
= make_node (BLOCK
);
10283 bind
= gimple_build_bind (NULL
, NULL
, block
);
10284 gsi_replace (gsi_p
, bind
, true);
10285 gimple_bind_add_stmt (bind
, stmt
);
10287 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
10288 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
10289 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
10290 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
10292 gimplify_and_add (x
, &tseq
);
10293 gimple_bind_add_seq (bind
, tseq
);
10295 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10296 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10297 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10298 gimple_omp_set_body (stmt
, NULL
);
10300 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
10302 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10304 pop_gimplify_context (bind
);
10306 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10307 BLOCK_VARS (block
) = ctx
->block_vars
;
10311 /* Expand code for an OpenMP taskgroup directive. */
10314 lower_omp_taskgroup (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10316 gimple stmt
= gsi_stmt (*gsi_p
);
10319 tree block
= make_node (BLOCK
);
10321 bind
= gimple_build_bind (NULL
, NULL
, block
);
10322 gsi_replace (gsi_p
, bind
, true);
10323 gimple_bind_add_stmt (bind
, stmt
);
10325 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START
),
10327 gimple_bind_add_stmt (bind
, x
);
10329 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10330 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10331 gimple_omp_set_body (stmt
, NULL
);
10333 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10335 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10336 BLOCK_VARS (block
) = ctx
->block_vars
;
10340 /* Expand code for an OpenMP ordered directive. */
10343 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10346 gimple stmt
= gsi_stmt (*gsi_p
);
10350 push_gimplify_context ();
10352 block
= make_node (BLOCK
);
10353 bind
= gimple_build_bind (NULL
, NULL
, block
);
10354 gsi_replace (gsi_p
, bind
, true);
10355 gimple_bind_add_stmt (bind
, stmt
);
10357 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
10359 gimple_bind_add_stmt (bind
, x
);
10361 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10362 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10363 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10364 gimple_omp_set_body (stmt
, NULL
);
10366 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
10367 gimple_bind_add_stmt (bind
, x
);
10369 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10371 pop_gimplify_context (bind
);
10373 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10374 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10378 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10379 substitution of a couple of function calls. But in the NAMED case,
10380 requires that languages coordinate a symbol name. It is therefore
10381 best put here in common code. */
10383 static GTY(()) hash_map
<tree
, tree
> *critical_name_mutexes
;
10386 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10389 tree name
, lock
, unlock
;
10390 gomp_critical
*stmt
= as_a
<gomp_critical
*> (gsi_stmt (*gsi_p
));
10392 location_t loc
= gimple_location (stmt
);
10395 name
= gimple_omp_critical_name (stmt
);
10400 if (!critical_name_mutexes
)
10401 critical_name_mutexes
= hash_map
<tree
, tree
>::create_ggc (10);
10403 tree
*n
= critical_name_mutexes
->get (name
);
10408 decl
= create_tmp_var_raw (ptr_type_node
);
10410 new_str
= ACONCAT ((".gomp_critical_user_",
10411 IDENTIFIER_POINTER (name
), NULL
));
10412 DECL_NAME (decl
) = get_identifier (new_str
);
10413 TREE_PUBLIC (decl
) = 1;
10414 TREE_STATIC (decl
) = 1;
10415 DECL_COMMON (decl
) = 1;
10416 DECL_ARTIFICIAL (decl
) = 1;
10417 DECL_IGNORED_P (decl
) = 1;
10419 varpool_node::finalize_decl (decl
);
10421 critical_name_mutexes
->put (name
, decl
);
10426 /* If '#pragma omp critical' is inside offloaded region or
10427 inside function marked as offloadable, the symbol must be
10428 marked as offloadable too. */
10430 if (cgraph_node::get (current_function_decl
)->offloadable
)
10431 varpool_node::get_create (decl
)->offloadable
= 1;
10433 for (octx
= ctx
->outer
; octx
; octx
= octx
->outer
)
10434 if (is_gimple_omp_offloaded (octx
->stmt
))
10436 varpool_node::get_create (decl
)->offloadable
= 1;
10440 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
10441 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
10443 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
10444 unlock
= build_call_expr_loc (loc
, unlock
, 1,
10445 build_fold_addr_expr_loc (loc
, decl
));
10449 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
10450 lock
= build_call_expr_loc (loc
, lock
, 0);
10452 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
10453 unlock
= build_call_expr_loc (loc
, unlock
, 0);
10456 push_gimplify_context ();
10458 block
= make_node (BLOCK
);
10459 bind
= gimple_build_bind (NULL
, NULL
, block
);
10460 gsi_replace (gsi_p
, bind
, true);
10461 gimple_bind_add_stmt (bind
, stmt
);
10463 tbody
= gimple_bind_body (bind
);
10464 gimplify_and_add (lock
, &tbody
);
10465 gimple_bind_set_body (bind
, tbody
);
10467 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10468 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
10469 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
10470 gimple_omp_set_body (stmt
, NULL
);
10472 tbody
= gimple_bind_body (bind
);
10473 gimplify_and_add (unlock
, &tbody
);
10474 gimple_bind_set_body (bind
, tbody
);
10476 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
10478 pop_gimplify_context (bind
);
10479 gimple_bind_append_vars (bind
, ctx
->block_vars
);
10480 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
10484 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10485 for a lastprivate clause. Given a loop control predicate of (V
10486 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10487 is appended to *DLIST, iterator initialization is appended to
10491 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
10492 gimple_seq
*dlist
, struct omp_context
*ctx
)
10494 tree clauses
, cond
, vinit
;
10495 enum tree_code cond_code
;
10498 cond_code
= fd
->loop
.cond_code
;
10499 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
10501 /* When possible, use a strict equality expression. This can let VRP
10502 type optimizations deduce the value and remove a copy. */
10503 if (tree_fits_shwi_p (fd
->loop
.step
))
10505 HOST_WIDE_INT step
= tree_to_shwi (fd
->loop
.step
);
10506 if (step
== 1 || step
== -1)
10507 cond_code
= EQ_EXPR
;
10510 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, fd
->loop
.n2
);
10512 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
10514 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
10515 if (!gimple_seq_empty_p (stmts
))
10517 gimple_seq_add_seq (&stmts
, *dlist
);
10520 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10521 vinit
= fd
->loop
.n1
;
10522 if (cond_code
== EQ_EXPR
10523 && tree_fits_shwi_p (fd
->loop
.n2
)
10524 && ! integer_zerop (fd
->loop
.n2
))
10525 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
10527 vinit
= unshare_expr (vinit
);
10529 /* Initialize the iterator variable, so that threads that don't execute
10530 any iterations don't execute the lastprivate clauses by accident. */
10531 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
10536 /* Lower code for an OMP loop directive. */
10539 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
10541 tree
*rhs_p
, block
;
10542 struct omp_for_data fd
, *fdp
= NULL
;
10543 gomp_for
*stmt
= as_a
<gomp_for
*> (gsi_stmt (*gsi_p
));
10545 gimple_seq omp_for_body
, body
, dlist
;
10548 push_gimplify_context ();
10550 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
10552 block
= make_node (BLOCK
);
10553 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
10554 /* Replace at gsi right away, so that 'stmt' is no member
10555 of a sequence anymore as we're going to add to to a different
10557 gsi_replace (gsi_p
, new_stmt
, true);
10559 /* Move declaration of temporaries in the loop body before we make
10561 omp_for_body
= gimple_omp_body (stmt
);
10562 if (!gimple_seq_empty_p (omp_for_body
)
10563 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
10566 = as_a
<gbind
*> (gimple_seq_first_stmt (omp_for_body
));
10567 tree vars
= gimple_bind_vars (inner_bind
);
10568 gimple_bind_append_vars (new_stmt
, vars
);
10569 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10570 keep them on the inner_bind and it's block. */
10571 gimple_bind_set_vars (inner_bind
, NULL_TREE
);
10572 if (gimple_bind_block (inner_bind
))
10573 BLOCK_VARS (gimple_bind_block (inner_bind
)) = NULL_TREE
;
10576 if (gimple_omp_for_combined_into_p (stmt
))
10578 extract_omp_for_data (stmt
, &fd
, NULL
);
10581 /* We need two temporaries with fd.loop.v type (istart/iend)
10582 and then (fd.collapse - 1) temporaries with the same
10583 type for count2 ... countN-1 vars if not constant. */
10585 tree type
= fd
.iter_type
;
10586 if (fd
.collapse
> 1
10587 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
10588 count
+= fd
.collapse
- 1;
10589 bool parallel_for
= gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_FOR
;
10590 tree outerc
= NULL
, *pc
= gimple_omp_for_clauses_ptr (stmt
);
10591 tree clauses
= *pc
;
10594 = find_omp_clause (gimple_omp_parallel_clauses (ctx
->outer
->stmt
),
10595 OMP_CLAUSE__LOOPTEMP_
);
10596 for (i
= 0; i
< count
; i
++)
10601 gcc_assert (outerc
);
10602 temp
= lookup_decl (OMP_CLAUSE_DECL (outerc
), ctx
->outer
);
10603 outerc
= find_omp_clause (OMP_CLAUSE_CHAIN (outerc
),
10604 OMP_CLAUSE__LOOPTEMP_
);
10608 temp
= create_tmp_var (type
);
10609 insert_decl_map (&ctx
->outer
->cb
, temp
, temp
);
10611 *pc
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__LOOPTEMP_
);
10612 OMP_CLAUSE_DECL (*pc
) = temp
;
10613 pc
= &OMP_CLAUSE_CHAIN (*pc
);
10618 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10621 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
,
10623 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
10625 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
10627 /* Lower the header expressions. At this point, we can assume that
10628 the header is of the form:
10630 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10632 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10633 using the .omp_data_s mapping, if needed. */
10634 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
10636 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
10637 if (!is_gimple_min_invariant (*rhs_p
))
10638 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10640 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
10641 if (!is_gimple_min_invariant (*rhs_p
))
10642 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10644 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
10645 if (!is_gimple_min_invariant (*rhs_p
))
10646 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
10649 /* Once lowered, extract the bounds and clauses. */
10650 extract_omp_for_data (stmt
, &fd
, NULL
);
10652 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
10654 gimple_seq_add_stmt (&body
, stmt
);
10655 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
10657 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
10660 /* After the loop, add exit clauses. */
10661 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
10663 if (ctx
->cancellable
)
10664 gimple_seq_add_stmt (&body
, gimple_build_label (ctx
->cancel_label
));
10666 gimple_seq_add_seq (&body
, dlist
);
10668 body
= maybe_catch_exception (body
);
10670 /* Region exit marker goes at the end of the loop body. */
10671 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
10672 maybe_add_implicit_barrier_cancel (ctx
, &body
);
10673 pop_gimplify_context (new_stmt
);
10675 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
10676 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
10677 if (BLOCK_VARS (block
))
10678 TREE_USED (block
) = 1;
10680 gimple_bind_set_body (new_stmt
, body
);
10681 gimple_omp_set_body (stmt
, NULL
);
10682 gimple_omp_for_set_pre_body (stmt
, NULL
);
10685 /* Callback for walk_stmts. Check if the current statement only contains
10686 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10689 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
10690 bool *handled_ops_p
,
10691 struct walk_stmt_info
*wi
)
10693 int *info
= (int *) wi
->info
;
10694 gimple stmt
= gsi_stmt (*gsi_p
);
10696 *handled_ops_p
= true;
10697 switch (gimple_code (stmt
))
10701 case GIMPLE_OMP_FOR
:
10702 case GIMPLE_OMP_SECTIONS
:
10703 *info
= *info
== 0 ? 1 : -1;
10712 struct omp_taskcopy_context
10714 /* This field must be at the beginning, as we do "inheritance": Some
10715 callback functions for tree-inline.c (e.g., omp_copy_decl)
10716 receive a copy_body_data pointer that is up-casted to an
10717 omp_context pointer. */
10723 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
10725 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
10727 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
10728 return create_tmp_var (TREE_TYPE (var
));
10734 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
10736 tree name
, new_fields
= NULL
, type
, f
;
10738 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
10739 name
= DECL_NAME (TYPE_NAME (orig_type
));
10740 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
10741 TYPE_DECL
, name
, type
);
10742 TYPE_NAME (type
) = name
;
10744 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
10746 tree new_f
= copy_node (f
);
10747 DECL_CONTEXT (new_f
) = type
;
10748 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
10749 TREE_CHAIN (new_f
) = new_fields
;
10750 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10751 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
10752 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
10754 new_fields
= new_f
;
10755 tcctx
->cb
.decl_map
->put (f
, new_f
);
10757 TYPE_FIELDS (type
) = nreverse (new_fields
);
10758 layout_type (type
);
10762 /* Create task copyfn. */
10765 create_task_copyfn (gomp_task
*task_stmt
, omp_context
*ctx
)
10767 struct function
*child_cfun
;
10768 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
10769 tree record_type
, srecord_type
, bind
, list
;
10770 bool record_needs_remap
= false, srecord_needs_remap
= false;
10772 struct omp_taskcopy_context tcctx
;
10773 location_t loc
= gimple_location (task_stmt
);
10775 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
10776 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
10777 gcc_assert (child_cfun
->cfg
== NULL
);
10778 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
10780 /* Reset DECL_CONTEXT on function arguments. */
10781 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
10782 DECL_CONTEXT (t
) = child_fn
;
10784 /* Populate the function. */
10785 push_gimplify_context ();
10786 push_cfun (child_cfun
);
10788 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
10789 TREE_SIDE_EFFECTS (bind
) = 1;
10791 DECL_SAVED_TREE (child_fn
) = bind
;
10792 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
10794 /* Remap src and dst argument types if needed. */
10795 record_type
= ctx
->record_type
;
10796 srecord_type
= ctx
->srecord_type
;
10797 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
10798 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10800 record_needs_remap
= true;
10803 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
10804 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
10806 srecord_needs_remap
= true;
10810 if (record_needs_remap
|| srecord_needs_remap
)
10812 memset (&tcctx
, '\0', sizeof (tcctx
));
10813 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
10814 tcctx
.cb
.dst_fn
= child_fn
;
10815 tcctx
.cb
.src_node
= cgraph_node::get (tcctx
.cb
.src_fn
);
10816 gcc_checking_assert (tcctx
.cb
.src_node
);
10817 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
10818 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
10819 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
10820 tcctx
.cb
.eh_lp_nr
= 0;
10821 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
10822 tcctx
.cb
.decl_map
= new hash_map
<tree
, tree
>;
10825 if (record_needs_remap
)
10826 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
10827 if (srecord_needs_remap
)
10828 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
10831 tcctx
.cb
.decl_map
= NULL
;
10833 arg
= DECL_ARGUMENTS (child_fn
);
10834 TREE_TYPE (arg
) = build_pointer_type (record_type
);
10835 sarg
= DECL_CHAIN (arg
);
10836 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
10838 /* First pass: initialize temporaries used in record_type and srecord_type
10839 sizes and field offsets. */
10840 if (tcctx
.cb
.decl_map
)
10841 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10842 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
10846 decl
= OMP_CLAUSE_DECL (c
);
10847 p
= tcctx
.cb
.decl_map
->get (decl
);
10850 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10851 sf
= (tree
) n
->value
;
10852 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10853 src
= build_simple_mem_ref_loc (loc
, sarg
);
10854 src
= omp_build_component_ref (src
, sf
);
10855 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
10856 append_to_statement_list (t
, &list
);
10859 /* Second pass: copy shared var pointers and copy construct non-VLA
10860 firstprivate vars. */
10861 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10862 switch (OMP_CLAUSE_CODE (c
))
10864 case OMP_CLAUSE_SHARED
:
10865 decl
= OMP_CLAUSE_DECL (c
);
10866 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10869 f
= (tree
) n
->value
;
10870 if (tcctx
.cb
.decl_map
)
10871 f
= *tcctx
.cb
.decl_map
->get (f
);
10872 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10873 sf
= (tree
) n
->value
;
10874 if (tcctx
.cb
.decl_map
)
10875 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10876 src
= build_simple_mem_ref_loc (loc
, sarg
);
10877 src
= omp_build_component_ref (src
, sf
);
10878 dst
= build_simple_mem_ref_loc (loc
, arg
);
10879 dst
= omp_build_component_ref (dst
, f
);
10880 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
10881 append_to_statement_list (t
, &list
);
10883 case OMP_CLAUSE_FIRSTPRIVATE
:
10884 decl
= OMP_CLAUSE_DECL (c
);
10885 if (is_variable_sized (decl
))
10887 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10890 f
= (tree
) n
->value
;
10891 if (tcctx
.cb
.decl_map
)
10892 f
= *tcctx
.cb
.decl_map
->get (f
);
10893 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
10896 sf
= (tree
) n
->value
;
10897 if (tcctx
.cb
.decl_map
)
10898 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10899 src
= build_simple_mem_ref_loc (loc
, sarg
);
10900 src
= omp_build_component_ref (src
, sf
);
10901 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
10902 src
= build_simple_mem_ref_loc (loc
, src
);
10906 dst
= build_simple_mem_ref_loc (loc
, arg
);
10907 dst
= omp_build_component_ref (dst
, f
);
10908 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
10909 append_to_statement_list (t
, &list
);
10911 case OMP_CLAUSE_PRIVATE
:
10912 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
10914 decl
= OMP_CLAUSE_DECL (c
);
10915 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
))
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
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
10935 append_to_statement_list (t
, &list
);
10941 /* Last pass: handle VLA firstprivates. */
10942 if (tcctx
.cb
.decl_map
)
10943 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
10944 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
10948 decl
= OMP_CLAUSE_DECL (c
);
10949 if (!is_variable_sized (decl
))
10951 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
10954 f
= (tree
) n
->value
;
10955 f
= *tcctx
.cb
.decl_map
->get (f
);
10956 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
10957 ind
= DECL_VALUE_EXPR (decl
);
10958 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
10959 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
10960 n
= splay_tree_lookup (ctx
->sfield_map
,
10961 (splay_tree_key
) TREE_OPERAND (ind
, 0));
10962 sf
= (tree
) n
->value
;
10963 sf
= *tcctx
.cb
.decl_map
->get (sf
);
10964 src
= build_simple_mem_ref_loc (loc
, sarg
);
10965 src
= omp_build_component_ref (src
, sf
);
10966 src
= build_simple_mem_ref_loc (loc
, src
);
10967 dst
= build_simple_mem_ref_loc (loc
, arg
);
10968 dst
= omp_build_component_ref (dst
, f
);
10969 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
10970 append_to_statement_list (t
, &list
);
10971 n
= splay_tree_lookup (ctx
->field_map
,
10972 (splay_tree_key
) TREE_OPERAND (ind
, 0));
10973 df
= (tree
) n
->value
;
10974 df
= *tcctx
.cb
.decl_map
->get (df
);
10975 ptr
= build_simple_mem_ref_loc (loc
, arg
);
10976 ptr
= omp_build_component_ref (ptr
, df
);
10977 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
10978 build_fold_addr_expr_loc (loc
, dst
));
10979 append_to_statement_list (t
, &list
);
10982 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
10983 append_to_statement_list (t
, &list
);
10985 if (tcctx
.cb
.decl_map
)
10986 delete tcctx
.cb
.decl_map
;
10987 pop_gimplify_context (NULL
);
10988 BIND_EXPR_BODY (bind
) = list
;
10993 lower_depend_clauses (gimple stmt
, gimple_seq
*iseq
, gimple_seq
*oseq
)
10997 size_t n_in
= 0, n_out
= 0, idx
= 2, i
;
10999 clauses
= find_omp_clause (gimple_omp_task_clauses (stmt
),
11000 OMP_CLAUSE_DEPEND
);
11001 gcc_assert (clauses
);
11002 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11003 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
)
11004 switch (OMP_CLAUSE_DEPEND_KIND (c
))
11006 case OMP_CLAUSE_DEPEND_IN
:
11009 case OMP_CLAUSE_DEPEND_OUT
:
11010 case OMP_CLAUSE_DEPEND_INOUT
:
11014 gcc_unreachable ();
11016 tree type
= build_array_type_nelts (ptr_type_node
, n_in
+ n_out
+ 2);
11017 tree array
= create_tmp_var (type
);
11018 tree r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (0), NULL_TREE
,
11020 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_in
+ n_out
));
11021 gimple_seq_add_stmt (iseq
, g
);
11022 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (1), NULL_TREE
,
11024 g
= gimple_build_assign (r
, build_int_cst (ptr_type_node
, n_out
));
11025 gimple_seq_add_stmt (iseq
, g
);
11026 for (i
= 0; i
< 2; i
++)
11028 if ((i
? n_in
: n_out
) == 0)
11030 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11031 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_DEPEND
11032 && ((OMP_CLAUSE_DEPEND_KIND (c
) != OMP_CLAUSE_DEPEND_IN
) ^ i
))
11034 tree t
= OMP_CLAUSE_DECL (c
);
11035 t
= fold_convert (ptr_type_node
, t
);
11036 gimplify_expr (&t
, iseq
, NULL
, is_gimple_val
, fb_rvalue
);
11037 r
= build4 (ARRAY_REF
, ptr_type_node
, array
, size_int (idx
++),
11038 NULL_TREE
, NULL_TREE
);
11039 g
= gimple_build_assign (r
, t
);
11040 gimple_seq_add_stmt (iseq
, g
);
11043 tree
*p
= gimple_omp_task_clauses_ptr (stmt
);
11044 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_DEPEND
);
11045 OMP_CLAUSE_DECL (c
) = build_fold_addr_expr (array
);
11046 OMP_CLAUSE_CHAIN (c
) = *p
;
11048 tree clobber
= build_constructor (type
, NULL
);
11049 TREE_THIS_VOLATILE (clobber
) = 1;
11050 g
= gimple_build_assign (array
, clobber
);
11051 gimple_seq_add_stmt (oseq
, g
);
11054 /* Lower the OpenMP parallel or task directive in the current statement
11055 in GSI_P. CTX holds context information for the directive. */
11058 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11062 gimple stmt
= gsi_stmt (*gsi_p
);
11063 gbind
*par_bind
, *bind
, *dep_bind
= NULL
;
11064 gimple_seq par_body
, olist
, ilist
, par_olist
, par_rlist
, par_ilist
, new_body
;
11065 location_t loc
= gimple_location (stmt
);
11067 clauses
= gimple_omp_taskreg_clauses (stmt
);
11069 = as_a
<gbind
*> (gimple_seq_first_stmt (gimple_omp_body (stmt
)));
11070 par_body
= gimple_bind_body (par_bind
);
11071 child_fn
= ctx
->cb
.dst_fn
;
11072 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
11073 && !gimple_omp_parallel_combined_p (stmt
))
11075 struct walk_stmt_info wi
;
11078 memset (&wi
, 0, sizeof (wi
));
11080 wi
.val_only
= true;
11081 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
11083 gimple_omp_parallel_set_combined_p (stmt
, true);
11085 gimple_seq dep_ilist
= NULL
;
11086 gimple_seq dep_olist
= NULL
;
11087 if (gimple_code (stmt
) == GIMPLE_OMP_TASK
11088 && find_omp_clause (clauses
, OMP_CLAUSE_DEPEND
))
11090 push_gimplify_context ();
11091 dep_bind
= gimple_build_bind (NULL
, NULL
, make_node (BLOCK
));
11092 lower_depend_clauses (stmt
, &dep_ilist
, &dep_olist
);
11095 if (ctx
->srecord_type
)
11096 create_task_copyfn (as_a
<gomp_task
*> (stmt
), ctx
);
11098 push_gimplify_context ();
11103 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
, NULL
);
11104 lower_omp (&par_body
, ctx
);
11105 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
11106 lower_reduction_clauses (clauses
, &par_rlist
, ctx
);
11108 /* Declare all the variables created by mapping and the variables
11109 declared in the scope of the parallel body. */
11110 record_vars_into (ctx
->block_vars
, child_fn
);
11111 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
11113 if (ctx
->record_type
)
11116 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
11117 : ctx
->record_type
, ".omp_data_o");
11118 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11119 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11120 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
11125 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
11126 lower_send_shared_vars (&ilist
, &olist
, ctx
);
11128 if (ctx
->record_type
)
11130 tree clobber
= build_constructor (TREE_TYPE (ctx
->sender_decl
), NULL
);
11131 TREE_THIS_VOLATILE (clobber
) = 1;
11132 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11136 /* Once all the expansions are done, sequence all the different
11137 fragments inside gimple_omp_body. */
11141 if (ctx
->record_type
)
11143 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11144 /* fixup_child_record_type might have changed receiver_decl's type. */
11145 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11146 gimple_seq_add_stmt (&new_body
,
11147 gimple_build_assign (ctx
->receiver_decl
, t
));
11150 gimple_seq_add_seq (&new_body
, par_ilist
);
11151 gimple_seq_add_seq (&new_body
, par_body
);
11152 gimple_seq_add_seq (&new_body
, par_rlist
);
11153 if (ctx
->cancellable
)
11154 gimple_seq_add_stmt (&new_body
, gimple_build_label (ctx
->cancel_label
));
11155 gimple_seq_add_seq (&new_body
, par_olist
);
11156 new_body
= maybe_catch_exception (new_body
);
11157 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11158 gimple_omp_set_body (stmt
, new_body
);
11160 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
11161 gsi_replace (gsi_p
, dep_bind
? dep_bind
: bind
, true);
11162 gimple_bind_add_seq (bind
, ilist
);
11163 gimple_bind_add_stmt (bind
, stmt
);
11164 gimple_bind_add_seq (bind
, olist
);
11166 pop_gimplify_context (NULL
);
11170 gimple_bind_add_seq (dep_bind
, dep_ilist
);
11171 gimple_bind_add_stmt (dep_bind
, bind
);
11172 gimple_bind_add_seq (dep_bind
, dep_olist
);
11173 pop_gimplify_context (dep_bind
);
11177 /* Lower the GIMPLE_OMP_TARGET in the current statement
11178 in GSI_P. CTX holds context information for the directive. */
11181 lower_omp_target (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11184 tree child_fn
, t
, c
;
11185 gomp_target
*stmt
= as_a
<gomp_target
*> (gsi_stmt (*gsi_p
));
11186 gbind
*tgt_bind
, *bind
;
11187 gimple_seq tgt_body
, olist
, ilist
, orlist
, irlist
, new_body
;
11188 location_t loc
= gimple_location (stmt
);
11189 bool offloaded
, data_region
;
11190 unsigned int map_cnt
= 0;
11192 offloaded
= is_gimple_omp_offloaded (stmt
);
11193 switch (gimple_omp_target_kind (stmt
))
11195 case GF_OMP_TARGET_KIND_REGION
:
11196 case GF_OMP_TARGET_KIND_UPDATE
:
11197 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
11198 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
11199 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
11200 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
11201 data_region
= false;
11203 case GF_OMP_TARGET_KIND_DATA
:
11204 case GF_OMP_TARGET_KIND_OACC_DATA
:
11205 data_region
= true;
11208 gcc_unreachable ();
11211 clauses
= gimple_omp_target_clauses (stmt
);
11217 tgt_bind
= gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt
));
11218 tgt_body
= gimple_bind_body (tgt_bind
);
11220 else if (data_region
)
11221 tgt_body
= gimple_omp_body (stmt
);
11222 child_fn
= ctx
->cb
.dst_fn
;
11224 push_gimplify_context ();
11229 && is_gimple_omp_oacc (stmt
))
11230 oacc_process_reduction_data (&tgt_body
, &irlist
, &orlist
, ctx
);
11232 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11233 switch (OMP_CLAUSE_CODE (c
))
11239 case OMP_CLAUSE_MAP
:
11240 #ifdef ENABLE_CHECKING
11241 /* First check what we're prepared to handle in the following. */
11242 switch (OMP_CLAUSE_MAP_KIND (c
))
11244 case GOMP_MAP_ALLOC
:
11246 case GOMP_MAP_FROM
:
11247 case GOMP_MAP_TOFROM
:
11248 case GOMP_MAP_POINTER
:
11249 case GOMP_MAP_TO_PSET
:
11251 case GOMP_MAP_FORCE_ALLOC
:
11252 case GOMP_MAP_FORCE_TO
:
11253 case GOMP_MAP_FORCE_FROM
:
11254 case GOMP_MAP_FORCE_TOFROM
:
11255 case GOMP_MAP_FORCE_PRESENT
:
11256 case GOMP_MAP_FORCE_DEALLOC
:
11257 case GOMP_MAP_FORCE_DEVICEPTR
:
11258 gcc_assert (is_gimple_omp_oacc (stmt
));
11261 gcc_unreachable ();
11265 case OMP_CLAUSE_TO
:
11266 case OMP_CLAUSE_FROM
:
11267 var
= OMP_CLAUSE_DECL (c
);
11270 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_MAP
11271 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11276 if (DECL_SIZE (var
)
11277 && TREE_CODE (DECL_SIZE (var
)) != INTEGER_CST
)
11279 tree var2
= DECL_VALUE_EXPR (var
);
11280 gcc_assert (TREE_CODE (var2
) == INDIRECT_REF
);
11281 var2
= TREE_OPERAND (var2
, 0);
11282 gcc_assert (DECL_P (var2
));
11286 if (!maybe_lookup_field (var
, ctx
))
11291 x
= build_receiver_ref (var
, true, ctx
);
11292 tree new_var
= lookup_decl (var
, ctx
);
11293 if (OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11294 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11295 && TREE_CODE (TREE_TYPE (var
)) == ARRAY_TYPE
)
11296 x
= build_simple_mem_ref (x
);
11297 SET_DECL_VALUE_EXPR (new_var
, x
);
11298 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
11305 target_nesting_level
++;
11306 lower_omp (&tgt_body
, ctx
);
11307 target_nesting_level
--;
11309 else if (data_region
)
11310 lower_omp (&tgt_body
, ctx
);
11314 /* Declare all the variables created by mapping and the variables
11315 declared in the scope of the target body. */
11316 record_vars_into (ctx
->block_vars
, child_fn
);
11317 record_vars_into (gimple_bind_vars (tgt_bind
), child_fn
);
11322 if (ctx
->record_type
)
11325 = create_tmp_var (ctx
->record_type
, ".omp_data_arr");
11326 DECL_NAMELESS (ctx
->sender_decl
) = 1;
11327 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
11328 t
= make_tree_vec (3);
11329 TREE_VEC_ELT (t
, 0) = ctx
->sender_decl
;
11330 TREE_VEC_ELT (t
, 1)
11331 = create_tmp_var (build_array_type_nelts (size_type_node
, map_cnt
),
11332 ".omp_data_sizes");
11333 DECL_NAMELESS (TREE_VEC_ELT (t
, 1)) = 1;
11334 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 1)) = 1;
11335 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 1;
11338 if (is_gimple_omp_oacc (stmt
))
11340 tkind_type
= short_unsigned_type_node
;
11345 tkind_type
= unsigned_char_type_node
;
11348 TREE_VEC_ELT (t
, 2)
11349 = create_tmp_var (build_array_type_nelts (tkind_type
, map_cnt
),
11350 ".omp_data_kinds");
11351 DECL_NAMELESS (TREE_VEC_ELT (t
, 2)) = 1;
11352 TREE_ADDRESSABLE (TREE_VEC_ELT (t
, 2)) = 1;
11353 TREE_STATIC (TREE_VEC_ELT (t
, 2)) = 1;
11354 gimple_omp_target_set_data_arg (stmt
, t
);
11356 vec
<constructor_elt
, va_gc
> *vsize
;
11357 vec
<constructor_elt
, va_gc
> *vkind
;
11358 vec_alloc (vsize
, map_cnt
);
11359 vec_alloc (vkind
, map_cnt
);
11360 unsigned int map_idx
= 0;
11362 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
11363 switch (OMP_CLAUSE_CODE (c
))
11369 case OMP_CLAUSE_MAP
:
11370 case OMP_CLAUSE_TO
:
11371 case OMP_CLAUSE_FROM
:
11373 ovar
= OMP_CLAUSE_DECL (c
);
11374 if (!DECL_P (ovar
))
11376 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11377 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
))
11379 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c
))
11380 == get_base_address (ovar
));
11381 nc
= OMP_CLAUSE_CHAIN (c
);
11382 ovar
= OMP_CLAUSE_DECL (nc
);
11386 tree x
= build_sender_ref (ovar
, ctx
);
11388 = build_fold_addr_expr_with_type (ovar
, ptr_type_node
);
11389 gimplify_assign (x
, v
, &ilist
);
11395 if (DECL_SIZE (ovar
)
11396 && TREE_CODE (DECL_SIZE (ovar
)) != INTEGER_CST
)
11398 tree ovar2
= DECL_VALUE_EXPR (ovar
);
11399 gcc_assert (TREE_CODE (ovar2
) == INDIRECT_REF
);
11400 ovar2
= TREE_OPERAND (ovar2
, 0);
11401 gcc_assert (DECL_P (ovar2
));
11404 if (!maybe_lookup_field (ovar
, ctx
))
11408 unsigned int talign
= TYPE_ALIGN_UNIT (TREE_TYPE (ovar
));
11409 if (DECL_P (ovar
) && DECL_ALIGN_UNIT (ovar
) > talign
)
11410 talign
= DECL_ALIGN_UNIT (ovar
);
11413 tree var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
11414 tree x
= build_sender_ref (ovar
, ctx
);
11415 if (maybe_lookup_oacc_reduction (var
, ctx
))
11417 gcc_checking_assert (offloaded
11418 && is_gimple_omp_oacc (stmt
));
11419 gimplify_assign (x
, var
, &ilist
);
11421 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_MAP
11422 && OMP_CLAUSE_MAP_KIND (c
) == GOMP_MAP_POINTER
11423 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c
)
11424 && TREE_CODE (TREE_TYPE (ovar
)) == ARRAY_TYPE
)
11426 gcc_assert (offloaded
);
11428 = create_tmp_var (TREE_TYPE (TREE_TYPE (x
)));
11429 mark_addressable (avar
);
11430 gimplify_assign (avar
, build_fold_addr_expr (var
), &ilist
);
11431 talign
= DECL_ALIGN_UNIT (avar
);
11432 avar
= build_fold_addr_expr (avar
);
11433 gimplify_assign (x
, avar
, &ilist
);
11435 else if (is_gimple_reg (var
))
11437 gcc_assert (offloaded
);
11438 tree avar
= create_tmp_var (TREE_TYPE (var
));
11439 mark_addressable (avar
);
11440 enum gomp_map_kind map_kind
= OMP_CLAUSE_MAP_KIND (c
);
11441 if (GOMP_MAP_COPY_TO_P (map_kind
)
11442 || map_kind
== GOMP_MAP_POINTER
11443 || map_kind
== GOMP_MAP_TO_PSET
11444 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11445 gimplify_assign (avar
, var
, &ilist
);
11446 avar
= build_fold_addr_expr (avar
);
11447 gimplify_assign (x
, avar
, &ilist
);
11448 if ((GOMP_MAP_COPY_FROM_P (map_kind
)
11449 || map_kind
== GOMP_MAP_FORCE_DEVICEPTR
)
11450 && !TYPE_READONLY (TREE_TYPE (var
)))
11452 x
= build_sender_ref (ovar
, ctx
);
11453 x
= build_simple_mem_ref (x
);
11454 gimplify_assign (var
, x
, &olist
);
11459 var
= build_fold_addr_expr (var
);
11460 gimplify_assign (x
, var
, &ilist
);
11463 tree s
= OMP_CLAUSE_SIZE (c
);
11464 if (s
== NULL_TREE
)
11465 s
= TYPE_SIZE_UNIT (TREE_TYPE (ovar
));
11466 s
= fold_convert (size_type_node
, s
);
11467 tree purpose
= size_int (map_idx
++);
11468 CONSTRUCTOR_APPEND_ELT (vsize
, purpose
, s
);
11469 if (TREE_CODE (s
) != INTEGER_CST
)
11470 TREE_STATIC (TREE_VEC_ELT (t
, 1)) = 0;
11472 unsigned HOST_WIDE_INT tkind
;
11473 switch (OMP_CLAUSE_CODE (c
))
11475 case OMP_CLAUSE_MAP
:
11476 tkind
= OMP_CLAUSE_MAP_KIND (c
);
11478 case OMP_CLAUSE_TO
:
11479 tkind
= GOMP_MAP_TO
;
11481 case OMP_CLAUSE_FROM
:
11482 tkind
= GOMP_MAP_FROM
;
11485 gcc_unreachable ();
11487 gcc_checking_assert (tkind
11488 < (HOST_WIDE_INT_C (1U) << talign_shift
));
11489 talign
= ceil_log2 (talign
);
11490 tkind
|= talign
<< talign_shift
;
11491 gcc_checking_assert (tkind
11492 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type
)));
11493 CONSTRUCTOR_APPEND_ELT (vkind
, purpose
,
11494 build_int_cstu (tkind_type
, tkind
));
11499 gcc_assert (map_idx
== map_cnt
);
11501 DECL_INITIAL (TREE_VEC_ELT (t
, 1))
11502 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)), vsize
);
11503 DECL_INITIAL (TREE_VEC_ELT (t
, 2))
11504 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 2)), vkind
);
11505 if (!TREE_STATIC (TREE_VEC_ELT (t
, 1)))
11507 gimple_seq initlist
= NULL
;
11508 force_gimple_operand (build1 (DECL_EXPR
, void_type_node
,
11509 TREE_VEC_ELT (t
, 1)),
11510 &initlist
, true, NULL_TREE
);
11511 gimple_seq_add_seq (&ilist
, initlist
);
11513 tree clobber
= build_constructor (TREE_TYPE (TREE_VEC_ELT (t
, 1)),
11515 TREE_THIS_VOLATILE (clobber
) = 1;
11516 gimple_seq_add_stmt (&olist
,
11517 gimple_build_assign (TREE_VEC_ELT (t
, 1),
11521 tree clobber
= build_constructor (ctx
->record_type
, NULL
);
11522 TREE_THIS_VOLATILE (clobber
) = 1;
11523 gimple_seq_add_stmt (&olist
, gimple_build_assign (ctx
->sender_decl
,
11527 /* Once all the expansions are done, sequence all the different
11528 fragments inside gimple_omp_body. */
11533 && ctx
->record_type
)
11535 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
11536 /* fixup_child_record_type might have changed receiver_decl's type. */
11537 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
11538 gimple_seq_add_stmt (&new_body
,
11539 gimple_build_assign (ctx
->receiver_decl
, t
));
11544 gimple_seq_add_seq (&new_body
, tgt_body
);
11545 new_body
= maybe_catch_exception (new_body
);
11547 else if (data_region
)
11548 new_body
= tgt_body
;
11549 if (offloaded
|| data_region
)
11551 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
11552 gimple_omp_set_body (stmt
, new_body
);
11555 bind
= gimple_build_bind (NULL
, NULL
,
11556 tgt_bind
? gimple_bind_block (tgt_bind
)
11558 gsi_replace (gsi_p
, bind
, true);
11559 gimple_bind_add_seq (bind
, irlist
);
11560 gimple_bind_add_seq (bind
, ilist
);
11561 gimple_bind_add_stmt (bind
, stmt
);
11562 gimple_bind_add_seq (bind
, olist
);
11563 gimple_bind_add_seq (bind
, orlist
);
11565 pop_gimplify_context (NULL
);
11568 /* Expand code for an OpenMP teams directive. */
11571 lower_omp_teams (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11573 gomp_teams
*teams_stmt
= as_a
<gomp_teams
*> (gsi_stmt (*gsi_p
));
11574 push_gimplify_context ();
11576 tree block
= make_node (BLOCK
);
11577 gbind
*bind
= gimple_build_bind (NULL
, NULL
, block
);
11578 gsi_replace (gsi_p
, bind
, true);
11579 gimple_seq bind_body
= NULL
;
11580 gimple_seq dlist
= NULL
;
11581 gimple_seq olist
= NULL
;
11583 tree num_teams
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11584 OMP_CLAUSE_NUM_TEAMS
);
11585 if (num_teams
== NULL_TREE
)
11586 num_teams
= build_int_cst (unsigned_type_node
, 0);
11589 num_teams
= OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams
);
11590 num_teams
= fold_convert (unsigned_type_node
, num_teams
);
11591 gimplify_expr (&num_teams
, &bind_body
, NULL
, is_gimple_val
, fb_rvalue
);
11593 tree thread_limit
= find_omp_clause (gimple_omp_teams_clauses (teams_stmt
),
11594 OMP_CLAUSE_THREAD_LIMIT
);
11595 if (thread_limit
== NULL_TREE
)
11596 thread_limit
= build_int_cst (unsigned_type_node
, 0);
11599 thread_limit
= OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit
);
11600 thread_limit
= fold_convert (unsigned_type_node
, thread_limit
);
11601 gimplify_expr (&thread_limit
, &bind_body
, NULL
, is_gimple_val
,
11605 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt
),
11606 &bind_body
, &dlist
, ctx
, NULL
);
11607 lower_omp (gimple_omp_body_ptr (teams_stmt
), ctx
);
11608 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt
), &olist
, ctx
);
11609 gimple_seq_add_stmt (&bind_body
, teams_stmt
);
11611 location_t loc
= gimple_location (teams_stmt
);
11612 tree decl
= builtin_decl_explicit (BUILT_IN_GOMP_TEAMS
);
11613 gimple call
= gimple_build_call (decl
, 2, num_teams
, thread_limit
);
11614 gimple_set_location (call
, loc
);
11615 gimple_seq_add_stmt (&bind_body
, call
);
11617 gimple_seq_add_seq (&bind_body
, gimple_omp_body (teams_stmt
));
11618 gimple_omp_set_body (teams_stmt
, NULL
);
11619 gimple_seq_add_seq (&bind_body
, olist
);
11620 gimple_seq_add_seq (&bind_body
, dlist
);
11621 gimple_seq_add_stmt (&bind_body
, gimple_build_omp_return (true));
11622 gimple_bind_set_body (bind
, bind_body
);
11624 pop_gimplify_context (bind
);
11626 gimple_bind_append_vars (bind
, ctx
->block_vars
);
11627 BLOCK_VARS (block
) = ctx
->block_vars
;
11628 if (BLOCK_VARS (block
))
11629 TREE_USED (block
) = 1;
11633 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11634 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11635 of OMP context, but with task_shared_vars set. */
11638 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
11643 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11644 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
11647 if (task_shared_vars
11649 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
11652 /* If a global variable has been privatized, TREE_CONSTANT on
11653 ADDR_EXPR might be wrong. */
11654 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
11655 recompute_tree_invariant_for_addr_expr (t
);
11657 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
11662 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
11664 gimple stmt
= gsi_stmt (*gsi_p
);
11665 struct walk_stmt_info wi
;
11668 if (gimple_has_location (stmt
))
11669 input_location
= gimple_location (stmt
);
11671 if (task_shared_vars
)
11672 memset (&wi
, '\0', sizeof (wi
));
11674 /* If we have issued syntax errors, avoid doing any heavy lifting.
11675 Just replace the OMP directives with a NOP to avoid
11676 confusing RTL expansion. */
11677 if (seen_error () && is_gimple_omp (stmt
))
11679 gsi_replace (gsi_p
, gimple_build_nop (), true);
11683 switch (gimple_code (stmt
))
11687 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
11688 if ((ctx
|| task_shared_vars
)
11689 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt
),
11690 lower_omp_regimplify_p
,
11691 ctx
? NULL
: &wi
, NULL
)
11692 || walk_tree (gimple_cond_rhs_ptr (cond_stmt
),
11693 lower_omp_regimplify_p
,
11694 ctx
? NULL
: &wi
, NULL
)))
11695 gimple_regimplify_operands (cond_stmt
, gsi_p
);
11699 lower_omp (gimple_catch_handler_ptr (as_a
<gcatch
*> (stmt
)), ctx
);
11701 case GIMPLE_EH_FILTER
:
11702 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
11705 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
11706 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
11708 case GIMPLE_TRANSACTION
:
11709 lower_omp (gimple_transaction_body_ptr (
11710 as_a
<gtransaction
*> (stmt
)),
11714 lower_omp (gimple_bind_body_ptr (as_a
<gbind
*> (stmt
)), ctx
);
11716 case GIMPLE_OMP_PARALLEL
:
11717 case GIMPLE_OMP_TASK
:
11718 ctx
= maybe_lookup_ctx (stmt
);
11720 if (ctx
->cancellable
)
11721 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11722 lower_omp_taskreg (gsi_p
, ctx
);
11724 case GIMPLE_OMP_FOR
:
11725 ctx
= maybe_lookup_ctx (stmt
);
11727 if (ctx
->cancellable
)
11728 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11729 lower_omp_for (gsi_p
, ctx
);
11731 case GIMPLE_OMP_SECTIONS
:
11732 ctx
= maybe_lookup_ctx (stmt
);
11734 if (ctx
->cancellable
)
11735 ctx
->cancel_label
= create_artificial_label (UNKNOWN_LOCATION
);
11736 lower_omp_sections (gsi_p
, ctx
);
11738 case GIMPLE_OMP_SINGLE
:
11739 ctx
= maybe_lookup_ctx (stmt
);
11741 lower_omp_single (gsi_p
, ctx
);
11743 case GIMPLE_OMP_MASTER
:
11744 ctx
= maybe_lookup_ctx (stmt
);
11746 lower_omp_master (gsi_p
, ctx
);
11748 case GIMPLE_OMP_TASKGROUP
:
11749 ctx
= maybe_lookup_ctx (stmt
);
11751 lower_omp_taskgroup (gsi_p
, ctx
);
11753 case GIMPLE_OMP_ORDERED
:
11754 ctx
= maybe_lookup_ctx (stmt
);
11756 lower_omp_ordered (gsi_p
, ctx
);
11758 case GIMPLE_OMP_CRITICAL
:
11759 ctx
= maybe_lookup_ctx (stmt
);
11761 lower_omp_critical (gsi_p
, ctx
);
11763 case GIMPLE_OMP_ATOMIC_LOAD
:
11764 if ((ctx
|| task_shared_vars
)
11765 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11766 as_a
<gomp_atomic_load
*> (stmt
)),
11767 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
11768 gimple_regimplify_operands (stmt
, gsi_p
);
11770 case GIMPLE_OMP_TARGET
:
11771 ctx
= maybe_lookup_ctx (stmt
);
11773 lower_omp_target (gsi_p
, ctx
);
11775 case GIMPLE_OMP_TEAMS
:
11776 ctx
= maybe_lookup_ctx (stmt
);
11778 lower_omp_teams (gsi_p
, ctx
);
11782 call_stmt
= as_a
<gcall
*> (stmt
);
11783 fndecl
= gimple_call_fndecl (call_stmt
);
11785 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
11786 switch (DECL_FUNCTION_CODE (fndecl
))
11788 case BUILT_IN_GOMP_BARRIER
:
11792 case BUILT_IN_GOMP_CANCEL
:
11793 case BUILT_IN_GOMP_CANCELLATION_POINT
:
11796 if (gimple_code (cctx
->stmt
) == GIMPLE_OMP_SECTION
)
11797 cctx
= cctx
->outer
;
11798 gcc_assert (gimple_call_lhs (call_stmt
) == NULL_TREE
);
11799 if (!cctx
->cancellable
)
11801 if (DECL_FUNCTION_CODE (fndecl
)
11802 == BUILT_IN_GOMP_CANCELLATION_POINT
)
11804 stmt
= gimple_build_nop ();
11805 gsi_replace (gsi_p
, stmt
, false);
11809 if (DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
11811 fndecl
= builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL
);
11812 gimple_call_set_fndecl (call_stmt
, fndecl
);
11813 gimple_call_set_fntype (call_stmt
, TREE_TYPE (fndecl
));
11816 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl
)));
11817 gimple_call_set_lhs (call_stmt
, lhs
);
11818 tree fallthru_label
;
11819 fallthru_label
= create_artificial_label (UNKNOWN_LOCATION
);
11821 g
= gimple_build_label (fallthru_label
);
11822 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11823 g
= gimple_build_cond (NE_EXPR
, lhs
,
11824 fold_convert (TREE_TYPE (lhs
),
11825 boolean_false_node
),
11826 cctx
->cancel_label
, fallthru_label
);
11827 gsi_insert_after (gsi_p
, g
, GSI_SAME_STMT
);
11834 if ((ctx
|| task_shared_vars
)
11835 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
11838 /* Just remove clobbers, this should happen only if we have
11839 "privatized" local addressable variables in SIMD regions,
11840 the clobber isn't needed in that case and gimplifying address
11841 of the ARRAY_REF into a pointer and creating MEM_REF based
11842 clobber would create worse code than we get with the clobber
11844 if (gimple_clobber_p (stmt
))
11846 gsi_replace (gsi_p
, gimple_build_nop (), true);
11849 gimple_regimplify_operands (stmt
, gsi_p
);
11856 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
11858 location_t saved_location
= input_location
;
11859 gimple_stmt_iterator gsi
;
11860 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11861 lower_omp_1 (&gsi
, ctx
);
11862 /* During gimplification, we haven't folded statments inside offloading
11863 regions (gimplify.c:maybe_fold_stmt); do that now. */
11864 if (target_nesting_level
)
11865 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
11867 input_location
= saved_location
;
11870 /* Main entry point. */
11872 static unsigned int
11873 execute_lower_omp (void)
11879 /* This pass always runs, to provide PROP_gimple_lomp.
11880 But often, there is nothing to do. */
11881 if (flag_cilkplus
== 0 && flag_openacc
== 0 && flag_openmp
== 0
11882 && flag_openmp_simd
== 0)
11885 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
11886 delete_omp_context
);
11888 body
= gimple_body (current_function_decl
);
11889 scan_omp (&body
, NULL
);
11890 gcc_assert (taskreg_nesting_level
== 0);
11891 FOR_EACH_VEC_ELT (taskreg_contexts
, i
, ctx
)
11892 finish_taskreg_scan (ctx
);
11893 taskreg_contexts
.release ();
11895 if (all_contexts
->root
)
11897 if (task_shared_vars
)
11898 push_gimplify_context ();
11899 lower_omp (&body
, NULL
);
11900 if (task_shared_vars
)
11901 pop_gimplify_context (NULL
);
11906 splay_tree_delete (all_contexts
);
11907 all_contexts
= NULL
;
11909 BITMAP_FREE (task_shared_vars
);
11915 const pass_data pass_data_lower_omp
=
11917 GIMPLE_PASS
, /* type */
11918 "omplower", /* name */
11919 OPTGROUP_NONE
, /* optinfo_flags */
11920 TV_NONE
, /* tv_id */
11921 PROP_gimple_any
, /* properties_required */
11922 PROP_gimple_lomp
, /* properties_provided */
11923 0, /* properties_destroyed */
11924 0, /* todo_flags_start */
11925 0, /* todo_flags_finish */
11928 class pass_lower_omp
: public gimple_opt_pass
11931 pass_lower_omp (gcc::context
*ctxt
)
11932 : gimple_opt_pass (pass_data_lower_omp
, ctxt
)
11935 /* opt_pass methods: */
11936 virtual unsigned int execute (function
*) { return execute_lower_omp (); }
11938 }; // class pass_lower_omp
11940 } // anon namespace
11943 make_pass_lower_omp (gcc::context
*ctxt
)
11945 return new pass_lower_omp (ctxt
);
11948 /* The following is a utility to diagnose structured block violations.
11949 It is not part of the "omplower" pass, as that's invoked too late. It
11950 should be invoked by the respective front ends after gimplification. */
11952 static splay_tree all_labels
;
11954 /* Check for mismatched contexts and generate an error if needed. Return
11955 true if an error is detected. */
11958 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
11959 gimple branch_ctx
, gimple label_ctx
)
11961 gcc_checking_assert (!branch_ctx
|| is_gimple_omp (branch_ctx
));
11962 gcc_checking_assert (!label_ctx
|| is_gimple_omp (label_ctx
));
11964 if (label_ctx
== branch_ctx
)
11967 const char* kind
= NULL
;
11972 && gimple_code (branch_ctx
) == GIMPLE_OMP_FOR
11973 && gimple_omp_for_kind (branch_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
)
11975 && gimple_code (label_ctx
) == GIMPLE_OMP_FOR
11976 && gimple_omp_for_kind (label_ctx
) == GF_OMP_FOR_KIND_CILKSIMD
))
11977 kind
= "Cilk Plus";
11981 if ((branch_ctx
&& is_gimple_omp_oacc (branch_ctx
))
11982 || (label_ctx
&& is_gimple_omp_oacc (label_ctx
)))
11984 gcc_checking_assert (kind
== NULL
);
11990 gcc_checking_assert (flag_openmp
);
11995 Previously we kept track of the label's entire context in diagnose_sb_[12]
11996 so we could traverse it and issue a correct "exit" or "enter" error
11997 message upon a structured block violation.
11999 We built the context by building a list with tree_cons'ing, but there is
12000 no easy counterpart in gimple tuples. It seems like far too much work
12001 for issuing exit/enter error messages. If someone really misses the
12002 distinct error message... patches welcome.
12006 /* Try to avoid confusing the user by producing and error message
12007 with correct "exit" or "enter" verbiage. We prefer "exit"
12008 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12009 if (branch_ctx
== NULL
)
12015 if (TREE_VALUE (label_ctx
) == branch_ctx
)
12020 label_ctx
= TREE_CHAIN (label_ctx
);
12025 error ("invalid exit from %s structured block", kind
);
12027 error ("invalid entry to %s structured block", kind
);
12030 /* If it's obvious we have an invalid entry, be specific about the error. */
12031 if (branch_ctx
== NULL
)
12032 error ("invalid entry to %s structured block", kind
);
12035 /* Otherwise, be vague and lazy, but efficient. */
12036 error ("invalid branch to/from %s structured block", kind
);
12039 gsi_replace (gsi_p
, gimple_build_nop (), false);
12043 /* Pass 1: Create a minimal tree of structured blocks, and record
12044 where each label is found. */
12047 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12048 struct walk_stmt_info
*wi
)
12050 gimple context
= (gimple
) wi
->info
;
12051 gimple inner_context
;
12052 gimple stmt
= gsi_stmt (*gsi_p
);
12054 *handled_ops_p
= true;
12056 switch (gimple_code (stmt
))
12060 case GIMPLE_OMP_PARALLEL
:
12061 case GIMPLE_OMP_TASK
:
12062 case GIMPLE_OMP_SECTIONS
:
12063 case GIMPLE_OMP_SINGLE
:
12064 case GIMPLE_OMP_SECTION
:
12065 case GIMPLE_OMP_MASTER
:
12066 case GIMPLE_OMP_ORDERED
:
12067 case GIMPLE_OMP_CRITICAL
:
12068 case GIMPLE_OMP_TARGET
:
12069 case GIMPLE_OMP_TEAMS
:
12070 case GIMPLE_OMP_TASKGROUP
:
12071 /* The minimal context here is just the current OMP construct. */
12072 inner_context
= stmt
;
12073 wi
->info
= inner_context
;
12074 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12075 wi
->info
= context
;
12078 case GIMPLE_OMP_FOR
:
12079 inner_context
= stmt
;
12080 wi
->info
= inner_context
;
12081 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12083 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
12084 diagnose_sb_1
, NULL
, wi
);
12085 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
12086 wi
->info
= context
;
12090 splay_tree_insert (all_labels
,
12091 (splay_tree_key
) gimple_label_label (
12092 as_a
<glabel
*> (stmt
)),
12093 (splay_tree_value
) context
);
12103 /* Pass 2: Check each branch and see if its context differs from that of
12104 the destination label's context. */
12107 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
12108 struct walk_stmt_info
*wi
)
12110 gimple context
= (gimple
) wi
->info
;
12112 gimple stmt
= gsi_stmt (*gsi_p
);
12114 *handled_ops_p
= true;
12116 switch (gimple_code (stmt
))
12120 case GIMPLE_OMP_PARALLEL
:
12121 case GIMPLE_OMP_TASK
:
12122 case GIMPLE_OMP_SECTIONS
:
12123 case GIMPLE_OMP_SINGLE
:
12124 case GIMPLE_OMP_SECTION
:
12125 case GIMPLE_OMP_MASTER
:
12126 case GIMPLE_OMP_ORDERED
:
12127 case GIMPLE_OMP_CRITICAL
:
12128 case GIMPLE_OMP_TARGET
:
12129 case GIMPLE_OMP_TEAMS
:
12130 case GIMPLE_OMP_TASKGROUP
:
12132 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12133 wi
->info
= context
;
12136 case GIMPLE_OMP_FOR
:
12138 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12140 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
12141 diagnose_sb_2
, NULL
, wi
);
12142 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
12143 wi
->info
= context
;
12148 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
12149 tree lab
= gimple_cond_true_label (cond_stmt
);
12152 n
= splay_tree_lookup (all_labels
,
12153 (splay_tree_key
) lab
);
12154 diagnose_sb_0 (gsi_p
, context
,
12155 n
? (gimple
) n
->value
: NULL
);
12157 lab
= gimple_cond_false_label (cond_stmt
);
12160 n
= splay_tree_lookup (all_labels
,
12161 (splay_tree_key
) lab
);
12162 diagnose_sb_0 (gsi_p
, context
,
12163 n
? (gimple
) n
->value
: NULL
);
12170 tree lab
= gimple_goto_dest (stmt
);
12171 if (TREE_CODE (lab
) != LABEL_DECL
)
12174 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12175 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
12179 case GIMPLE_SWITCH
:
12181 gswitch
*switch_stmt
= as_a
<gswitch
*> (stmt
);
12183 for (i
= 0; i
< gimple_switch_num_labels (switch_stmt
); ++i
)
12185 tree lab
= CASE_LABEL (gimple_switch_label (switch_stmt
, i
));
12186 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
12187 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
12193 case GIMPLE_RETURN
:
12194 diagnose_sb_0 (gsi_p
, context
, NULL
);
12204 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12207 make_gimple_omp_edges (basic_block bb
, struct omp_region
**region
,
12210 gimple last
= last_stmt (bb
);
12211 enum gimple_code code
= gimple_code (last
);
12212 struct omp_region
*cur_region
= *region
;
12213 bool fallthru
= false;
12217 case GIMPLE_OMP_PARALLEL
:
12218 case GIMPLE_OMP_TASK
:
12219 case GIMPLE_OMP_FOR
:
12220 case GIMPLE_OMP_SINGLE
:
12221 case GIMPLE_OMP_TEAMS
:
12222 case GIMPLE_OMP_MASTER
:
12223 case GIMPLE_OMP_TASKGROUP
:
12224 case GIMPLE_OMP_ORDERED
:
12225 case GIMPLE_OMP_CRITICAL
:
12226 case GIMPLE_OMP_SECTION
:
12227 cur_region
= new_omp_region (bb
, code
, cur_region
);
12231 case GIMPLE_OMP_TARGET
:
12232 cur_region
= new_omp_region (bb
, code
, cur_region
);
12234 switch (gimple_omp_target_kind (last
))
12236 case GF_OMP_TARGET_KIND_REGION
:
12237 case GF_OMP_TARGET_KIND_DATA
:
12238 case GF_OMP_TARGET_KIND_OACC_PARALLEL
:
12239 case GF_OMP_TARGET_KIND_OACC_KERNELS
:
12240 case GF_OMP_TARGET_KIND_OACC_DATA
:
12242 case GF_OMP_TARGET_KIND_UPDATE
:
12243 case GF_OMP_TARGET_KIND_OACC_UPDATE
:
12244 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA
:
12245 cur_region
= cur_region
->outer
;
12248 gcc_unreachable ();
12252 case GIMPLE_OMP_SECTIONS
:
12253 cur_region
= new_omp_region (bb
, code
, cur_region
);
12257 case GIMPLE_OMP_SECTIONS_SWITCH
:
12261 case GIMPLE_OMP_ATOMIC_LOAD
:
12262 case GIMPLE_OMP_ATOMIC_STORE
:
12266 case GIMPLE_OMP_RETURN
:
12267 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12268 somewhere other than the next block. This will be
12270 cur_region
->exit
= bb
;
12271 fallthru
= cur_region
->type
!= GIMPLE_OMP_SECTION
;
12272 cur_region
= cur_region
->outer
;
12275 case GIMPLE_OMP_CONTINUE
:
12276 cur_region
->cont
= bb
;
12277 switch (cur_region
->type
)
12279 case GIMPLE_OMP_FOR
:
12280 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12281 succs edges as abnormal to prevent splitting
12283 single_succ_edge (cur_region
->entry
)->flags
|= EDGE_ABNORMAL
;
12284 /* Make the loopback edge. */
12285 make_edge (bb
, single_succ (cur_region
->entry
),
12288 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12289 corresponds to the case that the body of the loop
12290 is not executed at all. */
12291 make_edge (cur_region
->entry
, bb
->next_bb
, EDGE_ABNORMAL
);
12292 make_edge (bb
, bb
->next_bb
, EDGE_FALLTHRU
| EDGE_ABNORMAL
);
12296 case GIMPLE_OMP_SECTIONS
:
12297 /* Wire up the edges into and out of the nested sections. */
12299 basic_block switch_bb
= single_succ (cur_region
->entry
);
12301 struct omp_region
*i
;
12302 for (i
= cur_region
->inner
; i
; i
= i
->next
)
12304 gcc_assert (i
->type
== GIMPLE_OMP_SECTION
);
12305 make_edge (switch_bb
, i
->entry
, 0);
12306 make_edge (i
->exit
, bb
, EDGE_FALLTHRU
);
12309 /* Make the loopback edge to the block with
12310 GIMPLE_OMP_SECTIONS_SWITCH. */
12311 make_edge (bb
, switch_bb
, 0);
12313 /* Make the edge from the switch to exit. */
12314 make_edge (switch_bb
, bb
->next_bb
, 0);
12320 gcc_unreachable ();
12325 gcc_unreachable ();
12328 if (*region
!= cur_region
)
12330 *region
= cur_region
;
12332 *region_idx
= cur_region
->entry
->index
;
12340 static unsigned int
12341 diagnose_omp_structured_block_errors (void)
12343 struct walk_stmt_info wi
;
12344 gimple_seq body
= gimple_body (current_function_decl
);
12346 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
12348 memset (&wi
, 0, sizeof (wi
));
12349 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
12351 memset (&wi
, 0, sizeof (wi
));
12352 wi
.want_locations
= true;
12353 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
12355 gimple_set_body (current_function_decl
, body
);
12357 splay_tree_delete (all_labels
);
12365 const pass_data pass_data_diagnose_omp_blocks
=
12367 GIMPLE_PASS
, /* type */
12368 "*diagnose_omp_blocks", /* name */
12369 OPTGROUP_NONE
, /* optinfo_flags */
12370 TV_NONE
, /* tv_id */
12371 PROP_gimple_any
, /* properties_required */
12372 0, /* properties_provided */
12373 0, /* properties_destroyed */
12374 0, /* todo_flags_start */
12375 0, /* todo_flags_finish */
12378 class pass_diagnose_omp_blocks
: public gimple_opt_pass
12381 pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12382 : gimple_opt_pass (pass_data_diagnose_omp_blocks
, ctxt
)
12385 /* opt_pass methods: */
12386 virtual bool gate (function
*)
12388 return flag_cilkplus
|| flag_openacc
|| flag_openmp
;
12390 virtual unsigned int execute (function
*)
12392 return diagnose_omp_structured_block_errors ();
12395 }; // class pass_diagnose_omp_blocks
12397 } // anon namespace
12400 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
12402 return new pass_diagnose_omp_blocks (ctxt
);
12405 /* SIMD clone supporting code. */
12407 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12408 of arguments to reserve space for. */
12410 static struct cgraph_simd_clone
*
12411 simd_clone_struct_alloc (int nargs
)
12413 struct cgraph_simd_clone
*clone_info
;
12414 size_t len
= (sizeof (struct cgraph_simd_clone
)
12415 + nargs
* sizeof (struct cgraph_simd_clone_arg
));
12416 clone_info
= (struct cgraph_simd_clone
*)
12417 ggc_internal_cleared_alloc (len
);
12421 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12424 simd_clone_struct_copy (struct cgraph_simd_clone
*to
,
12425 struct cgraph_simd_clone
*from
)
12427 memcpy (to
, from
, (sizeof (struct cgraph_simd_clone
)
12428 + ((from
->nargs
- from
->inbranch
)
12429 * sizeof (struct cgraph_simd_clone_arg
))));
12432 /* Return vector of parameter types of function FNDECL. This uses
12433 TYPE_ARG_TYPES if available, otherwise falls back to types of
12434 DECL_ARGUMENTS types. */
12437 simd_clone_vector_of_formal_parm_types (tree fndecl
)
12439 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)))
12440 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl
));
12441 vec
<tree
> args
= ipa_get_vector_of_formal_parms (fndecl
);
12444 FOR_EACH_VEC_ELT (args
, i
, arg
)
12445 args
[i
] = TREE_TYPE (args
[i
]);
12449 /* Given a simd function in NODE, extract the simd specific
12450 information from the OMP clauses passed in CLAUSES, and return
12451 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12452 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12453 otherwise set to FALSE. */
12455 static struct cgraph_simd_clone
*
12456 simd_clone_clauses_extract (struct cgraph_node
*node
, tree clauses
,
12457 bool *inbranch_specified
)
12459 vec
<tree
> args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12462 *inbranch_specified
= false;
12464 n
= args
.length ();
12465 if (n
> 0 && args
.last () == void_type_node
)
12468 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12469 be cloned have a distinctive artificial label in addition to "omp
12473 && lookup_attribute ("cilk simd function",
12474 DECL_ATTRIBUTES (node
->decl
)));
12476 /* Allocate one more than needed just in case this is an in-branch
12477 clone which will require a mask argument. */
12478 struct cgraph_simd_clone
*clone_info
= simd_clone_struct_alloc (n
+ 1);
12479 clone_info
->nargs
= n
;
12480 clone_info
->cilk_elemental
= cilk_clone
;
12487 clauses
= TREE_VALUE (clauses
);
12488 if (!clauses
|| TREE_CODE (clauses
) != OMP_CLAUSE
)
12491 for (t
= clauses
; t
; t
= OMP_CLAUSE_CHAIN (t
))
12493 switch (OMP_CLAUSE_CODE (t
))
12495 case OMP_CLAUSE_INBRANCH
:
12496 clone_info
->inbranch
= 1;
12497 *inbranch_specified
= true;
12499 case OMP_CLAUSE_NOTINBRANCH
:
12500 clone_info
->inbranch
= 0;
12501 *inbranch_specified
= true;
12503 case OMP_CLAUSE_SIMDLEN
:
12504 clone_info
->simdlen
12505 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t
));
12507 case OMP_CLAUSE_LINEAR
:
12509 tree decl
= OMP_CLAUSE_DECL (t
);
12510 tree step
= OMP_CLAUSE_LINEAR_STEP (t
);
12511 int argno
= TREE_INT_CST_LOW (decl
);
12512 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t
))
12514 clone_info
->args
[argno
].arg_type
12515 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
;
12516 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12517 gcc_assert (clone_info
->args
[argno
].linear_step
>= 0
12518 && clone_info
->args
[argno
].linear_step
< n
);
12522 if (POINTER_TYPE_P (args
[argno
]))
12523 step
= fold_convert (ssizetype
, step
);
12524 if (!tree_fits_shwi_p (step
))
12526 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12527 "ignoring large linear step");
12531 else if (integer_zerop (step
))
12533 warning_at (OMP_CLAUSE_LOCATION (t
), 0,
12534 "ignoring zero linear step");
12540 clone_info
->args
[argno
].arg_type
12541 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
;
12542 clone_info
->args
[argno
].linear_step
= tree_to_shwi (step
);
12547 case OMP_CLAUSE_UNIFORM
:
12549 tree decl
= OMP_CLAUSE_DECL (t
);
12550 int argno
= tree_to_uhwi (decl
);
12551 clone_info
->args
[argno
].arg_type
12552 = SIMD_CLONE_ARG_TYPE_UNIFORM
;
12555 case OMP_CLAUSE_ALIGNED
:
12557 tree decl
= OMP_CLAUSE_DECL (t
);
12558 int argno
= tree_to_uhwi (decl
);
12559 clone_info
->args
[argno
].alignment
12560 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t
));
12571 /* Given a SIMD clone in NODE, calculate the characteristic data
12572 type and return the coresponding type. The characteristic data
12573 type is computed as described in the Intel Vector ABI. */
12576 simd_clone_compute_base_data_type (struct cgraph_node
*node
,
12577 struct cgraph_simd_clone
*clone_info
)
12579 tree type
= integer_type_node
;
12580 tree fndecl
= node
->decl
;
12582 /* a) For non-void function, the characteristic data type is the
12584 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) != VOID_TYPE
)
12585 type
= TREE_TYPE (TREE_TYPE (fndecl
));
12587 /* b) If the function has any non-uniform, non-linear parameters,
12588 then the characteristic data type is the type of the first
12592 vec
<tree
> map
= simd_clone_vector_of_formal_parm_types (fndecl
);
12593 for (unsigned int i
= 0; i
< clone_info
->nargs
; ++i
)
12594 if (clone_info
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_VECTOR
)
12602 /* c) If the characteristic data type determined by a) or b) above
12603 is struct, union, or class type which is pass-by-value (except
12604 for the type that maps to the built-in complex data type), the
12605 characteristic data type is int. */
12606 if (RECORD_OR_UNION_TYPE_P (type
)
12607 && !aggregate_value_p (type
, NULL
)
12608 && TREE_CODE (type
) != COMPLEX_TYPE
)
12609 return integer_type_node
;
12611 /* d) If none of the above three classes is applicable, the
12612 characteristic data type is int. */
12616 /* e) For Intel Xeon Phi native and offload compilation, if the
12617 resulting characteristic data type is 8-bit or 16-bit integer
12618 data type, the characteristic data type is int. */
12619 /* Well, we don't handle Xeon Phi yet. */
12623 simd_clone_mangle (struct cgraph_node
*node
,
12624 struct cgraph_simd_clone
*clone_info
)
12626 char vecsize_mangle
= clone_info
->vecsize_mangle
;
12627 char mask
= clone_info
->inbranch
? 'M' : 'N';
12628 unsigned int simdlen
= clone_info
->simdlen
;
12632 gcc_assert (vecsize_mangle
&& simdlen
);
12634 pp_string (&pp
, "_ZGV");
12635 pp_character (&pp
, vecsize_mangle
);
12636 pp_character (&pp
, mask
);
12637 pp_decimal_int (&pp
, simdlen
);
12639 for (n
= 0; n
< clone_info
->nargs
; ++n
)
12641 struct cgraph_simd_clone_arg arg
= clone_info
->args
[n
];
12643 if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
)
12644 pp_character (&pp
, 'u');
12645 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
12647 gcc_assert (arg
.linear_step
!= 0);
12648 pp_character (&pp
, 'l');
12649 if (arg
.linear_step
> 1)
12650 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12651 else if (arg
.linear_step
< 0)
12653 pp_character (&pp
, 'n');
12654 pp_unsigned_wide_integer (&pp
, (-(unsigned HOST_WIDE_INT
)
12658 else if (arg
.arg_type
== SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
)
12660 pp_character (&pp
, 's');
12661 pp_unsigned_wide_integer (&pp
, arg
.linear_step
);
12664 pp_character (&pp
, 'v');
12667 pp_character (&pp
, 'a');
12668 pp_decimal_int (&pp
, arg
.alignment
);
12672 pp_underscore (&pp
);
12673 const char *str
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node
->decl
));
12676 pp_string (&pp
, str
);
12677 str
= pp_formatted_text (&pp
);
12679 /* If there already is a SIMD clone with the same mangled name, don't
12680 add another one. This can happen e.g. for
12681 #pragma omp declare simd
12682 #pragma omp declare simd simdlen(8)
12683 int foo (int, int);
12684 if the simdlen is assumed to be 8 for the first one, etc. */
12685 for (struct cgraph_node
*clone
= node
->simd_clones
; clone
;
12686 clone
= clone
->simdclone
->next_clone
)
12687 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone
->decl
)),
12691 return get_identifier (str
);
12694 /* Create a simd clone of OLD_NODE and return it. */
12696 static struct cgraph_node
*
12697 simd_clone_create (struct cgraph_node
*old_node
)
12699 struct cgraph_node
*new_node
;
12700 if (old_node
->definition
)
12702 if (!old_node
->has_gimple_body_p ())
12704 old_node
->get_body ();
12705 new_node
= old_node
->create_version_clone_with_body (vNULL
, NULL
, NULL
,
12711 tree old_decl
= old_node
->decl
;
12712 tree new_decl
= copy_node (old_node
->decl
);
12713 DECL_NAME (new_decl
) = clone_function_name (old_decl
, "simdclone");
12714 SET_DECL_ASSEMBLER_NAME (new_decl
, DECL_NAME (new_decl
));
12715 SET_DECL_RTL (new_decl
, NULL
);
12716 DECL_STATIC_CONSTRUCTOR (new_decl
) = 0;
12717 DECL_STATIC_DESTRUCTOR (new_decl
) = 0;
12718 new_node
= old_node
->create_version_clone (new_decl
, vNULL
, NULL
);
12719 symtab
->call_cgraph_insertion_hooks (new_node
);
12721 if (new_node
== NULL
)
12724 TREE_PUBLIC (new_node
->decl
) = TREE_PUBLIC (old_node
->decl
);
12726 /* The function cgraph_function_versioning () will force the new
12727 symbol local. Undo this, and inherit external visability from
12729 new_node
->local
.local
= old_node
->local
.local
;
12730 new_node
->externally_visible
= old_node
->externally_visible
;
12735 /* Adjust the return type of the given function to its appropriate
12736 vector counterpart. Returns a simd array to be used throughout the
12737 function as a return value. */
12740 simd_clone_adjust_return_type (struct cgraph_node
*node
)
12742 tree fndecl
= node
->decl
;
12743 tree orig_rettype
= TREE_TYPE (TREE_TYPE (fndecl
));
12744 unsigned int veclen
;
12747 /* Adjust the function return type. */
12748 if (orig_rettype
== void_type_node
)
12750 TREE_TYPE (fndecl
) = build_distinct_type_copy (TREE_TYPE (fndecl
));
12751 t
= TREE_TYPE (TREE_TYPE (fndecl
));
12752 if (INTEGRAL_TYPE_P (t
) || POINTER_TYPE_P (t
))
12753 veclen
= node
->simdclone
->vecsize_int
;
12755 veclen
= node
->simdclone
->vecsize_float
;
12756 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (t
));
12757 if (veclen
> node
->simdclone
->simdlen
)
12758 veclen
= node
->simdclone
->simdlen
;
12759 if (POINTER_TYPE_P (t
))
12760 t
= pointer_sized_int_node
;
12761 if (veclen
== node
->simdclone
->simdlen
)
12762 t
= build_vector_type (t
, node
->simdclone
->simdlen
);
12765 t
= build_vector_type (t
, veclen
);
12766 t
= build_array_type_nelts (t
, node
->simdclone
->simdlen
/ veclen
);
12768 TREE_TYPE (TREE_TYPE (fndecl
)) = t
;
12769 if (!node
->definition
)
12772 t
= DECL_RESULT (fndecl
);
12773 /* Adjust the DECL_RESULT. */
12774 gcc_assert (TREE_TYPE (t
) != void_type_node
);
12775 TREE_TYPE (t
) = TREE_TYPE (TREE_TYPE (fndecl
));
12778 tree atype
= build_array_type_nelts (orig_rettype
,
12779 node
->simdclone
->simdlen
);
12780 if (veclen
!= node
->simdclone
->simdlen
)
12781 return build1 (VIEW_CONVERT_EXPR
, atype
, t
);
12783 /* Set up a SIMD array to use as the return value. */
12784 tree retval
= create_tmp_var_raw (atype
, "retval");
12785 gimple_add_tmp_var (retval
);
12789 /* Each vector argument has a corresponding array to be used locally
12790 as part of the eventual loop. Create such temporary array and
12793 PREFIX is the prefix to be used for the temporary.
12795 TYPE is the inner element type.
12797 SIMDLEN is the number of elements. */
12800 create_tmp_simd_array (const char *prefix
, tree type
, int simdlen
)
12802 tree atype
= build_array_type_nelts (type
, simdlen
);
12803 tree avar
= create_tmp_var_raw (atype
, prefix
);
12804 gimple_add_tmp_var (avar
);
12808 /* Modify the function argument types to their corresponding vector
12809 counterparts if appropriate. Also, create one array for each simd
12810 argument to be used locally when using the function arguments as
12813 NODE is the function whose arguments are to be adjusted.
12815 Returns an adjustment vector that will be filled describing how the
12816 argument types will be adjusted. */
12818 static ipa_parm_adjustment_vec
12819 simd_clone_adjust_argument_types (struct cgraph_node
*node
)
12822 ipa_parm_adjustment_vec adjustments
;
12824 if (node
->definition
)
12825 args
= ipa_get_vector_of_formal_parms (node
->decl
);
12827 args
= simd_clone_vector_of_formal_parm_types (node
->decl
);
12828 adjustments
.create (args
.length ());
12829 unsigned i
, j
, veclen
;
12830 struct ipa_parm_adjustment adj
;
12831 for (i
= 0; i
< node
->simdclone
->nargs
; ++i
)
12833 memset (&adj
, 0, sizeof (adj
));
12834 tree parm
= args
[i
];
12835 tree parm_type
= node
->definition
? TREE_TYPE (parm
) : parm
;
12836 adj
.base_index
= i
;
12839 node
->simdclone
->args
[i
].orig_arg
= node
->definition
? parm
: NULL_TREE
;
12840 node
->simdclone
->args
[i
].orig_type
= parm_type
;
12842 if (node
->simdclone
->args
[i
].arg_type
!= SIMD_CLONE_ARG_TYPE_VECTOR
)
12844 /* No adjustment necessary for scalar arguments. */
12845 adj
.op
= IPA_PARM_OP_COPY
;
12849 if (INTEGRAL_TYPE_P (parm_type
) || POINTER_TYPE_P (parm_type
))
12850 veclen
= node
->simdclone
->vecsize_int
;
12852 veclen
= node
->simdclone
->vecsize_float
;
12853 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (parm_type
));
12854 if (veclen
> node
->simdclone
->simdlen
)
12855 veclen
= node
->simdclone
->simdlen
;
12856 adj
.arg_prefix
= "simd";
12857 if (POINTER_TYPE_P (parm_type
))
12858 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
12860 adj
.type
= build_vector_type (parm_type
, veclen
);
12861 node
->simdclone
->args
[i
].vector_type
= adj
.type
;
12862 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
12864 adjustments
.safe_push (adj
);
12867 memset (&adj
, 0, sizeof (adj
));
12868 adj
.op
= IPA_PARM_OP_NEW
;
12869 adj
.arg_prefix
= "simd";
12870 adj
.base_index
= i
;
12871 adj
.type
= node
->simdclone
->args
[i
].vector_type
;
12875 if (node
->definition
)
12876 node
->simdclone
->args
[i
].simd_array
12877 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm
)),
12878 parm_type
, node
->simdclone
->simdlen
);
12880 adjustments
.safe_push (adj
);
12883 if (node
->simdclone
->inbranch
)
12886 = simd_clone_compute_base_data_type (node
->simdclone
->origin
,
12889 memset (&adj
, 0, sizeof (adj
));
12890 adj
.op
= IPA_PARM_OP_NEW
;
12891 adj
.arg_prefix
= "mask";
12893 adj
.base_index
= i
;
12894 if (INTEGRAL_TYPE_P (base_type
) || POINTER_TYPE_P (base_type
))
12895 veclen
= node
->simdclone
->vecsize_int
;
12897 veclen
= node
->simdclone
->vecsize_float
;
12898 veclen
/= GET_MODE_BITSIZE (TYPE_MODE (base_type
));
12899 if (veclen
> node
->simdclone
->simdlen
)
12900 veclen
= node
->simdclone
->simdlen
;
12901 if (POINTER_TYPE_P (base_type
))
12902 adj
.type
= build_vector_type (pointer_sized_int_node
, veclen
);
12904 adj
.type
= build_vector_type (base_type
, veclen
);
12905 adjustments
.safe_push (adj
);
12907 for (j
= veclen
; j
< node
->simdclone
->simdlen
; j
+= veclen
)
12908 adjustments
.safe_push (adj
);
12910 /* We have previously allocated one extra entry for the mask. Use
12912 struct cgraph_simd_clone
*sc
= node
->simdclone
;
12914 if (node
->definition
)
12916 sc
->args
[i
].orig_arg
12917 = build_decl (UNKNOWN_LOCATION
, PARM_DECL
, NULL
, base_type
);
12918 sc
->args
[i
].simd_array
12919 = create_tmp_simd_array ("mask", base_type
, sc
->simdlen
);
12921 sc
->args
[i
].orig_type
= base_type
;
12922 sc
->args
[i
].arg_type
= SIMD_CLONE_ARG_TYPE_MASK
;
12925 if (node
->definition
)
12926 ipa_modify_formal_parameters (node
->decl
, adjustments
);
12929 tree new_arg_types
= NULL_TREE
, new_reversed
;
12930 bool last_parm_void
= false;
12931 if (args
.length () > 0 && args
.last () == void_type_node
)
12932 last_parm_void
= true;
12934 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)));
12935 j
= adjustments
.length ();
12936 for (i
= 0; i
< j
; i
++)
12938 struct ipa_parm_adjustment
*adj
= &adjustments
[i
];
12940 if (adj
->op
== IPA_PARM_OP_COPY
)
12941 ptype
= args
[adj
->base_index
];
12944 new_arg_types
= tree_cons (NULL_TREE
, ptype
, new_arg_types
);
12946 new_reversed
= nreverse (new_arg_types
);
12947 if (last_parm_void
)
12950 TREE_CHAIN (new_arg_types
) = void_list_node
;
12952 new_reversed
= void_list_node
;
12955 tree new_type
= build_distinct_type_copy (TREE_TYPE (node
->decl
));
12956 TYPE_ARG_TYPES (new_type
) = new_reversed
;
12957 TREE_TYPE (node
->decl
) = new_type
;
12959 adjustments
.release ();
12962 return adjustments
;
12965 /* Initialize and copy the function arguments in NODE to their
12966 corresponding local simd arrays. Returns a fresh gimple_seq with
12967 the instruction sequence generated. */
12970 simd_clone_init_simd_arrays (struct cgraph_node
*node
,
12971 ipa_parm_adjustment_vec adjustments
)
12973 gimple_seq seq
= NULL
;
12974 unsigned i
= 0, j
= 0, k
;
12976 for (tree arg
= DECL_ARGUMENTS (node
->decl
);
12978 arg
= DECL_CHAIN (arg
), i
++, j
++)
12980 if (adjustments
[j
].op
== IPA_PARM_OP_COPY
)
12983 node
->simdclone
->args
[i
].vector_arg
= arg
;
12985 tree array
= node
->simdclone
->args
[i
].simd_array
;
12986 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
)) == node
->simdclone
->simdlen
)
12988 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
12989 tree ptr
= build_fold_addr_expr (array
);
12990 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
12991 build_int_cst (ptype
, 0));
12992 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
12993 gimplify_and_add (t
, &seq
);
12997 unsigned int simdlen
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg
));
12998 tree ptype
= build_pointer_type (TREE_TYPE (TREE_TYPE (array
)));
12999 for (k
= 0; k
< node
->simdclone
->simdlen
; k
+= simdlen
)
13001 tree ptr
= build_fold_addr_expr (array
);
13005 arg
= DECL_CHAIN (arg
);
13009 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg
))));
13010 tree t
= build2 (MEM_REF
, TREE_TYPE (arg
), ptr
,
13011 build_int_cst (ptype
, k
* elemsize
));
13012 t
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), t
, arg
);
13013 gimplify_and_add (t
, &seq
);
13020 /* Callback info for ipa_simd_modify_stmt_ops below. */
13022 struct modify_stmt_info
{
13023 ipa_parm_adjustment_vec adjustments
;
13025 /* True if the parent statement was modified by
13026 ipa_simd_modify_stmt_ops. */
13030 /* Callback for walk_gimple_op.
13032 Adjust operands from a given statement as specified in the
13033 adjustments vector in the callback data. */
13036 ipa_simd_modify_stmt_ops (tree
*tp
, int *walk_subtrees
, void *data
)
13038 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
13039 struct modify_stmt_info
*info
= (struct modify_stmt_info
*) wi
->info
;
13040 tree
*orig_tp
= tp
;
13041 if (TREE_CODE (*tp
) == ADDR_EXPR
)
13042 tp
= &TREE_OPERAND (*tp
, 0);
13043 struct ipa_parm_adjustment
*cand
= NULL
;
13044 if (TREE_CODE (*tp
) == PARM_DECL
)
13045 cand
= ipa_get_adjustment_candidate (&tp
, NULL
, info
->adjustments
, true);
13049 *walk_subtrees
= 0;
13052 tree repl
= NULL_TREE
;
13054 repl
= unshare_expr (cand
->new_decl
);
13059 *walk_subtrees
= 0;
13060 bool modified
= info
->modified
;
13061 info
->modified
= false;
13062 walk_tree (tp
, ipa_simd_modify_stmt_ops
, wi
, wi
->pset
);
13063 if (!info
->modified
)
13065 info
->modified
= modified
;
13068 info
->modified
= modified
;
13077 repl
= build_fold_addr_expr (repl
);
13079 if (is_gimple_debug (info
->stmt
))
13081 tree vexpr
= make_node (DEBUG_EXPR_DECL
);
13082 stmt
= gimple_build_debug_source_bind (vexpr
, repl
, NULL
);
13083 DECL_ARTIFICIAL (vexpr
) = 1;
13084 TREE_TYPE (vexpr
) = TREE_TYPE (repl
);
13085 DECL_MODE (vexpr
) = TYPE_MODE (TREE_TYPE (repl
));
13090 stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl
)), repl
);
13091 repl
= gimple_assign_lhs (stmt
);
13093 gimple_stmt_iterator gsi
= gsi_for_stmt (info
->stmt
);
13094 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13097 else if (!useless_type_conversion_p (TREE_TYPE (*tp
), TREE_TYPE (repl
)))
13099 tree vce
= build1 (VIEW_CONVERT_EXPR
, TREE_TYPE (*tp
), repl
);
13105 info
->modified
= true;
13109 /* Traverse the function body and perform all modifications as
13110 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13111 modified such that the replacement/reduction value will now be an
13112 offset into the corresponding simd_array.
13114 This function will replace all function argument uses with their
13115 corresponding simd array elements, and ajust the return values
13119 ipa_simd_modify_function_body (struct cgraph_node
*node
,
13120 ipa_parm_adjustment_vec adjustments
,
13121 tree retval_array
, tree iter
)
13124 unsigned int i
, j
, l
;
13126 /* Re-use the adjustments array, but this time use it to replace
13127 every function argument use to an offset into the corresponding
13129 for (i
= 0, j
= 0; i
< node
->simdclone
->nargs
; ++i
, ++j
)
13131 if (!node
->simdclone
->args
[i
].vector_arg
)
13134 tree basetype
= TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
);
13135 tree vectype
= TREE_TYPE (node
->simdclone
->args
[i
].vector_arg
);
13136 adjustments
[j
].new_decl
13137 = build4 (ARRAY_REF
,
13139 node
->simdclone
->args
[i
].simd_array
,
13141 NULL_TREE
, NULL_TREE
);
13142 if (adjustments
[j
].op
== IPA_PARM_OP_NONE
13143 && TYPE_VECTOR_SUBPARTS (vectype
) < node
->simdclone
->simdlen
)
13144 j
+= node
->simdclone
->simdlen
/ TYPE_VECTOR_SUBPARTS (vectype
) - 1;
13147 l
= adjustments
.length ();
13148 for (i
= 1; i
< num_ssa_names
; i
++)
13150 tree name
= ssa_name (i
);
13152 && SSA_NAME_VAR (name
)
13153 && TREE_CODE (SSA_NAME_VAR (name
)) == PARM_DECL
)
13155 for (j
= 0; j
< l
; j
++)
13156 if (SSA_NAME_VAR (name
) == adjustments
[j
].base
13157 && adjustments
[j
].new_decl
)
13160 if (adjustments
[j
].new_ssa_base
== NULL_TREE
)
13163 = copy_var_decl (adjustments
[j
].base
,
13164 DECL_NAME (adjustments
[j
].base
),
13165 TREE_TYPE (adjustments
[j
].base
));
13166 adjustments
[j
].new_ssa_base
= base_var
;
13169 base_var
= adjustments
[j
].new_ssa_base
;
13170 if (SSA_NAME_IS_DEFAULT_DEF (name
))
13172 bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13173 gimple_stmt_iterator gsi
= gsi_after_labels (bb
);
13174 tree new_decl
= unshare_expr (adjustments
[j
].new_decl
);
13175 set_ssa_default_def (cfun
, adjustments
[j
].base
, NULL_TREE
);
13176 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13177 SSA_NAME_IS_DEFAULT_DEF (name
) = 0;
13178 gimple stmt
= gimple_build_assign (name
, new_decl
);
13179 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
13182 SET_SSA_NAME_VAR_OR_IDENTIFIER (name
, base_var
);
13187 struct modify_stmt_info info
;
13188 info
.adjustments
= adjustments
;
13190 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->decl
))
13192 gimple_stmt_iterator gsi
;
13194 gsi
= gsi_start_bb (bb
);
13195 while (!gsi_end_p (gsi
))
13197 gimple stmt
= gsi_stmt (gsi
);
13199 struct walk_stmt_info wi
;
13201 memset (&wi
, 0, sizeof (wi
));
13202 info
.modified
= false;
13204 walk_gimple_op (stmt
, ipa_simd_modify_stmt_ops
, &wi
);
13206 if (greturn
*return_stmt
= dyn_cast
<greturn
*> (stmt
))
13208 tree retval
= gimple_return_retval (return_stmt
);
13211 gsi_remove (&gsi
, true);
13215 /* Replace `return foo' with `retval_array[iter] = foo'. */
13216 tree ref
= build4 (ARRAY_REF
, TREE_TYPE (retval
),
13217 retval_array
, iter
, NULL
, NULL
);
13218 stmt
= gimple_build_assign (ref
, retval
);
13219 gsi_replace (&gsi
, stmt
, true);
13220 info
.modified
= true;
13225 update_stmt (stmt
);
13226 if (maybe_clean_eh_stmt (stmt
))
13227 gimple_purge_dead_eh_edges (gimple_bb (stmt
));
13234 /* Adjust the argument types in NODE to their appropriate vector
13238 simd_clone_adjust (struct cgraph_node
*node
)
13240 push_cfun (DECL_STRUCT_FUNCTION (node
->decl
));
13242 targetm
.simd_clone
.adjust (node
);
13244 tree retval
= simd_clone_adjust_return_type (node
);
13245 ipa_parm_adjustment_vec adjustments
13246 = simd_clone_adjust_argument_types (node
);
13248 push_gimplify_context ();
13250 gimple_seq seq
= simd_clone_init_simd_arrays (node
, adjustments
);
13252 /* Adjust all uses of vector arguments accordingly. Adjust all
13253 return values accordingly. */
13254 tree iter
= create_tmp_var (unsigned_type_node
, "iter");
13255 tree iter1
= make_ssa_name (iter
);
13256 tree iter2
= make_ssa_name (iter
);
13257 ipa_simd_modify_function_body (node
, adjustments
, retval
, iter1
);
13259 /* Initialize the iteration variable. */
13260 basic_block entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13261 basic_block body_bb
= split_block_after_labels (entry_bb
)->dest
;
13262 gimple_stmt_iterator gsi
= gsi_after_labels (entry_bb
);
13263 /* Insert the SIMD array and iv initialization at function
13265 gsi_insert_seq_before (&gsi
, seq
, GSI_NEW_STMT
);
13267 pop_gimplify_context (NULL
);
13269 /* Create a new BB right before the original exit BB, to hold the
13270 iteration increment and the condition/branch. */
13271 basic_block orig_exit
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), 0)->src
;
13272 basic_block incr_bb
= create_empty_bb (orig_exit
);
13273 add_bb_to_loop (incr_bb
, body_bb
->loop_father
);
13274 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13275 flag. Set it now to be a FALLTHRU_EDGE. */
13276 gcc_assert (EDGE_COUNT (orig_exit
->succs
) == 1);
13277 EDGE_SUCC (orig_exit
, 0)->flags
|= EDGE_FALLTHRU
;
13278 for (unsigned i
= 0;
13279 i
< EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
); ++i
)
13281 edge e
= EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun
), i
);
13282 redirect_edge_succ (e
, incr_bb
);
13284 edge e
= make_edge (incr_bb
, EXIT_BLOCK_PTR_FOR_FN (cfun
), 0);
13285 e
->probability
= REG_BR_PROB_BASE
;
13286 gsi
= gsi_last_bb (incr_bb
);
13287 gimple g
= gimple_build_assign (iter2
, PLUS_EXPR
, iter1
,
13288 build_int_cst (unsigned_type_node
, 1));
13289 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13291 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13292 struct loop
*loop
= alloc_loop ();
13293 cfun
->has_force_vectorize_loops
= true;
13294 loop
->safelen
= node
->simdclone
->simdlen
;
13295 loop
->force_vectorize
= true;
13296 loop
->header
= body_bb
;
13298 /* Branch around the body if the mask applies. */
13299 if (node
->simdclone
->inbranch
)
13301 gimple_stmt_iterator gsi
= gsi_last_bb (loop
->header
);
13303 = node
->simdclone
->args
[node
->simdclone
->nargs
- 1].simd_array
;
13304 tree mask
= make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array
)));
13305 tree aref
= build4 (ARRAY_REF
,
13306 TREE_TYPE (TREE_TYPE (mask_array
)),
13309 g
= gimple_build_assign (mask
, aref
);
13310 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13311 int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref
)));
13312 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref
)))
13314 aref
= build1 (VIEW_CONVERT_EXPR
,
13315 build_nonstandard_integer_type (bitsize
, 0), mask
);
13316 mask
= make_ssa_name (TREE_TYPE (aref
));
13317 g
= gimple_build_assign (mask
, aref
);
13318 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13321 g
= gimple_build_cond (EQ_EXPR
, mask
, build_zero_cst (TREE_TYPE (mask
)),
13323 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13324 make_edge (loop
->header
, incr_bb
, EDGE_TRUE_VALUE
);
13325 FALLTHRU_EDGE (loop
->header
)->flags
= EDGE_FALSE_VALUE
;
13328 /* Generate the condition. */
13329 g
= gimple_build_cond (LT_EXPR
,
13331 build_int_cst (unsigned_type_node
,
13332 node
->simdclone
->simdlen
),
13334 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13335 e
= split_block (incr_bb
, gsi_stmt (gsi
));
13336 basic_block latch_bb
= e
->dest
;
13337 basic_block new_exit_bb
;
13338 new_exit_bb
= split_block (latch_bb
, NULL
)->dest
;
13339 loop
->latch
= latch_bb
;
13341 redirect_edge_succ (FALLTHRU_EDGE (latch_bb
), body_bb
);
13343 make_edge (incr_bb
, new_exit_bb
, EDGE_FALSE_VALUE
);
13344 /* The successor of incr_bb is already pointing to latch_bb; just
13346 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13347 FALLTHRU_EDGE (incr_bb
)->flags
= EDGE_TRUE_VALUE
;
13349 gphi
*phi
= create_phi_node (iter1
, body_bb
);
13350 edge preheader_edge
= find_edge (entry_bb
, body_bb
);
13351 edge latch_edge
= single_succ_edge (latch_bb
);
13352 add_phi_arg (phi
, build_zero_cst (unsigned_type_node
), preheader_edge
,
13354 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13356 /* Generate the new return. */
13357 gsi
= gsi_last_bb (new_exit_bb
);
13359 && TREE_CODE (retval
) == VIEW_CONVERT_EXPR
13360 && TREE_CODE (TREE_OPERAND (retval
, 0)) == RESULT_DECL
)
13361 retval
= TREE_OPERAND (retval
, 0);
13364 retval
= build1 (VIEW_CONVERT_EXPR
,
13365 TREE_TYPE (TREE_TYPE (node
->decl
)),
13367 retval
= force_gimple_operand_gsi (&gsi
, retval
, true, NULL
,
13368 false, GSI_CONTINUE_LINKING
);
13370 g
= gimple_build_return (retval
);
13371 gsi_insert_after (&gsi
, g
, GSI_CONTINUE_LINKING
);
13373 /* Handle aligned clauses by replacing default defs of the aligned
13374 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13375 lhs. Handle linear by adding PHIs. */
13376 for (unsigned i
= 0; i
< node
->simdclone
->nargs
; i
++)
13377 if (node
->simdclone
->args
[i
].alignment
13378 && node
->simdclone
->args
[i
].arg_type
== SIMD_CLONE_ARG_TYPE_UNIFORM
13379 && (node
->simdclone
->args
[i
].alignment
13380 & (node
->simdclone
->args
[i
].alignment
- 1)) == 0
13381 && TREE_CODE (TREE_TYPE (node
->simdclone
->args
[i
].orig_arg
))
13384 unsigned int alignment
= node
->simdclone
->args
[i
].alignment
;
13385 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13386 tree def
= ssa_default_def (cfun
, orig_arg
);
13387 if (def
&& !has_zero_uses (def
))
13389 tree fn
= builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED
);
13390 gimple_seq seq
= NULL
;
13391 bool need_cvt
= false;
13393 = gimple_build_call (fn
, 2, def
, size_int (alignment
));
13395 if (!useless_type_conversion_p (TREE_TYPE (orig_arg
),
13398 tree t
= make_ssa_name (need_cvt
? ptr_type_node
: orig_arg
);
13399 gimple_call_set_lhs (g
, t
);
13400 gimple_seq_add_stmt_without_update (&seq
, g
);
13403 t
= make_ssa_name (orig_arg
);
13404 g
= gimple_build_assign (t
, NOP_EXPR
, gimple_call_lhs (g
));
13405 gimple_seq_add_stmt_without_update (&seq
, g
);
13407 gsi_insert_seq_on_edge_immediate
13408 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun
)), seq
);
13410 entry_bb
= single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun
));
13411 int freq
= compute_call_stmt_bb_frequency (current_function_decl
,
13413 node
->create_edge (cgraph_node::get_create (fn
),
13414 call
, entry_bb
->count
, freq
);
13416 imm_use_iterator iter
;
13417 use_operand_p use_p
;
13419 tree repl
= gimple_get_lhs (g
);
13420 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13421 if (is_gimple_debug (use_stmt
) || use_stmt
== call
)
13424 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13425 SET_USE (use_p
, repl
);
13428 else if (node
->simdclone
->args
[i
].arg_type
13429 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP
)
13431 tree orig_arg
= node
->simdclone
->args
[i
].orig_arg
;
13432 tree def
= ssa_default_def (cfun
, orig_arg
);
13433 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13434 || POINTER_TYPE_P (TREE_TYPE (orig_arg
)));
13435 if (def
&& !has_zero_uses (def
))
13437 iter1
= make_ssa_name (orig_arg
);
13438 iter2
= make_ssa_name (orig_arg
);
13439 phi
= create_phi_node (iter1
, body_bb
);
13440 add_phi_arg (phi
, def
, preheader_edge
, UNKNOWN_LOCATION
);
13441 add_phi_arg (phi
, iter2
, latch_edge
, UNKNOWN_LOCATION
);
13442 enum tree_code code
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13443 ? PLUS_EXPR
: POINTER_PLUS_EXPR
;
13444 tree addtype
= INTEGRAL_TYPE_P (TREE_TYPE (orig_arg
))
13445 ? TREE_TYPE (orig_arg
) : sizetype
;
13447 = build_int_cst (addtype
, node
->simdclone
->args
[i
].linear_step
);
13448 g
= gimple_build_assign (iter2
, code
, iter1
, addcst
);
13449 gsi
= gsi_last_bb (incr_bb
);
13450 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
13452 imm_use_iterator iter
;
13453 use_operand_p use_p
;
13455 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, def
)
13456 if (use_stmt
== phi
)
13459 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
13460 SET_USE (use_p
, iter1
);
13464 calculate_dominance_info (CDI_DOMINATORS
);
13465 add_loop (loop
, loop
->header
->loop_father
);
13466 update_ssa (TODO_update_ssa
);
13471 /* If the function in NODE is tagged as an elemental SIMD function,
13472 create the appropriate SIMD clones. */
13475 expand_simd_clones (struct cgraph_node
*node
)
13477 tree attr
= lookup_attribute ("omp declare simd",
13478 DECL_ATTRIBUTES (node
->decl
));
13479 if (attr
== NULL_TREE
13480 || node
->global
.inlined_to
13481 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node
->decl
)))
13485 #pragma omp declare simd
13487 in C, there we don't know the argument types at all. */
13488 if (!node
->definition
13489 && TYPE_ARG_TYPES (TREE_TYPE (node
->decl
)) == NULL_TREE
)
13494 /* Start with parsing the "omp declare simd" attribute(s). */
13495 bool inbranch_clause_specified
;
13496 struct cgraph_simd_clone
*clone_info
13497 = simd_clone_clauses_extract (node
, TREE_VALUE (attr
),
13498 &inbranch_clause_specified
);
13499 if (clone_info
== NULL
)
13502 int orig_simdlen
= clone_info
->simdlen
;
13503 tree base_type
= simd_clone_compute_base_data_type (node
, clone_info
);
13504 /* The target can return 0 (no simd clones should be created),
13505 1 (just one ISA of simd clones should be created) or higher
13506 count of ISA variants. In that case, clone_info is initialized
13507 for the first ISA variant. */
13509 = targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone_info
,
13514 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13515 also create one inbranch and one !inbranch clone of it. */
13516 for (int i
= 0; i
< count
* 2; i
++)
13518 struct cgraph_simd_clone
*clone
= clone_info
;
13519 if (inbranch_clause_specified
&& (i
& 1) != 0)
13524 clone
= simd_clone_struct_alloc (clone_info
->nargs
13526 simd_clone_struct_copy (clone
, clone_info
);
13527 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13528 and simd_clone_adjust_argument_types did to the first
13530 clone
->nargs
-= clone_info
->inbranch
;
13531 clone
->simdlen
= orig_simdlen
;
13532 /* And call the target hook again to get the right ISA. */
13533 targetm
.simd_clone
.compute_vecsize_and_simdlen (node
, clone
,
13537 clone
->inbranch
= 1;
13540 /* simd_clone_mangle might fail if such a clone has been created
13542 tree id
= simd_clone_mangle (node
, clone
);
13543 if (id
== NULL_TREE
)
13546 /* Only when we are sure we want to create the clone actually
13547 clone the function (or definitions) or create another
13548 extern FUNCTION_DECL (for prototypes without definitions). */
13549 struct cgraph_node
*n
= simd_clone_create (node
);
13553 n
->simdclone
= clone
;
13554 clone
->origin
= node
;
13555 clone
->next_clone
= NULL
;
13556 if (node
->simd_clones
== NULL
)
13558 clone
->prev_clone
= n
;
13559 node
->simd_clones
= n
;
13563 clone
->prev_clone
= node
->simd_clones
->simdclone
->prev_clone
;
13564 clone
->prev_clone
->simdclone
->next_clone
= n
;
13565 node
->simd_clones
->simdclone
->prev_clone
= n
;
13567 symtab
->change_decl_assembler_name (n
->decl
, id
);
13568 /* And finally adjust the return type, parameters and for
13569 definitions also function body. */
13570 if (node
->definition
)
13571 simd_clone_adjust (n
);
13574 simd_clone_adjust_return_type (n
);
13575 simd_clone_adjust_argument_types (n
);
13579 while ((attr
= lookup_attribute ("omp declare simd", TREE_CHAIN (attr
))));
13582 /* Entry point for IPA simd clone creation pass. */
13584 static unsigned int
13585 ipa_omp_simd_clone (void)
13587 struct cgraph_node
*node
;
13588 FOR_EACH_FUNCTION (node
)
13589 expand_simd_clones (node
);
13595 const pass_data pass_data_omp_simd_clone
=
13597 SIMPLE_IPA_PASS
, /* type */
13598 "simdclone", /* name */
13599 OPTGROUP_NONE
, /* optinfo_flags */
13600 TV_NONE
, /* tv_id */
13601 ( PROP_ssa
| PROP_cfg
), /* properties_required */
13602 0, /* properties_provided */
13603 0, /* properties_destroyed */
13604 0, /* todo_flags_start */
13605 0, /* todo_flags_finish */
13608 class pass_omp_simd_clone
: public simple_ipa_opt_pass
13611 pass_omp_simd_clone(gcc::context
*ctxt
)
13612 : simple_ipa_opt_pass(pass_data_omp_simd_clone
, ctxt
)
13615 /* opt_pass methods: */
13616 virtual bool gate (function
*);
13617 virtual unsigned int execute (function
*) { return ipa_omp_simd_clone (); }
13621 pass_omp_simd_clone::gate (function
*)
13623 return ((flag_openmp
|| flag_openmp_simd
13625 || (in_lto_p
&& !flag_wpa
))
13626 && (targetm
.simd_clone
.compute_vecsize_and_simdlen
!= NULL
));
13629 } // anon namespace
13631 simple_ipa_opt_pass
*
13632 make_pass_omp_simd_clone (gcc::context
*ctxt
)
13634 return new pass_omp_simd_clone (ctxt
);
13637 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13638 adds their addresses and sizes to constructor-vector V_CTOR. */
13640 add_decls_addresses_to_decl_constructor (vec
<tree
, va_gc
> *v_decls
,
13641 vec
<constructor_elt
, va_gc
> *v_ctor
)
13643 unsigned len
= vec_safe_length (v_decls
);
13644 for (unsigned i
= 0; i
< len
; i
++)
13646 tree it
= (*v_decls
)[i
];
13647 bool is_function
= TREE_CODE (it
) != VAR_DECL
;
13649 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
, build_fold_addr_expr (it
));
13651 CONSTRUCTOR_APPEND_ELT (v_ctor
, NULL_TREE
,
13652 fold_convert (const_ptr_type_node
,
13653 DECL_SIZE_UNIT (it
)));
13657 /* Create new symbols containing (address, size) pairs for global variables,
13658 marked with "omp declare target" attribute, as well as addresses for the
13659 functions, which are outlined offloading regions. */
13661 omp_finish_file (void)
13663 unsigned num_funcs
= vec_safe_length (offload_funcs
);
13664 unsigned num_vars
= vec_safe_length (offload_vars
);
13666 if (num_funcs
== 0 && num_vars
== 0)
13669 if (targetm_common
.have_named_sections
)
13671 vec
<constructor_elt
, va_gc
> *v_f
, *v_v
;
13672 vec_alloc (v_f
, num_funcs
);
13673 vec_alloc (v_v
, num_vars
* 2);
13675 add_decls_addresses_to_decl_constructor (offload_funcs
, v_f
);
13676 add_decls_addresses_to_decl_constructor (offload_vars
, v_v
);
13678 tree vars_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13680 tree funcs_decl_type
= build_array_type_nelts (pointer_sized_int_node
,
13682 TYPE_ALIGN (vars_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13683 TYPE_ALIGN (funcs_decl_type
) = TYPE_ALIGN (pointer_sized_int_node
);
13684 tree ctor_v
= build_constructor (vars_decl_type
, v_v
);
13685 tree ctor_f
= build_constructor (funcs_decl_type
, v_f
);
13686 TREE_CONSTANT (ctor_v
) = TREE_CONSTANT (ctor_f
) = 1;
13687 TREE_STATIC (ctor_v
) = TREE_STATIC (ctor_f
) = 1;
13688 tree funcs_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13689 get_identifier (".offload_func_table"),
13691 tree vars_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
13692 get_identifier (".offload_var_table"),
13694 TREE_STATIC (funcs_decl
) = TREE_STATIC (vars_decl
) = 1;
13695 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13696 otherwise a joint table in a binary will contain padding between
13697 tables from multiple object files. */
13698 DECL_USER_ALIGN (funcs_decl
) = DECL_USER_ALIGN (vars_decl
) = 1;
13699 DECL_ALIGN (funcs_decl
) = TYPE_ALIGN (funcs_decl_type
);
13700 DECL_ALIGN (vars_decl
) = TYPE_ALIGN (vars_decl_type
);
13701 DECL_INITIAL (funcs_decl
) = ctor_f
;
13702 DECL_INITIAL (vars_decl
) = ctor_v
;
13703 set_decl_section_name (funcs_decl
, OFFLOAD_FUNC_TABLE_SECTION_NAME
);
13704 set_decl_section_name (vars_decl
, OFFLOAD_VAR_TABLE_SECTION_NAME
);
13706 varpool_node::finalize_decl (vars_decl
);
13707 varpool_node::finalize_decl (funcs_decl
);
13711 for (unsigned i
= 0; i
< num_funcs
; i
++)
13713 tree it
= (*offload_funcs
)[i
];
13714 targetm
.record_offload_symbol (it
);
13716 for (unsigned i
= 0; i
< num_vars
; i
++)
13718 tree it
= (*offload_vars
)[i
];
13719 targetm
.record_offload_symbol (it
);
13724 #include "gt-omp-low.h"