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-2021 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"
45 #include "data-streamer.h"
46 #include "streamer-hooks.h"
48 enum omp_requires omp_requires_mask
;
51 omp_find_clause (tree clauses
, enum omp_clause_code kind
)
53 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
54 if (OMP_CLAUSE_CODE (clauses
) == kind
)
60 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
61 allocatable or pointer attribute. */
63 omp_is_allocatable_or_ptr (tree decl
)
65 return lang_hooks
.decls
.omp_is_allocatable_or_ptr (decl
);
68 /* Check whether this DECL belongs to a Fortran optional argument.
69 With 'for_present_check' set to false, decls which are optional parameters
70 themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
71 always pointers. With 'for_present_check' set to true, the decl for checking
72 whether an argument is present is returned; for arguments with value
73 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
74 unrelated to optional arguments, NULL_TREE is returned. */
77 omp_check_optional_argument (tree decl
, bool for_present_check
)
79 return lang_hooks
.decls
.omp_check_optional_argument (decl
, for_present_check
);
82 /* Return true if DECL is a reference type. */
85 omp_is_reference (tree decl
)
87 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
90 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
91 given that V is the loop index variable and STEP is loop step. */
94 omp_adjust_for_condition (location_t loc
, enum tree_code
*cond_code
, tree
*n2
,
104 gcc_assert (TREE_CODE (step
) == INTEGER_CST
);
105 if (TREE_CODE (TREE_TYPE (v
)) == INTEGER_TYPE
)
107 if (integer_onep (step
))
108 *cond_code
= LT_EXPR
;
111 gcc_assert (integer_minus_onep (step
));
112 *cond_code
= GT_EXPR
;
117 tree unit
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v
)));
118 gcc_assert (TREE_CODE (unit
) == INTEGER_CST
);
119 if (tree_int_cst_equal (unit
, step
))
120 *cond_code
= LT_EXPR
;
123 gcc_assert (wi::neg (wi::to_widest (unit
))
124 == wi::to_widest (step
));
125 *cond_code
= GT_EXPR
;
132 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
133 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, 1);
135 *n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (*n2
), *n2
,
136 build_int_cst (TREE_TYPE (*n2
), 1));
137 *cond_code
= LT_EXPR
;
140 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
141 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, -1);
143 *n2
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (*n2
), *n2
,
144 build_int_cst (TREE_TYPE (*n2
), 1));
145 *cond_code
= GT_EXPR
;
152 /* Return the looping step from INCR, extracted from the step of a gimple omp
156 omp_get_for_step_from_incr (location_t loc
, tree incr
)
159 switch (TREE_CODE (incr
))
162 step
= TREE_OPERAND (incr
, 1);
164 case POINTER_PLUS_EXPR
:
165 step
= fold_convert (ssizetype
, TREE_OPERAND (incr
, 1));
168 step
= TREE_OPERAND (incr
, 1);
169 step
= fold_build1_loc (loc
, NEGATE_EXPR
, TREE_TYPE (step
), step
);
177 /* Extract the header elements of parallel loop FOR_STMT and store
181 omp_extract_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
182 struct omp_for_data_loop
*loops
)
184 tree t
, var
, *collapse_iter
, *collapse_count
;
185 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
186 struct omp_for_data_loop
*loop
;
188 struct omp_for_data_loop dummy_loop
;
189 location_t loc
= gimple_location (for_stmt
);
190 bool simd
= gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_SIMD
;
191 bool distribute
= gimple_omp_for_kind (for_stmt
)
192 == GF_OMP_FOR_KIND_DISTRIBUTE
;
193 bool taskloop
= gimple_omp_for_kind (for_stmt
)
194 == GF_OMP_FOR_KIND_TASKLOOP
;
197 fd
->for_stmt
= for_stmt
;
199 fd
->have_nowait
= distribute
|| simd
;
200 fd
->have_ordered
= false;
201 fd
->have_reductemp
= false;
202 fd
->have_pointer_condtemp
= false;
203 fd
->have_scantemp
= false;
204 fd
->have_nonctrl_scantemp
= false;
205 fd
->non_rect
= false;
206 fd
->lastprivate_conditional
= 0;
207 fd
->tiling
= NULL_TREE
;
210 fd
->first_nonrect
= -1;
211 fd
->last_nonrect
= -1;
212 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
213 fd
->sched_modifiers
= 0;
214 fd
->chunk_size
= NULL_TREE
;
215 fd
->simd_schedule
= false;
216 fd
->first_inner_iterations
= NULL_TREE
;
217 fd
->factor
= NULL_TREE
;
218 fd
->adjn1
= NULL_TREE
;
219 collapse_iter
= NULL
;
220 collapse_count
= NULL
;
222 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
223 switch (OMP_CLAUSE_CODE (t
))
225 case OMP_CLAUSE_NOWAIT
:
226 fd
->have_nowait
= true;
228 case OMP_CLAUSE_ORDERED
:
229 fd
->have_ordered
= true;
230 if (OMP_CLAUSE_ORDERED_EXPR (t
))
231 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
233 case OMP_CLAUSE_SCHEDULE
:
234 gcc_assert (!distribute
&& !taskloop
);
236 = (enum omp_clause_schedule_kind
)
237 (OMP_CLAUSE_SCHEDULE_KIND (t
) & OMP_CLAUSE_SCHEDULE_MASK
);
238 fd
->sched_modifiers
= (OMP_CLAUSE_SCHEDULE_KIND (t
)
239 & ~OMP_CLAUSE_SCHEDULE_MASK
);
240 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
241 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
243 case OMP_CLAUSE_DIST_SCHEDULE
:
244 gcc_assert (distribute
);
245 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
247 case OMP_CLAUSE_COLLAPSE
:
248 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
249 if (fd
->collapse
> 1)
251 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
252 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
255 case OMP_CLAUSE_TILE
:
256 fd
->tiling
= OMP_CLAUSE_TILE_LIST (t
);
257 fd
->collapse
= list_length (fd
->tiling
);
258 gcc_assert (fd
->collapse
);
259 collapse_iter
= &OMP_CLAUSE_TILE_ITERVAR (t
);
260 collapse_count
= &OMP_CLAUSE_TILE_COUNT (t
);
262 case OMP_CLAUSE__REDUCTEMP_
:
263 fd
->have_reductemp
= true;
265 case OMP_CLAUSE_LASTPRIVATE
:
266 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t
))
267 fd
->lastprivate_conditional
++;
269 case OMP_CLAUSE__CONDTEMP_
:
270 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t
))))
271 fd
->have_pointer_condtemp
= true;
273 case OMP_CLAUSE__SCANTEMP_
:
274 fd
->have_scantemp
= true;
275 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t
)
276 && !OMP_CLAUSE__SCANTEMP__CONTROL (t
))
277 fd
->have_nonctrl_scantemp
= true;
283 if (fd
->collapse
> 1 || fd
->tiling
)
286 fd
->loops
= &fd
->loop
;
288 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
293 collapse_iter
= &iterv
;
294 collapse_count
= &countv
;
297 /* FIXME: for now map schedule(auto) to schedule(static).
298 There should be analysis to determine whether all iterations
299 are approximately the same amount of work (then schedule(static)
300 is best) or if it varies (then schedule(dynamic,N) is better). */
301 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
303 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
304 gcc_assert (fd
->chunk_size
== NULL
);
306 gcc_assert ((fd
->collapse
== 1 && !fd
->tiling
) || collapse_iter
!= NULL
);
308 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
309 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
310 gcc_assert (fd
->chunk_size
== NULL
);
311 else if (fd
->chunk_size
== NULL
)
313 /* We only need to compute a default chunk size for ordered
314 static loops and dynamic loops. */
315 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
317 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
318 ? integer_zero_node
: integer_one_node
;
321 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
322 int single_nonrect
= -1;
323 tree single_nonrect_count
= NULL_TREE
;
324 enum tree_code single_nonrect_cond_code
= ERROR_MARK
;
325 for (i
= 1; i
< cnt
; i
++)
327 tree n1
= gimple_omp_for_initial (for_stmt
, i
);
328 tree n2
= gimple_omp_for_final (for_stmt
, i
);
329 if (TREE_CODE (n1
) == TREE_VEC
)
336 for (int j
= i
- 1; j
>= 0; j
--)
337 if (TREE_VEC_ELT (n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
344 else if (TREE_CODE (n2
) == TREE_VEC
)
351 for (int j
= i
- 1; j
>= 0; j
--)
352 if (TREE_VEC_ELT (n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
360 for (i
= 0; i
< cnt
; i
++)
365 && (fd
->ordered
== 0 || loops
== NULL
))
367 else if (loops
!= NULL
)
372 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
373 gcc_assert (SSA_VAR_P (loop
->v
));
374 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
375 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
376 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
377 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
378 loop
->m1
= NULL_TREE
;
379 loop
->m2
= NULL_TREE
;
381 loop
->non_rect_referenced
= false;
382 if (TREE_CODE (loop
->n1
) == TREE_VEC
)
384 for (int j
= i
- 1; j
>= 0; j
--)
385 if (TREE_VEC_ELT (loop
->n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
389 loops
[j
].non_rect_referenced
= true;
390 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
391 fd
->first_nonrect
= j
;
394 gcc_assert (loop
->outer
);
395 loop
->m1
= TREE_VEC_ELT (loop
->n1
, 1);
396 loop
->n1
= TREE_VEC_ELT (loop
->n1
, 2);
398 fd
->last_nonrect
= i
;
401 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
402 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
403 gcc_assert (loop
->cond_code
!= NE_EXPR
404 || (gimple_omp_for_kind (for_stmt
)
405 != GF_OMP_FOR_KIND_OACC_LOOP
));
406 if (TREE_CODE (loop
->n2
) == TREE_VEC
)
409 gcc_assert (TREE_VEC_ELT (loop
->n2
, 0)
410 == gimple_omp_for_index (for_stmt
, i
- loop
->outer
));
412 for (int j
= i
- 1; j
>= 0; j
--)
413 if (TREE_VEC_ELT (loop
->n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
417 loops
[j
].non_rect_referenced
= true;
418 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
419 fd
->first_nonrect
= j
;
422 gcc_assert (loop
->outer
);
423 loop
->m2
= TREE_VEC_ELT (loop
->n2
, 1);
424 loop
->n2
= TREE_VEC_ELT (loop
->n2
, 2);
426 fd
->last_nonrect
= i
;
429 t
= gimple_omp_for_incr (for_stmt
, i
);
430 gcc_assert (TREE_OPERAND (t
, 0) == var
);
431 loop
->step
= omp_get_for_step_from_incr (loc
, t
);
433 omp_adjust_for_condition (loc
, &loop
->cond_code
, &loop
->n2
, loop
->v
,
437 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
438 && !fd
->have_ordered
))
440 if (fd
->collapse
== 1 && !fd
->tiling
)
441 iter_type
= TREE_TYPE (loop
->v
);
443 || TYPE_PRECISION (iter_type
)
444 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
446 = build_nonstandard_integer_type
447 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
449 else if (iter_type
!= long_long_unsigned_type_node
)
451 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
452 iter_type
= long_long_unsigned_type_node
;
453 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
454 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
455 >= TYPE_PRECISION (iter_type
))
459 if (loop
->cond_code
== LT_EXPR
)
460 n
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
461 loop
->n2
, loop
->step
);
466 || TREE_CODE (n
) != INTEGER_CST
467 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
468 iter_type
= long_long_unsigned_type_node
;
470 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
471 > TYPE_PRECISION (iter_type
))
475 if (loop
->cond_code
== LT_EXPR
)
478 n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
479 loop
->n2
, loop
->step
);
483 n1
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (loop
->v
),
484 loop
->n2
, loop
->step
);
489 || TREE_CODE (n1
) != INTEGER_CST
490 || TREE_CODE (n2
) != INTEGER_CST
491 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
492 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
493 iter_type
= long_long_unsigned_type_node
;
497 if (i
>= fd
->collapse
)
500 if (collapse_count
&& *collapse_count
== NULL
)
502 if (count
&& integer_zerop (count
))
504 tree n1first
= NULL_TREE
, n2first
= NULL_TREE
;
505 tree n1last
= NULL_TREE
, n2last
= NULL_TREE
;
506 tree ostep
= NULL_TREE
;
507 if (loop
->m1
|| loop
->m2
)
509 if (count
== NULL_TREE
)
511 if (single_nonrect
== -1
512 || (loop
->m1
&& TREE_CODE (loop
->m1
) != INTEGER_CST
)
513 || (loop
->m2
&& TREE_CODE (loop
->m2
) != INTEGER_CST
)
514 || TREE_CODE (loop
->n1
) != INTEGER_CST
515 || TREE_CODE (loop
->n2
) != INTEGER_CST
516 || TREE_CODE (loop
->step
) != INTEGER_CST
)
521 tree var
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
522 tree itype
= TREE_TYPE (var
);
523 tree first
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
524 t
= gimple_omp_for_incr (for_stmt
, single_nonrect
);
525 ostep
= omp_get_for_step_from_incr (loc
, t
);
526 t
= fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
527 single_nonrect_count
,
528 build_one_cst (long_long_unsigned_type_node
));
529 t
= fold_convert (itype
, t
);
530 first
= fold_convert (itype
, first
);
531 ostep
= fold_convert (itype
, ostep
);
532 tree last
= fold_binary (PLUS_EXPR
, itype
, first
,
533 fold_binary (MULT_EXPR
, itype
, t
,
535 if (TREE_CODE (first
) != INTEGER_CST
536 || TREE_CODE (last
) != INTEGER_CST
)
543 tree m1
= fold_convert (itype
, loop
->m1
);
544 tree n1
= fold_convert (itype
, loop
->n1
);
545 n1first
= fold_binary (PLUS_EXPR
, itype
,
546 fold_binary (MULT_EXPR
, itype
,
548 n1last
= fold_binary (PLUS_EXPR
, itype
,
549 fold_binary (MULT_EXPR
, itype
,
553 n1first
= n1last
= loop
->n1
;
556 tree n2
= fold_convert (itype
, loop
->n2
);
557 tree m2
= fold_convert (itype
, loop
->m2
);
558 n2first
= fold_binary (PLUS_EXPR
, itype
,
559 fold_binary (MULT_EXPR
, itype
,
561 n2last
= fold_binary (PLUS_EXPR
, itype
,
562 fold_binary (MULT_EXPR
, itype
,
566 n2first
= n2last
= loop
->n2
;
567 n1first
= fold_convert (TREE_TYPE (loop
->v
), n1first
);
568 n2first
= fold_convert (TREE_TYPE (loop
->v
), n2first
);
569 n1last
= fold_convert (TREE_TYPE (loop
->v
), n1last
);
570 n2last
= fold_convert (TREE_TYPE (loop
->v
), n2last
);
571 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
573 tree t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
575 if (t
&& t2
&& integer_nonzerop (t
) && integer_nonzerop (t2
))
576 /* All outer loop iterators have at least one inner loop
577 iteration. Try to compute the count at compile time. */
579 else if (t
&& t2
&& integer_zerop (t
) && integer_zerop (t2
))
580 /* No iterations of the inner loop. count will be set to
582 else if (TYPE_UNSIGNED (itype
)
585 || TREE_CODE (t
) != INTEGER_CST
586 || TREE_CODE (t2
) != INTEGER_CST
)
588 /* Punt (for now). */
594 /* Some iterations of the outer loop have zero iterations
595 of the inner loop, while others have at least one.
596 In this case, we need to adjust one of those outer
597 loop bounds. If ADJ_FIRST, we need to adjust outer n1
598 (first), otherwise outer n2 (last). */
599 bool adj_first
= integer_zerop (t
);
600 tree n1
= fold_convert (itype
, loop
->n1
);
601 tree n2
= fold_convert (itype
, loop
->n2
);
602 tree m1
= loop
->m1
? fold_convert (itype
, loop
->m1
)
603 : build_zero_cst (itype
);
604 tree m2
= loop
->m2
? fold_convert (itype
, loop
->m2
)
605 : build_zero_cst (itype
);
606 t
= fold_binary (MINUS_EXPR
, itype
, n1
, n2
);
607 t2
= fold_binary (MINUS_EXPR
, itype
, m2
, m1
);
608 t
= fold_binary (TRUNC_DIV_EXPR
, itype
, t
, t2
);
609 t2
= fold_binary (MINUS_EXPR
, itype
, t
, first
);
610 t2
= fold_binary (TRUNC_MOD_EXPR
, itype
, t2
, ostep
);
611 t
= fold_binary (MINUS_EXPR
, itype
, t
, t2
);
613 = fold_binary (PLUS_EXPR
, itype
, n1
,
614 fold_binary (MULT_EXPR
, itype
, m1
, t
));
616 = fold_binary (PLUS_EXPR
, itype
, n2
,
617 fold_binary (MULT_EXPR
, itype
, m2
, t
));
618 t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
620 tree t3
= fold_binary (MULT_EXPR
, itype
, m1
, ostep
);
621 tree t4
= fold_binary (MULT_EXPR
, itype
, m2
, ostep
);
626 if (integer_nonzerop (t2
))
633 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
634 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
635 t3
= fold_binary (loop
->cond_code
,
636 boolean_type_node
, t3
, t4
);
637 gcc_assert (integer_zerop (t3
));
642 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
643 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
644 new_first
= fold_binary (PLUS_EXPR
, itype
, t
, ostep
);
649 t3
= fold_binary (loop
->cond_code
,
650 boolean_type_node
, t3
, t4
);
651 gcc_assert (integer_nonzerop (t3
));
654 diff
= fold_binary (MINUS_EXPR
, itype
, new_first
, first
);
661 if (integer_zerop (t2
))
663 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
664 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
665 new_last
= fold_binary (MINUS_EXPR
, itype
, t
, ostep
);
670 t3
= fold_binary (loop
->cond_code
,
671 boolean_type_node
, t3
, t4
);
672 gcc_assert (integer_nonzerop (t3
));
682 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
683 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
684 t3
= fold_binary (loop
->cond_code
,
685 boolean_type_node
, t3
, t4
);
686 gcc_assert (integer_zerop (t3
));
689 diff
= fold_binary (MINUS_EXPR
, itype
, last
, new_last
);
691 if (TYPE_UNSIGNED (itype
)
692 && single_nonrect_cond_code
== GT_EXPR
)
693 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
,
694 fold_unary (NEGATE_EXPR
, itype
, diff
),
695 fold_unary (NEGATE_EXPR
, itype
,
698 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
, diff
, ostep
);
699 diff
= fold_convert (long_long_unsigned_type_node
, diff
);
701 = fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
702 single_nonrect_count
, diff
);
707 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
708 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
709 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
710 if (t
&& integer_zerop (t
))
711 count
= build_zero_cst (long_long_unsigned_type_node
);
712 else if ((i
== 0 || count
!= NULL_TREE
)
713 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
714 && TREE_CONSTANT (loop
->n1
)
715 && TREE_CONSTANT (loop
->n2
)
716 && TREE_CODE (loop
->step
) == INTEGER_CST
)
718 tree itype
= TREE_TYPE (loop
->v
);
720 if (POINTER_TYPE_P (itype
))
721 itype
= signed_type_for (itype
);
722 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
723 t
= fold_build2 (PLUS_EXPR
, itype
,
724 fold_convert (itype
, loop
->step
), t
);
727 if (loop
->m1
|| loop
->m2
)
729 gcc_assert (single_nonrect
!= -1);
733 t
= fold_build2 (PLUS_EXPR
, itype
, t
, fold_convert (itype
, n2
));
734 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
735 tree step
= fold_convert_loc (loc
, itype
, loop
->step
);
736 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
737 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
738 fold_build1 (NEGATE_EXPR
, itype
, t
),
739 fold_build1 (NEGATE_EXPR
, itype
, step
));
741 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
742 tree llutype
= long_long_unsigned_type_node
;
743 t
= fold_convert (llutype
, t
);
744 if (loop
->m1
|| loop
->m2
)
746 /* t is number of iterations of inner loop at either first
747 or last value of the outer iterator (the one with fewer
749 Compute t2 = ((m2 - m1) * ostep) / step
750 and niters = outer_count * t
751 + t2 * ((outer_count - 1) * outer_count / 2)
753 tree m1
= loop
->m1
? loop
->m1
: integer_zero_node
;
754 tree m2
= loop
->m2
? loop
->m2
: integer_zero_node
;
755 m1
= fold_convert (itype
, m1
);
756 m2
= fold_convert (itype
, m2
);
757 tree t2
= fold_build2 (MINUS_EXPR
, itype
, m2
, m1
);
758 t2
= fold_build2 (MULT_EXPR
, itype
, t2
, ostep
);
759 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
760 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
761 fold_build1 (NEGATE_EXPR
, itype
, t2
),
762 fold_build1 (NEGATE_EXPR
, itype
, step
));
764 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t2
, step
);
765 t2
= fold_convert (llutype
, t2
);
766 fd
->first_inner_iterations
= t
;
768 t
= fold_build2 (MULT_EXPR
, llutype
, t
,
769 single_nonrect_count
);
770 tree t3
= fold_build2 (MINUS_EXPR
, llutype
,
771 single_nonrect_count
,
772 build_one_cst (llutype
));
773 t3
= fold_build2 (MULT_EXPR
, llutype
, t3
,
774 single_nonrect_count
);
775 t3
= fold_build2 (TRUNC_DIV_EXPR
, llutype
, t3
,
776 build_int_cst (llutype
, 2));
777 t2
= fold_build2 (MULT_EXPR
, llutype
, t2
, t3
);
778 t
= fold_build2 (PLUS_EXPR
, llutype
, t
, t2
);
780 if (i
== single_nonrect
)
782 if (integer_zerop (t
) || TREE_CODE (t
) != INTEGER_CST
)
786 single_nonrect_count
= t
;
787 single_nonrect_cond_code
= loop
->cond_code
;
788 if (count
== NULL_TREE
)
789 count
= build_one_cst (llutype
);
792 else if (count
!= NULL_TREE
)
793 count
= fold_build2 (MULT_EXPR
, llutype
, count
, t
);
796 if (TREE_CODE (count
) != INTEGER_CST
)
799 else if (count
&& !integer_zerop (count
))
806 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
807 || fd
->have_ordered
))
809 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
810 iter_type
= long_long_unsigned_type_node
;
812 iter_type
= long_integer_type_node
;
814 else if (collapse_iter
&& *collapse_iter
!= NULL
)
815 iter_type
= TREE_TYPE (*collapse_iter
);
816 fd
->iter_type
= iter_type
;
817 if (collapse_iter
&& *collapse_iter
== NULL
)
818 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
819 if (collapse_count
&& *collapse_count
== NULL
)
823 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
824 if (fd
->first_inner_iterations
&& fd
->factor
)
826 t
= make_tree_vec (4);
827 TREE_VEC_ELT (t
, 0) = *collapse_count
;
828 TREE_VEC_ELT (t
, 1) = fd
->first_inner_iterations
;
829 TREE_VEC_ELT (t
, 2) = fd
->factor
;
830 TREE_VEC_ELT (t
, 3) = fd
->adjn1
;
835 *collapse_count
= create_tmp_var (iter_type
, ".count");
838 if (fd
->collapse
> 1 || fd
->tiling
|| (fd
->ordered
&& loops
))
840 fd
->loop
.v
= *collapse_iter
;
841 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
842 fd
->loop
.n2
= *collapse_count
;
843 if (TREE_CODE (fd
->loop
.n2
) == TREE_VEC
)
845 gcc_assert (fd
->non_rect
);
846 fd
->first_inner_iterations
= TREE_VEC_ELT (fd
->loop
.n2
, 1);
847 fd
->factor
= TREE_VEC_ELT (fd
->loop
.n2
, 2);
848 fd
->adjn1
= TREE_VEC_ELT (fd
->loop
.n2
, 3);
849 fd
->loop
.n2
= TREE_VEC_ELT (fd
->loop
.n2
, 0);
851 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
852 fd
->loop
.m1
= NULL_TREE
;
853 fd
->loop
.m2
= NULL_TREE
;
855 fd
->loop
.cond_code
= LT_EXPR
;
861 /* Build a call to GOMP_barrier. */
864 omp_build_barrier (tree lhs
)
866 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
867 : BUILT_IN_GOMP_BARRIER
);
868 gcall
*g
= gimple_build_call (fndecl
, 0);
870 gimple_call_set_lhs (g
, lhs
);
874 /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
875 array, pdata[0] non-NULL if there is anything non-trivial in between,
876 pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
877 of OMP_FOR in between if any and pdata[3] is address of the inner
881 find_combined_omp_for (tree
*tp
, int *walk_subtrees
, void *data
)
883 tree
**pdata
= (tree
**) data
;
885 switch (TREE_CODE (*tp
))
888 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
897 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
904 if (BIND_EXPR_VARS (*tp
)
905 || (BIND_EXPR_BLOCK (*tp
)
906 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp
))))
911 if (!tsi_one_before_end_p (tsi_start (*tp
)))
915 case TRY_FINALLY_EXPR
:
929 /* Return maximum possible vectorization factor for the target. */
936 || !flag_tree_loop_optimize
937 || (!flag_tree_loop_vectorize
938 && global_options_set
.x_flag_tree_loop_vectorize
))
941 auto_vector_modes modes
;
942 targetm
.vectorize
.autovectorize_vector_modes (&modes
, true);
943 if (!modes
.is_empty ())
946 for (unsigned int i
= 0; i
< modes
.length (); ++i
)
947 /* The returned modes use the smallest element size (and thus
948 the largest nunits) for the vectorization approach that they
950 vf
= ordered_max (vf
, GET_MODE_NUNITS (modes
[i
]));
954 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
955 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
956 return GET_MODE_NUNITS (vqimode
);
961 /* Return maximum SIMT width if offloading may target SIMT hardware. */
964 omp_max_simt_vf (void)
968 if (ENABLE_OFFLOADING
)
969 for (const char *c
= getenv ("OFFLOAD_TARGET_NAMES"); c
;)
971 if (!strncmp (c
, "nvptx", strlen ("nvptx")))
973 else if ((c
= strchr (c
, ':')))
979 /* Store the construct selectors as tree codes from last to first,
980 return their number. */
983 omp_constructor_traits_to_codes (tree ctx
, enum tree_code
*constructs
)
985 int nconstructs
= list_length (ctx
);
986 int i
= nconstructs
- 1;
987 for (tree t2
= ctx
; t2
; t2
= TREE_CHAIN (t2
), i
--)
989 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
990 if (!strcmp (sel
, "target"))
991 constructs
[i
] = OMP_TARGET
;
992 else if (!strcmp (sel
, "teams"))
993 constructs
[i
] = OMP_TEAMS
;
994 else if (!strcmp (sel
, "parallel"))
995 constructs
[i
] = OMP_PARALLEL
;
996 else if (!strcmp (sel
, "for") || !strcmp (sel
, "do"))
997 constructs
[i
] = OMP_FOR
;
998 else if (!strcmp (sel
, "simd"))
999 constructs
[i
] = OMP_SIMD
;
1003 gcc_assert (i
== -1);
1007 /* Return true if PROP is possibly present in one of the offloading target's
1008 OpenMP contexts. The format of PROPS string is always offloading target's
1009 name terminated by '\0', followed by properties for that offloading
1010 target separated by '\0' and terminated by another '\0'. The strings
1011 are created from omp-device-properties installed files of all configured
1012 offloading targets. */
1015 omp_offload_device_kind_arch_isa (const char *props
, const char *prop
)
1017 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1018 if (names
== NULL
|| *names
== '\0')
1020 while (*props
!= '\0')
1022 size_t name_len
= strlen (props
);
1023 bool matches
= false;
1024 for (const char *c
= names
; c
; )
1026 if (strncmp (props
, c
, name_len
) == 0
1027 && (c
[name_len
] == '\0'
1028 || c
[name_len
] == ':'
1029 || c
[name_len
] == '='))
1034 else if ((c
= strchr (c
, ':')))
1037 props
= props
+ name_len
+ 1;
1038 while (*props
!= '\0')
1040 if (matches
&& strcmp (props
, prop
) == 0)
1042 props
= strchr (props
, '\0') + 1;
1049 /* Return true if the current code location is or might be offloaded.
1050 Return true in declare target functions, or when nested in a target
1051 region or when unsure, return false otherwise. */
1054 omp_maybe_offloaded (void)
1056 if (!ENABLE_OFFLOADING
)
1058 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1059 if (names
== NULL
|| *names
== '\0')
1062 if (symtab
->state
== PARSING
)
1065 if (cfun
&& cfun
->after_inlining
)
1067 if (current_function_decl
1068 && lookup_attribute ("omp declare target",
1069 DECL_ATTRIBUTES (current_function_decl
)))
1071 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) == 0)
1073 enum tree_code construct
= OMP_TARGET
;
1074 if (omp_construct_selector_matches (&construct
, 1, NULL
))
1080 /* Return a name from PROP, a property in selectors accepting
1084 omp_context_name_list_prop (tree prop
)
1086 if (TREE_PURPOSE (prop
))
1087 return IDENTIFIER_POINTER (TREE_PURPOSE (prop
));
1090 const char *ret
= TREE_STRING_POINTER (TREE_VALUE (prop
));
1091 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop
)) == strlen (ret
) + 1)
1097 /* Return 1 if context selector matches the current OpenMP context, 0
1098 if it does not and -1 if it is unknown and need to be determined later.
1099 Some properties can be checked right away during parsing (this routine),
1100 others need to wait until the whole TU is parsed, others need to wait until
1101 IPA, others until vectorization. */
1104 omp_context_selector_matches (tree ctx
)
1107 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1109 char set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
))[0];
1112 /* For now, ignore the construct set. While something can be
1113 determined already during parsing, we don't know until end of TU
1114 whether additional constructs aren't added through declare variant
1115 unless "omp declare variant variant" attribute exists already
1116 (so in most of the cases), and we'd need to maintain set of
1117 surrounding OpenMP constructs, which is better handled during
1119 if (symtab
->state
== PARSING
)
1125 enum tree_code constructs
[5];
1127 = omp_constructor_traits_to_codes (TREE_VALUE (t1
), constructs
);
1129 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1131 if (!cfun
->after_inlining
)
1137 for (i
= 0; i
< nconstructs
; ++i
)
1138 if (constructs
[i
] == OMP_SIMD
)
1140 if (i
< nconstructs
)
1145 /* If there is no simd, assume it is ok after IPA,
1146 constructs should have been checked before. */
1150 int r
= omp_construct_selector_matches (constructs
, nconstructs
,
1158 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1160 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
1164 if (set
== 'i' && !strcmp (sel
, "vendor"))
1165 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1167 const char *prop
= omp_context_name_list_prop (t3
);
1170 if ((!strcmp (prop
, " score") && TREE_PURPOSE (t3
))
1171 || !strcmp (prop
, "gnu"))
1177 if (set
== 'i' && !strcmp (sel
, "extension"))
1178 /* We don't support any extensions right now. */
1182 if (set
== 'i' && !strcmp (sel
, "atomic_default_mem_order"))
1184 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1187 enum omp_memory_order omo
1188 = ((enum omp_memory_order
)
1190 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER
));
1191 if (omo
== OMP_MEMORY_ORDER_UNSPECIFIED
)
1193 /* We don't know yet, until end of TU. */
1194 if (symtab
->state
== PARSING
)
1200 omo
= OMP_MEMORY_ORDER_RELAXED
;
1202 tree t3
= TREE_VALUE (t2
);
1203 const char *prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1204 if (!strcmp (prop
, " score"))
1206 t3
= TREE_CHAIN (t3
);
1207 prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1209 if (!strcmp (prop
, "relaxed")
1210 && omo
!= OMP_MEMORY_ORDER_RELAXED
)
1212 else if (!strcmp (prop
, "seq_cst")
1213 && omo
!= OMP_MEMORY_ORDER_SEQ_CST
)
1215 else if (!strcmp (prop
, "acq_rel")
1216 && omo
!= OMP_MEMORY_ORDER_ACQ_REL
)
1219 if (set
== 'd' && !strcmp (sel
, "arch"))
1220 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1222 const char *arch
= omp_context_name_list_prop (t3
);
1226 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1227 r
= targetm
.omp
.device_kind_arch_isa (omp_device_arch
,
1229 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1231 /* If we are or might be in a target region or
1232 declare target function, need to take into account
1233 also offloading values. */
1234 if (!omp_maybe_offloaded ())
1236 if (ENABLE_OFFLOADING
)
1238 const char *arches
= omp_offload_device_arch
;
1239 if (omp_offload_device_kind_arch_isa (arches
,
1250 /* If arch matches on the host, it still might not match
1251 in the offloading region. */
1252 else if (omp_maybe_offloaded ())
1257 if (set
== 'i' && !strcmp (sel
, "unified_address"))
1259 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1262 if ((omp_requires_mask
& OMP_REQUIRES_UNIFIED_ADDRESS
) == 0)
1264 if (symtab
->state
== PARSING
)
1271 if (set
== 'i' && !strcmp (sel
, "unified_shared_memory"))
1273 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1276 if ((omp_requires_mask
1277 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY
) == 0)
1279 if (symtab
->state
== PARSING
)
1288 if (set
== 'i' && !strcmp (sel
, "dynamic_allocators"))
1290 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1293 if ((omp_requires_mask
1294 & OMP_REQUIRES_DYNAMIC_ALLOCATORS
) == 0)
1296 if (symtab
->state
== PARSING
)
1305 if (set
== 'i' && !strcmp (sel
, "reverse_offload"))
1307 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1310 if ((omp_requires_mask
& OMP_REQUIRES_REVERSE_OFFLOAD
) == 0)
1312 if (symtab
->state
== PARSING
)
1321 if (set
== 'd' && !strcmp (sel
, "kind"))
1322 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1324 const char *prop
= omp_context_name_list_prop (t3
);
1327 if (!strcmp (prop
, "any"))
1329 if (!strcmp (prop
, "host"))
1331 if (omp_maybe_offloaded ())
1335 if (!strcmp (prop
, "nohost"))
1337 if (omp_maybe_offloaded ())
1344 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1345 r
= targetm
.omp
.device_kind_arch_isa (omp_device_kind
,
1348 r
= strcmp (prop
, "cpu") == 0;
1349 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1351 /* If we are or might be in a target region or
1352 declare target function, need to take into account
1353 also offloading values. */
1354 if (!omp_maybe_offloaded ())
1356 if (ENABLE_OFFLOADING
)
1358 const char *kinds
= omp_offload_device_kind
;
1359 if (omp_offload_device_kind_arch_isa (kinds
, prop
))
1369 /* If kind matches on the host, it still might not match
1370 in the offloading region. */
1371 else if (omp_maybe_offloaded ())
1376 if (set
== 'd' && !strcmp (sel
, "isa"))
1377 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1379 const char *isa
= omp_context_name_list_prop (t3
);
1383 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1384 r
= targetm
.omp
.device_kind_arch_isa (omp_device_isa
,
1386 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1388 /* If isa is valid on the target, but not in the
1389 current function and current function has
1390 #pragma omp declare simd on it, some simd clones
1391 might have the isa added later on. */
1393 && targetm
.simd_clone
.compute_vecsize_and_simdlen
1394 && (cfun
== NULL
|| !cfun
->after_inlining
))
1397 = DECL_ATTRIBUTES (current_function_decl
);
1398 if (lookup_attribute ("omp declare simd", attrs
))
1404 /* If we are or might be in a target region or
1405 declare target function, need to take into account
1406 also offloading values. */
1407 if (!omp_maybe_offloaded ())
1409 if (ENABLE_OFFLOADING
)
1411 const char *isas
= omp_offload_device_isa
;
1412 if (omp_offload_device_kind_arch_isa (isas
, isa
))
1422 /* If isa matches on the host, it still might not match
1423 in the offloading region. */
1424 else if (omp_maybe_offloaded ())
1429 if (set
== 'u' && !strcmp (sel
, "condition"))
1430 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1431 if (TREE_PURPOSE (t3
) == NULL_TREE
)
1433 if (integer_zerop (TREE_VALUE (t3
)))
1435 if (integer_nonzerop (TREE_VALUE (t3
)))
1448 /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1449 in omp_context_selector_set_compare. */
1452 omp_construct_simd_compare (tree clauses1
, tree clauses2
)
1454 if (clauses1
== NULL_TREE
)
1455 return clauses2
== NULL_TREE
? 0 : -1;
1456 if (clauses2
== NULL_TREE
)
1460 struct declare_variant_simd_data
{
1461 bool inbranch
, notinbranch
;
1463 auto_vec
<tree
,16> data_sharing
;
1464 auto_vec
<tree
,16> aligned
;
1465 declare_variant_simd_data ()
1466 : inbranch(false), notinbranch(false), simdlen(NULL_TREE
) {}
1469 for (i
= 0; i
< 2; i
++)
1470 for (tree c
= i
? clauses2
: clauses1
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1473 switch (OMP_CLAUSE_CODE (c
))
1475 case OMP_CLAUSE_INBRANCH
:
1476 data
[i
].inbranch
= true;
1478 case OMP_CLAUSE_NOTINBRANCH
:
1479 data
[i
].notinbranch
= true;
1481 case OMP_CLAUSE_SIMDLEN
:
1482 data
[i
].simdlen
= OMP_CLAUSE_SIMDLEN_EXPR (c
);
1484 case OMP_CLAUSE_UNIFORM
:
1485 case OMP_CLAUSE_LINEAR
:
1486 v
= &data
[i
].data_sharing
;
1488 case OMP_CLAUSE_ALIGNED
:
1489 v
= &data
[i
].aligned
;
1494 unsigned HOST_WIDE_INT argno
= tree_to_uhwi (OMP_CLAUSE_DECL (c
));
1495 if (argno
>= v
->length ())
1496 v
->safe_grow_cleared (argno
+ 1, true);
1499 /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1500 CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1501 doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1502 -1, r == 2 implies 1 and r == 0 implies 0. */
1503 if (data
[0].inbranch
!= data
[1].inbranch
)
1504 r
|= data
[0].inbranch
? 2 : 1;
1505 if (data
[0].notinbranch
!= data
[1].notinbranch
)
1506 r
|= data
[0].notinbranch
? 2 : 1;
1507 if (!simple_cst_equal (data
[0].simdlen
, data
[1].simdlen
))
1509 if (data
[0].simdlen
&& data
[1].simdlen
)
1511 r
|= data
[0].simdlen
? 2 : 1;
1513 if (data
[0].data_sharing
.length () < data
[1].data_sharing
.length ()
1514 || data
[0].aligned
.length () < data
[1].aligned
.length ())
1517 FOR_EACH_VEC_ELT (data
[0].data_sharing
, i
, c1
)
1519 c2
= (i
< data
[1].data_sharing
.length ()
1520 ? data
[1].data_sharing
[i
] : NULL_TREE
);
1521 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1523 r
|= c1
!= NULL_TREE
? 2 : 1;
1526 if (c1
== NULL_TREE
)
1528 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_CODE (c2
))
1530 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_LINEAR
)
1532 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1
)
1533 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2
))
1535 if (OMP_CLAUSE_LINEAR_KIND (c1
) != OMP_CLAUSE_LINEAR_KIND (c2
))
1537 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1
),
1538 OMP_CLAUSE_LINEAR_STEP (c2
)))
1541 FOR_EACH_VEC_ELT (data
[0].aligned
, i
, c1
)
1543 c2
= i
< data
[1].aligned
.length () ? data
[1].aligned
[i
] : NULL_TREE
;
1544 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1546 r
|= c1
!= NULL_TREE
? 2 : 1;
1549 if (c1
== NULL_TREE
)
1551 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1
),
1552 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2
)))
1561 default: gcc_unreachable ();
1565 /* Compare properties of selectors SEL from SET other than construct.
1566 Return 0/-1/1/2 as in omp_context_selector_set_compare.
1567 Unlike set names or selector names, properties can have duplicates. */
1570 omp_context_selector_props_compare (const char *set
, const char *sel
,
1571 tree ctx1
, tree ctx2
)
1574 for (int pass
= 0; pass
< 2; pass
++)
1575 for (tree t1
= pass
? ctx2
: ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1578 for (t2
= pass
? ctx1
: ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1579 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1581 if (TREE_PURPOSE (t1
) == NULL_TREE
)
1583 if (set
[0] == 'u' && strcmp (sel
, "condition") == 0)
1585 if (integer_zerop (TREE_VALUE (t1
))
1586 != integer_zerop (TREE_VALUE (t2
)))
1590 if (simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1593 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1
)),
1596 if (!simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1603 else if (TREE_PURPOSE (t1
)
1604 && TREE_PURPOSE (t2
) == NULL_TREE
1605 && TREE_CODE (TREE_VALUE (t2
)) == STRING_CST
)
1607 const char *p1
= omp_context_name_list_prop (t1
);
1608 const char *p2
= omp_context_name_list_prop (t2
);
1610 && strcmp (p1
, p2
) == 0
1611 && strcmp (p1
, " score"))
1614 else if (TREE_PURPOSE (t1
) == NULL_TREE
1615 && TREE_PURPOSE (t2
)
1616 && TREE_CODE (TREE_VALUE (t1
)) == STRING_CST
)
1618 const char *p1
= omp_context_name_list_prop (t1
);
1619 const char *p2
= omp_context_name_list_prop (t2
);
1621 && strcmp (p1
, p2
) == 0
1622 && strcmp (p1
, " score"))
1625 if (t2
== NULL_TREE
)
1627 int r
= pass
? -1 : 1;
1628 if (ret
&& ret
!= r
)
1642 /* Compare single context selector sets CTX1 and CTX2 with SET name.
1643 Return 0 if CTX1 is equal to CTX2,
1644 -1 if CTX1 is a strict subset of CTX2,
1645 1 if CTX2 is a strict subset of CTX1, or
1646 2 if neither context is a subset of another one. */
1649 omp_context_selector_set_compare (const char *set
, tree ctx1
, tree ctx2
)
1651 bool swapped
= false;
1653 int len1
= list_length (ctx1
);
1654 int len2
= list_length (ctx2
);
1659 std::swap (ctx1
, ctx2
);
1660 std::swap (len1
, len2
);
1666 tree simd
= get_identifier ("simd");
1667 /* Handle construct set specially. In this case the order
1668 of the selector matters too. */
1669 for (t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1670 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1673 if (TREE_PURPOSE (t1
) == simd
)
1674 r
= omp_construct_simd_compare (TREE_VALUE (t1
),
1676 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1680 t2
= TREE_CHAIN (t2
);
1681 if (t2
== NULL_TREE
)
1683 t1
= TREE_CHAIN (t1
);
1691 if (t2
!= NULL_TREE
)
1693 if (t1
!= NULL_TREE
)
1701 return swapped
? -ret
: ret
;
1703 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1706 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1707 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1709 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1710 int r
= omp_context_selector_props_compare (set
, sel
,
1713 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1720 if (t2
== NULL_TREE
)
1731 return swapped
? -ret
: ret
;
1734 /* Compare whole context selector specification CTX1 and CTX2.
1735 Return 0 if CTX1 is equal to CTX2,
1736 -1 if CTX1 is a strict subset of CTX2,
1737 1 if CTX2 is a strict subset of CTX1, or
1738 2 if neither context is a subset of another one. */
1741 omp_context_selector_compare (tree ctx1
, tree ctx2
)
1743 bool swapped
= false;
1745 int len1
= list_length (ctx1
);
1746 int len2
= list_length (ctx2
);
1751 std::swap (ctx1
, ctx2
);
1752 std::swap (len1
, len2
);
1754 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1757 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1758 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1760 const char *set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1761 int r
= omp_context_selector_set_compare (set
, TREE_VALUE (t1
),
1763 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1770 if (t2
== NULL_TREE
)
1781 return swapped
? -ret
: ret
;
1784 /* From context selector CTX, return trait-selector with name SEL in
1785 trait-selector-set with name SET if any, or NULL_TREE if not found.
1786 If SEL is NULL, return the list of trait-selectors in SET. */
1789 omp_get_context_selector (tree ctx
, const char *set
, const char *sel
)
1791 tree setid
= get_identifier (set
);
1792 tree selid
= sel
? get_identifier (sel
) : NULL_TREE
;
1793 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1794 if (TREE_PURPOSE (t1
) == setid
)
1797 return TREE_VALUE (t1
);
1798 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1799 if (TREE_PURPOSE (t2
) == selid
)
1805 /* Compute *SCORE for context selector CTX. Return true if the score
1806 would be different depending on whether it is a declare simd clone or
1807 not. DECLARE_SIMD should be true for the case when it would be
1808 a declare simd clone. */
1811 omp_context_compute_score (tree ctx
, widest_int
*score
, bool declare_simd
)
1813 tree construct
= omp_get_context_selector (ctx
, "construct", NULL
);
1814 bool has_kind
= omp_get_context_selector (ctx
, "device", "kind");
1815 bool has_arch
= omp_get_context_selector (ctx
, "device", "arch");
1816 bool has_isa
= omp_get_context_selector (ctx
, "device", "isa");
1819 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1820 if (TREE_VALUE (t1
) != construct
)
1821 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1822 if (tree t3
= TREE_VALUE (t2
))
1823 if (TREE_PURPOSE (t3
)
1824 && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3
)), " score") == 0
1825 && TREE_CODE (TREE_VALUE (t3
)) == INTEGER_CST
)
1826 *score
+= wi::to_widest (TREE_VALUE (t3
));
1827 if (construct
|| has_kind
|| has_arch
|| has_isa
)
1830 enum tree_code constructs
[5];
1831 int nconstructs
= 0;
1833 nconstructs
= omp_constructor_traits_to_codes (construct
, constructs
);
1834 if (omp_construct_selector_matches (constructs
, nconstructs
, scores
)
1837 int b
= declare_simd
? nconstructs
+ 1 : 0;
1838 if (scores
[b
+ nconstructs
] + 4U < score
->get_precision ())
1840 for (int n
= 0; n
< nconstructs
; ++n
)
1842 if (scores
[b
+ n
] < 0)
1847 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ n
], 1, false);
1850 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
],
1853 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 1,
1856 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 2,
1859 else /* FIXME: Implement this. */
1865 /* Class describing a single variant. */
1866 struct GTY(()) omp_declare_variant_entry
{
1867 /* NODE of the variant. */
1868 cgraph_node
*variant
;
1869 /* Score if not in declare simd clone. */
1871 /* Score if in declare simd clone. */
1872 widest_int score_in_declare_simd_clone
;
1873 /* Context selector for the variant. */
1875 /* True if the context selector is known to match already. */
1879 /* Class describing a function with variants. */
1880 struct GTY((for_user
)) omp_declare_variant_base_entry
{
1881 /* NODE of the base function. */
1883 /* NODE of the artificial function created for the deferred variant
1886 /* Vector of the variants. */
1887 vec
<omp_declare_variant_entry
, va_gc
> *variants
;
1890 struct omp_declare_variant_hasher
1891 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1892 static hashval_t
hash (omp_declare_variant_base_entry
*);
1893 static bool equal (omp_declare_variant_base_entry
*,
1894 omp_declare_variant_base_entry
*);
1898 omp_declare_variant_hasher::hash (omp_declare_variant_base_entry
*x
)
1900 inchash::hash hstate
;
1901 hstate
.add_int (DECL_UID (x
->base
->decl
));
1902 hstate
.add_int (x
->variants
->length ());
1903 omp_declare_variant_entry
*variant
;
1905 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1907 hstate
.add_int (DECL_UID (variant
->variant
->decl
));
1908 hstate
.add_wide_int (variant
->score
);
1909 hstate
.add_wide_int (variant
->score_in_declare_simd_clone
);
1910 hstate
.add_ptr (variant
->ctx
);
1911 hstate
.add_int (variant
->matches
);
1913 return hstate
.end ();
1917 omp_declare_variant_hasher::equal (omp_declare_variant_base_entry
*x
,
1918 omp_declare_variant_base_entry
*y
)
1920 if (x
->base
!= y
->base
1921 || x
->variants
->length () != y
->variants
->length ())
1923 omp_declare_variant_entry
*variant
;
1925 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1926 if (variant
->variant
!= (*y
->variants
)[i
].variant
1927 || variant
->score
!= (*y
->variants
)[i
].score
1928 || (variant
->score_in_declare_simd_clone
1929 != (*y
->variants
)[i
].score_in_declare_simd_clone
)
1930 || variant
->ctx
!= (*y
->variants
)[i
].ctx
1931 || variant
->matches
!= (*y
->variants
)[i
].matches
)
1936 static GTY(()) hash_table
<omp_declare_variant_hasher
> *omp_declare_variants
;
1938 struct omp_declare_variant_alt_hasher
1939 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1940 static hashval_t
hash (omp_declare_variant_base_entry
*);
1941 static bool equal (omp_declare_variant_base_entry
*,
1942 omp_declare_variant_base_entry
*);
1946 omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry
*x
)
1948 return DECL_UID (x
->node
->decl
);
1952 omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry
*x
,
1953 omp_declare_variant_base_entry
*y
)
1955 return x
->node
== y
->node
;
1958 static GTY(()) hash_table
<omp_declare_variant_alt_hasher
>
1959 *omp_declare_variant_alt
;
1961 /* Try to resolve declare variant after gimplification. */
1964 omp_resolve_late_declare_variant (tree alt
)
1966 cgraph_node
*node
= cgraph_node::get (alt
);
1967 cgraph_node
*cur_node
= cgraph_node::get (cfun
->decl
);
1969 || !node
->declare_variant_alt
1970 || !cfun
->after_inlining
)
1973 omp_declare_variant_base_entry entry
;
1976 entry
.variants
= NULL
;
1977 omp_declare_variant_base_entry
*entryp
1978 = omp_declare_variant_alt
->find_with_hash (&entry
, DECL_UID (alt
));
1981 omp_declare_variant_entry
*varentry1
, *varentry2
;
1982 auto_vec
<bool, 16> matches
;
1983 unsigned int nmatches
= 0;
1984 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
1986 if (varentry1
->matches
)
1988 /* This has been checked to be ok already. */
1989 matches
.safe_push (true);
1993 switch (omp_context_selector_matches (varentry1
->ctx
))
1996 matches
.safe_push (false);
2001 matches
.safe_push (true);
2008 return entryp
->base
->decl
;
2010 /* A context selector that is a strict subset of another context selector
2011 has a score of zero. */
2012 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2016 vec_safe_iterate (entryp
->variants
, j
, &varentry2
); ++j
)
2019 int r
= omp_context_selector_compare (varentry1
->ctx
,
2023 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2028 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2033 widest_int max_score
= -1;
2035 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2039 = (cur_node
->simdclone
? varentry1
->score_in_declare_simd_clone
2040 : varentry1
->score
);
2041 if (score
> max_score
)
2044 varentry2
= varentry1
;
2047 return varentry2
->variant
->decl
;
2050 /* Hook to adjust hash tables on cgraph_node removal. */
2053 omp_declare_variant_remove_hook (struct cgraph_node
*node
, void *)
2055 if (!node
->declare_variant_alt
)
2058 /* Drop this hash table completely. */
2059 omp_declare_variants
= NULL
;
2060 /* And remove node from the other hash table. */
2061 if (omp_declare_variant_alt
)
2063 omp_declare_variant_base_entry entry
;
2066 entry
.variants
= NULL
;
2067 omp_declare_variant_alt
->remove_elt_with_hash (&entry
,
2068 DECL_UID (node
->decl
));
2072 /* Try to resolve declare variant, return the variant decl if it should
2073 be used instead of base, or base otherwise. */
2076 omp_resolve_declare_variant (tree base
)
2078 tree variant1
= NULL_TREE
, variant2
= NULL_TREE
;
2079 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
2080 return omp_resolve_late_declare_variant (base
);
2082 auto_vec
<tree
, 16> variants
;
2083 auto_vec
<bool, 16> defer
;
2084 bool any_deferred
= false;
2085 for (tree attr
= DECL_ATTRIBUTES (base
); attr
; attr
= TREE_CHAIN (attr
))
2087 attr
= lookup_attribute ("omp declare variant base", attr
);
2088 if (attr
== NULL_TREE
)
2090 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr
))) != FUNCTION_DECL
)
2092 cgraph_node
*node
= cgraph_node::get (base
);
2093 /* If this is already a magic decl created by this function,
2094 don't process it again. */
2095 if (node
&& node
->declare_variant_alt
)
2097 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr
))))
2100 /* No match, ignore. */
2103 /* Needs to be deferred. */
2104 any_deferred
= true;
2105 variants
.safe_push (attr
);
2106 defer
.safe_push (true);
2109 variants
.safe_push (attr
);
2110 defer
.safe_push (false);
2114 if (variants
.length () == 0)
2119 widest_int max_score1
= 0;
2120 widest_int max_score2
= 0;
2124 omp_declare_variant_base_entry entry
;
2125 entry
.base
= cgraph_node::get_create (base
);
2127 vec_alloc (entry
.variants
, variants
.length ());
2128 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2133 tree ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2134 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2136 omp_context_compute_score (ctx
, &score2
, true);
2142 max_score1
= score1
;
2143 max_score2
= score2
;
2152 if (max_score1
== score1
)
2153 variant1
= NULL_TREE
;
2154 else if (score1
> max_score1
)
2156 max_score1
= score1
;
2157 variant1
= defer
[i
] ? NULL_TREE
: attr1
;
2159 if (max_score2
== score2
)
2160 variant2
= NULL_TREE
;
2161 else if (score2
> max_score2
)
2163 max_score2
= score2
;
2164 variant2
= defer
[i
] ? NULL_TREE
: attr1
;
2167 omp_declare_variant_entry varentry
;
2169 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1
)));
2170 varentry
.score
= score1
;
2171 varentry
.score_in_declare_simd_clone
= score2
;
2173 varentry
.matches
= !defer
[i
];
2174 entry
.variants
->quick_push (varentry
);
2177 /* If there is a clear winner variant with the score which is not
2178 deferred, verify it is not a strict subset of any other context
2179 selector and if it is not, it is the best alternative no matter
2180 whether the others do or don't match. */
2181 if (variant1
&& variant1
== variant2
)
2183 tree ctx1
= TREE_VALUE (TREE_VALUE (variant1
));
2184 FOR_EACH_VEC_ELT (variants
, i
, attr2
)
2186 if (attr2
== variant1
)
2188 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2189 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2192 /* The winner is a strict subset of ctx2, can't
2194 variant1
= NULL_TREE
;
2200 vec_free (entry
.variants
);
2201 return TREE_PURPOSE (TREE_VALUE (variant1
));
2205 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
2206 if (!node_removal_hook_holder
)
2207 node_removal_hook_holder
2208 = symtab
->add_cgraph_removal_hook (omp_declare_variant_remove_hook
,
2211 if (omp_declare_variants
== NULL
)
2212 omp_declare_variants
2213 = hash_table
<omp_declare_variant_hasher
>::create_ggc (64);
2214 omp_declare_variant_base_entry
**slot
2215 = omp_declare_variants
->find_slot (&entry
, INSERT
);
2218 vec_free (entry
.variants
);
2219 return (*slot
)->node
->decl
;
2222 *slot
= ggc_cleared_alloc
<omp_declare_variant_base_entry
> ();
2223 (*slot
)->base
= entry
.base
;
2224 (*slot
)->node
= entry
.base
;
2225 (*slot
)->variants
= entry
.variants
;
2226 tree alt
= build_decl (DECL_SOURCE_LOCATION (base
), FUNCTION_DECL
,
2227 DECL_NAME (base
), TREE_TYPE (base
));
2228 DECL_ARTIFICIAL (alt
) = 1;
2229 DECL_IGNORED_P (alt
) = 1;
2230 TREE_STATIC (alt
) = 1;
2231 tree attributes
= DECL_ATTRIBUTES (base
);
2232 if (lookup_attribute ("noipa", attributes
) == NULL
)
2234 attributes
= tree_cons (get_identifier ("noipa"), NULL
, attributes
);
2235 if (lookup_attribute ("noinline", attributes
) == NULL
)
2236 attributes
= tree_cons (get_identifier ("noinline"), NULL
,
2238 if (lookup_attribute ("noclone", attributes
) == NULL
)
2239 attributes
= tree_cons (get_identifier ("noclone"), NULL
,
2241 if (lookup_attribute ("no_icf", attributes
) == NULL
)
2242 attributes
= tree_cons (get_identifier ("no_icf"), NULL
,
2245 DECL_ATTRIBUTES (alt
) = attributes
;
2246 DECL_INITIAL (alt
) = error_mark_node
;
2247 (*slot
)->node
= cgraph_node::create (alt
);
2248 (*slot
)->node
->declare_variant_alt
= 1;
2249 (*slot
)->node
->create_reference (entry
.base
, IPA_REF_ADDR
);
2250 omp_declare_variant_entry
*varentry
;
2251 FOR_EACH_VEC_SAFE_ELT (entry
.variants
, i
, varentry
)
2252 (*slot
)->node
->create_reference (varentry
->variant
, IPA_REF_ADDR
);
2253 if (omp_declare_variant_alt
== NULL
)
2254 omp_declare_variant_alt
2255 = hash_table
<omp_declare_variant_alt_hasher
>::create_ggc (64);
2256 *omp_declare_variant_alt
->find_slot_with_hash (*slot
, DECL_UID (alt
),
2261 if (variants
.length () == 1)
2262 return TREE_PURPOSE (TREE_VALUE (variants
[0]));
2264 /* A context selector that is a strict subset of another context selector
2265 has a score of zero. */
2268 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2271 tree ctx1
= TREE_VALUE (TREE_VALUE (attr1
));
2272 FOR_EACH_VEC_ELT_FROM (variants
, j
, attr2
, i
+ 1)
2275 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2276 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2279 /* ctx1 is a strict subset of ctx2, remove
2280 attr1 from the vector. */
2281 variants
[i
] = NULL_TREE
;
2285 /* ctx2 is a strict subset of ctx1, remove attr2
2287 variants
[j
] = NULL_TREE
;
2290 widest_int max_score1
= 0;
2291 widest_int max_score2
= 0;
2293 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2305 ctx
= TREE_VALUE (TREE_VALUE (variant1
));
2306 need_two
= omp_context_compute_score (ctx
, &max_score1
, false);
2308 omp_context_compute_score (ctx
, &max_score2
, true);
2310 max_score2
= max_score1
;
2312 ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2313 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2315 omp_context_compute_score (ctx
, &score2
, true);
2318 if (score1
> max_score1
)
2320 max_score1
= score1
;
2323 if (score2
> max_score2
)
2325 max_score2
= score2
;
2335 /* If there is a disagreement on which variant has the highest score
2336 depending on whether it will be in a declare simd clone or not,
2337 punt for now and defer until after IPA where we will know that. */
2338 return ((variant1
&& variant1
== variant2
)
2339 ? TREE_PURPOSE (TREE_VALUE (variant1
)) : base
);
2343 omp_lto_output_declare_variant_alt (lto_simple_output_block
*ob
,
2345 lto_symtab_encoder_t encoder
)
2347 gcc_assert (node
->declare_variant_alt
);
2349 omp_declare_variant_base_entry entry
;
2352 entry
.variants
= NULL
;
2353 omp_declare_variant_base_entry
*entryp
2354 = omp_declare_variant_alt
->find_with_hash (&entry
, DECL_UID (node
->decl
));
2355 gcc_assert (entryp
);
2357 int nbase
= lto_symtab_encoder_lookup (encoder
, entryp
->base
);
2358 gcc_assert (nbase
!= LCC_NOT_FOUND
);
2359 streamer_write_hwi_stream (ob
->main_stream
, nbase
);
2361 streamer_write_hwi_stream (ob
->main_stream
, entryp
->variants
->length ());
2364 omp_declare_variant_entry
*varentry
;
2365 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry
)
2367 int nvar
= lto_symtab_encoder_lookup (encoder
, varentry
->variant
);
2368 gcc_assert (nvar
!= LCC_NOT_FOUND
);
2369 streamer_write_hwi_stream (ob
->main_stream
, nvar
);
2371 for (widest_int
*w
= &varentry
->score
; ;
2372 w
= &varentry
->score_in_declare_simd_clone
)
2374 unsigned len
= w
->get_len ();
2375 streamer_write_hwi_stream (ob
->main_stream
, len
);
2376 const HOST_WIDE_INT
*val
= w
->get_val ();
2377 for (unsigned j
= 0; j
< len
; j
++)
2378 streamer_write_hwi_stream (ob
->main_stream
, val
[j
]);
2379 if (w
== &varentry
->score_in_declare_simd_clone
)
2383 HOST_WIDE_INT cnt
= -1;
2384 HOST_WIDE_INT i
= varentry
->matches
? 1 : 0;
2385 for (tree attr
= DECL_ATTRIBUTES (entryp
->base
->decl
);
2386 attr
; attr
= TREE_CHAIN (attr
), i
+= 2)
2388 attr
= lookup_attribute ("omp declare variant base", attr
);
2389 if (attr
== NULL_TREE
)
2392 if (varentry
->ctx
== TREE_VALUE (TREE_VALUE (attr
)))
2399 gcc_assert (cnt
!= -1);
2400 streamer_write_hwi_stream (ob
->main_stream
, cnt
);
2405 omp_lto_input_declare_variant_alt (lto_input_block
*ib
, cgraph_node
*node
,
2406 vec
<symtab_node
*> nodes
)
2408 gcc_assert (node
->declare_variant_alt
);
2409 omp_declare_variant_base_entry
*entryp
2410 = ggc_cleared_alloc
<omp_declare_variant_base_entry
> ();
2411 entryp
->base
= dyn_cast
<cgraph_node
*> (nodes
[streamer_read_hwi (ib
)]);
2412 entryp
->node
= node
;
2413 unsigned int len
= streamer_read_hwi (ib
);
2414 vec_alloc (entryp
->variants
, len
);
2416 for (unsigned int i
= 0; i
< len
; i
++)
2418 omp_declare_variant_entry varentry
;
2420 = dyn_cast
<cgraph_node
*> (nodes
[streamer_read_hwi (ib
)]);
2421 for (widest_int
*w
= &varentry
.score
; ;
2422 w
= &varentry
.score_in_declare_simd_clone
)
2424 unsigned len2
= streamer_read_hwi (ib
);
2425 HOST_WIDE_INT arr
[WIDE_INT_MAX_ELTS
];
2426 gcc_assert (len2
<= WIDE_INT_MAX_ELTS
);
2427 for (unsigned int j
= 0; j
< len2
; j
++)
2428 arr
[j
] = streamer_read_hwi (ib
);
2429 *w
= widest_int::from_array (arr
, len2
, true);
2430 if (w
== &varentry
.score_in_declare_simd_clone
)
2434 HOST_WIDE_INT cnt
= streamer_read_hwi (ib
);
2435 HOST_WIDE_INT j
= 0;
2436 varentry
.ctx
= NULL_TREE
;
2437 varentry
.matches
= (cnt
& 1) ? true : false;
2438 cnt
&= ~HOST_WIDE_INT_1
;
2439 for (tree attr
= DECL_ATTRIBUTES (entryp
->base
->decl
);
2440 attr
; attr
= TREE_CHAIN (attr
), j
+= 2)
2442 attr
= lookup_attribute ("omp declare variant base", attr
);
2443 if (attr
== NULL_TREE
)
2448 varentry
.ctx
= TREE_VALUE (TREE_VALUE (attr
));
2452 gcc_assert (varentry
.ctx
!= NULL_TREE
);
2453 entryp
->variants
->quick_push (varentry
);
2455 if (omp_declare_variant_alt
== NULL
)
2456 omp_declare_variant_alt
2457 = hash_table
<omp_declare_variant_alt_hasher
>::create_ggc (64);
2458 *omp_declare_variant_alt
->find_slot_with_hash (entryp
, DECL_UID (node
->decl
),
2462 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2463 macro on gomp-constants.h. We do not check for overflow. */
2466 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
2470 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
2473 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
2474 device
, build_int_cst (unsigned_type_node
,
2475 GOMP_LAUNCH_DEVICE_SHIFT
));
2476 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
2481 /* FIXME: What is the following comment for? */
2482 /* Look for compute grid dimension clauses and convert to an attribute
2483 attached to FN. This permits the target-side code to (a) massage
2484 the dimensions, (b) emit that data and (c) optimize. Non-constant
2485 dimensions are pushed onto ARGS.
2487 The attribute value is a TREE_LIST. A set of dimensions is
2488 represented as a list of INTEGER_CST. Those that are runtime
2489 exprs are represented as an INTEGER_CST of zero.
2491 TODO: Normally the attribute will just contain a single such list. If
2492 however it contains a list of lists, this will represent the use of
2493 device_type. Each member of the outer list is an assoc list of
2494 dimensions, keyed by the device type. The first entry will be the
2495 default. Well, that's the plan. */
2497 /* Replace any existing oacc fn attribute with updated dimensions. */
2499 /* Variant working on a list of attributes. */
2502 oacc_replace_fn_attrib_attr (tree attribs
, tree dims
)
2504 tree ident
= get_identifier (OACC_FN_ATTRIB
);
2506 /* If we happen to be present as the first attrib, drop it. */
2507 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
2508 attribs
= TREE_CHAIN (attribs
);
2509 return tree_cons (ident
, dims
, attribs
);
2512 /* Variant working on a function decl. */
2515 oacc_replace_fn_attrib (tree fn
, tree dims
)
2517 DECL_ATTRIBUTES (fn
)
2518 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn
), dims
);
2521 /* Scan CLAUSES for launch dimensions and attach them to the oacc
2522 function attribute. Push any that are non-constant onto the ARGS
2523 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
2526 oacc_set_fn_attrib (tree fn
, tree clauses
, vec
<tree
> *args
)
2528 /* Must match GOMP_DIM ordering. */
2529 static const omp_clause_code ids
[]
2530 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
2531 OMP_CLAUSE_VECTOR_LENGTH
};
2533 tree dims
[GOMP_DIM_MAX
];
2535 tree attr
= NULL_TREE
;
2536 unsigned non_const
= 0;
2538 for (ix
= GOMP_DIM_MAX
; ix
--;)
2540 tree clause
= omp_find_clause (clauses
, ids
[ix
]);
2541 tree dim
= NULL_TREE
;
2544 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
2546 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
2548 dim
= integer_zero_node
;
2549 non_const
|= GOMP_DIM_MASK (ix
);
2551 attr
= tree_cons (NULL_TREE
, dim
, attr
);
2554 oacc_replace_fn_attrib (fn
, attr
);
2558 /* Push a dynamic argument set. */
2559 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
2560 NULL_TREE
, non_const
));
2561 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
2562 if (non_const
& GOMP_DIM_MASK (ix
))
2563 args
->safe_push (dims
[ix
]);
2567 /* Verify OpenACC routine clauses.
2569 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
2570 if it has already been marked in compatible way, and -1 if incompatible.
2571 Upon returning, the chain of clauses will contain exactly one clause
2572 specifying the level of parallelism. */
2575 oacc_verify_routine_clauses (tree fndecl
, tree
*clauses
, location_t loc
,
2576 const char *routine_str
)
2578 tree c_level
= NULL_TREE
;
2579 tree c_p
= NULL_TREE
;
2580 for (tree c
= *clauses
; c
; c_p
= c
, c
= OMP_CLAUSE_CHAIN (c
))
2581 switch (OMP_CLAUSE_CODE (c
))
2583 case OMP_CLAUSE_GANG
:
2584 case OMP_CLAUSE_WORKER
:
2585 case OMP_CLAUSE_VECTOR
:
2586 case OMP_CLAUSE_SEQ
:
2587 if (c_level
== NULL_TREE
)
2589 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_CODE (c_level
))
2591 /* This has already been diagnosed in the front ends. */
2592 /* Drop the duplicate clause. */
2593 gcc_checking_assert (c_p
!= NULL_TREE
);
2594 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2599 error_at (OMP_CLAUSE_LOCATION (c
),
2600 "%qs specifies a conflicting level of parallelism",
2601 omp_clause_code_name
[OMP_CLAUSE_CODE (c
)]);
2602 inform (OMP_CLAUSE_LOCATION (c_level
),
2603 "... to the previous %qs clause here",
2604 omp_clause_code_name
[OMP_CLAUSE_CODE (c_level
)]);
2605 /* Drop the conflicting clause. */
2606 gcc_checking_assert (c_p
!= NULL_TREE
);
2607 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2614 if (c_level
== NULL_TREE
)
2616 /* Default to an implicit 'seq' clause. */
2617 c_level
= build_omp_clause (loc
, OMP_CLAUSE_SEQ
);
2618 OMP_CLAUSE_CHAIN (c_level
) = *clauses
;
2621 /* In *clauses, we now have exactly one clause specifying the level of
2625 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl
));
2626 if (attr
!= NULL_TREE
)
2628 /* Diagnose if "#pragma omp declare target" has also been applied. */
2629 if (TREE_VALUE (attr
) == NULL_TREE
)
2631 /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
2632 OpenACC and OpenMP 'target' are not clear. */
2634 "cannot apply %<%s%> to %qD, which has also been"
2635 " marked with an OpenMP 'declare target' directive",
2636 routine_str
, fndecl
);
2641 /* If a "#pragma acc routine" has already been applied, just verify
2642 this one for compatibility. */
2643 /* Collect previous directive's clauses. */
2644 tree c_level_p
= NULL_TREE
;
2645 for (tree c
= TREE_VALUE (attr
); c
; c
= OMP_CLAUSE_CHAIN (c
))
2646 switch (OMP_CLAUSE_CODE (c
))
2648 case OMP_CLAUSE_GANG
:
2649 case OMP_CLAUSE_WORKER
:
2650 case OMP_CLAUSE_VECTOR
:
2651 case OMP_CLAUSE_SEQ
:
2652 gcc_checking_assert (c_level_p
== NULL_TREE
);
2658 gcc_checking_assert (c_level_p
!= NULL_TREE
);
2659 /* ..., and compare to current directive's, which we've already collected
2663 /* Matching level of parallelism? */
2664 if (OMP_CLAUSE_CODE (c_level
) != OMP_CLAUSE_CODE (c_level_p
))
2667 c_diag_p
= c_level_p
;
2674 if (c_diag
!= NULL_TREE
)
2675 error_at (OMP_CLAUSE_LOCATION (c_diag
),
2676 "incompatible %qs clause when applying"
2677 " %<%s%> to %qD, which has already been"
2678 " marked with an OpenACC 'routine' directive",
2679 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)],
2680 routine_str
, fndecl
);
2681 else if (c_diag_p
!= NULL_TREE
)
2683 "missing %qs clause when applying"
2684 " %<%s%> to %qD, which has already been"
2685 " marked with an OpenACC 'routine' directive",
2686 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)],
2687 routine_str
, fndecl
);
2690 if (c_diag_p
!= NULL_TREE
)
2691 inform (OMP_CLAUSE_LOCATION (c_diag_p
),
2692 "... with %qs clause here",
2693 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)]);
2696 /* In the front ends, we don't preserve location information for the
2697 OpenACC routine directive itself. However, that of c_level_p
2699 location_t loc_routine
= OMP_CLAUSE_LOCATION (c_level_p
);
2700 inform (loc_routine
, "... without %qs clause near to here",
2701 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)]);
2710 /* Process the OpenACC 'routine' directive clauses to generate an attribute
2711 for the level of parallelism. All dimensions have a size of zero
2712 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
2713 can have a loop partitioned on it. non-zero indicates
2714 yes, zero indicates no. By construction once a non-zero has been
2715 reached, further inner dimensions must also be non-zero. We set
2716 TREE_VALUE to zero for the dimensions that may be partitioned and
2717 1 for the other ones -- if a loop is (erroneously) spawned at
2718 an outer level, we don't want to try and partition it. */
2721 oacc_build_routine_dims (tree clauses
)
2723 /* Must match GOMP_DIM ordering. */
2724 static const omp_clause_code ids
[]
2725 = {OMP_CLAUSE_GANG
, OMP_CLAUSE_WORKER
, OMP_CLAUSE_VECTOR
, OMP_CLAUSE_SEQ
};
2729 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
2730 for (ix
= GOMP_DIM_MAX
+ 1; ix
--;)
2731 if (OMP_CLAUSE_CODE (clauses
) == ids
[ix
])
2736 gcc_checking_assert (level
>= 0);
2738 tree dims
= NULL_TREE
;
2740 for (ix
= GOMP_DIM_MAX
; ix
--;)
2741 dims
= tree_cons (build_int_cst (boolean_type_node
, ix
>= level
),
2742 build_int_cst (integer_type_node
, ix
< level
), dims
);
2747 /* Retrieve the oacc function attrib and return it. Non-oacc
2748 functions will return NULL. */
2751 oacc_get_fn_attrib (tree fn
)
2753 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
2756 /* Return true if FN is an OpenMP or OpenACC offloading function. */
2759 offloading_function_p (tree fn
)
2761 tree attrs
= DECL_ATTRIBUTES (fn
);
2762 return (lookup_attribute ("omp declare target", attrs
)
2763 || lookup_attribute ("omp target entrypoint", attrs
));
2766 /* Extract an oacc execution dimension from FN. FN must be an
2767 offloaded function or routine that has already had its execution
2768 dimensions lowered to the target-specific values. */
2771 oacc_get_fn_dim_size (tree fn
, int axis
)
2773 tree attrs
= oacc_get_fn_attrib (fn
);
2775 gcc_assert (axis
< GOMP_DIM_MAX
);
2777 tree dims
= TREE_VALUE (attrs
);
2779 dims
= TREE_CHAIN (dims
);
2781 int size
= TREE_INT_CST_LOW (TREE_VALUE (dims
));
2786 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
2787 IFN_GOACC_DIM_SIZE call. */
2790 oacc_get_ifn_dim_arg (const gimple
*stmt
)
2792 gcc_checking_assert (gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_SIZE
2793 || gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_POS
);
2794 tree arg
= gimple_call_arg (stmt
, 0);
2795 HOST_WIDE_INT axis
= TREE_INT_CST_LOW (arg
);
2797 gcc_checking_assert (axis
>= 0 && axis
< GOMP_DIM_MAX
);
2801 #include "gt-omp-general.h"