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 /* True if OpenMP should privatize what this DECL points to rather
83 than the DECL itself. */
86 omp_privatize_by_reference (tree decl
)
88 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
91 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
92 given that V is the loop index variable and STEP is loop step. */
95 omp_adjust_for_condition (location_t loc
, enum tree_code
*cond_code
, tree
*n2
,
105 gcc_assert (TREE_CODE (step
) == INTEGER_CST
);
106 if (TREE_CODE (TREE_TYPE (v
)) == INTEGER_TYPE
)
108 if (integer_onep (step
))
109 *cond_code
= LT_EXPR
;
112 gcc_assert (integer_minus_onep (step
));
113 *cond_code
= GT_EXPR
;
118 tree unit
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v
)));
119 gcc_assert (TREE_CODE (unit
) == INTEGER_CST
);
120 if (tree_int_cst_equal (unit
, step
))
121 *cond_code
= LT_EXPR
;
124 gcc_assert (wi::neg (wi::to_widest (unit
))
125 == wi::to_widest (step
));
126 *cond_code
= GT_EXPR
;
133 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
134 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, 1);
136 *n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (*n2
), *n2
,
137 build_int_cst (TREE_TYPE (*n2
), 1));
138 *cond_code
= LT_EXPR
;
141 if (POINTER_TYPE_P (TREE_TYPE (*n2
)))
142 *n2
= fold_build_pointer_plus_hwi_loc (loc
, *n2
, -1);
144 *n2
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (*n2
), *n2
,
145 build_int_cst (TREE_TYPE (*n2
), 1));
146 *cond_code
= GT_EXPR
;
153 /* Return the looping step from INCR, extracted from the step of a gimple omp
157 omp_get_for_step_from_incr (location_t loc
, tree incr
)
160 switch (TREE_CODE (incr
))
163 step
= TREE_OPERAND (incr
, 1);
165 case POINTER_PLUS_EXPR
:
166 step
= fold_convert (ssizetype
, TREE_OPERAND (incr
, 1));
169 step
= TREE_OPERAND (incr
, 1);
170 step
= fold_build1_loc (loc
, NEGATE_EXPR
, TREE_TYPE (step
), step
);
178 /* Extract the header elements of parallel loop FOR_STMT and store
182 omp_extract_for_data (gomp_for
*for_stmt
, struct omp_for_data
*fd
,
183 struct omp_for_data_loop
*loops
)
185 tree t
, var
, *collapse_iter
, *collapse_count
;
186 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
187 struct omp_for_data_loop
*loop
;
189 struct omp_for_data_loop dummy_loop
;
190 location_t loc
= gimple_location (for_stmt
);
191 bool simd
= gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_SIMD
;
192 bool distribute
= gimple_omp_for_kind (for_stmt
)
193 == GF_OMP_FOR_KIND_DISTRIBUTE
;
194 bool taskloop
= gimple_omp_for_kind (for_stmt
)
195 == GF_OMP_FOR_KIND_TASKLOOP
;
198 fd
->for_stmt
= for_stmt
;
200 fd
->have_nowait
= distribute
|| simd
;
201 fd
->have_ordered
= false;
202 fd
->have_reductemp
= false;
203 fd
->have_pointer_condtemp
= false;
204 fd
->have_scantemp
= false;
205 fd
->have_nonctrl_scantemp
= false;
206 fd
->non_rect
= false;
207 fd
->lastprivate_conditional
= 0;
208 fd
->tiling
= NULL_TREE
;
211 fd
->first_nonrect
= -1;
212 fd
->last_nonrect
= -1;
213 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
214 fd
->sched_modifiers
= 0;
215 fd
->chunk_size
= NULL_TREE
;
216 fd
->simd_schedule
= false;
217 fd
->first_inner_iterations
= NULL_TREE
;
218 fd
->factor
= NULL_TREE
;
219 fd
->adjn1
= NULL_TREE
;
220 collapse_iter
= NULL
;
221 collapse_count
= NULL
;
223 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
224 switch (OMP_CLAUSE_CODE (t
))
226 case OMP_CLAUSE_NOWAIT
:
227 fd
->have_nowait
= true;
229 case OMP_CLAUSE_ORDERED
:
230 fd
->have_ordered
= true;
231 if (OMP_CLAUSE_ORDERED_EXPR (t
))
232 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
234 case OMP_CLAUSE_SCHEDULE
:
235 gcc_assert (!distribute
&& !taskloop
);
237 = (enum omp_clause_schedule_kind
)
238 (OMP_CLAUSE_SCHEDULE_KIND (t
) & OMP_CLAUSE_SCHEDULE_MASK
);
239 fd
->sched_modifiers
= (OMP_CLAUSE_SCHEDULE_KIND (t
)
240 & ~OMP_CLAUSE_SCHEDULE_MASK
);
241 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
242 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
244 case OMP_CLAUSE_DIST_SCHEDULE
:
245 gcc_assert (distribute
);
246 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
248 case OMP_CLAUSE_COLLAPSE
:
249 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
250 if (fd
->collapse
> 1)
252 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
253 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
256 case OMP_CLAUSE_TILE
:
257 fd
->tiling
= OMP_CLAUSE_TILE_LIST (t
);
258 fd
->collapse
= list_length (fd
->tiling
);
259 gcc_assert (fd
->collapse
);
260 collapse_iter
= &OMP_CLAUSE_TILE_ITERVAR (t
);
261 collapse_count
= &OMP_CLAUSE_TILE_COUNT (t
);
263 case OMP_CLAUSE__REDUCTEMP_
:
264 fd
->have_reductemp
= true;
266 case OMP_CLAUSE_LASTPRIVATE
:
267 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t
))
268 fd
->lastprivate_conditional
++;
270 case OMP_CLAUSE__CONDTEMP_
:
271 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t
))))
272 fd
->have_pointer_condtemp
= true;
274 case OMP_CLAUSE__SCANTEMP_
:
275 fd
->have_scantemp
= true;
276 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t
)
277 && !OMP_CLAUSE__SCANTEMP__CONTROL (t
))
278 fd
->have_nonctrl_scantemp
= true;
284 if (fd
->collapse
> 1 || fd
->tiling
)
287 fd
->loops
= &fd
->loop
;
289 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
294 collapse_iter
= &iterv
;
295 collapse_count
= &countv
;
298 /* FIXME: for now map schedule(auto) to schedule(static).
299 There should be analysis to determine whether all iterations
300 are approximately the same amount of work (then schedule(static)
301 is best) or if it varies (then schedule(dynamic,N) is better). */
302 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
304 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
305 gcc_assert (fd
->chunk_size
== NULL
);
307 gcc_assert ((fd
->collapse
== 1 && !fd
->tiling
) || collapse_iter
!= NULL
);
309 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
310 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
311 gcc_assert (fd
->chunk_size
== NULL
);
312 else if (fd
->chunk_size
== NULL
)
314 /* We only need to compute a default chunk size for ordered
315 static loops and dynamic loops. */
316 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
318 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
319 ? integer_zero_node
: integer_one_node
;
322 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
323 int single_nonrect
= -1;
324 tree single_nonrect_count
= NULL_TREE
;
325 enum tree_code single_nonrect_cond_code
= ERROR_MARK
;
326 for (i
= 1; i
< cnt
; i
++)
328 tree n1
= gimple_omp_for_initial (for_stmt
, i
);
329 tree n2
= gimple_omp_for_final (for_stmt
, i
);
330 if (TREE_CODE (n1
) == TREE_VEC
)
337 for (int j
= i
- 1; j
>= 0; j
--)
338 if (TREE_VEC_ELT (n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
345 else if (TREE_CODE (n2
) == TREE_VEC
)
352 for (int j
= i
- 1; j
>= 0; j
--)
353 if (TREE_VEC_ELT (n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
361 for (i
= 0; i
< cnt
; i
++)
366 && (fd
->ordered
== 0 || loops
== NULL
))
368 else if (loops
!= NULL
)
373 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
374 gcc_assert (SSA_VAR_P (loop
->v
));
375 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
376 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
377 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
378 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
379 loop
->m1
= NULL_TREE
;
380 loop
->m2
= NULL_TREE
;
382 loop
->non_rect_referenced
= false;
383 if (TREE_CODE (loop
->n1
) == TREE_VEC
)
385 for (int j
= i
- 1; j
>= 0; j
--)
386 if (TREE_VEC_ELT (loop
->n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
390 loops
[j
].non_rect_referenced
= true;
391 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
392 fd
->first_nonrect
= j
;
395 gcc_assert (loop
->outer
);
396 loop
->m1
= TREE_VEC_ELT (loop
->n1
, 1);
397 loop
->n1
= TREE_VEC_ELT (loop
->n1
, 2);
399 fd
->last_nonrect
= i
;
402 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
403 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
404 gcc_assert (loop
->cond_code
!= NE_EXPR
405 || (gimple_omp_for_kind (for_stmt
)
406 != GF_OMP_FOR_KIND_OACC_LOOP
));
407 if (TREE_CODE (loop
->n2
) == TREE_VEC
)
410 gcc_assert (TREE_VEC_ELT (loop
->n2
, 0)
411 == gimple_omp_for_index (for_stmt
, i
- loop
->outer
));
413 for (int j
= i
- 1; j
>= 0; j
--)
414 if (TREE_VEC_ELT (loop
->n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
418 loops
[j
].non_rect_referenced
= true;
419 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
420 fd
->first_nonrect
= j
;
423 gcc_assert (loop
->outer
);
424 loop
->m2
= TREE_VEC_ELT (loop
->n2
, 1);
425 loop
->n2
= TREE_VEC_ELT (loop
->n2
, 2);
427 fd
->last_nonrect
= i
;
430 t
= gimple_omp_for_incr (for_stmt
, i
);
431 gcc_assert (TREE_OPERAND (t
, 0) == var
);
432 loop
->step
= omp_get_for_step_from_incr (loc
, t
);
434 omp_adjust_for_condition (loc
, &loop
->cond_code
, &loop
->n2
, loop
->v
,
438 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
439 && !fd
->have_ordered
))
441 if (fd
->collapse
== 1 && !fd
->tiling
)
442 iter_type
= TREE_TYPE (loop
->v
);
444 || TYPE_PRECISION (iter_type
)
445 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
447 = build_nonstandard_integer_type
448 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
450 else if (iter_type
!= long_long_unsigned_type_node
)
452 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
453 iter_type
= long_long_unsigned_type_node
;
454 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
455 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
456 >= TYPE_PRECISION (iter_type
))
460 if (loop
->cond_code
== LT_EXPR
)
461 n
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
462 loop
->n2
, loop
->step
);
467 || TREE_CODE (n
) != INTEGER_CST
468 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
469 iter_type
= long_long_unsigned_type_node
;
471 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
472 > TYPE_PRECISION (iter_type
))
476 if (loop
->cond_code
== LT_EXPR
)
479 n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
480 loop
->n2
, loop
->step
);
484 n1
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (loop
->v
),
485 loop
->n2
, loop
->step
);
490 || TREE_CODE (n1
) != INTEGER_CST
491 || TREE_CODE (n2
) != INTEGER_CST
492 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
493 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
494 iter_type
= long_long_unsigned_type_node
;
498 if (i
>= fd
->collapse
)
501 if (collapse_count
&& *collapse_count
== NULL
)
503 if (count
&& integer_zerop (count
))
505 tree n1first
= NULL_TREE
, n2first
= NULL_TREE
;
506 tree n1last
= NULL_TREE
, n2last
= NULL_TREE
;
507 tree ostep
= NULL_TREE
;
508 if (loop
->m1
|| loop
->m2
)
510 if (count
== NULL_TREE
)
512 if (single_nonrect
== -1
513 || (loop
->m1
&& TREE_CODE (loop
->m1
) != INTEGER_CST
)
514 || (loop
->m2
&& TREE_CODE (loop
->m2
) != INTEGER_CST
)
515 || TREE_CODE (loop
->n1
) != INTEGER_CST
516 || TREE_CODE (loop
->n2
) != INTEGER_CST
517 || TREE_CODE (loop
->step
) != INTEGER_CST
)
522 tree var
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
523 tree itype
= TREE_TYPE (var
);
524 tree first
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
525 t
= gimple_omp_for_incr (for_stmt
, single_nonrect
);
526 ostep
= omp_get_for_step_from_incr (loc
, t
);
527 t
= fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
528 single_nonrect_count
,
529 build_one_cst (long_long_unsigned_type_node
));
530 t
= fold_convert (itype
, t
);
531 first
= fold_convert (itype
, first
);
532 ostep
= fold_convert (itype
, ostep
);
533 tree last
= fold_binary (PLUS_EXPR
, itype
, first
,
534 fold_binary (MULT_EXPR
, itype
, t
,
536 if (TREE_CODE (first
) != INTEGER_CST
537 || TREE_CODE (last
) != INTEGER_CST
)
544 tree m1
= fold_convert (itype
, loop
->m1
);
545 tree n1
= fold_convert (itype
, loop
->n1
);
546 n1first
= fold_binary (PLUS_EXPR
, itype
,
547 fold_binary (MULT_EXPR
, itype
,
549 n1last
= fold_binary (PLUS_EXPR
, itype
,
550 fold_binary (MULT_EXPR
, itype
,
554 n1first
= n1last
= loop
->n1
;
557 tree n2
= fold_convert (itype
, loop
->n2
);
558 tree m2
= fold_convert (itype
, loop
->m2
);
559 n2first
= fold_binary (PLUS_EXPR
, itype
,
560 fold_binary (MULT_EXPR
, itype
,
562 n2last
= fold_binary (PLUS_EXPR
, itype
,
563 fold_binary (MULT_EXPR
, itype
,
567 n2first
= n2last
= loop
->n2
;
568 n1first
= fold_convert (TREE_TYPE (loop
->v
), n1first
);
569 n2first
= fold_convert (TREE_TYPE (loop
->v
), n2first
);
570 n1last
= fold_convert (TREE_TYPE (loop
->v
), n1last
);
571 n2last
= fold_convert (TREE_TYPE (loop
->v
), n2last
);
572 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
574 tree t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
576 if (t
&& t2
&& integer_nonzerop (t
) && integer_nonzerop (t2
))
577 /* All outer loop iterators have at least one inner loop
578 iteration. Try to compute the count at compile time. */
580 else if (t
&& t2
&& integer_zerop (t
) && integer_zerop (t2
))
581 /* No iterations of the inner loop. count will be set to
583 else if (TYPE_UNSIGNED (itype
)
586 || TREE_CODE (t
) != INTEGER_CST
587 || TREE_CODE (t2
) != INTEGER_CST
)
589 /* Punt (for now). */
595 /* Some iterations of the outer loop have zero iterations
596 of the inner loop, while others have at least one.
597 In this case, we need to adjust one of those outer
598 loop bounds. If ADJ_FIRST, we need to adjust outer n1
599 (first), otherwise outer n2 (last). */
600 bool adj_first
= integer_zerop (t
);
601 tree n1
= fold_convert (itype
, loop
->n1
);
602 tree n2
= fold_convert (itype
, loop
->n2
);
603 tree m1
= loop
->m1
? fold_convert (itype
, loop
->m1
)
604 : build_zero_cst (itype
);
605 tree m2
= loop
->m2
? fold_convert (itype
, loop
->m2
)
606 : build_zero_cst (itype
);
607 t
= fold_binary (MINUS_EXPR
, itype
, n1
, n2
);
608 t2
= fold_binary (MINUS_EXPR
, itype
, m2
, m1
);
609 t
= fold_binary (TRUNC_DIV_EXPR
, itype
, t
, t2
);
610 t2
= fold_binary (MINUS_EXPR
, itype
, t
, first
);
611 t2
= fold_binary (TRUNC_MOD_EXPR
, itype
, t2
, ostep
);
612 t
= fold_binary (MINUS_EXPR
, itype
, t
, t2
);
614 = fold_binary (PLUS_EXPR
, itype
, n1
,
615 fold_binary (MULT_EXPR
, itype
, m1
, t
));
617 = fold_binary (PLUS_EXPR
, itype
, n2
,
618 fold_binary (MULT_EXPR
, itype
, m2
, t
));
619 t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
621 tree t3
= fold_binary (MULT_EXPR
, itype
, m1
, ostep
);
622 tree t4
= fold_binary (MULT_EXPR
, itype
, m2
, ostep
);
627 if (integer_nonzerop (t2
))
634 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
635 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
636 t3
= fold_binary (loop
->cond_code
,
637 boolean_type_node
, t3
, t4
);
638 gcc_assert (integer_zerop (t3
));
643 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
644 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
645 new_first
= fold_binary (PLUS_EXPR
, itype
, t
, ostep
);
650 t3
= fold_binary (loop
->cond_code
,
651 boolean_type_node
, t3
, t4
);
652 gcc_assert (integer_nonzerop (t3
));
655 diff
= fold_binary (MINUS_EXPR
, itype
, new_first
, first
);
662 if (integer_zerop (t2
))
664 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
665 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
666 new_last
= fold_binary (MINUS_EXPR
, itype
, t
, ostep
);
671 t3
= fold_binary (loop
->cond_code
,
672 boolean_type_node
, t3
, t4
);
673 gcc_assert (integer_nonzerop (t3
));
683 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
684 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
685 t3
= fold_binary (loop
->cond_code
,
686 boolean_type_node
, t3
, t4
);
687 gcc_assert (integer_zerop (t3
));
690 diff
= fold_binary (MINUS_EXPR
, itype
, last
, new_last
);
692 if (TYPE_UNSIGNED (itype
)
693 && single_nonrect_cond_code
== GT_EXPR
)
694 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
,
695 fold_unary (NEGATE_EXPR
, itype
, diff
),
696 fold_unary (NEGATE_EXPR
, itype
,
699 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
, diff
, ostep
);
700 diff
= fold_convert (long_long_unsigned_type_node
, diff
);
702 = fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
703 single_nonrect_count
, diff
);
708 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
709 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
710 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
711 if (t
&& integer_zerop (t
))
712 count
= build_zero_cst (long_long_unsigned_type_node
);
713 else if ((i
== 0 || count
!= NULL_TREE
)
714 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
715 && TREE_CONSTANT (loop
->n1
)
716 && TREE_CONSTANT (loop
->n2
)
717 && TREE_CODE (loop
->step
) == INTEGER_CST
)
719 tree itype
= TREE_TYPE (loop
->v
);
721 if (POINTER_TYPE_P (itype
))
722 itype
= signed_type_for (itype
);
723 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
724 t
= fold_build2 (PLUS_EXPR
, itype
,
725 fold_convert (itype
, loop
->step
), t
);
728 if (loop
->m1
|| loop
->m2
)
730 gcc_assert (single_nonrect
!= -1);
734 t
= fold_build2 (PLUS_EXPR
, itype
, t
, fold_convert (itype
, n2
));
735 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
736 tree step
= fold_convert_loc (loc
, itype
, loop
->step
);
737 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
738 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
739 fold_build1 (NEGATE_EXPR
, itype
, t
),
740 fold_build1 (NEGATE_EXPR
, itype
, step
));
742 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
743 tree llutype
= long_long_unsigned_type_node
;
744 t
= fold_convert (llutype
, t
);
745 if (loop
->m1
|| loop
->m2
)
747 /* t is number of iterations of inner loop at either first
748 or last value of the outer iterator (the one with fewer
750 Compute t2 = ((m2 - m1) * ostep) / step
751 and niters = outer_count * t
752 + t2 * ((outer_count - 1) * outer_count / 2)
754 tree m1
= loop
->m1
? loop
->m1
: integer_zero_node
;
755 tree m2
= loop
->m2
? loop
->m2
: integer_zero_node
;
756 m1
= fold_convert (itype
, m1
);
757 m2
= fold_convert (itype
, m2
);
758 tree t2
= fold_build2 (MINUS_EXPR
, itype
, m2
, m1
);
759 t2
= fold_build2 (MULT_EXPR
, itype
, t2
, ostep
);
760 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
761 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
762 fold_build1 (NEGATE_EXPR
, itype
, t2
),
763 fold_build1 (NEGATE_EXPR
, itype
, step
));
765 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t2
, step
);
766 t2
= fold_convert (llutype
, t2
);
767 fd
->first_inner_iterations
= t
;
769 t
= fold_build2 (MULT_EXPR
, llutype
, t
,
770 single_nonrect_count
);
771 tree t3
= fold_build2 (MINUS_EXPR
, llutype
,
772 single_nonrect_count
,
773 build_one_cst (llutype
));
774 t3
= fold_build2 (MULT_EXPR
, llutype
, t3
,
775 single_nonrect_count
);
776 t3
= fold_build2 (TRUNC_DIV_EXPR
, llutype
, t3
,
777 build_int_cst (llutype
, 2));
778 t2
= fold_build2 (MULT_EXPR
, llutype
, t2
, t3
);
779 t
= fold_build2 (PLUS_EXPR
, llutype
, t
, t2
);
781 if (i
== single_nonrect
)
783 if (integer_zerop (t
) || TREE_CODE (t
) != INTEGER_CST
)
787 single_nonrect_count
= t
;
788 single_nonrect_cond_code
= loop
->cond_code
;
789 if (count
== NULL_TREE
)
790 count
= build_one_cst (llutype
);
793 else if (count
!= NULL_TREE
)
794 count
= fold_build2 (MULT_EXPR
, llutype
, count
, t
);
797 if (TREE_CODE (count
) != INTEGER_CST
)
800 else if (count
&& !integer_zerop (count
))
807 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
808 || fd
->have_ordered
))
810 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
811 iter_type
= long_long_unsigned_type_node
;
813 iter_type
= long_integer_type_node
;
815 else if (collapse_iter
&& *collapse_iter
!= NULL
)
816 iter_type
= TREE_TYPE (*collapse_iter
);
817 fd
->iter_type
= iter_type
;
818 if (collapse_iter
&& *collapse_iter
== NULL
)
819 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
820 if (collapse_count
&& *collapse_count
== NULL
)
824 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
825 if (fd
->first_inner_iterations
&& fd
->factor
)
827 t
= make_tree_vec (4);
828 TREE_VEC_ELT (t
, 0) = *collapse_count
;
829 TREE_VEC_ELT (t
, 1) = fd
->first_inner_iterations
;
830 TREE_VEC_ELT (t
, 2) = fd
->factor
;
831 TREE_VEC_ELT (t
, 3) = fd
->adjn1
;
836 *collapse_count
= create_tmp_var (iter_type
, ".count");
839 if (fd
->collapse
> 1 || fd
->tiling
|| (fd
->ordered
&& loops
))
841 fd
->loop
.v
= *collapse_iter
;
842 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
843 fd
->loop
.n2
= *collapse_count
;
844 if (TREE_CODE (fd
->loop
.n2
) == TREE_VEC
)
846 gcc_assert (fd
->non_rect
);
847 fd
->first_inner_iterations
= TREE_VEC_ELT (fd
->loop
.n2
, 1);
848 fd
->factor
= TREE_VEC_ELT (fd
->loop
.n2
, 2);
849 fd
->adjn1
= TREE_VEC_ELT (fd
->loop
.n2
, 3);
850 fd
->loop
.n2
= TREE_VEC_ELT (fd
->loop
.n2
, 0);
852 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
853 fd
->loop
.m1
= NULL_TREE
;
854 fd
->loop
.m2
= NULL_TREE
;
856 fd
->loop
.cond_code
= LT_EXPR
;
862 /* Build a call to GOMP_barrier. */
865 omp_build_barrier (tree lhs
)
867 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
868 : BUILT_IN_GOMP_BARRIER
);
869 gcall
*g
= gimple_build_call (fndecl
, 0);
871 gimple_call_set_lhs (g
, lhs
);
875 /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
876 array, pdata[0] non-NULL if there is anything non-trivial in between,
877 pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
878 of OMP_FOR in between if any and pdata[3] is address of the inner
882 find_combined_omp_for (tree
*tp
, int *walk_subtrees
, void *data
)
884 tree
**pdata
= (tree
**) data
;
886 switch (TREE_CODE (*tp
))
889 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
898 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
905 if (BIND_EXPR_VARS (*tp
)
906 || (BIND_EXPR_BLOCK (*tp
)
907 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp
))))
912 if (!tsi_one_before_end_p (tsi_start (*tp
)))
916 case TRY_FINALLY_EXPR
:
930 /* Return maximum possible vectorization factor for the target. */
937 || !flag_tree_loop_optimize
938 || (!flag_tree_loop_vectorize
939 && global_options_set
.x_flag_tree_loop_vectorize
))
942 auto_vector_modes modes
;
943 targetm
.vectorize
.autovectorize_vector_modes (&modes
, true);
944 if (!modes
.is_empty ())
947 for (unsigned int i
= 0; i
< modes
.length (); ++i
)
948 /* The returned modes use the smallest element size (and thus
949 the largest nunits) for the vectorization approach that they
951 vf
= ordered_max (vf
, GET_MODE_NUNITS (modes
[i
]));
955 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
956 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
957 return GET_MODE_NUNITS (vqimode
);
962 /* Return maximum SIMT width if offloading may target SIMT hardware. */
965 omp_max_simt_vf (void)
969 if (ENABLE_OFFLOADING
)
970 for (const char *c
= getenv ("OFFLOAD_TARGET_NAMES"); c
;)
972 if (startswith (c
, "nvptx"))
974 else if ((c
= strchr (c
, ':')))
980 /* Store the construct selectors as tree codes from last to first,
981 return their number. */
984 omp_constructor_traits_to_codes (tree ctx
, enum tree_code
*constructs
)
986 int nconstructs
= list_length (ctx
);
987 int i
= nconstructs
- 1;
988 for (tree t2
= ctx
; t2
; t2
= TREE_CHAIN (t2
), i
--)
990 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
991 if (!strcmp (sel
, "target"))
992 constructs
[i
] = OMP_TARGET
;
993 else if (!strcmp (sel
, "teams"))
994 constructs
[i
] = OMP_TEAMS
;
995 else if (!strcmp (sel
, "parallel"))
996 constructs
[i
] = OMP_PARALLEL
;
997 else if (!strcmp (sel
, "for") || !strcmp (sel
, "do"))
998 constructs
[i
] = OMP_FOR
;
999 else if (!strcmp (sel
, "simd"))
1000 constructs
[i
] = OMP_SIMD
;
1004 gcc_assert (i
== -1);
1008 /* Return true if PROP is possibly present in one of the offloading target's
1009 OpenMP contexts. The format of PROPS string is always offloading target's
1010 name terminated by '\0', followed by properties for that offloading
1011 target separated by '\0' and terminated by another '\0'. The strings
1012 are created from omp-device-properties installed files of all configured
1013 offloading targets. */
1016 omp_offload_device_kind_arch_isa (const char *props
, const char *prop
)
1018 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1019 if (names
== NULL
|| *names
== '\0')
1021 while (*props
!= '\0')
1023 size_t name_len
= strlen (props
);
1024 bool matches
= false;
1025 for (const char *c
= names
; c
; )
1027 if (strncmp (props
, c
, name_len
) == 0
1028 && (c
[name_len
] == '\0'
1029 || c
[name_len
] == ':'
1030 || c
[name_len
] == '='))
1035 else if ((c
= strchr (c
, ':')))
1038 props
= props
+ name_len
+ 1;
1039 while (*props
!= '\0')
1041 if (matches
&& strcmp (props
, prop
) == 0)
1043 props
= strchr (props
, '\0') + 1;
1050 /* Return true if the current code location is or might be offloaded.
1051 Return true in declare target functions, or when nested in a target
1052 region or when unsure, return false otherwise. */
1055 omp_maybe_offloaded (void)
1057 if (!ENABLE_OFFLOADING
)
1059 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1060 if (names
== NULL
|| *names
== '\0')
1063 if (symtab
->state
== PARSING
)
1066 if (cfun
&& cfun
->after_inlining
)
1068 if (current_function_decl
1069 && lookup_attribute ("omp declare target",
1070 DECL_ATTRIBUTES (current_function_decl
)))
1072 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) == 0)
1074 enum tree_code construct
= OMP_TARGET
;
1075 if (omp_construct_selector_matches (&construct
, 1, NULL
))
1081 /* Return a name from PROP, a property in selectors accepting
1085 omp_context_name_list_prop (tree prop
)
1087 if (TREE_PURPOSE (prop
))
1088 return IDENTIFIER_POINTER (TREE_PURPOSE (prop
));
1091 const char *ret
= TREE_STRING_POINTER (TREE_VALUE (prop
));
1092 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop
)) == strlen (ret
) + 1)
1098 /* Return 1 if context selector matches the current OpenMP context, 0
1099 if it does not and -1 if it is unknown and need to be determined later.
1100 Some properties can be checked right away during parsing (this routine),
1101 others need to wait until the whole TU is parsed, others need to wait until
1102 IPA, others until vectorization. */
1105 omp_context_selector_matches (tree ctx
)
1108 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1110 char set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
))[0];
1113 /* For now, ignore the construct set. While something can be
1114 determined already during parsing, we don't know until end of TU
1115 whether additional constructs aren't added through declare variant
1116 unless "omp declare variant variant" attribute exists already
1117 (so in most of the cases), and we'd need to maintain set of
1118 surrounding OpenMP constructs, which is better handled during
1120 if (symtab
->state
== PARSING
)
1126 enum tree_code constructs
[5];
1128 = omp_constructor_traits_to_codes (TREE_VALUE (t1
), constructs
);
1130 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1132 if (!cfun
->after_inlining
)
1138 for (i
= 0; i
< nconstructs
; ++i
)
1139 if (constructs
[i
] == OMP_SIMD
)
1141 if (i
< nconstructs
)
1146 /* If there is no simd, assume it is ok after IPA,
1147 constructs should have been checked before. */
1151 int r
= omp_construct_selector_matches (constructs
, nconstructs
,
1159 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1161 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
1165 if (set
== 'i' && !strcmp (sel
, "vendor"))
1166 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1168 const char *prop
= omp_context_name_list_prop (t3
);
1171 if ((!strcmp (prop
, " score") && TREE_PURPOSE (t3
))
1172 || !strcmp (prop
, "gnu"))
1178 if (set
== 'i' && !strcmp (sel
, "extension"))
1179 /* We don't support any extensions right now. */
1183 if (set
== 'i' && !strcmp (sel
, "atomic_default_mem_order"))
1185 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1188 enum omp_memory_order omo
1189 = ((enum omp_memory_order
)
1191 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER
));
1192 if (omo
== OMP_MEMORY_ORDER_UNSPECIFIED
)
1194 /* We don't know yet, until end of TU. */
1195 if (symtab
->state
== PARSING
)
1201 omo
= OMP_MEMORY_ORDER_RELAXED
;
1203 tree t3
= TREE_VALUE (t2
);
1204 const char *prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1205 if (!strcmp (prop
, " score"))
1207 t3
= TREE_CHAIN (t3
);
1208 prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1210 if (!strcmp (prop
, "relaxed")
1211 && omo
!= OMP_MEMORY_ORDER_RELAXED
)
1213 else if (!strcmp (prop
, "seq_cst")
1214 && omo
!= OMP_MEMORY_ORDER_SEQ_CST
)
1216 else if (!strcmp (prop
, "acq_rel")
1217 && omo
!= OMP_MEMORY_ORDER_ACQ_REL
)
1220 if (set
== 'd' && !strcmp (sel
, "arch"))
1221 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1223 const char *arch
= omp_context_name_list_prop (t3
);
1227 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1228 r
= targetm
.omp
.device_kind_arch_isa (omp_device_arch
,
1230 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1232 /* If we are or might be in a target region or
1233 declare target function, need to take into account
1234 also offloading values. */
1235 if (!omp_maybe_offloaded ())
1237 if (ENABLE_OFFLOADING
)
1239 const char *arches
= omp_offload_device_arch
;
1240 if (omp_offload_device_kind_arch_isa (arches
,
1251 /* If arch matches on the host, it still might not match
1252 in the offloading region. */
1253 else if (omp_maybe_offloaded ())
1258 if (set
== 'i' && !strcmp (sel
, "unified_address"))
1260 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1263 if ((omp_requires_mask
& OMP_REQUIRES_UNIFIED_ADDRESS
) == 0)
1265 if (symtab
->state
== PARSING
)
1272 if (set
== 'i' && !strcmp (sel
, "unified_shared_memory"))
1274 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1277 if ((omp_requires_mask
1278 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY
) == 0)
1280 if (symtab
->state
== PARSING
)
1289 if (set
== 'i' && !strcmp (sel
, "dynamic_allocators"))
1291 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1294 if ((omp_requires_mask
1295 & OMP_REQUIRES_DYNAMIC_ALLOCATORS
) == 0)
1297 if (symtab
->state
== PARSING
)
1306 if (set
== 'i' && !strcmp (sel
, "reverse_offload"))
1308 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1311 if ((omp_requires_mask
& OMP_REQUIRES_REVERSE_OFFLOAD
) == 0)
1313 if (symtab
->state
== PARSING
)
1322 if (set
== 'd' && !strcmp (sel
, "kind"))
1323 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1325 const char *prop
= omp_context_name_list_prop (t3
);
1328 if (!strcmp (prop
, "any"))
1330 if (!strcmp (prop
, "host"))
1332 if (omp_maybe_offloaded ())
1336 if (!strcmp (prop
, "nohost"))
1338 if (omp_maybe_offloaded ())
1345 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1346 r
= targetm
.omp
.device_kind_arch_isa (omp_device_kind
,
1349 r
= strcmp (prop
, "cpu") == 0;
1350 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1352 /* If we are or might be in a target region or
1353 declare target function, need to take into account
1354 also offloading values. */
1355 if (!omp_maybe_offloaded ())
1357 if (ENABLE_OFFLOADING
)
1359 const char *kinds
= omp_offload_device_kind
;
1360 if (omp_offload_device_kind_arch_isa (kinds
, prop
))
1370 /* If kind matches on the host, it still might not match
1371 in the offloading region. */
1372 else if (omp_maybe_offloaded ())
1377 if (set
== 'd' && !strcmp (sel
, "isa"))
1378 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1380 const char *isa
= omp_context_name_list_prop (t3
);
1384 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1385 r
= targetm
.omp
.device_kind_arch_isa (omp_device_isa
,
1387 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1389 /* If isa is valid on the target, but not in the
1390 current function and current function has
1391 #pragma omp declare simd on it, some simd clones
1392 might have the isa added later on. */
1394 && targetm
.simd_clone
.compute_vecsize_and_simdlen
1395 && (cfun
== NULL
|| !cfun
->after_inlining
))
1398 = DECL_ATTRIBUTES (current_function_decl
);
1399 if (lookup_attribute ("omp declare simd", attrs
))
1405 /* If we are or might be in a target region or
1406 declare target function, need to take into account
1407 also offloading values. */
1408 if (!omp_maybe_offloaded ())
1410 if (ENABLE_OFFLOADING
)
1412 const char *isas
= omp_offload_device_isa
;
1413 if (omp_offload_device_kind_arch_isa (isas
, isa
))
1423 /* If isa matches on the host, it still might not match
1424 in the offloading region. */
1425 else if (omp_maybe_offloaded ())
1430 if (set
== 'u' && !strcmp (sel
, "condition"))
1431 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1432 if (TREE_PURPOSE (t3
) == NULL_TREE
)
1434 if (integer_zerop (TREE_VALUE (t3
)))
1436 if (integer_nonzerop (TREE_VALUE (t3
)))
1449 /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1450 in omp_context_selector_set_compare. */
1453 omp_construct_simd_compare (tree clauses1
, tree clauses2
)
1455 if (clauses1
== NULL_TREE
)
1456 return clauses2
== NULL_TREE
? 0 : -1;
1457 if (clauses2
== NULL_TREE
)
1461 struct declare_variant_simd_data
{
1462 bool inbranch
, notinbranch
;
1464 auto_vec
<tree
,16> data_sharing
;
1465 auto_vec
<tree
,16> aligned
;
1466 declare_variant_simd_data ()
1467 : inbranch(false), notinbranch(false), simdlen(NULL_TREE
) {}
1470 for (i
= 0; i
< 2; i
++)
1471 for (tree c
= i
? clauses2
: clauses1
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1474 switch (OMP_CLAUSE_CODE (c
))
1476 case OMP_CLAUSE_INBRANCH
:
1477 data
[i
].inbranch
= true;
1479 case OMP_CLAUSE_NOTINBRANCH
:
1480 data
[i
].notinbranch
= true;
1482 case OMP_CLAUSE_SIMDLEN
:
1483 data
[i
].simdlen
= OMP_CLAUSE_SIMDLEN_EXPR (c
);
1485 case OMP_CLAUSE_UNIFORM
:
1486 case OMP_CLAUSE_LINEAR
:
1487 v
= &data
[i
].data_sharing
;
1489 case OMP_CLAUSE_ALIGNED
:
1490 v
= &data
[i
].aligned
;
1495 unsigned HOST_WIDE_INT argno
= tree_to_uhwi (OMP_CLAUSE_DECL (c
));
1496 if (argno
>= v
->length ())
1497 v
->safe_grow_cleared (argno
+ 1, true);
1500 /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1501 CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1502 doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1503 -1, r == 2 implies 1 and r == 0 implies 0. */
1504 if (data
[0].inbranch
!= data
[1].inbranch
)
1505 r
|= data
[0].inbranch
? 2 : 1;
1506 if (data
[0].notinbranch
!= data
[1].notinbranch
)
1507 r
|= data
[0].notinbranch
? 2 : 1;
1508 if (!simple_cst_equal (data
[0].simdlen
, data
[1].simdlen
))
1510 if (data
[0].simdlen
&& data
[1].simdlen
)
1512 r
|= data
[0].simdlen
? 2 : 1;
1514 if (data
[0].data_sharing
.length () < data
[1].data_sharing
.length ()
1515 || data
[0].aligned
.length () < data
[1].aligned
.length ())
1518 FOR_EACH_VEC_ELT (data
[0].data_sharing
, i
, c1
)
1520 c2
= (i
< data
[1].data_sharing
.length ()
1521 ? data
[1].data_sharing
[i
] : NULL_TREE
);
1522 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1524 r
|= c1
!= NULL_TREE
? 2 : 1;
1527 if (c1
== NULL_TREE
)
1529 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_CODE (c2
))
1531 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_LINEAR
)
1533 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1
)
1534 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2
))
1536 if (OMP_CLAUSE_LINEAR_KIND (c1
) != OMP_CLAUSE_LINEAR_KIND (c2
))
1538 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1
),
1539 OMP_CLAUSE_LINEAR_STEP (c2
)))
1542 FOR_EACH_VEC_ELT (data
[0].aligned
, i
, c1
)
1544 c2
= i
< data
[1].aligned
.length () ? data
[1].aligned
[i
] : NULL_TREE
;
1545 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1547 r
|= c1
!= NULL_TREE
? 2 : 1;
1550 if (c1
== NULL_TREE
)
1552 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1
),
1553 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2
)))
1562 default: gcc_unreachable ();
1566 /* Compare properties of selectors SEL from SET other than construct.
1567 Return 0/-1/1/2 as in omp_context_selector_set_compare.
1568 Unlike set names or selector names, properties can have duplicates. */
1571 omp_context_selector_props_compare (const char *set
, const char *sel
,
1572 tree ctx1
, tree ctx2
)
1575 for (int pass
= 0; pass
< 2; pass
++)
1576 for (tree t1
= pass
? ctx2
: ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1579 for (t2
= pass
? ctx1
: ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1580 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1582 if (TREE_PURPOSE (t1
) == NULL_TREE
)
1584 if (set
[0] == 'u' && strcmp (sel
, "condition") == 0)
1586 if (integer_zerop (TREE_VALUE (t1
))
1587 != integer_zerop (TREE_VALUE (t2
)))
1591 if (simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1594 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1
)),
1597 if (!simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1604 else if (TREE_PURPOSE (t1
)
1605 && TREE_PURPOSE (t2
) == NULL_TREE
1606 && TREE_CODE (TREE_VALUE (t2
)) == STRING_CST
)
1608 const char *p1
= omp_context_name_list_prop (t1
);
1609 const char *p2
= omp_context_name_list_prop (t2
);
1611 && strcmp (p1
, p2
) == 0
1612 && strcmp (p1
, " score"))
1615 else if (TREE_PURPOSE (t1
) == NULL_TREE
1616 && TREE_PURPOSE (t2
)
1617 && TREE_CODE (TREE_VALUE (t1
)) == STRING_CST
)
1619 const char *p1
= omp_context_name_list_prop (t1
);
1620 const char *p2
= omp_context_name_list_prop (t2
);
1622 && strcmp (p1
, p2
) == 0
1623 && strcmp (p1
, " score"))
1626 if (t2
== NULL_TREE
)
1628 int r
= pass
? -1 : 1;
1629 if (ret
&& ret
!= r
)
1643 /* Compare single context selector sets CTX1 and CTX2 with SET name.
1644 Return 0 if CTX1 is equal to CTX2,
1645 -1 if CTX1 is a strict subset of CTX2,
1646 1 if CTX2 is a strict subset of CTX1, or
1647 2 if neither context is a subset of another one. */
1650 omp_context_selector_set_compare (const char *set
, tree ctx1
, tree ctx2
)
1652 bool swapped
= false;
1654 int len1
= list_length (ctx1
);
1655 int len2
= list_length (ctx2
);
1660 std::swap (ctx1
, ctx2
);
1661 std::swap (len1
, len2
);
1667 tree simd
= get_identifier ("simd");
1668 /* Handle construct set specially. In this case the order
1669 of the selector matters too. */
1670 for (t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1671 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1674 if (TREE_PURPOSE (t1
) == simd
)
1675 r
= omp_construct_simd_compare (TREE_VALUE (t1
),
1677 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1681 t2
= TREE_CHAIN (t2
);
1682 if (t2
== NULL_TREE
)
1684 t1
= TREE_CHAIN (t1
);
1692 if (t2
!= NULL_TREE
)
1694 if (t1
!= NULL_TREE
)
1702 return swapped
? -ret
: ret
;
1704 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1707 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1708 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1710 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1711 int r
= omp_context_selector_props_compare (set
, sel
,
1714 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1721 if (t2
== NULL_TREE
)
1732 return swapped
? -ret
: ret
;
1735 /* Compare whole context selector specification CTX1 and CTX2.
1736 Return 0 if CTX1 is equal to CTX2,
1737 -1 if CTX1 is a strict subset of CTX2,
1738 1 if CTX2 is a strict subset of CTX1, or
1739 2 if neither context is a subset of another one. */
1742 omp_context_selector_compare (tree ctx1
, tree ctx2
)
1744 bool swapped
= false;
1746 int len1
= list_length (ctx1
);
1747 int len2
= list_length (ctx2
);
1752 std::swap (ctx1
, ctx2
);
1753 std::swap (len1
, len2
);
1755 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1758 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1759 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1761 const char *set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1762 int r
= omp_context_selector_set_compare (set
, TREE_VALUE (t1
),
1764 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1771 if (t2
== NULL_TREE
)
1782 return swapped
? -ret
: ret
;
1785 /* From context selector CTX, return trait-selector with name SEL in
1786 trait-selector-set with name SET if any, or NULL_TREE if not found.
1787 If SEL is NULL, return the list of trait-selectors in SET. */
1790 omp_get_context_selector (tree ctx
, const char *set
, const char *sel
)
1792 tree setid
= get_identifier (set
);
1793 tree selid
= sel
? get_identifier (sel
) : NULL_TREE
;
1794 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1795 if (TREE_PURPOSE (t1
) == setid
)
1798 return TREE_VALUE (t1
);
1799 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1800 if (TREE_PURPOSE (t2
) == selid
)
1806 /* Compute *SCORE for context selector CTX. Return true if the score
1807 would be different depending on whether it is a declare simd clone or
1808 not. DECLARE_SIMD should be true for the case when it would be
1809 a declare simd clone. */
1812 omp_context_compute_score (tree ctx
, widest_int
*score
, bool declare_simd
)
1814 tree construct
= omp_get_context_selector (ctx
, "construct", NULL
);
1815 bool has_kind
= omp_get_context_selector (ctx
, "device", "kind");
1816 bool has_arch
= omp_get_context_selector (ctx
, "device", "arch");
1817 bool has_isa
= omp_get_context_selector (ctx
, "device", "isa");
1820 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1821 if (TREE_VALUE (t1
) != construct
)
1822 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1823 if (tree t3
= TREE_VALUE (t2
))
1824 if (TREE_PURPOSE (t3
)
1825 && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3
)), " score") == 0
1826 && TREE_CODE (TREE_VALUE (t3
)) == INTEGER_CST
)
1827 *score
+= wi::to_widest (TREE_VALUE (t3
));
1828 if (construct
|| has_kind
|| has_arch
|| has_isa
)
1831 enum tree_code constructs
[5];
1832 int nconstructs
= 0;
1834 nconstructs
= omp_constructor_traits_to_codes (construct
, constructs
);
1835 if (omp_construct_selector_matches (constructs
, nconstructs
, scores
)
1838 int b
= declare_simd
? nconstructs
+ 1 : 0;
1839 if (scores
[b
+ nconstructs
] + 4U < score
->get_precision ())
1841 for (int n
= 0; n
< nconstructs
; ++n
)
1843 if (scores
[b
+ n
] < 0)
1848 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ n
], 1, false);
1851 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
],
1854 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 1,
1857 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 2,
1860 else /* FIXME: Implement this. */
1866 /* Class describing a single variant. */
1867 struct GTY(()) omp_declare_variant_entry
{
1868 /* NODE of the variant. */
1869 cgraph_node
*variant
;
1870 /* Score if not in declare simd clone. */
1872 /* Score if in declare simd clone. */
1873 widest_int score_in_declare_simd_clone
;
1874 /* Context selector for the variant. */
1876 /* True if the context selector is known to match already. */
1880 /* Class describing a function with variants. */
1881 struct GTY((for_user
)) omp_declare_variant_base_entry
{
1882 /* NODE of the base function. */
1884 /* NODE of the artificial function created for the deferred variant
1887 /* Vector of the variants. */
1888 vec
<omp_declare_variant_entry
, va_gc
> *variants
;
1891 struct omp_declare_variant_hasher
1892 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1893 static hashval_t
hash (omp_declare_variant_base_entry
*);
1894 static bool equal (omp_declare_variant_base_entry
*,
1895 omp_declare_variant_base_entry
*);
1899 omp_declare_variant_hasher::hash (omp_declare_variant_base_entry
*x
)
1901 inchash::hash hstate
;
1902 hstate
.add_int (DECL_UID (x
->base
->decl
));
1903 hstate
.add_int (x
->variants
->length ());
1904 omp_declare_variant_entry
*variant
;
1906 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1908 hstate
.add_int (DECL_UID (variant
->variant
->decl
));
1909 hstate
.add_wide_int (variant
->score
);
1910 hstate
.add_wide_int (variant
->score_in_declare_simd_clone
);
1911 hstate
.add_ptr (variant
->ctx
);
1912 hstate
.add_int (variant
->matches
);
1914 return hstate
.end ();
1918 omp_declare_variant_hasher::equal (omp_declare_variant_base_entry
*x
,
1919 omp_declare_variant_base_entry
*y
)
1921 if (x
->base
!= y
->base
1922 || x
->variants
->length () != y
->variants
->length ())
1924 omp_declare_variant_entry
*variant
;
1926 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1927 if (variant
->variant
!= (*y
->variants
)[i
].variant
1928 || variant
->score
!= (*y
->variants
)[i
].score
1929 || (variant
->score_in_declare_simd_clone
1930 != (*y
->variants
)[i
].score_in_declare_simd_clone
)
1931 || variant
->ctx
!= (*y
->variants
)[i
].ctx
1932 || variant
->matches
!= (*y
->variants
)[i
].matches
)
1937 static GTY(()) hash_table
<omp_declare_variant_hasher
> *omp_declare_variants
;
1939 struct omp_declare_variant_alt_hasher
1940 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1941 static hashval_t
hash (omp_declare_variant_base_entry
*);
1942 static bool equal (omp_declare_variant_base_entry
*,
1943 omp_declare_variant_base_entry
*);
1947 omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry
*x
)
1949 return DECL_UID (x
->node
->decl
);
1953 omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry
*x
,
1954 omp_declare_variant_base_entry
*y
)
1956 return x
->node
== y
->node
;
1959 static GTY(()) hash_table
<omp_declare_variant_alt_hasher
>
1960 *omp_declare_variant_alt
;
1962 /* Try to resolve declare variant after gimplification. */
1965 omp_resolve_late_declare_variant (tree alt
)
1967 cgraph_node
*node
= cgraph_node::get (alt
);
1968 cgraph_node
*cur_node
= cgraph_node::get (cfun
->decl
);
1970 || !node
->declare_variant_alt
1971 || !cfun
->after_inlining
)
1974 omp_declare_variant_base_entry entry
;
1977 entry
.variants
= NULL
;
1978 omp_declare_variant_base_entry
*entryp
1979 = omp_declare_variant_alt
->find_with_hash (&entry
, DECL_UID (alt
));
1982 omp_declare_variant_entry
*varentry1
, *varentry2
;
1983 auto_vec
<bool, 16> matches
;
1984 unsigned int nmatches
= 0;
1985 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
1987 if (varentry1
->matches
)
1989 /* This has been checked to be ok already. */
1990 matches
.safe_push (true);
1994 switch (omp_context_selector_matches (varentry1
->ctx
))
1997 matches
.safe_push (false);
2002 matches
.safe_push (true);
2009 return entryp
->base
->decl
;
2011 /* A context selector that is a strict subset of another context selector
2012 has a score of zero. */
2013 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2017 vec_safe_iterate (entryp
->variants
, j
, &varentry2
); ++j
)
2020 int r
= omp_context_selector_compare (varentry1
->ctx
,
2024 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2029 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2034 widest_int max_score
= -1;
2036 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2040 = (cur_node
->simdclone
? varentry1
->score_in_declare_simd_clone
2041 : varentry1
->score
);
2042 if (score
> max_score
)
2045 varentry2
= varentry1
;
2048 return varentry2
->variant
->decl
;
2051 /* Hook to adjust hash tables on cgraph_node removal. */
2054 omp_declare_variant_remove_hook (struct cgraph_node
*node
, void *)
2056 if (!node
->declare_variant_alt
)
2059 /* Drop this hash table completely. */
2060 omp_declare_variants
= NULL
;
2061 /* And remove node from the other hash table. */
2062 if (omp_declare_variant_alt
)
2064 omp_declare_variant_base_entry entry
;
2067 entry
.variants
= NULL
;
2068 omp_declare_variant_alt
->remove_elt_with_hash (&entry
,
2069 DECL_UID (node
->decl
));
2073 /* Try to resolve declare variant, return the variant decl if it should
2074 be used instead of base, or base otherwise. */
2077 omp_resolve_declare_variant (tree base
)
2079 tree variant1
= NULL_TREE
, variant2
= NULL_TREE
;
2080 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
2081 return omp_resolve_late_declare_variant (base
);
2083 auto_vec
<tree
, 16> variants
;
2084 auto_vec
<bool, 16> defer
;
2085 bool any_deferred
= false;
2086 for (tree attr
= DECL_ATTRIBUTES (base
); attr
; attr
= TREE_CHAIN (attr
))
2088 attr
= lookup_attribute ("omp declare variant base", attr
);
2089 if (attr
== NULL_TREE
)
2091 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr
))) != FUNCTION_DECL
)
2093 cgraph_node
*node
= cgraph_node::get (base
);
2094 /* If this is already a magic decl created by this function,
2095 don't process it again. */
2096 if (node
&& node
->declare_variant_alt
)
2098 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr
))))
2101 /* No match, ignore. */
2104 /* Needs to be deferred. */
2105 any_deferred
= true;
2106 variants
.safe_push (attr
);
2107 defer
.safe_push (true);
2110 variants
.safe_push (attr
);
2111 defer
.safe_push (false);
2115 if (variants
.length () == 0)
2120 widest_int max_score1
= 0;
2121 widest_int max_score2
= 0;
2125 omp_declare_variant_base_entry entry
;
2126 entry
.base
= cgraph_node::get_create (base
);
2128 vec_alloc (entry
.variants
, variants
.length ());
2129 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2134 tree ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2135 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2137 omp_context_compute_score (ctx
, &score2
, true);
2143 max_score1
= score1
;
2144 max_score2
= score2
;
2153 if (max_score1
== score1
)
2154 variant1
= NULL_TREE
;
2155 else if (score1
> max_score1
)
2157 max_score1
= score1
;
2158 variant1
= defer
[i
] ? NULL_TREE
: attr1
;
2160 if (max_score2
== score2
)
2161 variant2
= NULL_TREE
;
2162 else if (score2
> max_score2
)
2164 max_score2
= score2
;
2165 variant2
= defer
[i
] ? NULL_TREE
: attr1
;
2168 omp_declare_variant_entry varentry
;
2170 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1
)));
2171 varentry
.score
= score1
;
2172 varentry
.score_in_declare_simd_clone
= score2
;
2174 varentry
.matches
= !defer
[i
];
2175 entry
.variants
->quick_push (varentry
);
2178 /* If there is a clear winner variant with the score which is not
2179 deferred, verify it is not a strict subset of any other context
2180 selector and if it is not, it is the best alternative no matter
2181 whether the others do or don't match. */
2182 if (variant1
&& variant1
== variant2
)
2184 tree ctx1
= TREE_VALUE (TREE_VALUE (variant1
));
2185 FOR_EACH_VEC_ELT (variants
, i
, attr2
)
2187 if (attr2
== variant1
)
2189 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2190 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2193 /* The winner is a strict subset of ctx2, can't
2195 variant1
= NULL_TREE
;
2201 vec_free (entry
.variants
);
2202 return TREE_PURPOSE (TREE_VALUE (variant1
));
2206 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
2207 if (!node_removal_hook_holder
)
2208 node_removal_hook_holder
2209 = symtab
->add_cgraph_removal_hook (omp_declare_variant_remove_hook
,
2212 if (omp_declare_variants
== NULL
)
2213 omp_declare_variants
2214 = hash_table
<omp_declare_variant_hasher
>::create_ggc (64);
2215 omp_declare_variant_base_entry
**slot
2216 = omp_declare_variants
->find_slot (&entry
, INSERT
);
2219 vec_free (entry
.variants
);
2220 return (*slot
)->node
->decl
;
2223 *slot
= ggc_cleared_alloc
<omp_declare_variant_base_entry
> ();
2224 (*slot
)->base
= entry
.base
;
2225 (*slot
)->node
= entry
.base
;
2226 (*slot
)->variants
= entry
.variants
;
2227 tree alt
= build_decl (DECL_SOURCE_LOCATION (base
), FUNCTION_DECL
,
2228 DECL_NAME (base
), TREE_TYPE (base
));
2229 DECL_ARTIFICIAL (alt
) = 1;
2230 DECL_IGNORED_P (alt
) = 1;
2231 TREE_STATIC (alt
) = 1;
2232 tree attributes
= DECL_ATTRIBUTES (base
);
2233 if (lookup_attribute ("noipa", attributes
) == NULL
)
2235 attributes
= tree_cons (get_identifier ("noipa"), NULL
, attributes
);
2236 if (lookup_attribute ("noinline", attributes
) == NULL
)
2237 attributes
= tree_cons (get_identifier ("noinline"), NULL
,
2239 if (lookup_attribute ("noclone", attributes
) == NULL
)
2240 attributes
= tree_cons (get_identifier ("noclone"), NULL
,
2242 if (lookup_attribute ("no_icf", attributes
) == NULL
)
2243 attributes
= tree_cons (get_identifier ("no_icf"), NULL
,
2246 DECL_ATTRIBUTES (alt
) = attributes
;
2247 DECL_INITIAL (alt
) = error_mark_node
;
2248 (*slot
)->node
= cgraph_node::create (alt
);
2249 (*slot
)->node
->declare_variant_alt
= 1;
2250 (*slot
)->node
->create_reference (entry
.base
, IPA_REF_ADDR
);
2251 omp_declare_variant_entry
*varentry
;
2252 FOR_EACH_VEC_SAFE_ELT (entry
.variants
, i
, varentry
)
2253 (*slot
)->node
->create_reference (varentry
->variant
, IPA_REF_ADDR
);
2254 if (omp_declare_variant_alt
== NULL
)
2255 omp_declare_variant_alt
2256 = hash_table
<omp_declare_variant_alt_hasher
>::create_ggc (64);
2257 *omp_declare_variant_alt
->find_slot_with_hash (*slot
, DECL_UID (alt
),
2262 if (variants
.length () == 1)
2263 return TREE_PURPOSE (TREE_VALUE (variants
[0]));
2265 /* A context selector that is a strict subset of another context selector
2266 has a score of zero. */
2269 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2272 tree ctx1
= TREE_VALUE (TREE_VALUE (attr1
));
2273 FOR_EACH_VEC_ELT_FROM (variants
, j
, attr2
, i
+ 1)
2276 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2277 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2280 /* ctx1 is a strict subset of ctx2, remove
2281 attr1 from the vector. */
2282 variants
[i
] = NULL_TREE
;
2286 /* ctx2 is a strict subset of ctx1, remove attr2
2288 variants
[j
] = NULL_TREE
;
2291 widest_int max_score1
= 0;
2292 widest_int max_score2
= 0;
2294 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2306 ctx
= TREE_VALUE (TREE_VALUE (variant1
));
2307 need_two
= omp_context_compute_score (ctx
, &max_score1
, false);
2309 omp_context_compute_score (ctx
, &max_score2
, true);
2311 max_score2
= max_score1
;
2313 ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2314 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2316 omp_context_compute_score (ctx
, &score2
, true);
2319 if (score1
> max_score1
)
2321 max_score1
= score1
;
2324 if (score2
> max_score2
)
2326 max_score2
= score2
;
2336 /* If there is a disagreement on which variant has the highest score
2337 depending on whether it will be in a declare simd clone or not,
2338 punt for now and defer until after IPA where we will know that. */
2339 return ((variant1
&& variant1
== variant2
)
2340 ? TREE_PURPOSE (TREE_VALUE (variant1
)) : base
);
2344 omp_lto_output_declare_variant_alt (lto_simple_output_block
*ob
,
2346 lto_symtab_encoder_t encoder
)
2348 gcc_assert (node
->declare_variant_alt
);
2350 omp_declare_variant_base_entry entry
;
2353 entry
.variants
= NULL
;
2354 omp_declare_variant_base_entry
*entryp
2355 = omp_declare_variant_alt
->find_with_hash (&entry
, DECL_UID (node
->decl
));
2356 gcc_assert (entryp
);
2358 int nbase
= lto_symtab_encoder_lookup (encoder
, entryp
->base
);
2359 gcc_assert (nbase
!= LCC_NOT_FOUND
);
2360 streamer_write_hwi_stream (ob
->main_stream
, nbase
);
2362 streamer_write_hwi_stream (ob
->main_stream
, entryp
->variants
->length ());
2365 omp_declare_variant_entry
*varentry
;
2366 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry
)
2368 int nvar
= lto_symtab_encoder_lookup (encoder
, varentry
->variant
);
2369 gcc_assert (nvar
!= LCC_NOT_FOUND
);
2370 streamer_write_hwi_stream (ob
->main_stream
, nvar
);
2372 for (widest_int
*w
= &varentry
->score
; ;
2373 w
= &varentry
->score_in_declare_simd_clone
)
2375 unsigned len
= w
->get_len ();
2376 streamer_write_hwi_stream (ob
->main_stream
, len
);
2377 const HOST_WIDE_INT
*val
= w
->get_val ();
2378 for (unsigned j
= 0; j
< len
; j
++)
2379 streamer_write_hwi_stream (ob
->main_stream
, val
[j
]);
2380 if (w
== &varentry
->score_in_declare_simd_clone
)
2384 HOST_WIDE_INT cnt
= -1;
2385 HOST_WIDE_INT i
= varentry
->matches
? 1 : 0;
2386 for (tree attr
= DECL_ATTRIBUTES (entryp
->base
->decl
);
2387 attr
; attr
= TREE_CHAIN (attr
), i
+= 2)
2389 attr
= lookup_attribute ("omp declare variant base", attr
);
2390 if (attr
== NULL_TREE
)
2393 if (varentry
->ctx
== TREE_VALUE (TREE_VALUE (attr
)))
2400 gcc_assert (cnt
!= -1);
2401 streamer_write_hwi_stream (ob
->main_stream
, cnt
);
2406 omp_lto_input_declare_variant_alt (lto_input_block
*ib
, cgraph_node
*node
,
2407 vec
<symtab_node
*> nodes
)
2409 gcc_assert (node
->declare_variant_alt
);
2410 omp_declare_variant_base_entry
*entryp
2411 = ggc_cleared_alloc
<omp_declare_variant_base_entry
> ();
2412 entryp
->base
= dyn_cast
<cgraph_node
*> (nodes
[streamer_read_hwi (ib
)]);
2413 entryp
->node
= node
;
2414 unsigned int len
= streamer_read_hwi (ib
);
2415 vec_alloc (entryp
->variants
, len
);
2417 for (unsigned int i
= 0; i
< len
; i
++)
2419 omp_declare_variant_entry varentry
;
2421 = dyn_cast
<cgraph_node
*> (nodes
[streamer_read_hwi (ib
)]);
2422 for (widest_int
*w
= &varentry
.score
; ;
2423 w
= &varentry
.score_in_declare_simd_clone
)
2425 unsigned len2
= streamer_read_hwi (ib
);
2426 HOST_WIDE_INT arr
[WIDE_INT_MAX_ELTS
];
2427 gcc_assert (len2
<= WIDE_INT_MAX_ELTS
);
2428 for (unsigned int j
= 0; j
< len2
; j
++)
2429 arr
[j
] = streamer_read_hwi (ib
);
2430 *w
= widest_int::from_array (arr
, len2
, true);
2431 if (w
== &varentry
.score_in_declare_simd_clone
)
2435 HOST_WIDE_INT cnt
= streamer_read_hwi (ib
);
2436 HOST_WIDE_INT j
= 0;
2437 varentry
.ctx
= NULL_TREE
;
2438 varentry
.matches
= (cnt
& 1) ? true : false;
2439 cnt
&= ~HOST_WIDE_INT_1
;
2440 for (tree attr
= DECL_ATTRIBUTES (entryp
->base
->decl
);
2441 attr
; attr
= TREE_CHAIN (attr
), j
+= 2)
2443 attr
= lookup_attribute ("omp declare variant base", attr
);
2444 if (attr
== NULL_TREE
)
2449 varentry
.ctx
= TREE_VALUE (TREE_VALUE (attr
));
2453 gcc_assert (varentry
.ctx
!= NULL_TREE
);
2454 entryp
->variants
->quick_push (varentry
);
2456 if (omp_declare_variant_alt
== NULL
)
2457 omp_declare_variant_alt
2458 = hash_table
<omp_declare_variant_alt_hasher
>::create_ggc (64);
2459 *omp_declare_variant_alt
->find_slot_with_hash (entryp
, DECL_UID (node
->decl
),
2463 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2464 macro on gomp-constants.h. We do not check for overflow. */
2467 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
2471 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
2474 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
2475 device
, build_int_cst (unsigned_type_node
,
2476 GOMP_LAUNCH_DEVICE_SHIFT
));
2477 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
2482 /* FIXME: What is the following comment for? */
2483 /* Look for compute grid dimension clauses and convert to an attribute
2484 attached to FN. This permits the target-side code to (a) massage
2485 the dimensions, (b) emit that data and (c) optimize. Non-constant
2486 dimensions are pushed onto ARGS.
2488 The attribute value is a TREE_LIST. A set of dimensions is
2489 represented as a list of INTEGER_CST. Those that are runtime
2490 exprs are represented as an INTEGER_CST of zero.
2492 TODO: Normally the attribute will just contain a single such list. If
2493 however it contains a list of lists, this will represent the use of
2494 device_type. Each member of the outer list is an assoc list of
2495 dimensions, keyed by the device type. The first entry will be the
2496 default. Well, that's the plan. */
2498 /* Replace any existing oacc fn attribute with updated dimensions. */
2500 /* Variant working on a list of attributes. */
2503 oacc_replace_fn_attrib_attr (tree attribs
, tree dims
)
2505 tree ident
= get_identifier (OACC_FN_ATTRIB
);
2507 /* If we happen to be present as the first attrib, drop it. */
2508 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
2509 attribs
= TREE_CHAIN (attribs
);
2510 return tree_cons (ident
, dims
, attribs
);
2513 /* Variant working on a function decl. */
2516 oacc_replace_fn_attrib (tree fn
, tree dims
)
2518 DECL_ATTRIBUTES (fn
)
2519 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn
), dims
);
2522 /* Scan CLAUSES for launch dimensions and attach them to the oacc
2523 function attribute. Push any that are non-constant onto the ARGS
2524 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
2527 oacc_set_fn_attrib (tree fn
, tree clauses
, vec
<tree
> *args
)
2529 /* Must match GOMP_DIM ordering. */
2530 static const omp_clause_code ids
[]
2531 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
2532 OMP_CLAUSE_VECTOR_LENGTH
};
2534 tree dims
[GOMP_DIM_MAX
];
2536 tree attr
= NULL_TREE
;
2537 unsigned non_const
= 0;
2539 for (ix
= GOMP_DIM_MAX
; ix
--;)
2541 tree clause
= omp_find_clause (clauses
, ids
[ix
]);
2542 tree dim
= NULL_TREE
;
2545 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
2547 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
2549 dim
= integer_zero_node
;
2550 non_const
|= GOMP_DIM_MASK (ix
);
2552 attr
= tree_cons (NULL_TREE
, dim
, attr
);
2555 oacc_replace_fn_attrib (fn
, attr
);
2559 /* Push a dynamic argument set. */
2560 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
2561 NULL_TREE
, non_const
));
2562 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
2563 if (non_const
& GOMP_DIM_MASK (ix
))
2564 args
->safe_push (dims
[ix
]);
2568 /* Verify OpenACC routine clauses.
2570 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
2571 if it has already been marked in compatible way, and -1 if incompatible.
2572 Upon returning, the chain of clauses will contain exactly one clause
2573 specifying the level of parallelism. */
2576 oacc_verify_routine_clauses (tree fndecl
, tree
*clauses
, location_t loc
,
2577 const char *routine_str
)
2579 tree c_level
= NULL_TREE
;
2580 tree c_nohost
= NULL_TREE
;
2581 tree c_p
= NULL_TREE
;
2582 for (tree c
= *clauses
; c
; c_p
= c
, c
= OMP_CLAUSE_CHAIN (c
))
2583 switch (OMP_CLAUSE_CODE (c
))
2585 case OMP_CLAUSE_GANG
:
2586 case OMP_CLAUSE_WORKER
:
2587 case OMP_CLAUSE_VECTOR
:
2588 case OMP_CLAUSE_SEQ
:
2589 if (c_level
== NULL_TREE
)
2591 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_CODE (c_level
))
2593 /* This has already been diagnosed in the front ends. */
2594 /* Drop the duplicate clause. */
2595 gcc_checking_assert (c_p
!= NULL_TREE
);
2596 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2601 error_at (OMP_CLAUSE_LOCATION (c
),
2602 "%qs specifies a conflicting level of parallelism",
2603 omp_clause_code_name
[OMP_CLAUSE_CODE (c
)]);
2604 inform (OMP_CLAUSE_LOCATION (c_level
),
2605 "... to the previous %qs clause here",
2606 omp_clause_code_name
[OMP_CLAUSE_CODE (c_level
)]);
2607 /* Drop the conflicting clause. */
2608 gcc_checking_assert (c_p
!= NULL_TREE
);
2609 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2613 case OMP_CLAUSE_NOHOST
:
2614 /* Don't worry about duplicate clauses here. */
2620 if (c_level
== NULL_TREE
)
2622 /* Default to an implicit 'seq' clause. */
2623 c_level
= build_omp_clause (loc
, OMP_CLAUSE_SEQ
);
2624 OMP_CLAUSE_CHAIN (c_level
) = *clauses
;
2627 /* In *clauses, we now have exactly one clause specifying the level of
2631 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl
));
2632 if (attr
!= NULL_TREE
)
2634 /* Diagnose if "#pragma omp declare target" has also been applied. */
2635 if (TREE_VALUE (attr
) == NULL_TREE
)
2637 /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
2638 OpenACC and OpenMP 'target' are not clear. */
2640 "cannot apply %<%s%> to %qD, which has also been"
2641 " marked with an OpenMP 'declare target' directive",
2642 routine_str
, fndecl
);
2647 /* If a "#pragma acc routine" has already been applied, just verify
2648 this one for compatibility. */
2649 /* Collect previous directive's clauses. */
2650 tree c_level_p
= NULL_TREE
;
2651 tree c_nohost_p
= NULL_TREE
;
2652 for (tree c
= TREE_VALUE (attr
); c
; c
= OMP_CLAUSE_CHAIN (c
))
2653 switch (OMP_CLAUSE_CODE (c
))
2655 case OMP_CLAUSE_GANG
:
2656 case OMP_CLAUSE_WORKER
:
2657 case OMP_CLAUSE_VECTOR
:
2658 case OMP_CLAUSE_SEQ
:
2659 gcc_checking_assert (c_level_p
== NULL_TREE
);
2662 case OMP_CLAUSE_NOHOST
:
2663 gcc_checking_assert (c_nohost_p
== NULL_TREE
);
2669 gcc_checking_assert (c_level_p
!= NULL_TREE
);
2670 /* ..., and compare to current directive's, which we've already collected
2674 /* Matching level of parallelism? */
2675 if (OMP_CLAUSE_CODE (c_level
) != OMP_CLAUSE_CODE (c_level_p
))
2678 c_diag_p
= c_level_p
;
2681 /* Matching 'nohost' clauses? */
2682 if ((c_nohost
== NULL_TREE
) != (c_nohost_p
== NULL_TREE
))
2685 c_diag_p
= c_nohost_p
;
2692 if (c_diag
!= NULL_TREE
)
2693 error_at (OMP_CLAUSE_LOCATION (c_diag
),
2694 "incompatible %qs clause when applying"
2695 " %<%s%> to %qD, which has already been"
2696 " marked with an OpenACC 'routine' directive",
2697 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)],
2698 routine_str
, fndecl
);
2699 else if (c_diag_p
!= NULL_TREE
)
2701 "missing %qs clause when applying"
2702 " %<%s%> to %qD, which has already been"
2703 " marked with an OpenACC 'routine' directive",
2704 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)],
2705 routine_str
, fndecl
);
2708 if (c_diag_p
!= NULL_TREE
)
2709 inform (OMP_CLAUSE_LOCATION (c_diag_p
),
2710 "... with %qs clause here",
2711 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)]);
2714 /* In the front ends, we don't preserve location information for the
2715 OpenACC routine directive itself. However, that of c_level_p
2717 location_t loc_routine
= OMP_CLAUSE_LOCATION (c_level_p
);
2718 inform (loc_routine
, "... without %qs clause near to here",
2719 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)]);
2728 /* Process the OpenACC 'routine' directive clauses to generate an attribute
2729 for the level of parallelism. All dimensions have a size of zero
2730 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
2731 can have a loop partitioned on it. non-zero indicates
2732 yes, zero indicates no. By construction once a non-zero has been
2733 reached, further inner dimensions must also be non-zero. We set
2734 TREE_VALUE to zero for the dimensions that may be partitioned and
2735 1 for the other ones -- if a loop is (erroneously) spawned at
2736 an outer level, we don't want to try and partition it. */
2739 oacc_build_routine_dims (tree clauses
)
2741 /* Must match GOMP_DIM ordering. */
2742 static const omp_clause_code ids
[]
2743 = {OMP_CLAUSE_GANG
, OMP_CLAUSE_WORKER
, OMP_CLAUSE_VECTOR
, OMP_CLAUSE_SEQ
};
2747 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
2748 for (ix
= GOMP_DIM_MAX
+ 1; ix
--;)
2749 if (OMP_CLAUSE_CODE (clauses
) == ids
[ix
])
2754 gcc_checking_assert (level
>= 0);
2756 tree dims
= NULL_TREE
;
2758 for (ix
= GOMP_DIM_MAX
; ix
--;)
2759 dims
= tree_cons (build_int_cst (boolean_type_node
, ix
>= level
),
2760 build_int_cst (integer_type_node
, ix
< level
), dims
);
2765 /* Retrieve the oacc function attrib and return it. Non-oacc
2766 functions will return NULL. */
2769 oacc_get_fn_attrib (tree fn
)
2771 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
2774 /* Return true if FN is an OpenMP or OpenACC offloading function. */
2777 offloading_function_p (tree fn
)
2779 tree attrs
= DECL_ATTRIBUTES (fn
);
2780 return (lookup_attribute ("omp declare target", attrs
)
2781 || lookup_attribute ("omp target entrypoint", attrs
));
2784 /* Extract an oacc execution dimension from FN. FN must be an
2785 offloaded function or routine that has already had its execution
2786 dimensions lowered to the target-specific values. */
2789 oacc_get_fn_dim_size (tree fn
, int axis
)
2791 tree attrs
= oacc_get_fn_attrib (fn
);
2793 gcc_assert (axis
< GOMP_DIM_MAX
);
2795 tree dims
= TREE_VALUE (attrs
);
2797 dims
= TREE_CHAIN (dims
);
2799 int size
= TREE_INT_CST_LOW (TREE_VALUE (dims
));
2804 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
2805 IFN_GOACC_DIM_SIZE call. */
2808 oacc_get_ifn_dim_arg (const gimple
*stmt
)
2810 gcc_checking_assert (gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_SIZE
2811 || gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_POS
);
2812 tree arg
= gimple_call_arg (stmt
, 0);
2813 HOST_WIDE_INT axis
= TREE_INT_CST_LOW (arg
);
2815 gcc_checking_assert (axis
>= 0 && axis
< GOMP_DIM_MAX
);
2819 #include "gt-omp-general.h"