1 /* General types and functions that are uselful for processing of OpenMP,
2 OpenACC and similar directivers at various stages of compilation.
4 Copyright (C) 2005-2020 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* Find an OMP clause of type KIND within CLAUSES. */
26 #include "coretypes.h"
32 #include "diagnostic-core.h"
33 #include "fold-const.h"
34 #include "langhooks.h"
35 #include "omp-general.h"
36 #include "stringpool.h"
40 #include "alloc-pool.h"
41 #include "symbol-summary.h"
42 #include "tree-pass.h"
43 #include "omp-device-properties.h"
44 #include "tree-iterator.h"
46 enum omp_requires omp_requires_mask
;
49 omp_find_clause (tree clauses
, enum omp_clause_code kind
)
51 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
52 if (OMP_CLAUSE_CODE (clauses
) == kind
)
58 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
59 allocatable or pointer attribute. */
61 omp_is_allocatable_or_ptr (tree decl
)
63 return lang_hooks
.decls
.omp_is_allocatable_or_ptr (decl
);
66 /* Check whether this DECL belongs to a Fortran optional argument.
67 With 'for_present_check' set to false, decls which are optional parameters
68 themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
69 always pointers. With 'for_present_check' set to true, the decl for checking
70 whether an argument is present is returned; for arguments with value
71 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
72 unrelated to optional arguments, NULL_TREE is returned. */
75 omp_check_optional_argument (tree decl
, bool for_present_check
)
77 return lang_hooks
.decls
.omp_check_optional_argument (decl
, for_present_check
);
80 /* Return true if DECL is a reference type. */
83 omp_is_reference (tree decl
)
85 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
88 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
89 given that V is the loop index variable and STEP is loop step. */
92 omp_adjust_for_condition (location_t loc
, enum tree_code
*cond_code
, tree
*n2
,
102 gcc_assert (TREE_CODE (step
) == INTEGER_CST
);
103 if (TREE_CODE (TREE_TYPE (v
)) == INTEGER_TYPE
)
105 if (integer_onep (step
))
106 *cond_code
= LT_EXPR
;
109 gcc_assert (integer_minus_onep (step
));
110 *cond_code
= GT_EXPR
;
115 tree unit
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v
)));
116 gcc_assert (TREE_CODE (unit
) == INTEGER_CST
);
117 if (tree_int_cst_equal (unit
, step
))
118 *cond_code
= LT_EXPR
;
121 gcc_assert (wi::neg (wi::to_widest (unit
))
122 == wi::to_widest (step
));
123 *cond_code
= GT_EXPR
;
130 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
131 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, 1);
133 *n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (*n2
), *n2
,
134 build_int_cst (TREE_TYPE (*n2
), 1));
135 *cond_code
= LT_EXPR
;
138 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
139 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, -1);
141 *n2
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (*n2
), *n2
,
142 build_int_cst (TREE_TYPE (*n2
), 1));
143 *cond_code
= GT_EXPR
;
150 /* Return the looping step from INCR, extracted from the step of a gimple omp
154 omp_get_for_step_from_incr (location_t loc
, tree incr
)
157 switch (TREE_CODE (incr
))
160 step
= TREE_OPERAND (incr
, 1);
162 case POINTER_PLUS_EXPR
:
163 step
= fold_convert (ssizetype
, TREE_OPERAND (incr
, 1));
166 step
= TREE_OPERAND (incr
, 1);
167 step
= fold_build1_loc (loc
, NEGATE_EXPR
, TREE_TYPE (step
), step
);
175 /* Extract the header elements of parallel loop FOR_STMT and store
179 omp_extract_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
180 struct omp_for_data_loop
*loops
)
182 tree t
, var
, *collapse_iter
, *collapse_count
;
183 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
184 struct omp_for_data_loop
*loop
;
186 struct omp_for_data_loop dummy_loop
;
187 location_t loc
= gimple_location (for_stmt
);
188 bool simd
= gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_SIMD
;
189 bool distribute
= gimple_omp_for_kind (for_stmt
)
190 == GF_OMP_FOR_KIND_DISTRIBUTE
;
191 bool taskloop
= gimple_omp_for_kind (for_stmt
)
192 == GF_OMP_FOR_KIND_TASKLOOP
;
195 fd
->for_stmt
= for_stmt
;
197 fd
->have_nowait
= distribute
|| simd
;
198 fd
->have_ordered
= false;
199 fd
->have_reductemp
= false;
200 fd
->have_pointer_condtemp
= false;
201 fd
->have_scantemp
= false;
202 fd
->have_nonctrl_scantemp
= false;
203 fd
->non_rect
= false;
204 fd
->lastprivate_conditional
= 0;
205 fd
->tiling
= NULL_TREE
;
208 fd
->first_nonrect
= -1;
209 fd
->last_nonrect
= -1;
210 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
211 fd
->sched_modifiers
= 0;
212 fd
->chunk_size
= NULL_TREE
;
213 fd
->simd_schedule
= false;
214 fd
->first_inner_iterations
= NULL_TREE
;
215 fd
->factor
= NULL_TREE
;
216 fd
->adjn1
= NULL_TREE
;
217 collapse_iter
= NULL
;
218 collapse_count
= NULL
;
220 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
221 switch (OMP_CLAUSE_CODE (t
))
223 case OMP_CLAUSE_NOWAIT
:
224 fd
->have_nowait
= true;
226 case OMP_CLAUSE_ORDERED
:
227 fd
->have_ordered
= true;
228 if (OMP_CLAUSE_ORDERED_EXPR (t
))
229 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
231 case OMP_CLAUSE_SCHEDULE
:
232 gcc_assert (!distribute
&& !taskloop
);
234 = (enum omp_clause_schedule_kind
)
235 (OMP_CLAUSE_SCHEDULE_KIND (t
) & OMP_CLAUSE_SCHEDULE_MASK
);
236 fd
->sched_modifiers
= (OMP_CLAUSE_SCHEDULE_KIND (t
)
237 & ~OMP_CLAUSE_SCHEDULE_MASK
);
238 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
239 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
241 case OMP_CLAUSE_DIST_SCHEDULE
:
242 gcc_assert (distribute
);
243 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
245 case OMP_CLAUSE_COLLAPSE
:
246 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
247 if (fd
->collapse
> 1)
249 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
250 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
253 case OMP_CLAUSE_TILE
:
254 fd
->tiling
= OMP_CLAUSE_TILE_LIST (t
);
255 fd
->collapse
= list_length (fd
->tiling
);
256 gcc_assert (fd
->collapse
);
257 collapse_iter
= &OMP_CLAUSE_TILE_ITERVAR (t
);
258 collapse_count
= &OMP_CLAUSE_TILE_COUNT (t
);
260 case OMP_CLAUSE__REDUCTEMP_
:
261 fd
->have_reductemp
= true;
263 case OMP_CLAUSE_LASTPRIVATE
:
264 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t
))
265 fd
->lastprivate_conditional
++;
267 case OMP_CLAUSE__CONDTEMP_
:
268 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t
))))
269 fd
->have_pointer_condtemp
= true;
271 case OMP_CLAUSE__SCANTEMP_
:
272 fd
->have_scantemp
= true;
273 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t
)
274 && !OMP_CLAUSE__SCANTEMP__CONTROL (t
))
275 fd
->have_nonctrl_scantemp
= true;
281 if (fd
->collapse
> 1 || fd
->tiling
)
284 fd
->loops
= &fd
->loop
;
286 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
291 collapse_iter
= &iterv
;
292 collapse_count
= &countv
;
295 /* FIXME: for now map schedule(auto) to schedule(static).
296 There should be analysis to determine whether all iterations
297 are approximately the same amount of work (then schedule(static)
298 is best) or if it varies (then schedule(dynamic,N) is better). */
299 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
301 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
302 gcc_assert (fd
->chunk_size
== NULL
);
304 gcc_assert ((fd
->collapse
== 1 && !fd
->tiling
) || collapse_iter
!= NULL
);
306 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
307 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
308 gcc_assert (fd
->chunk_size
== NULL
);
309 else if (fd
->chunk_size
== NULL
)
311 /* We only need to compute a default chunk size for ordered
312 static loops and dynamic loops. */
313 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
315 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
316 ? integer_zero_node
: integer_one_node
;
319 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
320 int single_nonrect
= -1;
321 tree single_nonrect_count
= NULL_TREE
;
322 enum tree_code single_nonrect_cond_code
= ERROR_MARK
;
323 for (i
= 1; i
< cnt
; i
++)
325 tree n1
= gimple_omp_for_initial (for_stmt
, i
);
326 tree n2
= gimple_omp_for_final (for_stmt
, i
);
327 if (TREE_CODE (n1
) == TREE_VEC
)
334 for (int j
= i
- 1; j
>= 0; j
--)
335 if (TREE_VEC_ELT (n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
342 else if (TREE_CODE (n2
) == TREE_VEC
)
349 for (int j
= i
- 1; j
>= 0; j
--)
350 if (TREE_VEC_ELT (n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
358 for (i
= 0; i
< cnt
; i
++)
363 && (fd
->ordered
== 0 || loops
== NULL
))
365 else if (loops
!= NULL
)
370 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
371 gcc_assert (SSA_VAR_P (loop
->v
));
372 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
373 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
374 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
375 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
376 loop
->m1
= NULL_TREE
;
377 loop
->m2
= NULL_TREE
;
379 loop
->non_rect_referenced
= false;
380 if (TREE_CODE (loop
->n1
) == TREE_VEC
)
382 for (int j
= i
- 1; j
>= 0; j
--)
383 if (TREE_VEC_ELT (loop
->n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
387 loops
[j
].non_rect_referenced
= true;
388 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
389 fd
->first_nonrect
= j
;
392 gcc_assert (loop
->outer
);
393 loop
->m1
= TREE_VEC_ELT (loop
->n1
, 1);
394 loop
->n1
= TREE_VEC_ELT (loop
->n1
, 2);
396 fd
->last_nonrect
= i
;
399 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
400 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
401 gcc_assert (loop
->cond_code
!= NE_EXPR
402 || (gimple_omp_for_kind (for_stmt
)
403 != GF_OMP_FOR_KIND_OACC_LOOP
));
404 if (TREE_CODE (loop
->n2
) == TREE_VEC
)
407 gcc_assert (TREE_VEC_ELT (loop
->n2
, 0)
408 == gimple_omp_for_index (for_stmt
, i
- loop
->outer
));
410 for (int j
= i
- 1; j
>= 0; j
--)
411 if (TREE_VEC_ELT (loop
->n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
415 loops
[j
].non_rect_referenced
= true;
416 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
417 fd
->first_nonrect
= j
;
420 gcc_assert (loop
->outer
);
421 loop
->m2
= TREE_VEC_ELT (loop
->n2
, 1);
422 loop
->n2
= TREE_VEC_ELT (loop
->n2
, 2);
424 fd
->last_nonrect
= i
;
427 t
= gimple_omp_for_incr (for_stmt
, i
);
428 gcc_assert (TREE_OPERAND (t
, 0) == var
);
429 loop
->step
= omp_get_for_step_from_incr (loc
, t
);
431 omp_adjust_for_condition (loc
, &loop
->cond_code
, &loop
->n2
, loop
->v
,
435 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
436 && !fd
->have_ordered
))
438 if (fd
->collapse
== 1 && !fd
->tiling
)
439 iter_type
= TREE_TYPE (loop
->v
);
441 || TYPE_PRECISION (iter_type
)
442 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
444 = build_nonstandard_integer_type
445 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
447 else if (iter_type
!= long_long_unsigned_type_node
)
449 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
450 iter_type
= long_long_unsigned_type_node
;
451 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
452 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
453 >= TYPE_PRECISION (iter_type
))
457 if (loop
->cond_code
== LT_EXPR
)
458 n
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
459 loop
->n2
, loop
->step
);
464 || TREE_CODE (n
) != INTEGER_CST
465 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
466 iter_type
= long_long_unsigned_type_node
;
468 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
469 > TYPE_PRECISION (iter_type
))
473 if (loop
->cond_code
== LT_EXPR
)
476 n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
477 loop
->n2
, loop
->step
);
481 n1
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (loop
->v
),
482 loop
->n2
, loop
->step
);
487 || TREE_CODE (n1
) != INTEGER_CST
488 || TREE_CODE (n2
) != INTEGER_CST
489 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
490 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
491 iter_type
= long_long_unsigned_type_node
;
495 if (i
>= fd
->collapse
)
498 if (collapse_count
&& *collapse_count
== NULL
)
500 if (count
&& integer_zerop (count
))
502 tree n1first
= NULL_TREE
, n2first
= NULL_TREE
;
503 tree n1last
= NULL_TREE
, n2last
= NULL_TREE
;
504 tree ostep
= NULL_TREE
;
505 if (loop
->m1
|| loop
->m2
)
507 if (count
== NULL_TREE
)
509 if (single_nonrect
== -1
510 || (loop
->m1
&& TREE_CODE (loop
->m1
) != INTEGER_CST
)
511 || (loop
->m2
&& TREE_CODE (loop
->m2
) != INTEGER_CST
)
512 || TREE_CODE (loop
->n1
) != INTEGER_CST
513 || TREE_CODE (loop
->n2
) != INTEGER_CST
514 || TREE_CODE (loop
->step
) != INTEGER_CST
)
519 tree var
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
520 tree itype
= TREE_TYPE (var
);
521 tree first
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
522 t
= gimple_omp_for_incr (for_stmt
, single_nonrect
);
523 ostep
= omp_get_for_step_from_incr (loc
, t
);
524 t
= fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
525 single_nonrect_count
,
526 build_one_cst (long_long_unsigned_type_node
));
527 t
= fold_convert (itype
, t
);
528 first
= fold_convert (itype
, first
);
529 ostep
= fold_convert (itype
, ostep
);
530 tree last
= fold_binary (PLUS_EXPR
, itype
, first
,
531 fold_binary (MULT_EXPR
, itype
, t
,
533 if (TREE_CODE (first
) != INTEGER_CST
534 || TREE_CODE (last
) != INTEGER_CST
)
541 tree m1
= fold_convert (itype
, loop
->m1
);
542 tree n1
= fold_convert (itype
, loop
->n1
);
543 n1first
= fold_binary (PLUS_EXPR
, itype
,
544 fold_binary (MULT_EXPR
, itype
,
546 n1last
= fold_binary (PLUS_EXPR
, itype
,
547 fold_binary (MULT_EXPR
, itype
,
551 n1first
= n1last
= loop
->n1
;
554 tree n2
= fold_convert (itype
, loop
->n2
);
555 tree m2
= fold_convert (itype
, loop
->m2
);
556 n2first
= fold_binary (PLUS_EXPR
, itype
,
557 fold_binary (MULT_EXPR
, itype
,
559 n2last
= fold_binary (PLUS_EXPR
, itype
,
560 fold_binary (MULT_EXPR
, itype
,
564 n2first
= n2last
= loop
->n2
;
565 n1first
= fold_convert (TREE_TYPE (loop
->v
), n1first
);
566 n2first
= fold_convert (TREE_TYPE (loop
->v
), n2first
);
567 n1last
= fold_convert (TREE_TYPE (loop
->v
), n1last
);
568 n2last
= fold_convert (TREE_TYPE (loop
->v
), n2last
);
569 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
571 tree t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
573 if (t
&& t2
&& integer_nonzerop (t
) && integer_nonzerop (t2
))
574 /* All outer loop iterators have at least one inner loop
575 iteration. Try to compute the count at compile time. */
577 else if (t
&& t2
&& integer_zerop (t
) && integer_zerop (t2
))
578 /* No iterations of the inner loop. count will be set to
580 else if (TYPE_UNSIGNED (itype
)
583 || TREE_CODE (t
) != INTEGER_CST
584 || TREE_CODE (t2
) != INTEGER_CST
)
586 /* Punt (for now). */
592 /* Some iterations of the outer loop have zero iterations
593 of the inner loop, while others have at least one.
594 In this case, we need to adjust one of those outer
595 loop bounds. If ADJ_FIRST, we need to adjust outer n1
596 (first), otherwise outer n2 (last). */
597 bool adj_first
= integer_zerop (t
);
598 tree n1
= fold_convert (itype
, loop
->n1
);
599 tree n2
= fold_convert (itype
, loop
->n2
);
600 tree m1
= loop
->m1
? fold_convert (itype
, loop
->m1
)
601 : build_zero_cst (itype
);
602 tree m2
= loop
->m2
? fold_convert (itype
, loop
->m2
)
603 : build_zero_cst (itype
);
604 t
= fold_binary (MINUS_EXPR
, itype
, n1
, n2
);
605 t2
= fold_binary (MINUS_EXPR
, itype
, m2
, m1
);
606 t
= fold_binary (TRUNC_DIV_EXPR
, itype
, t
, t2
);
607 t2
= fold_binary (MINUS_EXPR
, itype
, t
, first
);
608 t2
= fold_binary (TRUNC_MOD_EXPR
, itype
, t2
, ostep
);
609 t
= fold_binary (MINUS_EXPR
, itype
, t
, t2
);
611 = fold_binary (PLUS_EXPR
, itype
, n1
,
612 fold_binary (MULT_EXPR
, itype
, m1
, t
));
614 = fold_binary (PLUS_EXPR
, itype
, n2
,
615 fold_binary (MULT_EXPR
, itype
, m2
, t
));
616 t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
618 tree t3
= fold_binary (MULT_EXPR
, itype
, m1
, ostep
);
619 tree t4
= fold_binary (MULT_EXPR
, itype
, m2
, ostep
);
624 if (integer_nonzerop (t2
))
631 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
632 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
633 t3
= fold_binary (loop
->cond_code
,
634 boolean_type_node
, t3
, t4
);
635 gcc_assert (integer_zerop (t3
));
640 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
641 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
642 new_first
= fold_binary (PLUS_EXPR
, itype
, t
, ostep
);
647 t3
= fold_binary (loop
->cond_code
,
648 boolean_type_node
, t3
, t4
);
649 gcc_assert (integer_nonzerop (t3
));
652 diff
= fold_binary (MINUS_EXPR
, itype
, new_first
, first
);
659 if (integer_zerop (t2
))
661 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
662 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
663 new_last
= fold_binary (MINUS_EXPR
, itype
, t
, ostep
);
668 t3
= fold_binary (loop
->cond_code
,
669 boolean_type_node
, t3
, t4
);
670 gcc_assert (integer_nonzerop (t3
));
680 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
681 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
682 t3
= fold_binary (loop
->cond_code
,
683 boolean_type_node
, t3
, t4
);
684 gcc_assert (integer_zerop (t3
));
687 diff
= fold_binary (MINUS_EXPR
, itype
, last
, new_last
);
689 if (TYPE_UNSIGNED (itype
)
690 && single_nonrect_cond_code
== GT_EXPR
)
691 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
,
692 fold_unary (NEGATE_EXPR
, itype
, diff
),
693 fold_unary (NEGATE_EXPR
, itype
,
696 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
, diff
, ostep
);
697 diff
= fold_convert (long_long_unsigned_type_node
, diff
);
699 = fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
700 single_nonrect_count
, diff
);
705 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
706 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
707 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
708 if (t
&& integer_zerop (t
))
709 count
= build_zero_cst (long_long_unsigned_type_node
);
710 else if ((i
== 0 || count
!= NULL_TREE
)
711 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
712 && TREE_CONSTANT (loop
->n1
)
713 && TREE_CONSTANT (loop
->n2
)
714 && TREE_CODE (loop
->step
) == INTEGER_CST
)
716 tree itype
= TREE_TYPE (loop
->v
);
718 if (POINTER_TYPE_P (itype
))
719 itype
= signed_type_for (itype
);
720 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
721 t
= fold_build2 (PLUS_EXPR
, itype
,
722 fold_convert (itype
, loop
->step
), t
);
725 if (loop
->m1
|| loop
->m2
)
727 gcc_assert (single_nonrect
!= -1);
731 t
= fold_build2 (PLUS_EXPR
, itype
, t
, fold_convert (itype
, n2
));
732 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
733 tree step
= fold_convert_loc (loc
, itype
, loop
->step
);
734 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
735 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
736 fold_build1 (NEGATE_EXPR
, itype
, t
),
737 fold_build1 (NEGATE_EXPR
, itype
, step
));
739 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
740 tree llutype
= long_long_unsigned_type_node
;
741 t
= fold_convert (llutype
, t
);
742 if (loop
->m1
|| loop
->m2
)
744 /* t is number of iterations of inner loop at either first
745 or last value of the outer iterator (the one with fewer
747 Compute t2 = ((m2 - m1) * ostep) / step
748 and niters = outer_count * t
749 + t2 * ((outer_count - 1) * outer_count / 2)
751 tree m1
= loop
->m1
? loop
->m1
: integer_zero_node
;
752 tree m2
= loop
->m2
? loop
->m2
: integer_zero_node
;
753 m1
= fold_convert (itype
, m1
);
754 m2
= fold_convert (itype
, m2
);
755 tree t2
= fold_build2 (MINUS_EXPR
, itype
, m2
, m1
);
756 t2
= fold_build2 (MULT_EXPR
, itype
, t2
, ostep
);
757 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
758 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
759 fold_build1 (NEGATE_EXPR
, itype
, t2
),
760 fold_build1 (NEGATE_EXPR
, itype
, step
));
762 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t2
, step
);
763 t2
= fold_convert (llutype
, t2
);
764 fd
->first_inner_iterations
= t
;
766 t
= fold_build2 (MULT_EXPR
, llutype
, t
,
767 single_nonrect_count
);
768 tree t3
= fold_build2 (MINUS_EXPR
, llutype
,
769 single_nonrect_count
,
770 build_one_cst (llutype
));
771 t3
= fold_build2 (MULT_EXPR
, llutype
, t3
,
772 single_nonrect_count
);
773 t3
= fold_build2 (TRUNC_DIV_EXPR
, llutype
, t3
,
774 build_int_cst (llutype
, 2));
775 t2
= fold_build2 (MULT_EXPR
, llutype
, t2
, t3
);
776 t
= fold_build2 (PLUS_EXPR
, llutype
, t
, t2
);
778 if (i
== single_nonrect
)
780 if (integer_zerop (t
) || TREE_CODE (t
) != INTEGER_CST
)
784 single_nonrect_count
= t
;
785 single_nonrect_cond_code
= loop
->cond_code
;
786 if (count
== NULL_TREE
)
787 count
= build_one_cst (llutype
);
790 else if (count
!= NULL_TREE
)
791 count
= fold_build2 (MULT_EXPR
, llutype
, count
, t
);
794 if (TREE_CODE (count
) != INTEGER_CST
)
797 else if (count
&& !integer_zerop (count
))
804 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
805 || fd
->have_ordered
))
807 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
808 iter_type
= long_long_unsigned_type_node
;
810 iter_type
= long_integer_type_node
;
812 else if (collapse_iter
&& *collapse_iter
!= NULL
)
813 iter_type
= TREE_TYPE (*collapse_iter
);
814 fd
->iter_type
= iter_type
;
815 if (collapse_iter
&& *collapse_iter
== NULL
)
816 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
817 if (collapse_count
&& *collapse_count
== NULL
)
821 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
822 if (fd
->first_inner_iterations
&& fd
->factor
)
824 t
= make_tree_vec (4);
825 TREE_VEC_ELT (t
, 0) = *collapse_count
;
826 TREE_VEC_ELT (t
, 1) = fd
->first_inner_iterations
;
827 TREE_VEC_ELT (t
, 2) = fd
->factor
;
828 TREE_VEC_ELT (t
, 3) = fd
->adjn1
;
833 *collapse_count
= create_tmp_var (iter_type
, ".count");
836 if (fd
->collapse
> 1 || fd
->tiling
|| (fd
->ordered
&& loops
))
838 fd
->loop
.v
= *collapse_iter
;
839 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
840 fd
->loop
.n2
= *collapse_count
;
841 if (TREE_CODE (fd
->loop
.n2
) == TREE_VEC
)
843 gcc_assert (fd
->non_rect
);
844 fd
->first_inner_iterations
= TREE_VEC_ELT (fd
->loop
.n2
, 1);
845 fd
->factor
= TREE_VEC_ELT (fd
->loop
.n2
, 2);
846 fd
->adjn1
= TREE_VEC_ELT (fd
->loop
.n2
, 3);
847 fd
->loop
.n2
= TREE_VEC_ELT (fd
->loop
.n2
, 0);
849 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
850 fd
->loop
.m1
= NULL_TREE
;
851 fd
->loop
.m2
= NULL_TREE
;
853 fd
->loop
.cond_code
= LT_EXPR
;
859 /* Build a call to GOMP_barrier. */
862 omp_build_barrier (tree lhs
)
864 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
865 : BUILT_IN_GOMP_BARRIER
);
866 gcall
*g
= gimple_build_call (fndecl
, 0);
868 gimple_call_set_lhs (g
, lhs
);
872 /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
873 array, pdata[0] non-NULL if there is anything non-trivial in between,
874 pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
875 of OMP_FOR in between if any and pdata[3] is address of the inner
879 find_combined_omp_for (tree
*tp
, int *walk_subtrees
, void *data
)
881 tree
**pdata
= (tree
**) data
;
883 switch (TREE_CODE (*tp
))
886 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
895 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
902 if (BIND_EXPR_VARS (*tp
)
903 || (BIND_EXPR_BLOCK (*tp
)
904 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp
))))
909 if (!tsi_one_before_end_p (tsi_start (*tp
)))
913 case TRY_FINALLY_EXPR
:
927 /* Return maximum possible vectorization factor for the target. */
934 || !flag_tree_loop_optimize
935 || (!flag_tree_loop_vectorize
936 && global_options_set
.x_flag_tree_loop_vectorize
))
939 auto_vector_modes modes
;
940 targetm
.vectorize
.autovectorize_vector_modes (&modes
, true);
941 if (!modes
.is_empty ())
944 for (unsigned int i
= 0; i
< modes
.length (); ++i
)
945 /* The returned modes use the smallest element size (and thus
946 the largest nunits) for the vectorization approach that they
948 vf
= ordered_max (vf
, GET_MODE_NUNITS (modes
[i
]));
952 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
953 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
954 return GET_MODE_NUNITS (vqimode
);
959 /* Return maximum SIMT width if offloading may target SIMT hardware. */
962 omp_max_simt_vf (void)
966 if (ENABLE_OFFLOADING
)
967 for (const char *c
= getenv ("OFFLOAD_TARGET_NAMES"); c
;)
969 if (!strncmp (c
, "nvptx", strlen ("nvptx")))
971 else if ((c
= strchr (c
, ':')))
977 /* Store the construct selectors as tree codes from last to first,
978 return their number. */
981 omp_constructor_traits_to_codes (tree ctx
, enum tree_code
*constructs
)
983 int nconstructs
= list_length (ctx
);
984 int i
= nconstructs
- 1;
985 for (tree t2
= ctx
; t2
; t2
= TREE_CHAIN (t2
), i
--)
987 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
988 if (!strcmp (sel
, "target"))
989 constructs
[i
] = OMP_TARGET
;
990 else if (!strcmp (sel
, "teams"))
991 constructs
[i
] = OMP_TEAMS
;
992 else if (!strcmp (sel
, "parallel"))
993 constructs
[i
] = OMP_PARALLEL
;
994 else if (!strcmp (sel
, "for") || !strcmp (sel
, "do"))
995 constructs
[i
] = OMP_FOR
;
996 else if (!strcmp (sel
, "simd"))
997 constructs
[i
] = OMP_SIMD
;
1001 gcc_assert (i
== -1);
1005 /* Return true if PROP is possibly present in one of the offloading target's
1006 OpenMP contexts. The format of PROPS string is always offloading target's
1007 name terminated by '\0', followed by properties for that offloading
1008 target separated by '\0' and terminated by another '\0'. The strings
1009 are created from omp-device-properties installed files of all configured
1010 offloading targets. */
1013 omp_offload_device_kind_arch_isa (const char *props
, const char *prop
)
1015 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1016 if (names
== NULL
|| *names
== '\0')
1018 while (*props
!= '\0')
1020 size_t name_len
= strlen (props
);
1021 bool matches
= false;
1022 for (const char *c
= names
; c
; )
1024 if (strncmp (props
, c
, name_len
) == 0
1025 && (c
[name_len
] == '\0'
1026 || c
[name_len
] == ':'
1027 || c
[name_len
] == '='))
1032 else if ((c
= strchr (c
, ':')))
1035 props
= props
+ name_len
+ 1;
1036 while (*props
!= '\0')
1038 if (matches
&& strcmp (props
, prop
) == 0)
1040 props
= strchr (props
, '\0') + 1;
1047 /* Return true if the current code location is or might be offloaded.
1048 Return true in declare target functions, or when nested in a target
1049 region or when unsure, return false otherwise. */
1052 omp_maybe_offloaded (void)
1054 if (!ENABLE_OFFLOADING
)
1056 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1057 if (names
== NULL
|| *names
== '\0')
1060 if (symtab
->state
== PARSING
)
1063 if (cfun
&& cfun
->after_inlining
)
1065 if (current_function_decl
1066 && lookup_attribute ("omp declare target",
1067 DECL_ATTRIBUTES (current_function_decl
)))
1069 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) == 0)
1071 enum tree_code construct
= OMP_TARGET
;
1072 if (omp_construct_selector_matches (&construct
, 1, NULL
))
1078 /* Return a name from PROP, a property in selectors accepting
1082 omp_context_name_list_prop (tree prop
)
1084 if (TREE_PURPOSE (prop
))
1085 return IDENTIFIER_POINTER (TREE_PURPOSE (prop
));
1088 const char *ret
= TREE_STRING_POINTER (TREE_VALUE (prop
));
1089 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop
)) == strlen (ret
) + 1)
1095 /* Return 1 if context selector matches the current OpenMP context, 0
1096 if it does not and -1 if it is unknown and need to be determined later.
1097 Some properties can be checked right away during parsing (this routine),
1098 others need to wait until the whole TU is parsed, others need to wait until
1099 IPA, others until vectorization. */
1102 omp_context_selector_matches (tree ctx
)
1105 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1107 char set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
))[0];
1110 /* For now, ignore the construct set. While something can be
1111 determined already during parsing, we don't know until end of TU
1112 whether additional constructs aren't added through declare variant
1113 unless "omp declare variant variant" attribute exists already
1114 (so in most of the cases), and we'd need to maintain set of
1115 surrounding OpenMP constructs, which is better handled during
1117 if (symtab
->state
== PARSING
)
1123 enum tree_code constructs
[5];
1125 = omp_constructor_traits_to_codes (TREE_VALUE (t1
), constructs
);
1127 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1129 if (!cfun
->after_inlining
)
1135 for (i
= 0; i
< nconstructs
; ++i
)
1136 if (constructs
[i
] == OMP_SIMD
)
1138 if (i
< nconstructs
)
1143 /* If there is no simd, assume it is ok after IPA,
1144 constructs should have been checked before. */
1148 int r
= omp_construct_selector_matches (constructs
, nconstructs
,
1156 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1158 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
1162 if (set
== 'i' && !strcmp (sel
, "vendor"))
1163 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1165 const char *prop
= omp_context_name_list_prop (t3
);
1168 if ((!strcmp (prop
, " score") && TREE_PURPOSE (t3
))
1169 || !strcmp (prop
, "gnu"))
1175 if (set
== 'i' && !strcmp (sel
, "extension"))
1176 /* We don't support any extensions right now. */
1180 if (set
== 'i' && !strcmp (sel
, "atomic_default_mem_order"))
1182 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1185 enum omp_memory_order omo
1186 = ((enum omp_memory_order
)
1188 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER
));
1189 if (omo
== OMP_MEMORY_ORDER_UNSPECIFIED
)
1191 /* We don't know yet, until end of TU. */
1192 if (symtab
->state
== PARSING
)
1198 omo
= OMP_MEMORY_ORDER_RELAXED
;
1200 tree t3
= TREE_VALUE (t2
);
1201 const char *prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1202 if (!strcmp (prop
, " score"))
1204 t3
= TREE_CHAIN (t3
);
1205 prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1207 if (!strcmp (prop
, "relaxed")
1208 && omo
!= OMP_MEMORY_ORDER_RELAXED
)
1210 else if (!strcmp (prop
, "seq_cst")
1211 && omo
!= OMP_MEMORY_ORDER_SEQ_CST
)
1213 else if (!strcmp (prop
, "acq_rel")
1214 && omo
!= OMP_MEMORY_ORDER_ACQ_REL
)
1217 if (set
== 'd' && !strcmp (sel
, "arch"))
1218 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1220 const char *arch
= omp_context_name_list_prop (t3
);
1224 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1225 r
= targetm
.omp
.device_kind_arch_isa (omp_device_arch
,
1227 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1229 /* If we are or might be in a target region or
1230 declare target function, need to take into account
1231 also offloading values. */
1232 if (!omp_maybe_offloaded ())
1234 if (ENABLE_OFFLOADING
)
1236 const char *arches
= omp_offload_device_arch
;
1237 if (omp_offload_device_kind_arch_isa (arches
,
1248 /* If arch matches on the host, it still might not match
1249 in the offloading region. */
1250 else if (omp_maybe_offloaded ())
1255 if (set
== 'i' && !strcmp (sel
, "unified_address"))
1257 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1260 if ((omp_requires_mask
& OMP_REQUIRES_UNIFIED_ADDRESS
) == 0)
1262 if (symtab
->state
== PARSING
)
1269 if (set
== 'i' && !strcmp (sel
, "unified_shared_memory"))
1271 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1274 if ((omp_requires_mask
1275 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY
) == 0)
1277 if (symtab
->state
== PARSING
)
1286 if (set
== 'i' && !strcmp (sel
, "dynamic_allocators"))
1288 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1291 if ((omp_requires_mask
1292 & OMP_REQUIRES_DYNAMIC_ALLOCATORS
) == 0)
1294 if (symtab
->state
== PARSING
)
1303 if (set
== 'i' && !strcmp (sel
, "reverse_offload"))
1305 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1308 if ((omp_requires_mask
& OMP_REQUIRES_REVERSE_OFFLOAD
) == 0)
1310 if (symtab
->state
== PARSING
)
1319 if (set
== 'd' && !strcmp (sel
, "kind"))
1320 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1322 const char *prop
= omp_context_name_list_prop (t3
);
1325 if (!strcmp (prop
, "any"))
1327 if (!strcmp (prop
, "host"))
1329 if (omp_maybe_offloaded ())
1333 if (!strcmp (prop
, "nohost"))
1335 if (omp_maybe_offloaded ())
1342 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1343 r
= targetm
.omp
.device_kind_arch_isa (omp_device_kind
,
1346 r
= strcmp (prop
, "cpu") == 0;
1347 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1349 /* If we are or might be in a target region or
1350 declare target function, need to take into account
1351 also offloading values. */
1352 if (!omp_maybe_offloaded ())
1354 if (ENABLE_OFFLOADING
)
1356 const char *kinds
= omp_offload_device_kind
;
1357 if (omp_offload_device_kind_arch_isa (kinds
, prop
))
1367 /* If kind matches on the host, it still might not match
1368 in the offloading region. */
1369 else if (omp_maybe_offloaded ())
1374 if (set
== 'd' && !strcmp (sel
, "isa"))
1375 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1377 const char *isa
= omp_context_name_list_prop (t3
);
1381 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1382 r
= targetm
.omp
.device_kind_arch_isa (omp_device_isa
,
1384 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1386 /* If isa is valid on the target, but not in the
1387 current function and current function has
1388 #pragma omp declare simd on it, some simd clones
1389 might have the isa added later on. */
1391 && targetm
.simd_clone
.compute_vecsize_and_simdlen
1392 && (cfun
== NULL
|| !cfun
->after_inlining
))
1395 = DECL_ATTRIBUTES (current_function_decl
);
1396 if (lookup_attribute ("omp declare simd", attrs
))
1402 /* If we are or might be in a target region or
1403 declare target function, need to take into account
1404 also offloading values. */
1405 if (!omp_maybe_offloaded ())
1407 if (ENABLE_OFFLOADING
)
1409 const char *isas
= omp_offload_device_isa
;
1410 if (omp_offload_device_kind_arch_isa (isas
, isa
))
1420 /* If isa matches on the host, it still might not match
1421 in the offloading region. */
1422 else if (omp_maybe_offloaded ())
1427 if (set
== 'u' && !strcmp (sel
, "condition"))
1428 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1429 if (TREE_PURPOSE (t3
) == NULL_TREE
)
1431 if (integer_zerop (TREE_VALUE (t3
)))
1433 if (integer_nonzerop (TREE_VALUE (t3
)))
1446 /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1447 in omp_context_selector_set_compare. */
1450 omp_construct_simd_compare (tree clauses1
, tree clauses2
)
1452 if (clauses1
== NULL_TREE
)
1453 return clauses2
== NULL_TREE
? 0 : -1;
1454 if (clauses2
== NULL_TREE
)
1458 struct declare_variant_simd_data
{
1459 bool inbranch
, notinbranch
;
1461 auto_vec
<tree
,16> data_sharing
;
1462 auto_vec
<tree
,16> aligned
;
1463 declare_variant_simd_data ()
1464 : inbranch(false), notinbranch(false), simdlen(NULL_TREE
) {}
1467 for (i
= 0; i
< 2; i
++)
1468 for (tree c
= i
? clauses2
: clauses1
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1471 switch (OMP_CLAUSE_CODE (c
))
1473 case OMP_CLAUSE_INBRANCH
:
1474 data
[i
].inbranch
= true;
1476 case OMP_CLAUSE_NOTINBRANCH
:
1477 data
[i
].notinbranch
= true;
1479 case OMP_CLAUSE_SIMDLEN
:
1480 data
[i
].simdlen
= OMP_CLAUSE_SIMDLEN_EXPR (c
);
1482 case OMP_CLAUSE_UNIFORM
:
1483 case OMP_CLAUSE_LINEAR
:
1484 v
= &data
[i
].data_sharing
;
1486 case OMP_CLAUSE_ALIGNED
:
1487 v
= &data
[i
].aligned
;
1492 unsigned HOST_WIDE_INT argno
= tree_to_uhwi (OMP_CLAUSE_DECL (c
));
1493 if (argno
>= v
->length ())
1494 v
->safe_grow_cleared (argno
+ 1, true);
1497 /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1498 CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1499 doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1500 -1, r == 2 implies 1 and r == 0 implies 0. */
1501 if (data
[0].inbranch
!= data
[1].inbranch
)
1502 r
|= data
[0].inbranch
? 2 : 1;
1503 if (data
[0].notinbranch
!= data
[1].notinbranch
)
1504 r
|= data
[0].notinbranch
? 2 : 1;
1505 if (!simple_cst_equal (data
[0].simdlen
, data
[1].simdlen
))
1507 if (data
[0].simdlen
&& data
[1].simdlen
)
1509 r
|= data
[0].simdlen
? 2 : 1;
1511 if (data
[0].data_sharing
.length () < data
[1].data_sharing
.length ()
1512 || data
[0].aligned
.length () < data
[1].aligned
.length ())
1515 FOR_EACH_VEC_ELT (data
[0].data_sharing
, i
, c1
)
1517 c2
= (i
< data
[1].data_sharing
.length ()
1518 ? data
[1].data_sharing
[i
] : NULL_TREE
);
1519 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1521 r
|= c1
!= NULL_TREE
? 2 : 1;
1524 if (c1
== NULL_TREE
)
1526 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_CODE (c2
))
1528 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_LINEAR
)
1530 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1
)
1531 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2
))
1533 if (OMP_CLAUSE_LINEAR_KIND (c1
) != OMP_CLAUSE_LINEAR_KIND (c2
))
1535 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1
),
1536 OMP_CLAUSE_LINEAR_STEP (c2
)))
1539 FOR_EACH_VEC_ELT (data
[0].aligned
, i
, c1
)
1541 c2
= i
< data
[1].aligned
.length () ? data
[1].aligned
[i
] : NULL_TREE
;
1542 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1544 r
|= c1
!= NULL_TREE
? 2 : 1;
1547 if (c1
== NULL_TREE
)
1549 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1
),
1550 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2
)))
1559 default: gcc_unreachable ();
1563 /* Compare properties of selectors SEL from SET other than construct.
1564 Return 0/-1/1/2 as in omp_context_selector_set_compare.
1565 Unlike set names or selector names, properties can have duplicates. */
1568 omp_context_selector_props_compare (const char *set
, const char *sel
,
1569 tree ctx1
, tree ctx2
)
1572 for (int pass
= 0; pass
< 2; pass
++)
1573 for (tree t1
= pass
? ctx2
: ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1576 for (t2
= pass
? ctx1
: ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1577 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1579 if (TREE_PURPOSE (t1
) == NULL_TREE
)
1581 if (set
[0] == 'u' && strcmp (sel
, "condition") == 0)
1583 if (integer_zerop (TREE_VALUE (t1
))
1584 != integer_zerop (TREE_VALUE (t2
)))
1588 if (simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1591 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1
)),
1594 if (!simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1601 else if (TREE_PURPOSE (t1
)
1602 && TREE_PURPOSE (t2
) == NULL_TREE
1603 && TREE_CODE (TREE_VALUE (t2
)) == STRING_CST
)
1605 const char *p1
= omp_context_name_list_prop (t1
);
1606 const char *p2
= omp_context_name_list_prop (t2
);
1608 && strcmp (p1
, p2
) == 0
1609 && strcmp (p1
, " score"))
1612 else if (TREE_PURPOSE (t1
) == NULL_TREE
1613 && TREE_PURPOSE (t2
)
1614 && TREE_CODE (TREE_VALUE (t1
)) == STRING_CST
)
1616 const char *p1
= omp_context_name_list_prop (t1
);
1617 const char *p2
= omp_context_name_list_prop (t2
);
1619 && strcmp (p1
, p2
) == 0
1620 && strcmp (p1
, " score"))
1623 if (t2
== NULL_TREE
)
1625 int r
= pass
? -1 : 1;
1626 if (ret
&& ret
!= r
)
1640 /* Compare single context selector sets CTX1 and CTX2 with SET name.
1641 Return 0 if CTX1 is equal to CTX2,
1642 -1 if CTX1 is a strict subset of CTX2,
1643 1 if CTX2 is a strict subset of CTX1, or
1644 2 if neither context is a subset of another one. */
1647 omp_context_selector_set_compare (const char *set
, tree ctx1
, tree ctx2
)
1649 bool swapped
= false;
1651 int len1
= list_length (ctx1
);
1652 int len2
= list_length (ctx2
);
1657 std::swap (ctx1
, ctx2
);
1658 std::swap (len1
, len2
);
1664 tree simd
= get_identifier ("simd");
1665 /* Handle construct set specially. In this case the order
1666 of the selector matters too. */
1667 for (t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1668 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1671 if (TREE_PURPOSE (t1
) == simd
)
1672 r
= omp_construct_simd_compare (TREE_VALUE (t1
),
1674 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1678 t2
= TREE_CHAIN (t2
);
1679 if (t2
== NULL_TREE
)
1681 t1
= TREE_CHAIN (t1
);
1689 if (t2
!= NULL_TREE
)
1691 if (t1
!= NULL_TREE
)
1699 return swapped
? -ret
: ret
;
1701 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1704 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1705 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1707 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1708 int r
= omp_context_selector_props_compare (set
, sel
,
1711 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1718 if (t2
== NULL_TREE
)
1729 return swapped
? -ret
: ret
;
1732 /* Compare whole context selector specification CTX1 and CTX2.
1733 Return 0 if CTX1 is equal to CTX2,
1734 -1 if CTX1 is a strict subset of CTX2,
1735 1 if CTX2 is a strict subset of CTX1, or
1736 2 if neither context is a subset of another one. */
1739 omp_context_selector_compare (tree ctx1
, tree ctx2
)
1741 bool swapped
= false;
1743 int len1
= list_length (ctx1
);
1744 int len2
= list_length (ctx2
);
1749 std::swap (ctx1
, ctx2
);
1750 std::swap (len1
, len2
);
1752 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1755 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1756 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1758 const char *set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1759 int r
= omp_context_selector_set_compare (set
, TREE_VALUE (t1
),
1761 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1768 if (t2
== NULL_TREE
)
1779 return swapped
? -ret
: ret
;
1782 /* From context selector CTX, return trait-selector with name SEL in
1783 trait-selector-set with name SET if any, or NULL_TREE if not found.
1784 If SEL is NULL, return the list of trait-selectors in SET. */
1787 omp_get_context_selector (tree ctx
, const char *set
, const char *sel
)
1789 tree setid
= get_identifier (set
);
1790 tree selid
= sel
? get_identifier (sel
) : NULL_TREE
;
1791 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1792 if (TREE_PURPOSE (t1
) == setid
)
1795 return TREE_VALUE (t1
);
1796 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1797 if (TREE_PURPOSE (t2
) == selid
)
1803 /* Compute *SCORE for context selector CTX. Return true if the score
1804 would be different depending on whether it is a declare simd clone or
1805 not. DECLARE_SIMD should be true for the case when it would be
1806 a declare simd clone. */
1809 omp_context_compute_score (tree ctx
, widest_int
*score
, bool declare_simd
)
1811 tree construct
= omp_get_context_selector (ctx
, "construct", NULL
);
1812 bool has_kind
= omp_get_context_selector (ctx
, "device", "kind");
1813 bool has_arch
= omp_get_context_selector (ctx
, "device", "arch");
1814 bool has_isa
= omp_get_context_selector (ctx
, "device", "isa");
1817 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1818 if (TREE_VALUE (t1
) != construct
)
1819 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1820 if (tree t3
= TREE_VALUE (t2
))
1821 if (TREE_PURPOSE (t3
)
1822 && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3
)), " score") == 0
1823 && TREE_CODE (TREE_VALUE (t3
)) == INTEGER_CST
)
1824 *score
+= wi::to_widest (TREE_VALUE (t3
));
1825 if (construct
|| has_kind
|| has_arch
|| has_isa
)
1828 enum tree_code constructs
[5];
1829 int nconstructs
= 0;
1831 nconstructs
= omp_constructor_traits_to_codes (construct
, constructs
);
1832 if (omp_construct_selector_matches (constructs
, nconstructs
, scores
)
1835 int b
= declare_simd
? nconstructs
+ 1 : 0;
1836 if (scores
[b
+ nconstructs
] + 4U < score
->get_precision ())
1838 for (int n
= 0; n
< nconstructs
; ++n
)
1840 if (scores
[b
+ n
] < 0)
1845 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ n
], 1, false);
1848 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
],
1851 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 1,
1854 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 2,
1857 else /* FIXME: Implement this. */
1863 /* Class describing a single variant. */
1864 struct GTY(()) omp_declare_variant_entry
{
1865 /* NODE of the variant. */
1866 cgraph_node
*variant
;
1867 /* Score if not in declare simd clone. */
1869 /* Score if in declare simd clone. */
1870 widest_int score_in_declare_simd_clone
;
1871 /* Context selector for the variant. */
1873 /* True if the context selector is known to match already. */
1877 /* Class describing a function with variants. */
1878 struct GTY((for_user
)) omp_declare_variant_base_entry
{
1879 /* NODE of the base function. */
1881 /* NODE of the artificial function created for the deferred variant
1884 /* Vector of the variants. */
1885 vec
<omp_declare_variant_entry
, va_gc
> *variants
;
1888 struct omp_declare_variant_hasher
1889 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1890 static hashval_t
hash (omp_declare_variant_base_entry
*);
1891 static bool equal (omp_declare_variant_base_entry
*,
1892 omp_declare_variant_base_entry
*);
1896 omp_declare_variant_hasher::hash (omp_declare_variant_base_entry
*x
)
1898 inchash::hash hstate
;
1899 hstate
.add_int (DECL_UID (x
->base
->decl
));
1900 hstate
.add_int (x
->variants
->length ());
1901 omp_declare_variant_entry
*variant
;
1903 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1905 hstate
.add_int (DECL_UID (variant
->variant
->decl
));
1906 hstate
.add_wide_int (variant
->score
);
1907 hstate
.add_wide_int (variant
->score_in_declare_simd_clone
);
1908 hstate
.add_ptr (variant
->ctx
);
1909 hstate
.add_int (variant
->matches
);
1911 return hstate
.end ();
1915 omp_declare_variant_hasher::equal (omp_declare_variant_base_entry
*x
,
1916 omp_declare_variant_base_entry
*y
)
1918 if (x
->base
!= y
->base
1919 || x
->variants
->length () != y
->variants
->length ())
1921 omp_declare_variant_entry
*variant
;
1923 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1924 if (variant
->variant
!= (*y
->variants
)[i
].variant
1925 || variant
->score
!= (*y
->variants
)[i
].score
1926 || (variant
->score_in_declare_simd_clone
1927 != (*y
->variants
)[i
].score_in_declare_simd_clone
)
1928 || variant
->ctx
!= (*y
->variants
)[i
].ctx
1929 || variant
->matches
!= (*y
->variants
)[i
].matches
)
1934 static GTY(()) hash_table
<omp_declare_variant_hasher
> *omp_declare_variants
;
1936 struct omp_declare_variant_alt_hasher
1937 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1938 static hashval_t
hash (omp_declare_variant_base_entry
*);
1939 static bool equal (omp_declare_variant_base_entry
*,
1940 omp_declare_variant_base_entry
*);
1944 omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry
*x
)
1946 return DECL_UID (x
->node
->decl
);
1950 omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry
*x
,
1951 omp_declare_variant_base_entry
*y
)
1953 return x
->node
== y
->node
;
1956 static GTY(()) hash_table
<omp_declare_variant_alt_hasher
>
1957 *omp_declare_variant_alt
;
1959 /* Try to resolve declare variant after gimplification. */
1962 omp_resolve_late_declare_variant (tree alt
)
1964 cgraph_node
*node
= cgraph_node::get (alt
);
1965 cgraph_node
*cur_node
= cgraph_node::get (cfun
->decl
);
1967 || !node
->declare_variant_alt
1968 || !cfun
->after_inlining
)
1971 omp_declare_variant_base_entry entry
;
1974 entry
.variants
= NULL
;
1975 omp_declare_variant_base_entry
*entryp
1976 = omp_declare_variant_alt
->find_with_hash (&entry
, DECL_UID (alt
));
1979 omp_declare_variant_entry
*varentry1
, *varentry2
;
1980 auto_vec
<bool, 16> matches
;
1981 unsigned int nmatches
= 0;
1982 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
1984 if (varentry1
->matches
)
1986 /* This has been checked to be ok already. */
1987 matches
.safe_push (true);
1991 switch (omp_context_selector_matches (varentry1
->ctx
))
1994 matches
.safe_push (false);
1999 matches
.safe_push (true);
2006 return entryp
->base
->decl
;
2008 /* A context selector that is a strict subset of another context selector
2009 has a score of zero. */
2010 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2014 vec_safe_iterate (entryp
->variants
, j
, &varentry2
); ++j
)
2017 int r
= omp_context_selector_compare (varentry1
->ctx
,
2021 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2026 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2031 widest_int max_score
= -1;
2033 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2037 = (cur_node
->simdclone
? varentry1
->score_in_declare_simd_clone
2038 : varentry1
->score
);
2039 if (score
> max_score
)
2042 varentry2
= varentry1
;
2045 return varentry2
->variant
->decl
;
2048 /* Hook to adjust hash tables on cgraph_node removal. */
2051 omp_declare_variant_remove_hook (struct cgraph_node
*node
, void *)
2053 if (!node
->declare_variant_alt
)
2056 /* Drop this hash table completely. */
2057 omp_declare_variants
= NULL
;
2058 /* And remove node from the other hash table. */
2059 if (omp_declare_variant_alt
)
2061 omp_declare_variant_base_entry entry
;
2064 entry
.variants
= NULL
;
2065 omp_declare_variant_alt
->remove_elt_with_hash (&entry
,
2066 DECL_UID (node
->decl
));
2070 /* Try to resolve declare variant, return the variant decl if it should
2071 be used instead of base, or base otherwise. */
2074 omp_resolve_declare_variant (tree base
)
2076 tree variant1
= NULL_TREE
, variant2
= NULL_TREE
;
2077 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
2078 return omp_resolve_late_declare_variant (base
);
2080 auto_vec
<tree
, 16> variants
;
2081 auto_vec
<bool, 16> defer
;
2082 bool any_deferred
= false;
2083 for (tree attr
= DECL_ATTRIBUTES (base
); attr
; attr
= TREE_CHAIN (attr
))
2085 attr
= lookup_attribute ("omp declare variant base", attr
);
2086 if (attr
== NULL_TREE
)
2088 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr
))) != FUNCTION_DECL
)
2090 cgraph_node
*node
= cgraph_node::get (base
);
2091 /* If this is already a magic decl created by this function,
2092 don't process it again. */
2093 if (node
&& node
->declare_variant_alt
)
2095 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr
))))
2098 /* No match, ignore. */
2101 /* Needs to be deferred. */
2102 any_deferred
= true;
2103 variants
.safe_push (attr
);
2104 defer
.safe_push (true);
2107 variants
.safe_push (attr
);
2108 defer
.safe_push (false);
2112 if (variants
.length () == 0)
2117 widest_int max_score1
= 0;
2118 widest_int max_score2
= 0;
2122 omp_declare_variant_base_entry entry
;
2123 entry
.base
= cgraph_node::get_create (base
);
2125 vec_alloc (entry
.variants
, variants
.length ());
2126 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2131 tree ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2132 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2134 omp_context_compute_score (ctx
, &score2
, true);
2140 max_score1
= score1
;
2141 max_score2
= score2
;
2150 if (max_score1
== score1
)
2151 variant1
= NULL_TREE
;
2152 else if (score1
> max_score1
)
2154 max_score1
= score1
;
2155 variant1
= defer
[i
] ? NULL_TREE
: attr1
;
2157 if (max_score2
== score2
)
2158 variant2
= NULL_TREE
;
2159 else if (score2
> max_score2
)
2161 max_score2
= score2
;
2162 variant2
= defer
[i
] ? NULL_TREE
: attr1
;
2165 omp_declare_variant_entry varentry
;
2167 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1
)));
2168 varentry
.score
= score1
;
2169 varentry
.score_in_declare_simd_clone
= score2
;
2171 varentry
.matches
= !defer
[i
];
2172 entry
.variants
->quick_push (varentry
);
2175 /* If there is a clear winner variant with the score which is not
2176 deferred, verify it is not a strict subset of any other context
2177 selector and if it is not, it is the best alternative no matter
2178 whether the others do or don't match. */
2179 if (variant1
&& variant1
== variant2
)
2181 tree ctx1
= TREE_VALUE (TREE_VALUE (variant1
));
2182 FOR_EACH_VEC_ELT (variants
, i
, attr2
)
2184 if (attr2
== variant1
)
2186 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2187 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2190 /* The winner is a strict subset of ctx2, can't
2192 variant1
= NULL_TREE
;
2198 vec_free (entry
.variants
);
2199 return TREE_PURPOSE (TREE_VALUE (variant1
));
2203 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
2204 if (!node_removal_hook_holder
)
2205 node_removal_hook_holder
2206 = symtab
->add_cgraph_removal_hook (omp_declare_variant_remove_hook
,
2209 if (omp_declare_variants
== NULL
)
2210 omp_declare_variants
2211 = hash_table
<omp_declare_variant_hasher
>::create_ggc (64);
2212 omp_declare_variant_base_entry
**slot
2213 = omp_declare_variants
->find_slot (&entry
, INSERT
);
2216 vec_free (entry
.variants
);
2217 return (*slot
)->node
->decl
;
2220 *slot
= ggc_cleared_alloc
<omp_declare_variant_base_entry
> ();
2221 (*slot
)->base
= entry
.base
;
2222 (*slot
)->node
= entry
.base
;
2223 (*slot
)->variants
= entry
.variants
;
2224 tree alt
= build_decl (DECL_SOURCE_LOCATION (base
), FUNCTION_DECL
,
2225 DECL_NAME (base
), TREE_TYPE (base
));
2226 DECL_ARTIFICIAL (alt
) = 1;
2227 DECL_IGNORED_P (alt
) = 1;
2228 TREE_STATIC (alt
) = 1;
2229 tree attributes
= DECL_ATTRIBUTES (base
);
2230 if (lookup_attribute ("noipa", attributes
) == NULL
)
2232 attributes
= tree_cons (get_identifier ("noipa"), NULL
, attributes
);
2233 if (lookup_attribute ("noinline", attributes
) == NULL
)
2234 attributes
= tree_cons (get_identifier ("noinline"), NULL
,
2236 if (lookup_attribute ("noclone", attributes
) == NULL
)
2237 attributes
= tree_cons (get_identifier ("noclone"), NULL
,
2239 if (lookup_attribute ("no_icf", attributes
) == NULL
)
2240 attributes
= tree_cons (get_identifier ("no_icf"), NULL
,
2243 DECL_ATTRIBUTES (alt
) = attributes
;
2244 DECL_INITIAL (alt
) = error_mark_node
;
2245 (*slot
)->node
= cgraph_node::create (alt
);
2246 (*slot
)->node
->declare_variant_alt
= 1;
2247 (*slot
)->node
->create_reference (entry
.base
, IPA_REF_ADDR
);
2248 omp_declare_variant_entry
*varentry
;
2249 FOR_EACH_VEC_SAFE_ELT (entry
.variants
, i
, varentry
)
2250 (*slot
)->node
->create_reference (varentry
->variant
, IPA_REF_ADDR
);
2251 if (omp_declare_variant_alt
== NULL
)
2252 omp_declare_variant_alt
2253 = hash_table
<omp_declare_variant_alt_hasher
>::create_ggc (64);
2254 *omp_declare_variant_alt
->find_slot_with_hash (*slot
, DECL_UID (alt
),
2259 if (variants
.length () == 1)
2260 return TREE_PURPOSE (TREE_VALUE (variants
[0]));
2262 /* A context selector that is a strict subset of another context selector
2263 has a score of zero. */
2266 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2269 tree ctx1
= TREE_VALUE (TREE_VALUE (attr1
));
2270 FOR_EACH_VEC_ELT_FROM (variants
, j
, attr2
, i
+ 1)
2273 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2274 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2277 /* ctx1 is a strict subset of ctx2, remove
2278 attr1 from the vector. */
2279 variants
[i
] = NULL_TREE
;
2283 /* ctx2 is a strict subset of ctx1, remove attr2
2285 variants
[j
] = NULL_TREE
;
2288 widest_int max_score1
= 0;
2289 widest_int max_score2
= 0;
2291 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2303 ctx
= TREE_VALUE (TREE_VALUE (variant1
));
2304 need_two
= omp_context_compute_score (ctx
, &max_score1
, false);
2306 omp_context_compute_score (ctx
, &max_score2
, true);
2308 max_score2
= max_score1
;
2310 ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2311 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2313 omp_context_compute_score (ctx
, &score2
, true);
2316 if (score1
> max_score1
)
2318 max_score1
= score1
;
2321 if (score2
> max_score2
)
2323 max_score2
= score2
;
2333 /* If there is a disagreement on which variant has the highest score
2334 depending on whether it will be in a declare simd clone or not,
2335 punt for now and defer until after IPA where we will know that. */
2336 return ((variant1
&& variant1
== variant2
)
2337 ? TREE_PURPOSE (TREE_VALUE (variant1
)) : base
);
2341 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2342 macro on gomp-constants.h. We do not check for overflow. */
2345 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
2349 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
2352 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
2353 device
, build_int_cst (unsigned_type_node
,
2354 GOMP_LAUNCH_DEVICE_SHIFT
));
2355 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
2360 /* FIXME: What is the following comment for? */
2361 /* Look for compute grid dimension clauses and convert to an attribute
2362 attached to FN. This permits the target-side code to (a) massage
2363 the dimensions, (b) emit that data and (c) optimize. Non-constant
2364 dimensions are pushed onto ARGS.
2366 The attribute value is a TREE_LIST. A set of dimensions is
2367 represented as a list of INTEGER_CST. Those that are runtime
2368 exprs are represented as an INTEGER_CST of zero.
2370 TODO: Normally the attribute will just contain a single such list. If
2371 however it contains a list of lists, this will represent the use of
2372 device_type. Each member of the outer list is an assoc list of
2373 dimensions, keyed by the device type. The first entry will be the
2374 default. Well, that's the plan. */
2376 /* Replace any existing oacc fn attribute with updated dimensions. */
2378 /* Variant working on a list of attributes. */
2381 oacc_replace_fn_attrib_attr (tree attribs
, tree dims
)
2383 tree ident
= get_identifier (OACC_FN_ATTRIB
);
2385 /* If we happen to be present as the first attrib, drop it. */
2386 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
2387 attribs
= TREE_CHAIN (attribs
);
2388 return tree_cons (ident
, dims
, attribs
);
2391 /* Variant working on a function decl. */
2394 oacc_replace_fn_attrib (tree fn
, tree dims
)
2396 DECL_ATTRIBUTES (fn
)
2397 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn
), dims
);
2400 /* Scan CLAUSES for launch dimensions and attach them to the oacc
2401 function attribute. Push any that are non-constant onto the ARGS
2402 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
2405 oacc_set_fn_attrib (tree fn
, tree clauses
, vec
<tree
> *args
)
2407 /* Must match GOMP_DIM ordering. */
2408 static const omp_clause_code ids
[]
2409 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
2410 OMP_CLAUSE_VECTOR_LENGTH
};
2412 tree dims
[GOMP_DIM_MAX
];
2414 tree attr
= NULL_TREE
;
2415 unsigned non_const
= 0;
2417 for (ix
= GOMP_DIM_MAX
; ix
--;)
2419 tree clause
= omp_find_clause (clauses
, ids
[ix
]);
2420 tree dim
= NULL_TREE
;
2423 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
2425 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
2427 dim
= integer_zero_node
;
2428 non_const
|= GOMP_DIM_MASK (ix
);
2430 attr
= tree_cons (NULL_TREE
, dim
, attr
);
2433 oacc_replace_fn_attrib (fn
, attr
);
2437 /* Push a dynamic argument set. */
2438 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
2439 NULL_TREE
, non_const
));
2440 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
2441 if (non_const
& GOMP_DIM_MASK (ix
))
2442 args
->safe_push (dims
[ix
]);
2446 /* Verify OpenACC routine clauses.
2448 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
2449 if it has already been marked in compatible way, and -1 if incompatible.
2450 Upon returning, the chain of clauses will contain exactly one clause
2451 specifying the level of parallelism. */
2454 oacc_verify_routine_clauses (tree fndecl
, tree
*clauses
, location_t loc
,
2455 const char *routine_str
)
2457 tree c_level
= NULL_TREE
;
2458 tree c_p
= NULL_TREE
;
2459 for (tree c
= *clauses
; c
; c_p
= c
, c
= OMP_CLAUSE_CHAIN (c
))
2460 switch (OMP_CLAUSE_CODE (c
))
2462 case OMP_CLAUSE_GANG
:
2463 case OMP_CLAUSE_WORKER
:
2464 case OMP_CLAUSE_VECTOR
:
2465 case OMP_CLAUSE_SEQ
:
2466 if (c_level
== NULL_TREE
)
2468 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_CODE (c_level
))
2470 /* This has already been diagnosed in the front ends. */
2471 /* Drop the duplicate clause. */
2472 gcc_checking_assert (c_p
!= NULL_TREE
);
2473 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2478 error_at (OMP_CLAUSE_LOCATION (c
),
2479 "%qs specifies a conflicting level of parallelism",
2480 omp_clause_code_name
[OMP_CLAUSE_CODE (c
)]);
2481 inform (OMP_CLAUSE_LOCATION (c_level
),
2482 "... to the previous %qs clause here",
2483 omp_clause_code_name
[OMP_CLAUSE_CODE (c_level
)]);
2484 /* Drop the conflicting clause. */
2485 gcc_checking_assert (c_p
!= NULL_TREE
);
2486 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2493 if (c_level
== NULL_TREE
)
2495 /* Default to an implicit 'seq' clause. */
2496 c_level
= build_omp_clause (loc
, OMP_CLAUSE_SEQ
);
2497 OMP_CLAUSE_CHAIN (c_level
) = *clauses
;
2500 /* In *clauses, we now have exactly one clause specifying the level of
2504 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl
));
2505 if (attr
!= NULL_TREE
)
2507 /* Diagnose if "#pragma omp declare target" has also been applied. */
2508 if (TREE_VALUE (attr
) == NULL_TREE
)
2510 /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
2511 OpenACC and OpenMP 'target' are not clear. */
2513 "cannot apply %<%s%> to %qD, which has also been"
2514 " marked with an OpenMP 'declare target' directive",
2515 routine_str
, fndecl
);
2520 /* If a "#pragma acc routine" has already been applied, just verify
2521 this one for compatibility. */
2522 /* Collect previous directive's clauses. */
2523 tree c_level_p
= NULL_TREE
;
2524 for (tree c
= TREE_VALUE (attr
); c
; c
= OMP_CLAUSE_CHAIN (c
))
2525 switch (OMP_CLAUSE_CODE (c
))
2527 case OMP_CLAUSE_GANG
:
2528 case OMP_CLAUSE_WORKER
:
2529 case OMP_CLAUSE_VECTOR
:
2530 case OMP_CLAUSE_SEQ
:
2531 gcc_checking_assert (c_level_p
== NULL_TREE
);
2537 gcc_checking_assert (c_level_p
!= NULL_TREE
);
2538 /* ..., and compare to current directive's, which we've already collected
2542 /* Matching level of parallelism? */
2543 if (OMP_CLAUSE_CODE (c_level
) != OMP_CLAUSE_CODE (c_level_p
))
2546 c_diag_p
= c_level_p
;
2553 if (c_diag
!= NULL_TREE
)
2554 error_at (OMP_CLAUSE_LOCATION (c_diag
),
2555 "incompatible %qs clause when applying"
2556 " %<%s%> to %qD, which has already been"
2557 " marked with an OpenACC 'routine' directive",
2558 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)],
2559 routine_str
, fndecl
);
2560 else if (c_diag_p
!= NULL_TREE
)
2562 "missing %qs clause when applying"
2563 " %<%s%> to %qD, which has already been"
2564 " marked with an OpenACC 'routine' directive",
2565 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)],
2566 routine_str
, fndecl
);
2569 if (c_diag_p
!= NULL_TREE
)
2570 inform (OMP_CLAUSE_LOCATION (c_diag_p
),
2571 "... with %qs clause here",
2572 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)]);
2575 /* In the front ends, we don't preserve location information for the
2576 OpenACC routine directive itself. However, that of c_level_p
2578 location_t loc_routine
= OMP_CLAUSE_LOCATION (c_level_p
);
2579 inform (loc_routine
, "... without %qs clause near to here",
2580 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)]);
2589 /* Process the OpenACC 'routine' directive clauses to generate an attribute
2590 for the level of parallelism. All dimensions have a size of zero
2591 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
2592 can have a loop partitioned on it. non-zero indicates
2593 yes, zero indicates no. By construction once a non-zero has been
2594 reached, further inner dimensions must also be non-zero. We set
2595 TREE_VALUE to zero for the dimensions that may be partitioned and
2596 1 for the other ones -- if a loop is (erroneously) spawned at
2597 an outer level, we don't want to try and partition it. */
2600 oacc_build_routine_dims (tree clauses
)
2602 /* Must match GOMP_DIM ordering. */
2603 static const omp_clause_code ids
[]
2604 = {OMP_CLAUSE_GANG
, OMP_CLAUSE_WORKER
, OMP_CLAUSE_VECTOR
, OMP_CLAUSE_SEQ
};
2608 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
2609 for (ix
= GOMP_DIM_MAX
+ 1; ix
--;)
2610 if (OMP_CLAUSE_CODE (clauses
) == ids
[ix
])
2615 gcc_checking_assert (level
>= 0);
2617 tree dims
= NULL_TREE
;
2619 for (ix
= GOMP_DIM_MAX
; ix
--;)
2620 dims
= tree_cons (build_int_cst (boolean_type_node
, ix
>= level
),
2621 build_int_cst (integer_type_node
, ix
< level
), dims
);
2626 /* Retrieve the oacc function attrib and return it. Non-oacc
2627 functions will return NULL. */
2630 oacc_get_fn_attrib (tree fn
)
2632 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
2635 /* Return true if FN is an OpenMP or OpenACC offloading function. */
2638 offloading_function_p (tree fn
)
2640 tree attrs
= DECL_ATTRIBUTES (fn
);
2641 return (lookup_attribute ("omp declare target", attrs
)
2642 || lookup_attribute ("omp target entrypoint", attrs
));
2645 /* Extract an oacc execution dimension from FN. FN must be an
2646 offloaded function or routine that has already had its execution
2647 dimensions lowered to the target-specific values. */
2650 oacc_get_fn_dim_size (tree fn
, int axis
)
2652 tree attrs
= oacc_get_fn_attrib (fn
);
2654 gcc_assert (axis
< GOMP_DIM_MAX
);
2656 tree dims
= TREE_VALUE (attrs
);
2658 dims
= TREE_CHAIN (dims
);
2660 int size
= TREE_INT_CST_LOW (TREE_VALUE (dims
));
2665 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
2666 IFN_GOACC_DIM_SIZE call. */
2669 oacc_get_ifn_dim_arg (const gimple
*stmt
)
2671 gcc_checking_assert (gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_SIZE
2672 || gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_POS
);
2673 tree arg
= gimple_call_arg (stmt
, 0);
2674 HOST_WIDE_INT axis
= TREE_INT_CST_LOW (arg
);
2676 gcc_checking_assert (axis
>= 0 && axis
< GOMP_DIM_MAX
);
2680 #include "gt-omp-general.h"