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
;
196 bool order_reproducible
= false;
199 fd
->for_stmt
= for_stmt
;
201 fd
->have_nowait
= distribute
|| simd
;
202 fd
->have_ordered
= false;
203 fd
->have_reductemp
= false;
204 fd
->have_pointer_condtemp
= false;
205 fd
->have_scantemp
= false;
206 fd
->have_nonctrl_scantemp
= false;
207 fd
->non_rect
= false;
208 fd
->lastprivate_conditional
= 0;
209 fd
->tiling
= NULL_TREE
;
212 fd
->first_nonrect
= -1;
213 fd
->last_nonrect
= -1;
214 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
215 fd
->sched_modifiers
= 0;
216 fd
->chunk_size
= NULL_TREE
;
217 fd
->simd_schedule
= false;
218 fd
->first_inner_iterations
= NULL_TREE
;
219 fd
->factor
= NULL_TREE
;
220 fd
->adjn1
= NULL_TREE
;
221 collapse_iter
= NULL
;
222 collapse_count
= NULL
;
224 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
225 switch (OMP_CLAUSE_CODE (t
))
227 case OMP_CLAUSE_NOWAIT
:
228 fd
->have_nowait
= true;
230 case OMP_CLAUSE_ORDERED
:
231 fd
->have_ordered
= true;
232 if (OMP_CLAUSE_ORDERED_EXPR (t
))
233 fd
->ordered
= tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t
));
235 case OMP_CLAUSE_SCHEDULE
:
236 gcc_assert (!distribute
&& !taskloop
);
238 = (enum omp_clause_schedule_kind
)
239 (OMP_CLAUSE_SCHEDULE_KIND (t
) & OMP_CLAUSE_SCHEDULE_MASK
);
240 fd
->sched_modifiers
= (OMP_CLAUSE_SCHEDULE_KIND (t
)
241 & ~OMP_CLAUSE_SCHEDULE_MASK
);
242 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
243 fd
->simd_schedule
= OMP_CLAUSE_SCHEDULE_SIMD (t
);
245 case OMP_CLAUSE_DIST_SCHEDULE
:
246 gcc_assert (distribute
);
247 fd
->chunk_size
= OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t
);
249 case OMP_CLAUSE_COLLAPSE
:
250 fd
->collapse
= tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t
));
251 if (fd
->collapse
> 1)
253 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
254 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
257 case OMP_CLAUSE_TILE
:
258 fd
->tiling
= OMP_CLAUSE_TILE_LIST (t
);
259 fd
->collapse
= list_length (fd
->tiling
);
260 gcc_assert (fd
->collapse
);
261 collapse_iter
= &OMP_CLAUSE_TILE_ITERVAR (t
);
262 collapse_count
= &OMP_CLAUSE_TILE_COUNT (t
);
264 case OMP_CLAUSE__REDUCTEMP_
:
265 fd
->have_reductemp
= true;
267 case OMP_CLAUSE_LASTPRIVATE
:
268 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t
))
269 fd
->lastprivate_conditional
++;
271 case OMP_CLAUSE__CONDTEMP_
:
272 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t
))))
273 fd
->have_pointer_condtemp
= true;
275 case OMP_CLAUSE__SCANTEMP_
:
276 fd
->have_scantemp
= true;
277 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t
)
278 && !OMP_CLAUSE__SCANTEMP__CONTROL (t
))
279 fd
->have_nonctrl_scantemp
= true;
281 case OMP_CLAUSE_ORDER
:
282 /* FIXME: For OpenMP 5.2 this should change to
283 if (OMP_CLAUSE_ORDER_REPRODUCIBLE (t))
284 (with the exception of loop construct but that lowers to
285 no schedule/dist_schedule clauses currently). */
286 if (!OMP_CLAUSE_ORDER_UNCONSTRAINED (t
))
287 order_reproducible
= true;
292 /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
293 we have either the option to expensively remember at runtime how we've
294 distributed work from first loop and reuse that in following loops with
295 the same number of iterations and schedule, or just force static schedule.
296 OpenMP API calls etc. aren't allowed in order(concurrent) bodies so
297 users can't observe it easily anyway. */
298 if (order_reproducible
)
299 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
300 if (fd
->collapse
> 1 || fd
->tiling
)
303 fd
->loops
= &fd
->loop
;
305 if (fd
->ordered
&& fd
->collapse
== 1 && loops
!= NULL
)
310 collapse_iter
= &iterv
;
311 collapse_count
= &countv
;
314 /* FIXME: for now map schedule(auto) to schedule(static).
315 There should be analysis to determine whether all iterations
316 are approximately the same amount of work (then schedule(static)
317 is best) or if it varies (then schedule(dynamic,N) is better). */
318 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
320 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
321 gcc_assert (fd
->chunk_size
== NULL
);
323 gcc_assert ((fd
->collapse
== 1 && !fd
->tiling
) || collapse_iter
!= NULL
);
325 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_RUNTIME
;
326 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
327 gcc_assert (fd
->chunk_size
== NULL
);
328 else if (fd
->chunk_size
== NULL
)
330 /* We only need to compute a default chunk size for ordered
331 static loops and dynamic loops. */
332 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
334 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
335 ? integer_zero_node
: integer_one_node
;
338 int cnt
= fd
->ordered
? fd
->ordered
: fd
->collapse
;
339 int single_nonrect
= -1;
340 tree single_nonrect_count
= NULL_TREE
;
341 enum tree_code single_nonrect_cond_code
= ERROR_MARK
;
342 for (i
= 1; i
< cnt
; i
++)
344 tree n1
= gimple_omp_for_initial (for_stmt
, i
);
345 tree n2
= gimple_omp_for_final (for_stmt
, i
);
346 if (TREE_CODE (n1
) == TREE_VEC
)
353 for (int j
= i
- 1; j
>= 0; j
--)
354 if (TREE_VEC_ELT (n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
361 else if (TREE_CODE (n2
) == TREE_VEC
)
368 for (int j
= i
- 1; j
>= 0; j
--)
369 if (TREE_VEC_ELT (n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
377 for (i
= 0; i
< cnt
; i
++)
382 && (fd
->ordered
== 0 || loops
== NULL
))
384 else if (loops
!= NULL
)
389 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
390 gcc_assert (SSA_VAR_P (loop
->v
));
391 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
392 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
393 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
394 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
395 loop
->m1
= NULL_TREE
;
396 loop
->m2
= NULL_TREE
;
398 loop
->non_rect_referenced
= false;
399 if (TREE_CODE (loop
->n1
) == TREE_VEC
)
401 for (int j
= i
- 1; j
>= 0; j
--)
402 if (TREE_VEC_ELT (loop
->n1
, 0) == gimple_omp_for_index (for_stmt
, j
))
406 loops
[j
].non_rect_referenced
= true;
407 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
408 fd
->first_nonrect
= j
;
411 gcc_assert (loop
->outer
);
412 loop
->m1
= TREE_VEC_ELT (loop
->n1
, 1);
413 loop
->n1
= TREE_VEC_ELT (loop
->n1
, 2);
415 fd
->last_nonrect
= i
;
418 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
419 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
420 gcc_assert (loop
->cond_code
!= NE_EXPR
421 || (gimple_omp_for_kind (for_stmt
)
422 != GF_OMP_FOR_KIND_OACC_LOOP
));
423 if (TREE_CODE (loop
->n2
) == TREE_VEC
)
426 gcc_assert (TREE_VEC_ELT (loop
->n2
, 0)
427 == gimple_omp_for_index (for_stmt
, i
- loop
->outer
));
429 for (int j
= i
- 1; j
>= 0; j
--)
430 if (TREE_VEC_ELT (loop
->n2
, 0) == gimple_omp_for_index (for_stmt
, j
))
434 loops
[j
].non_rect_referenced
= true;
435 if (fd
->first_nonrect
== -1 || fd
->first_nonrect
> j
)
436 fd
->first_nonrect
= j
;
439 gcc_assert (loop
->outer
);
440 loop
->m2
= TREE_VEC_ELT (loop
->n2
, 1);
441 loop
->n2
= TREE_VEC_ELT (loop
->n2
, 2);
443 fd
->last_nonrect
= i
;
446 t
= gimple_omp_for_incr (for_stmt
, i
);
447 gcc_assert (TREE_OPERAND (t
, 0) == var
);
448 loop
->step
= omp_get_for_step_from_incr (loc
, t
);
450 omp_adjust_for_condition (loc
, &loop
->cond_code
, &loop
->n2
, loop
->v
,
454 || (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
455 && !fd
->have_ordered
))
457 if (fd
->collapse
== 1 && !fd
->tiling
)
458 iter_type
= TREE_TYPE (loop
->v
);
460 || TYPE_PRECISION (iter_type
)
461 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
463 = build_nonstandard_integer_type
464 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
466 else if (iter_type
!= long_long_unsigned_type_node
)
468 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
469 iter_type
= long_long_unsigned_type_node
;
470 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
471 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
472 >= TYPE_PRECISION (iter_type
))
476 if (loop
->cond_code
== LT_EXPR
)
477 n
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
478 loop
->n2
, loop
->step
);
483 || TREE_CODE (n
) != INTEGER_CST
484 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
485 iter_type
= long_long_unsigned_type_node
;
487 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
488 > TYPE_PRECISION (iter_type
))
492 if (loop
->cond_code
== LT_EXPR
)
495 n2
= fold_build2_loc (loc
, PLUS_EXPR
, TREE_TYPE (loop
->v
),
496 loop
->n2
, loop
->step
);
500 n1
= fold_build2_loc (loc
, MINUS_EXPR
, TREE_TYPE (loop
->v
),
501 loop
->n2
, loop
->step
);
506 || TREE_CODE (n1
) != INTEGER_CST
507 || TREE_CODE (n2
) != INTEGER_CST
508 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
509 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
510 iter_type
= long_long_unsigned_type_node
;
514 if (i
>= fd
->collapse
)
517 if (collapse_count
&& *collapse_count
== NULL
)
519 if (count
&& integer_zerop (count
))
521 tree n1first
= NULL_TREE
, n2first
= NULL_TREE
;
522 tree n1last
= NULL_TREE
, n2last
= NULL_TREE
;
523 tree ostep
= NULL_TREE
;
524 if (loop
->m1
|| loop
->m2
)
526 if (count
== NULL_TREE
)
528 if (single_nonrect
== -1
529 || (loop
->m1
&& TREE_CODE (loop
->m1
) != INTEGER_CST
)
530 || (loop
->m2
&& TREE_CODE (loop
->m2
) != INTEGER_CST
)
531 || TREE_CODE (loop
->n1
) != INTEGER_CST
532 || TREE_CODE (loop
->n2
) != INTEGER_CST
533 || TREE_CODE (loop
->step
) != INTEGER_CST
)
538 tree var
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
539 tree itype
= TREE_TYPE (var
);
540 tree first
= gimple_omp_for_initial (for_stmt
, single_nonrect
);
541 t
= gimple_omp_for_incr (for_stmt
, single_nonrect
);
542 ostep
= omp_get_for_step_from_incr (loc
, t
);
543 t
= fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
544 single_nonrect_count
,
545 build_one_cst (long_long_unsigned_type_node
));
546 t
= fold_convert (itype
, t
);
547 first
= fold_convert (itype
, first
);
548 ostep
= fold_convert (itype
, ostep
);
549 tree last
= fold_binary (PLUS_EXPR
, itype
, first
,
550 fold_binary (MULT_EXPR
, itype
, t
,
552 if (TREE_CODE (first
) != INTEGER_CST
553 || TREE_CODE (last
) != INTEGER_CST
)
560 tree m1
= fold_convert (itype
, loop
->m1
);
561 tree n1
= fold_convert (itype
, loop
->n1
);
562 n1first
= fold_binary (PLUS_EXPR
, itype
,
563 fold_binary (MULT_EXPR
, itype
,
565 n1last
= fold_binary (PLUS_EXPR
, itype
,
566 fold_binary (MULT_EXPR
, itype
,
570 n1first
= n1last
= loop
->n1
;
573 tree n2
= fold_convert (itype
, loop
->n2
);
574 tree m2
= fold_convert (itype
, loop
->m2
);
575 n2first
= fold_binary (PLUS_EXPR
, itype
,
576 fold_binary (MULT_EXPR
, itype
,
578 n2last
= fold_binary (PLUS_EXPR
, itype
,
579 fold_binary (MULT_EXPR
, itype
,
583 n2first
= n2last
= loop
->n2
;
584 n1first
= fold_convert (TREE_TYPE (loop
->v
), n1first
);
585 n2first
= fold_convert (TREE_TYPE (loop
->v
), n2first
);
586 n1last
= fold_convert (TREE_TYPE (loop
->v
), n1last
);
587 n2last
= fold_convert (TREE_TYPE (loop
->v
), n2last
);
588 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
590 tree t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
592 if (t
&& t2
&& integer_nonzerop (t
) && integer_nonzerop (t2
))
593 /* All outer loop iterators have at least one inner loop
594 iteration. Try to compute the count at compile time. */
596 else if (t
&& t2
&& integer_zerop (t
) && integer_zerop (t2
))
597 /* No iterations of the inner loop. count will be set to
599 else if (TYPE_UNSIGNED (itype
)
602 || TREE_CODE (t
) != INTEGER_CST
603 || TREE_CODE (t2
) != INTEGER_CST
)
605 /* Punt (for now). */
611 /* Some iterations of the outer loop have zero iterations
612 of the inner loop, while others have at least one.
613 In this case, we need to adjust one of those outer
614 loop bounds. If ADJ_FIRST, we need to adjust outer n1
615 (first), otherwise outer n2 (last). */
616 bool adj_first
= integer_zerop (t
);
617 tree n1
= fold_convert (itype
, loop
->n1
);
618 tree n2
= fold_convert (itype
, loop
->n2
);
619 tree m1
= loop
->m1
? fold_convert (itype
, loop
->m1
)
620 : build_zero_cst (itype
);
621 tree m2
= loop
->m2
? fold_convert (itype
, loop
->m2
)
622 : build_zero_cst (itype
);
623 t
= fold_binary (MINUS_EXPR
, itype
, n1
, n2
);
624 t2
= fold_binary (MINUS_EXPR
, itype
, m2
, m1
);
625 t
= fold_binary (TRUNC_DIV_EXPR
, itype
, t
, t2
);
626 t2
= fold_binary (MINUS_EXPR
, itype
, t
, first
);
627 t2
= fold_binary (TRUNC_MOD_EXPR
, itype
, t2
, ostep
);
628 t
= fold_binary (MINUS_EXPR
, itype
, t
, t2
);
630 = fold_binary (PLUS_EXPR
, itype
, n1
,
631 fold_binary (MULT_EXPR
, itype
, m1
, t
));
633 = fold_binary (PLUS_EXPR
, itype
, n2
,
634 fold_binary (MULT_EXPR
, itype
, m2
, t
));
635 t2
= fold_binary (loop
->cond_code
, boolean_type_node
,
637 tree t3
= fold_binary (MULT_EXPR
, itype
, m1
, ostep
);
638 tree t4
= fold_binary (MULT_EXPR
, itype
, m2
, ostep
);
643 if (integer_nonzerop (t2
))
650 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
651 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
652 t3
= fold_binary (loop
->cond_code
,
653 boolean_type_node
, t3
, t4
);
654 gcc_assert (integer_zerop (t3
));
659 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
660 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
661 new_first
= fold_binary (PLUS_EXPR
, itype
, t
, ostep
);
666 t3
= fold_binary (loop
->cond_code
,
667 boolean_type_node
, t3
, t4
);
668 gcc_assert (integer_nonzerop (t3
));
671 diff
= fold_binary (MINUS_EXPR
, itype
, new_first
, first
);
678 if (integer_zerop (t2
))
680 t3
= fold_binary (MINUS_EXPR
, itype
, n1cur
, t3
);
681 t4
= fold_binary (MINUS_EXPR
, itype
, n2cur
, t4
);
682 new_last
= fold_binary (MINUS_EXPR
, itype
, t
, ostep
);
687 t3
= fold_binary (loop
->cond_code
,
688 boolean_type_node
, t3
, t4
);
689 gcc_assert (integer_nonzerop (t3
));
699 t3
= fold_binary (PLUS_EXPR
, itype
, n1cur
, t3
);
700 t4
= fold_binary (PLUS_EXPR
, itype
, n2cur
, t4
);
701 t3
= fold_binary (loop
->cond_code
,
702 boolean_type_node
, t3
, t4
);
703 gcc_assert (integer_zerop (t3
));
706 diff
= fold_binary (MINUS_EXPR
, itype
, last
, new_last
);
708 if (TYPE_UNSIGNED (itype
)
709 && single_nonrect_cond_code
== GT_EXPR
)
710 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
,
711 fold_unary (NEGATE_EXPR
, itype
, diff
),
712 fold_unary (NEGATE_EXPR
, itype
,
715 diff
= fold_binary (TRUNC_DIV_EXPR
, itype
, diff
, ostep
);
716 diff
= fold_convert (long_long_unsigned_type_node
, diff
);
718 = fold_binary (MINUS_EXPR
, long_long_unsigned_type_node
,
719 single_nonrect_count
, diff
);
724 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
725 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
726 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
727 if (t
&& integer_zerop (t
))
728 count
= build_zero_cst (long_long_unsigned_type_node
);
729 else if ((i
== 0 || count
!= NULL_TREE
)
730 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
731 && TREE_CONSTANT (loop
->n1
)
732 && TREE_CONSTANT (loop
->n2
)
733 && TREE_CODE (loop
->step
) == INTEGER_CST
)
735 tree itype
= TREE_TYPE (loop
->v
);
737 if (POINTER_TYPE_P (itype
))
738 itype
= signed_type_for (itype
);
739 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
740 t
= fold_build2 (PLUS_EXPR
, itype
,
741 fold_convert (itype
, loop
->step
), t
);
744 if (loop
->m1
|| loop
->m2
)
746 gcc_assert (single_nonrect
!= -1);
750 t
= fold_build2 (PLUS_EXPR
, itype
, t
, fold_convert (itype
, n2
));
751 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, n1
));
752 tree step
= fold_convert_loc (loc
, itype
, loop
->step
);
753 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
754 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
755 fold_build1 (NEGATE_EXPR
, itype
, t
),
756 fold_build1 (NEGATE_EXPR
, itype
, step
));
758 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, step
);
759 tree llutype
= long_long_unsigned_type_node
;
760 t
= fold_convert (llutype
, t
);
761 if (loop
->m1
|| loop
->m2
)
763 /* t is number of iterations of inner loop at either first
764 or last value of the outer iterator (the one with fewer
766 Compute t2 = ((m2 - m1) * ostep) / step
767 and niters = outer_count * t
768 + t2 * ((outer_count - 1) * outer_count / 2)
770 tree m1
= loop
->m1
? loop
->m1
: integer_zero_node
;
771 tree m2
= loop
->m2
? loop
->m2
: integer_zero_node
;
772 m1
= fold_convert (itype
, m1
);
773 m2
= fold_convert (itype
, m2
);
774 tree t2
= fold_build2 (MINUS_EXPR
, itype
, m2
, m1
);
775 t2
= fold_build2 (MULT_EXPR
, itype
, t2
, ostep
);
776 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
777 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
778 fold_build1 (NEGATE_EXPR
, itype
, t2
),
779 fold_build1 (NEGATE_EXPR
, itype
, step
));
781 t2
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t2
, step
);
782 t2
= fold_convert (llutype
, t2
);
783 fd
->first_inner_iterations
= t
;
785 t
= fold_build2 (MULT_EXPR
, llutype
, t
,
786 single_nonrect_count
);
787 tree t3
= fold_build2 (MINUS_EXPR
, llutype
,
788 single_nonrect_count
,
789 build_one_cst (llutype
));
790 t3
= fold_build2 (MULT_EXPR
, llutype
, t3
,
791 single_nonrect_count
);
792 t3
= fold_build2 (TRUNC_DIV_EXPR
, llutype
, t3
,
793 build_int_cst (llutype
, 2));
794 t2
= fold_build2 (MULT_EXPR
, llutype
, t2
, t3
);
795 t
= fold_build2 (PLUS_EXPR
, llutype
, t
, t2
);
797 if (i
== single_nonrect
)
799 if (integer_zerop (t
) || TREE_CODE (t
) != INTEGER_CST
)
803 single_nonrect_count
= t
;
804 single_nonrect_cond_code
= loop
->cond_code
;
805 if (count
== NULL_TREE
)
806 count
= build_one_cst (llutype
);
809 else if (count
!= NULL_TREE
)
810 count
= fold_build2 (MULT_EXPR
, llutype
, count
, t
);
813 if (TREE_CODE (count
) != INTEGER_CST
)
816 else if (count
&& !integer_zerop (count
))
823 && (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
824 || fd
->have_ordered
))
826 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
827 iter_type
= long_long_unsigned_type_node
;
829 iter_type
= long_integer_type_node
;
831 else if (collapse_iter
&& *collapse_iter
!= NULL
)
832 iter_type
= TREE_TYPE (*collapse_iter
);
833 fd
->iter_type
= iter_type
;
834 if (collapse_iter
&& *collapse_iter
== NULL
)
835 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
836 if (collapse_count
&& *collapse_count
== NULL
)
840 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
841 if (fd
->first_inner_iterations
&& fd
->factor
)
843 t
= make_tree_vec (4);
844 TREE_VEC_ELT (t
, 0) = *collapse_count
;
845 TREE_VEC_ELT (t
, 1) = fd
->first_inner_iterations
;
846 TREE_VEC_ELT (t
, 2) = fd
->factor
;
847 TREE_VEC_ELT (t
, 3) = fd
->adjn1
;
852 *collapse_count
= create_tmp_var (iter_type
, ".count");
855 if (fd
->collapse
> 1 || fd
->tiling
|| (fd
->ordered
&& loops
))
857 fd
->loop
.v
= *collapse_iter
;
858 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
859 fd
->loop
.n2
= *collapse_count
;
860 if (TREE_CODE (fd
->loop
.n2
) == TREE_VEC
)
862 gcc_assert (fd
->non_rect
);
863 fd
->first_inner_iterations
= TREE_VEC_ELT (fd
->loop
.n2
, 1);
864 fd
->factor
= TREE_VEC_ELT (fd
->loop
.n2
, 2);
865 fd
->adjn1
= TREE_VEC_ELT (fd
->loop
.n2
, 3);
866 fd
->loop
.n2
= TREE_VEC_ELT (fd
->loop
.n2
, 0);
868 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
869 fd
->loop
.m1
= NULL_TREE
;
870 fd
->loop
.m2
= NULL_TREE
;
872 fd
->loop
.cond_code
= LT_EXPR
;
878 /* Build a call to GOMP_barrier. */
881 omp_build_barrier (tree lhs
)
883 tree fndecl
= builtin_decl_explicit (lhs
? BUILT_IN_GOMP_BARRIER_CANCEL
884 : BUILT_IN_GOMP_BARRIER
);
885 gcall
*g
= gimple_build_call (fndecl
, 0);
887 gimple_call_set_lhs (g
, lhs
);
891 /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
892 array, pdata[0] non-NULL if there is anything non-trivial in between,
893 pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
894 of OMP_FOR in between if any and pdata[3] is address of the inner
898 find_combined_omp_for (tree
*tp
, int *walk_subtrees
, void *data
)
900 tree
**pdata
= (tree
**) data
;
902 switch (TREE_CODE (*tp
))
905 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
914 if (OMP_FOR_INIT (*tp
) != NULL_TREE
)
921 if (BIND_EXPR_VARS (*tp
)
922 || (BIND_EXPR_BLOCK (*tp
)
923 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp
))))
928 if (!tsi_one_before_end_p (tsi_start (*tp
)))
932 case TRY_FINALLY_EXPR
:
946 /* Return maximum possible vectorization factor for the target. */
953 || !flag_tree_loop_optimize
954 || (!flag_tree_loop_vectorize
955 && global_options_set
.x_flag_tree_loop_vectorize
))
958 auto_vector_modes modes
;
959 targetm
.vectorize
.autovectorize_vector_modes (&modes
, true);
960 if (!modes
.is_empty ())
963 for (unsigned int i
= 0; i
< modes
.length (); ++i
)
964 /* The returned modes use the smallest element size (and thus
965 the largest nunits) for the vectorization approach that they
967 vf
= ordered_max (vf
, GET_MODE_NUNITS (modes
[i
]));
971 machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
972 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
973 return GET_MODE_NUNITS (vqimode
);
978 /* Return maximum SIMT width if offloading may target SIMT hardware. */
981 omp_max_simt_vf (void)
985 if (ENABLE_OFFLOADING
)
986 for (const char *c
= getenv ("OFFLOAD_TARGET_NAMES"); c
;)
988 if (startswith (c
, "nvptx"))
990 else if ((c
= strchr (c
, ':')))
996 /* Store the construct selectors as tree codes from last to first,
997 return their number. */
1000 omp_constructor_traits_to_codes (tree ctx
, enum tree_code
*constructs
)
1002 int nconstructs
= list_length (ctx
);
1003 int i
= nconstructs
- 1;
1004 for (tree t2
= ctx
; t2
; t2
= TREE_CHAIN (t2
), i
--)
1006 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
1007 if (!strcmp (sel
, "target"))
1008 constructs
[i
] = OMP_TARGET
;
1009 else if (!strcmp (sel
, "teams"))
1010 constructs
[i
] = OMP_TEAMS
;
1011 else if (!strcmp (sel
, "parallel"))
1012 constructs
[i
] = OMP_PARALLEL
;
1013 else if (!strcmp (sel
, "for") || !strcmp (sel
, "do"))
1014 constructs
[i
] = OMP_FOR
;
1015 else if (!strcmp (sel
, "simd"))
1016 constructs
[i
] = OMP_SIMD
;
1020 gcc_assert (i
== -1);
1024 /* Return true if PROP is possibly present in one of the offloading target's
1025 OpenMP contexts. The format of PROPS string is always offloading target's
1026 name terminated by '\0', followed by properties for that offloading
1027 target separated by '\0' and terminated by another '\0'. The strings
1028 are created from omp-device-properties installed files of all configured
1029 offloading targets. */
1032 omp_offload_device_kind_arch_isa (const char *props
, const char *prop
)
1034 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1035 if (names
== NULL
|| *names
== '\0')
1037 while (*props
!= '\0')
1039 size_t name_len
= strlen (props
);
1040 bool matches
= false;
1041 for (const char *c
= names
; c
; )
1043 if (strncmp (props
, c
, name_len
) == 0
1044 && (c
[name_len
] == '\0'
1045 || c
[name_len
] == ':'
1046 || c
[name_len
] == '='))
1051 else if ((c
= strchr (c
, ':')))
1054 props
= props
+ name_len
+ 1;
1055 while (*props
!= '\0')
1057 if (matches
&& strcmp (props
, prop
) == 0)
1059 props
= strchr (props
, '\0') + 1;
1066 /* Return true if the current code location is or might be offloaded.
1067 Return true in declare target functions, or when nested in a target
1068 region or when unsure, return false otherwise. */
1071 omp_maybe_offloaded (void)
1073 if (!ENABLE_OFFLOADING
)
1075 const char *names
= getenv ("OFFLOAD_TARGET_NAMES");
1076 if (names
== NULL
|| *names
== '\0')
1079 if (symtab
->state
== PARSING
)
1082 if (cfun
&& cfun
->after_inlining
)
1084 if (current_function_decl
1085 && lookup_attribute ("omp declare target",
1086 DECL_ATTRIBUTES (current_function_decl
)))
1088 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) == 0)
1090 enum tree_code construct
= OMP_TARGET
;
1091 if (omp_construct_selector_matches (&construct
, 1, NULL
))
1097 /* Return a name from PROP, a property in selectors accepting
1101 omp_context_name_list_prop (tree prop
)
1103 if (TREE_PURPOSE (prop
))
1104 return IDENTIFIER_POINTER (TREE_PURPOSE (prop
));
1107 const char *ret
= TREE_STRING_POINTER (TREE_VALUE (prop
));
1108 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop
)) == strlen (ret
) + 1)
1114 /* Return 1 if context selector matches the current OpenMP context, 0
1115 if it does not and -1 if it is unknown and need to be determined later.
1116 Some properties can be checked right away during parsing (this routine),
1117 others need to wait until the whole TU is parsed, others need to wait until
1118 IPA, others until vectorization. */
1121 omp_context_selector_matches (tree ctx
)
1124 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1126 char set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
))[0];
1129 /* For now, ignore the construct set. While something can be
1130 determined already during parsing, we don't know until end of TU
1131 whether additional constructs aren't added through declare variant
1132 unless "omp declare variant variant" attribute exists already
1133 (so in most of the cases), and we'd need to maintain set of
1134 surrounding OpenMP constructs, which is better handled during
1136 if (symtab
->state
== PARSING
)
1142 enum tree_code constructs
[5];
1144 = omp_constructor_traits_to_codes (TREE_VALUE (t1
), constructs
);
1146 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1148 if (!cfun
->after_inlining
)
1154 for (i
= 0; i
< nconstructs
; ++i
)
1155 if (constructs
[i
] == OMP_SIMD
)
1157 if (i
< nconstructs
)
1162 /* If there is no simd, assume it is ok after IPA,
1163 constructs should have been checked before. */
1167 int r
= omp_construct_selector_matches (constructs
, nconstructs
,
1175 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1177 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t2
));
1181 if (set
== 'i' && !strcmp (sel
, "vendor"))
1182 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1184 const char *prop
= omp_context_name_list_prop (t3
);
1187 if ((!strcmp (prop
, " score") && TREE_PURPOSE (t3
))
1188 || !strcmp (prop
, "gnu"))
1194 if (set
== 'i' && !strcmp (sel
, "extension"))
1195 /* We don't support any extensions right now. */
1199 if (set
== 'i' && !strcmp (sel
, "atomic_default_mem_order"))
1201 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1204 enum omp_memory_order omo
1205 = ((enum omp_memory_order
)
1207 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER
));
1208 if (omo
== OMP_MEMORY_ORDER_UNSPECIFIED
)
1210 /* We don't know yet, until end of TU. */
1211 if (symtab
->state
== PARSING
)
1217 omo
= OMP_MEMORY_ORDER_RELAXED
;
1219 tree t3
= TREE_VALUE (t2
);
1220 const char *prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1221 if (!strcmp (prop
, " score"))
1223 t3
= TREE_CHAIN (t3
);
1224 prop
= IDENTIFIER_POINTER (TREE_PURPOSE (t3
));
1226 if (!strcmp (prop
, "relaxed")
1227 && omo
!= OMP_MEMORY_ORDER_RELAXED
)
1229 else if (!strcmp (prop
, "seq_cst")
1230 && omo
!= OMP_MEMORY_ORDER_SEQ_CST
)
1232 else if (!strcmp (prop
, "acq_rel")
1233 && omo
!= OMP_MEMORY_ORDER_ACQ_REL
)
1236 if (set
== 'd' && !strcmp (sel
, "arch"))
1237 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1239 const char *arch
= omp_context_name_list_prop (t3
);
1243 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1244 r
= targetm
.omp
.device_kind_arch_isa (omp_device_arch
,
1246 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1248 /* If we are or might be in a target region or
1249 declare target function, need to take into account
1250 also offloading values. */
1251 if (!omp_maybe_offloaded ())
1253 if (ENABLE_OFFLOADING
)
1255 const char *arches
= omp_offload_device_arch
;
1256 if (omp_offload_device_kind_arch_isa (arches
,
1267 /* If arch matches on the host, it still might not match
1268 in the offloading region. */
1269 else if (omp_maybe_offloaded ())
1274 if (set
== 'i' && !strcmp (sel
, "unified_address"))
1276 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1279 if ((omp_requires_mask
& OMP_REQUIRES_UNIFIED_ADDRESS
) == 0)
1281 if (symtab
->state
== PARSING
)
1288 if (set
== 'i' && !strcmp (sel
, "unified_shared_memory"))
1290 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1293 if ((omp_requires_mask
1294 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY
) == 0)
1296 if (symtab
->state
== PARSING
)
1305 if (set
== 'i' && !strcmp (sel
, "dynamic_allocators"))
1307 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1310 if ((omp_requires_mask
1311 & OMP_REQUIRES_DYNAMIC_ALLOCATORS
) == 0)
1313 if (symtab
->state
== PARSING
)
1322 if (set
== 'i' && !strcmp (sel
, "reverse_offload"))
1324 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
1327 if ((omp_requires_mask
& OMP_REQUIRES_REVERSE_OFFLOAD
) == 0)
1329 if (symtab
->state
== PARSING
)
1338 if (set
== 'd' && !strcmp (sel
, "kind"))
1339 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1341 const char *prop
= omp_context_name_list_prop (t3
);
1344 if (!strcmp (prop
, "any"))
1346 if (!strcmp (prop
, "host"))
1348 if (omp_maybe_offloaded ())
1352 if (!strcmp (prop
, "nohost"))
1354 if (omp_maybe_offloaded ())
1361 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1362 r
= targetm
.omp
.device_kind_arch_isa (omp_device_kind
,
1365 r
= strcmp (prop
, "cpu") == 0;
1366 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1368 /* If we are or might be in a target region or
1369 declare target function, need to take into account
1370 also offloading values. */
1371 if (!omp_maybe_offloaded ())
1373 if (ENABLE_OFFLOADING
)
1375 const char *kinds
= omp_offload_device_kind
;
1376 if (omp_offload_device_kind_arch_isa (kinds
, prop
))
1386 /* If kind matches on the host, it still might not match
1387 in the offloading region. */
1388 else if (omp_maybe_offloaded ())
1393 if (set
== 'd' && !strcmp (sel
, "isa"))
1394 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1396 const char *isa
= omp_context_name_list_prop (t3
);
1400 if (targetm
.omp
.device_kind_arch_isa
!= NULL
)
1401 r
= targetm
.omp
.device_kind_arch_isa (omp_device_isa
,
1403 if (r
== 0 || (r
== -1 && symtab
->state
!= PARSING
))
1405 /* If isa is valid on the target, but not in the
1406 current function and current function has
1407 #pragma omp declare simd on it, some simd clones
1408 might have the isa added later on. */
1410 && targetm
.simd_clone
.compute_vecsize_and_simdlen
1411 && (cfun
== NULL
|| !cfun
->after_inlining
))
1414 = DECL_ATTRIBUTES (current_function_decl
);
1415 if (lookup_attribute ("omp declare simd", attrs
))
1421 /* If we are or might be in a target region or
1422 declare target function, need to take into account
1423 also offloading values. */
1424 if (!omp_maybe_offloaded ())
1426 if (ENABLE_OFFLOADING
)
1428 const char *isas
= omp_offload_device_isa
;
1429 if (omp_offload_device_kind_arch_isa (isas
, isa
))
1439 /* If isa matches on the host, it still might not match
1440 in the offloading region. */
1441 else if (omp_maybe_offloaded ())
1446 if (set
== 'u' && !strcmp (sel
, "condition"))
1447 for (tree t3
= TREE_VALUE (t2
); t3
; t3
= TREE_CHAIN (t3
))
1448 if (TREE_PURPOSE (t3
) == NULL_TREE
)
1450 if (integer_zerop (TREE_VALUE (t3
)))
1452 if (integer_nonzerop (TREE_VALUE (t3
)))
1465 /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1466 in omp_context_selector_set_compare. */
1469 omp_construct_simd_compare (tree clauses1
, tree clauses2
)
1471 if (clauses1
== NULL_TREE
)
1472 return clauses2
== NULL_TREE
? 0 : -1;
1473 if (clauses2
== NULL_TREE
)
1477 struct declare_variant_simd_data
{
1478 bool inbranch
, notinbranch
;
1480 auto_vec
<tree
,16> data_sharing
;
1481 auto_vec
<tree
,16> aligned
;
1482 declare_variant_simd_data ()
1483 : inbranch(false), notinbranch(false), simdlen(NULL_TREE
) {}
1486 for (i
= 0; i
< 2; i
++)
1487 for (tree c
= i
? clauses2
: clauses1
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1490 switch (OMP_CLAUSE_CODE (c
))
1492 case OMP_CLAUSE_INBRANCH
:
1493 data
[i
].inbranch
= true;
1495 case OMP_CLAUSE_NOTINBRANCH
:
1496 data
[i
].notinbranch
= true;
1498 case OMP_CLAUSE_SIMDLEN
:
1499 data
[i
].simdlen
= OMP_CLAUSE_SIMDLEN_EXPR (c
);
1501 case OMP_CLAUSE_UNIFORM
:
1502 case OMP_CLAUSE_LINEAR
:
1503 v
= &data
[i
].data_sharing
;
1505 case OMP_CLAUSE_ALIGNED
:
1506 v
= &data
[i
].aligned
;
1511 unsigned HOST_WIDE_INT argno
= tree_to_uhwi (OMP_CLAUSE_DECL (c
));
1512 if (argno
>= v
->length ())
1513 v
->safe_grow_cleared (argno
+ 1, true);
1516 /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1517 CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1518 doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1519 -1, r == 2 implies 1 and r == 0 implies 0. */
1520 if (data
[0].inbranch
!= data
[1].inbranch
)
1521 r
|= data
[0].inbranch
? 2 : 1;
1522 if (data
[0].notinbranch
!= data
[1].notinbranch
)
1523 r
|= data
[0].notinbranch
? 2 : 1;
1524 if (!simple_cst_equal (data
[0].simdlen
, data
[1].simdlen
))
1526 if (data
[0].simdlen
&& data
[1].simdlen
)
1528 r
|= data
[0].simdlen
? 2 : 1;
1530 if (data
[0].data_sharing
.length () < data
[1].data_sharing
.length ()
1531 || data
[0].aligned
.length () < data
[1].aligned
.length ())
1534 FOR_EACH_VEC_ELT (data
[0].data_sharing
, i
, c1
)
1536 c2
= (i
< data
[1].data_sharing
.length ()
1537 ? data
[1].data_sharing
[i
] : NULL_TREE
);
1538 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1540 r
|= c1
!= NULL_TREE
? 2 : 1;
1543 if (c1
== NULL_TREE
)
1545 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_CODE (c2
))
1547 if (OMP_CLAUSE_CODE (c1
) != OMP_CLAUSE_LINEAR
)
1549 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1
)
1550 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2
))
1552 if (OMP_CLAUSE_LINEAR_KIND (c1
) != OMP_CLAUSE_LINEAR_KIND (c2
))
1554 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1
),
1555 OMP_CLAUSE_LINEAR_STEP (c2
)))
1558 FOR_EACH_VEC_ELT (data
[0].aligned
, i
, c1
)
1560 c2
= i
< data
[1].aligned
.length () ? data
[1].aligned
[i
] : NULL_TREE
;
1561 if ((c1
== NULL_TREE
) != (c2
== NULL_TREE
))
1563 r
|= c1
!= NULL_TREE
? 2 : 1;
1566 if (c1
== NULL_TREE
)
1568 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1
),
1569 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2
)))
1578 default: gcc_unreachable ();
1582 /* Compare properties of selectors SEL from SET other than construct.
1583 Return 0/-1/1/2 as in omp_context_selector_set_compare.
1584 Unlike set names or selector names, properties can have duplicates. */
1587 omp_context_selector_props_compare (const char *set
, const char *sel
,
1588 tree ctx1
, tree ctx2
)
1591 for (int pass
= 0; pass
< 2; pass
++)
1592 for (tree t1
= pass
? ctx2
: ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1595 for (t2
= pass
? ctx1
: ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1596 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1598 if (TREE_PURPOSE (t1
) == NULL_TREE
)
1600 if (set
[0] == 'u' && strcmp (sel
, "condition") == 0)
1602 if (integer_zerop (TREE_VALUE (t1
))
1603 != integer_zerop (TREE_VALUE (t2
)))
1607 if (simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1610 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1
)),
1613 if (!simple_cst_equal (TREE_VALUE (t1
), TREE_VALUE (t2
)))
1620 else if (TREE_PURPOSE (t1
)
1621 && TREE_PURPOSE (t2
) == NULL_TREE
1622 && TREE_CODE (TREE_VALUE (t2
)) == STRING_CST
)
1624 const char *p1
= omp_context_name_list_prop (t1
);
1625 const char *p2
= omp_context_name_list_prop (t2
);
1627 && strcmp (p1
, p2
) == 0
1628 && strcmp (p1
, " score"))
1631 else if (TREE_PURPOSE (t1
) == NULL_TREE
1632 && TREE_PURPOSE (t2
)
1633 && TREE_CODE (TREE_VALUE (t1
)) == STRING_CST
)
1635 const char *p1
= omp_context_name_list_prop (t1
);
1636 const char *p2
= omp_context_name_list_prop (t2
);
1638 && strcmp (p1
, p2
) == 0
1639 && strcmp (p1
, " score"))
1642 if (t2
== NULL_TREE
)
1644 int r
= pass
? -1 : 1;
1645 if (ret
&& ret
!= r
)
1659 /* Compare single context selector sets CTX1 and CTX2 with SET name.
1660 Return 0 if CTX1 is equal to CTX2,
1661 -1 if CTX1 is a strict subset of CTX2,
1662 1 if CTX2 is a strict subset of CTX1, or
1663 2 if neither context is a subset of another one. */
1666 omp_context_selector_set_compare (const char *set
, tree ctx1
, tree ctx2
)
1668 bool swapped
= false;
1670 int len1
= list_length (ctx1
);
1671 int len2
= list_length (ctx2
);
1676 std::swap (ctx1
, ctx2
);
1677 std::swap (len1
, len2
);
1683 tree simd
= get_identifier ("simd");
1684 /* Handle construct set specially. In this case the order
1685 of the selector matters too. */
1686 for (t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1687 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1690 if (TREE_PURPOSE (t1
) == simd
)
1691 r
= omp_construct_simd_compare (TREE_VALUE (t1
),
1693 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1697 t2
= TREE_CHAIN (t2
);
1698 if (t2
== NULL_TREE
)
1700 t1
= TREE_CHAIN (t1
);
1708 if (t2
!= NULL_TREE
)
1710 if (t1
!= NULL_TREE
)
1718 return swapped
? -ret
: ret
;
1720 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1723 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1724 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1726 const char *sel
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1727 int r
= omp_context_selector_props_compare (set
, sel
,
1730 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1737 if (t2
== NULL_TREE
)
1748 return swapped
? -ret
: ret
;
1751 /* Compare whole context selector specification CTX1 and CTX2.
1752 Return 0 if CTX1 is equal to CTX2,
1753 -1 if CTX1 is a strict subset of CTX2,
1754 1 if CTX2 is a strict subset of CTX1, or
1755 2 if neither context is a subset of another one. */
1758 omp_context_selector_compare (tree ctx1
, tree ctx2
)
1760 bool swapped
= false;
1762 int len1
= list_length (ctx1
);
1763 int len2
= list_length (ctx2
);
1768 std::swap (ctx1
, ctx2
);
1769 std::swap (len1
, len2
);
1771 for (tree t1
= ctx1
; t1
; t1
= TREE_CHAIN (t1
))
1774 for (t2
= ctx2
; t2
; t2
= TREE_CHAIN (t2
))
1775 if (TREE_PURPOSE (t1
) == TREE_PURPOSE (t2
))
1777 const char *set
= IDENTIFIER_POINTER (TREE_PURPOSE (t1
));
1778 int r
= omp_context_selector_set_compare (set
, TREE_VALUE (t1
),
1780 if (r
== 2 || (ret
&& r
&& (ret
< 0) != (r
< 0)))
1787 if (t2
== NULL_TREE
)
1798 return swapped
? -ret
: ret
;
1801 /* From context selector CTX, return trait-selector with name SEL in
1802 trait-selector-set with name SET if any, or NULL_TREE if not found.
1803 If SEL is NULL, return the list of trait-selectors in SET. */
1806 omp_get_context_selector (tree ctx
, const char *set
, const char *sel
)
1808 tree setid
= get_identifier (set
);
1809 tree selid
= sel
? get_identifier (sel
) : NULL_TREE
;
1810 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1811 if (TREE_PURPOSE (t1
) == setid
)
1814 return TREE_VALUE (t1
);
1815 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1816 if (TREE_PURPOSE (t2
) == selid
)
1822 /* Compute *SCORE for context selector CTX. Return true if the score
1823 would be different depending on whether it is a declare simd clone or
1824 not. DECLARE_SIMD should be true for the case when it would be
1825 a declare simd clone. */
1828 omp_context_compute_score (tree ctx
, widest_int
*score
, bool declare_simd
)
1830 tree construct
= omp_get_context_selector (ctx
, "construct", NULL
);
1831 bool has_kind
= omp_get_context_selector (ctx
, "device", "kind");
1832 bool has_arch
= omp_get_context_selector (ctx
, "device", "arch");
1833 bool has_isa
= omp_get_context_selector (ctx
, "device", "isa");
1836 for (tree t1
= ctx
; t1
; t1
= TREE_CHAIN (t1
))
1837 if (TREE_VALUE (t1
) != construct
)
1838 for (tree t2
= TREE_VALUE (t1
); t2
; t2
= TREE_CHAIN (t2
))
1839 if (tree t3
= TREE_VALUE (t2
))
1840 if (TREE_PURPOSE (t3
)
1841 && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3
)), " score") == 0
1842 && TREE_CODE (TREE_VALUE (t3
)) == INTEGER_CST
)
1843 *score
+= wi::to_widest (TREE_VALUE (t3
));
1844 if (construct
|| has_kind
|| has_arch
|| has_isa
)
1847 enum tree_code constructs
[5];
1848 int nconstructs
= 0;
1850 nconstructs
= omp_constructor_traits_to_codes (construct
, constructs
);
1851 if (omp_construct_selector_matches (constructs
, nconstructs
, scores
)
1854 int b
= declare_simd
? nconstructs
+ 1 : 0;
1855 if (scores
[b
+ nconstructs
] + 4U < score
->get_precision ())
1857 for (int n
= 0; n
< nconstructs
; ++n
)
1859 if (scores
[b
+ n
] < 0)
1864 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ n
], 1, false);
1867 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
],
1870 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 1,
1873 *score
+= wi::shifted_mask
<widest_int
> (scores
[b
+ nconstructs
] + 2,
1876 else /* FIXME: Implement this. */
1882 /* Class describing a single variant. */
1883 struct GTY(()) omp_declare_variant_entry
{
1884 /* NODE of the variant. */
1885 cgraph_node
*variant
;
1886 /* Score if not in declare simd clone. */
1888 /* Score if in declare simd clone. */
1889 widest_int score_in_declare_simd_clone
;
1890 /* Context selector for the variant. */
1892 /* True if the context selector is known to match already. */
1896 /* Class describing a function with variants. */
1897 struct GTY((for_user
)) omp_declare_variant_base_entry
{
1898 /* NODE of the base function. */
1900 /* NODE of the artificial function created for the deferred variant
1903 /* Vector of the variants. */
1904 vec
<omp_declare_variant_entry
, va_gc
> *variants
;
1907 struct omp_declare_variant_hasher
1908 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1909 static hashval_t
hash (omp_declare_variant_base_entry
*);
1910 static bool equal (omp_declare_variant_base_entry
*,
1911 omp_declare_variant_base_entry
*);
1915 omp_declare_variant_hasher::hash (omp_declare_variant_base_entry
*x
)
1917 inchash::hash hstate
;
1918 hstate
.add_int (DECL_UID (x
->base
->decl
));
1919 hstate
.add_int (x
->variants
->length ());
1920 omp_declare_variant_entry
*variant
;
1922 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1924 hstate
.add_int (DECL_UID (variant
->variant
->decl
));
1925 hstate
.add_wide_int (variant
->score
);
1926 hstate
.add_wide_int (variant
->score_in_declare_simd_clone
);
1927 hstate
.add_ptr (variant
->ctx
);
1928 hstate
.add_int (variant
->matches
);
1930 return hstate
.end ();
1934 omp_declare_variant_hasher::equal (omp_declare_variant_base_entry
*x
,
1935 omp_declare_variant_base_entry
*y
)
1937 if (x
->base
!= y
->base
1938 || x
->variants
->length () != y
->variants
->length ())
1940 omp_declare_variant_entry
*variant
;
1942 FOR_EACH_VEC_SAFE_ELT (x
->variants
, i
, variant
)
1943 if (variant
->variant
!= (*y
->variants
)[i
].variant
1944 || variant
->score
!= (*y
->variants
)[i
].score
1945 || (variant
->score_in_declare_simd_clone
1946 != (*y
->variants
)[i
].score_in_declare_simd_clone
)
1947 || variant
->ctx
!= (*y
->variants
)[i
].ctx
1948 || variant
->matches
!= (*y
->variants
)[i
].matches
)
1953 static GTY(()) hash_table
<omp_declare_variant_hasher
> *omp_declare_variants
;
1955 struct omp_declare_variant_alt_hasher
1956 : ggc_ptr_hash
<omp_declare_variant_base_entry
> {
1957 static hashval_t
hash (omp_declare_variant_base_entry
*);
1958 static bool equal (omp_declare_variant_base_entry
*,
1959 omp_declare_variant_base_entry
*);
1963 omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry
*x
)
1965 return DECL_UID (x
->node
->decl
);
1969 omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry
*x
,
1970 omp_declare_variant_base_entry
*y
)
1972 return x
->node
== y
->node
;
1975 static GTY(()) hash_table
<omp_declare_variant_alt_hasher
>
1976 *omp_declare_variant_alt
;
1978 /* Try to resolve declare variant after gimplification. */
1981 omp_resolve_late_declare_variant (tree alt
)
1983 cgraph_node
*node
= cgraph_node::get (alt
);
1984 cgraph_node
*cur_node
= cgraph_node::get (cfun
->decl
);
1986 || !node
->declare_variant_alt
1987 || !cfun
->after_inlining
)
1990 omp_declare_variant_base_entry entry
;
1993 entry
.variants
= NULL
;
1994 omp_declare_variant_base_entry
*entryp
1995 = omp_declare_variant_alt
->find_with_hash (&entry
, DECL_UID (alt
));
1998 omp_declare_variant_entry
*varentry1
, *varentry2
;
1999 auto_vec
<bool, 16> matches
;
2000 unsigned int nmatches
= 0;
2001 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2003 if (varentry1
->matches
)
2005 /* This has been checked to be ok already. */
2006 matches
.safe_push (true);
2010 switch (omp_context_selector_matches (varentry1
->ctx
))
2013 matches
.safe_push (false);
2018 matches
.safe_push (true);
2025 return entryp
->base
->decl
;
2027 /* A context selector that is a strict subset of another context selector
2028 has a score of zero. */
2029 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2033 vec_safe_iterate (entryp
->variants
, j
, &varentry2
); ++j
)
2036 int r
= omp_context_selector_compare (varentry1
->ctx
,
2040 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2045 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2050 widest_int max_score
= -1;
2052 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry1
)
2056 = (cur_node
->simdclone
? varentry1
->score_in_declare_simd_clone
2057 : varentry1
->score
);
2058 if (score
> max_score
)
2061 varentry2
= varentry1
;
2064 return varentry2
->variant
->decl
;
2067 /* Hook to adjust hash tables on cgraph_node removal. */
2070 omp_declare_variant_remove_hook (struct cgraph_node
*node
, void *)
2072 if (!node
->declare_variant_alt
)
2075 /* Drop this hash table completely. */
2076 omp_declare_variants
= NULL
;
2077 /* And remove node from the other hash table. */
2078 if (omp_declare_variant_alt
)
2080 omp_declare_variant_base_entry entry
;
2083 entry
.variants
= NULL
;
2084 omp_declare_variant_alt
->remove_elt_with_hash (&entry
,
2085 DECL_UID (node
->decl
));
2089 /* Try to resolve declare variant, return the variant decl if it should
2090 be used instead of base, or base otherwise. */
2093 omp_resolve_declare_variant (tree base
)
2095 tree variant1
= NULL_TREE
, variant2
= NULL_TREE
;
2096 if (cfun
&& (cfun
->curr_properties
& PROP_gimple_any
) != 0)
2097 return omp_resolve_late_declare_variant (base
);
2099 auto_vec
<tree
, 16> variants
;
2100 auto_vec
<bool, 16> defer
;
2101 bool any_deferred
= false;
2102 for (tree attr
= DECL_ATTRIBUTES (base
); attr
; attr
= TREE_CHAIN (attr
))
2104 attr
= lookup_attribute ("omp declare variant base", attr
);
2105 if (attr
== NULL_TREE
)
2107 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr
))) != FUNCTION_DECL
)
2109 cgraph_node
*node
= cgraph_node::get (base
);
2110 /* If this is already a magic decl created by this function,
2111 don't process it again. */
2112 if (node
&& node
->declare_variant_alt
)
2114 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr
))))
2117 /* No match, ignore. */
2120 /* Needs to be deferred. */
2121 any_deferred
= true;
2122 variants
.safe_push (attr
);
2123 defer
.safe_push (true);
2126 variants
.safe_push (attr
);
2127 defer
.safe_push (false);
2131 if (variants
.length () == 0)
2136 widest_int max_score1
= 0;
2137 widest_int max_score2
= 0;
2141 omp_declare_variant_base_entry entry
;
2142 entry
.base
= cgraph_node::get_create (base
);
2144 vec_alloc (entry
.variants
, variants
.length ());
2145 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2150 tree ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2151 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2153 omp_context_compute_score (ctx
, &score2
, true);
2159 max_score1
= score1
;
2160 max_score2
= score2
;
2169 if (max_score1
== score1
)
2170 variant1
= NULL_TREE
;
2171 else if (score1
> max_score1
)
2173 max_score1
= score1
;
2174 variant1
= defer
[i
] ? NULL_TREE
: attr1
;
2176 if (max_score2
== score2
)
2177 variant2
= NULL_TREE
;
2178 else if (score2
> max_score2
)
2180 max_score2
= score2
;
2181 variant2
= defer
[i
] ? NULL_TREE
: attr1
;
2184 omp_declare_variant_entry varentry
;
2186 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1
)));
2187 varentry
.score
= score1
;
2188 varentry
.score_in_declare_simd_clone
= score2
;
2190 varentry
.matches
= !defer
[i
];
2191 entry
.variants
->quick_push (varentry
);
2194 /* If there is a clear winner variant with the score which is not
2195 deferred, verify it is not a strict subset of any other context
2196 selector and if it is not, it is the best alternative no matter
2197 whether the others do or don't match. */
2198 if (variant1
&& variant1
== variant2
)
2200 tree ctx1
= TREE_VALUE (TREE_VALUE (variant1
));
2201 FOR_EACH_VEC_ELT (variants
, i
, attr2
)
2203 if (attr2
== variant1
)
2205 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2206 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2209 /* The winner is a strict subset of ctx2, can't
2211 variant1
= NULL_TREE
;
2217 vec_free (entry
.variants
);
2218 return TREE_PURPOSE (TREE_VALUE (variant1
));
2222 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
2223 if (!node_removal_hook_holder
)
2224 node_removal_hook_holder
2225 = symtab
->add_cgraph_removal_hook (omp_declare_variant_remove_hook
,
2228 if (omp_declare_variants
== NULL
)
2229 omp_declare_variants
2230 = hash_table
<omp_declare_variant_hasher
>::create_ggc (64);
2231 omp_declare_variant_base_entry
**slot
2232 = omp_declare_variants
->find_slot (&entry
, INSERT
);
2235 vec_free (entry
.variants
);
2236 return (*slot
)->node
->decl
;
2239 *slot
= ggc_cleared_alloc
<omp_declare_variant_base_entry
> ();
2240 (*slot
)->base
= entry
.base
;
2241 (*slot
)->node
= entry
.base
;
2242 (*slot
)->variants
= entry
.variants
;
2243 tree alt
= build_decl (DECL_SOURCE_LOCATION (base
), FUNCTION_DECL
,
2244 DECL_NAME (base
), TREE_TYPE (base
));
2245 DECL_ARTIFICIAL (alt
) = 1;
2246 DECL_IGNORED_P (alt
) = 1;
2247 TREE_STATIC (alt
) = 1;
2248 tree attributes
= DECL_ATTRIBUTES (base
);
2249 if (lookup_attribute ("noipa", attributes
) == NULL
)
2251 attributes
= tree_cons (get_identifier ("noipa"), NULL
, attributes
);
2252 if (lookup_attribute ("noinline", attributes
) == NULL
)
2253 attributes
= tree_cons (get_identifier ("noinline"), NULL
,
2255 if (lookup_attribute ("noclone", attributes
) == NULL
)
2256 attributes
= tree_cons (get_identifier ("noclone"), NULL
,
2258 if (lookup_attribute ("no_icf", attributes
) == NULL
)
2259 attributes
= tree_cons (get_identifier ("no_icf"), NULL
,
2262 DECL_ATTRIBUTES (alt
) = attributes
;
2263 DECL_INITIAL (alt
) = error_mark_node
;
2264 (*slot
)->node
= cgraph_node::create (alt
);
2265 (*slot
)->node
->declare_variant_alt
= 1;
2266 (*slot
)->node
->create_reference (entry
.base
, IPA_REF_ADDR
);
2267 omp_declare_variant_entry
*varentry
;
2268 FOR_EACH_VEC_SAFE_ELT (entry
.variants
, i
, varentry
)
2269 (*slot
)->node
->create_reference (varentry
->variant
, IPA_REF_ADDR
);
2270 if (omp_declare_variant_alt
== NULL
)
2271 omp_declare_variant_alt
2272 = hash_table
<omp_declare_variant_alt_hasher
>::create_ggc (64);
2273 *omp_declare_variant_alt
->find_slot_with_hash (*slot
, DECL_UID (alt
),
2278 if (variants
.length () == 1)
2279 return TREE_PURPOSE (TREE_VALUE (variants
[0]));
2281 /* A context selector that is a strict subset of another context selector
2282 has a score of zero. */
2285 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2288 tree ctx1
= TREE_VALUE (TREE_VALUE (attr1
));
2289 FOR_EACH_VEC_ELT_FROM (variants
, j
, attr2
, i
+ 1)
2292 tree ctx2
= TREE_VALUE (TREE_VALUE (attr2
));
2293 int r
= omp_context_selector_compare (ctx1
, ctx2
);
2296 /* ctx1 is a strict subset of ctx2, remove
2297 attr1 from the vector. */
2298 variants
[i
] = NULL_TREE
;
2302 /* ctx2 is a strict subset of ctx1, remove attr2
2304 variants
[j
] = NULL_TREE
;
2307 widest_int max_score1
= 0;
2308 widest_int max_score2
= 0;
2310 FOR_EACH_VEC_ELT (variants
, i
, attr1
)
2322 ctx
= TREE_VALUE (TREE_VALUE (variant1
));
2323 need_two
= omp_context_compute_score (ctx
, &max_score1
, false);
2325 omp_context_compute_score (ctx
, &max_score2
, true);
2327 max_score2
= max_score1
;
2329 ctx
= TREE_VALUE (TREE_VALUE (attr1
));
2330 need_two
= omp_context_compute_score (ctx
, &score1
, false);
2332 omp_context_compute_score (ctx
, &score2
, true);
2335 if (score1
> max_score1
)
2337 max_score1
= score1
;
2340 if (score2
> max_score2
)
2342 max_score2
= score2
;
2352 /* If there is a disagreement on which variant has the highest score
2353 depending on whether it will be in a declare simd clone or not,
2354 punt for now and defer until after IPA where we will know that. */
2355 return ((variant1
&& variant1
== variant2
)
2356 ? TREE_PURPOSE (TREE_VALUE (variant1
)) : base
);
2360 omp_lto_output_declare_variant_alt (lto_simple_output_block
*ob
,
2362 lto_symtab_encoder_t encoder
)
2364 gcc_assert (node
->declare_variant_alt
);
2366 omp_declare_variant_base_entry entry
;
2369 entry
.variants
= NULL
;
2370 omp_declare_variant_base_entry
*entryp
2371 = omp_declare_variant_alt
->find_with_hash (&entry
, DECL_UID (node
->decl
));
2372 gcc_assert (entryp
);
2374 int nbase
= lto_symtab_encoder_lookup (encoder
, entryp
->base
);
2375 gcc_assert (nbase
!= LCC_NOT_FOUND
);
2376 streamer_write_hwi_stream (ob
->main_stream
, nbase
);
2378 streamer_write_hwi_stream (ob
->main_stream
, entryp
->variants
->length ());
2381 omp_declare_variant_entry
*varentry
;
2382 FOR_EACH_VEC_SAFE_ELT (entryp
->variants
, i
, varentry
)
2384 int nvar
= lto_symtab_encoder_lookup (encoder
, varentry
->variant
);
2385 gcc_assert (nvar
!= LCC_NOT_FOUND
);
2386 streamer_write_hwi_stream (ob
->main_stream
, nvar
);
2388 for (widest_int
*w
= &varentry
->score
; ;
2389 w
= &varentry
->score_in_declare_simd_clone
)
2391 unsigned len
= w
->get_len ();
2392 streamer_write_hwi_stream (ob
->main_stream
, len
);
2393 const HOST_WIDE_INT
*val
= w
->get_val ();
2394 for (unsigned j
= 0; j
< len
; j
++)
2395 streamer_write_hwi_stream (ob
->main_stream
, val
[j
]);
2396 if (w
== &varentry
->score_in_declare_simd_clone
)
2400 HOST_WIDE_INT cnt
= -1;
2401 HOST_WIDE_INT i
= varentry
->matches
? 1 : 0;
2402 for (tree attr
= DECL_ATTRIBUTES (entryp
->base
->decl
);
2403 attr
; attr
= TREE_CHAIN (attr
), i
+= 2)
2405 attr
= lookup_attribute ("omp declare variant base", attr
);
2406 if (attr
== NULL_TREE
)
2409 if (varentry
->ctx
== TREE_VALUE (TREE_VALUE (attr
)))
2416 gcc_assert (cnt
!= -1);
2417 streamer_write_hwi_stream (ob
->main_stream
, cnt
);
2422 omp_lto_input_declare_variant_alt (lto_input_block
*ib
, cgraph_node
*node
,
2423 vec
<symtab_node
*> nodes
)
2425 gcc_assert (node
->declare_variant_alt
);
2426 omp_declare_variant_base_entry
*entryp
2427 = ggc_cleared_alloc
<omp_declare_variant_base_entry
> ();
2428 entryp
->base
= dyn_cast
<cgraph_node
*> (nodes
[streamer_read_hwi (ib
)]);
2429 entryp
->node
= node
;
2430 unsigned int len
= streamer_read_hwi (ib
);
2431 vec_alloc (entryp
->variants
, len
);
2433 for (unsigned int i
= 0; i
< len
; i
++)
2435 omp_declare_variant_entry varentry
;
2437 = dyn_cast
<cgraph_node
*> (nodes
[streamer_read_hwi (ib
)]);
2438 for (widest_int
*w
= &varentry
.score
; ;
2439 w
= &varentry
.score_in_declare_simd_clone
)
2441 unsigned len2
= streamer_read_hwi (ib
);
2442 HOST_WIDE_INT arr
[WIDE_INT_MAX_ELTS
];
2443 gcc_assert (len2
<= WIDE_INT_MAX_ELTS
);
2444 for (unsigned int j
= 0; j
< len2
; j
++)
2445 arr
[j
] = streamer_read_hwi (ib
);
2446 *w
= widest_int::from_array (arr
, len2
, true);
2447 if (w
== &varentry
.score_in_declare_simd_clone
)
2451 HOST_WIDE_INT cnt
= streamer_read_hwi (ib
);
2452 HOST_WIDE_INT j
= 0;
2453 varentry
.ctx
= NULL_TREE
;
2454 varentry
.matches
= (cnt
& 1) ? true : false;
2455 cnt
&= ~HOST_WIDE_INT_1
;
2456 for (tree attr
= DECL_ATTRIBUTES (entryp
->base
->decl
);
2457 attr
; attr
= TREE_CHAIN (attr
), j
+= 2)
2459 attr
= lookup_attribute ("omp declare variant base", attr
);
2460 if (attr
== NULL_TREE
)
2465 varentry
.ctx
= TREE_VALUE (TREE_VALUE (attr
));
2469 gcc_assert (varentry
.ctx
!= NULL_TREE
);
2470 entryp
->variants
->quick_push (varentry
);
2472 if (omp_declare_variant_alt
== NULL
)
2473 omp_declare_variant_alt
2474 = hash_table
<omp_declare_variant_alt_hasher
>::create_ggc (64);
2475 *omp_declare_variant_alt
->find_slot_with_hash (entryp
, DECL_UID (node
->decl
),
2479 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2480 macro on gomp-constants.h. We do not check for overflow. */
2483 oacc_launch_pack (unsigned code
, tree device
, unsigned op
)
2487 res
= build_int_cst (unsigned_type_node
, GOMP_LAUNCH_PACK (code
, 0, op
));
2490 device
= fold_build2 (LSHIFT_EXPR
, unsigned_type_node
,
2491 device
, build_int_cst (unsigned_type_node
,
2492 GOMP_LAUNCH_DEVICE_SHIFT
));
2493 res
= fold_build2 (BIT_IOR_EXPR
, unsigned_type_node
, res
, device
);
2498 /* FIXME: What is the following comment for? */
2499 /* Look for compute grid dimension clauses and convert to an attribute
2500 attached to FN. This permits the target-side code to (a) massage
2501 the dimensions, (b) emit that data and (c) optimize. Non-constant
2502 dimensions are pushed onto ARGS.
2504 The attribute value is a TREE_LIST. A set of dimensions is
2505 represented as a list of INTEGER_CST. Those that are runtime
2506 exprs are represented as an INTEGER_CST of zero.
2508 TODO: Normally the attribute will just contain a single such list. If
2509 however it contains a list of lists, this will represent the use of
2510 device_type. Each member of the outer list is an assoc list of
2511 dimensions, keyed by the device type. The first entry will be the
2512 default. Well, that's the plan. */
2514 /* Replace any existing oacc fn attribute with updated dimensions. */
2516 /* Variant working on a list of attributes. */
2519 oacc_replace_fn_attrib_attr (tree attribs
, tree dims
)
2521 tree ident
= get_identifier (OACC_FN_ATTRIB
);
2523 /* If we happen to be present as the first attrib, drop it. */
2524 if (attribs
&& TREE_PURPOSE (attribs
) == ident
)
2525 attribs
= TREE_CHAIN (attribs
);
2526 return tree_cons (ident
, dims
, attribs
);
2529 /* Variant working on a function decl. */
2532 oacc_replace_fn_attrib (tree fn
, tree dims
)
2534 DECL_ATTRIBUTES (fn
)
2535 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn
), dims
);
2538 /* Scan CLAUSES for launch dimensions and attach them to the oacc
2539 function attribute. Push any that are non-constant onto the ARGS
2540 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
2543 oacc_set_fn_attrib (tree fn
, tree clauses
, vec
<tree
> *args
)
2545 /* Must match GOMP_DIM ordering. */
2546 static const omp_clause_code ids
[]
2547 = { OMP_CLAUSE_NUM_GANGS
, OMP_CLAUSE_NUM_WORKERS
,
2548 OMP_CLAUSE_VECTOR_LENGTH
};
2550 tree dims
[GOMP_DIM_MAX
];
2552 tree attr
= NULL_TREE
;
2553 unsigned non_const
= 0;
2555 for (ix
= GOMP_DIM_MAX
; ix
--;)
2557 tree clause
= omp_find_clause (clauses
, ids
[ix
]);
2558 tree dim
= NULL_TREE
;
2561 dim
= OMP_CLAUSE_EXPR (clause
, ids
[ix
]);
2563 if (dim
&& TREE_CODE (dim
) != INTEGER_CST
)
2565 dim
= integer_zero_node
;
2566 non_const
|= GOMP_DIM_MASK (ix
);
2568 attr
= tree_cons (NULL_TREE
, dim
, attr
);
2571 oacc_replace_fn_attrib (fn
, attr
);
2575 /* Push a dynamic argument set. */
2576 args
->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM
,
2577 NULL_TREE
, non_const
));
2578 for (unsigned ix
= 0; ix
!= GOMP_DIM_MAX
; ix
++)
2579 if (non_const
& GOMP_DIM_MASK (ix
))
2580 args
->safe_push (dims
[ix
]);
2584 /* Verify OpenACC routine clauses.
2586 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
2587 if it has already been marked in compatible way, and -1 if incompatible.
2588 Upon returning, the chain of clauses will contain exactly one clause
2589 specifying the level of parallelism. */
2592 oacc_verify_routine_clauses (tree fndecl
, tree
*clauses
, location_t loc
,
2593 const char *routine_str
)
2595 tree c_level
= NULL_TREE
;
2596 tree c_nohost
= NULL_TREE
;
2597 tree c_p
= NULL_TREE
;
2598 for (tree c
= *clauses
; c
; c_p
= c
, c
= OMP_CLAUSE_CHAIN (c
))
2599 switch (OMP_CLAUSE_CODE (c
))
2601 case OMP_CLAUSE_GANG
:
2602 case OMP_CLAUSE_WORKER
:
2603 case OMP_CLAUSE_VECTOR
:
2604 case OMP_CLAUSE_SEQ
:
2605 if (c_level
== NULL_TREE
)
2607 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_CODE (c_level
))
2609 /* This has already been diagnosed in the front ends. */
2610 /* Drop the duplicate clause. */
2611 gcc_checking_assert (c_p
!= NULL_TREE
);
2612 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2617 error_at (OMP_CLAUSE_LOCATION (c
),
2618 "%qs specifies a conflicting level of parallelism",
2619 omp_clause_code_name
[OMP_CLAUSE_CODE (c
)]);
2620 inform (OMP_CLAUSE_LOCATION (c_level
),
2621 "... to the previous %qs clause here",
2622 omp_clause_code_name
[OMP_CLAUSE_CODE (c_level
)]);
2623 /* Drop the conflicting clause. */
2624 gcc_checking_assert (c_p
!= NULL_TREE
);
2625 OMP_CLAUSE_CHAIN (c_p
) = OMP_CLAUSE_CHAIN (c
);
2629 case OMP_CLAUSE_NOHOST
:
2630 /* Don't worry about duplicate clauses here. */
2636 if (c_level
== NULL_TREE
)
2638 /* Default to an implicit 'seq' clause. */
2639 c_level
= build_omp_clause (loc
, OMP_CLAUSE_SEQ
);
2640 OMP_CLAUSE_CHAIN (c_level
) = *clauses
;
2643 /* In *clauses, we now have exactly one clause specifying the level of
2647 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl
));
2648 if (attr
!= NULL_TREE
)
2650 /* Diagnose if "#pragma omp declare target" has also been applied. */
2651 if (TREE_VALUE (attr
) == NULL_TREE
)
2653 /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
2654 OpenACC and OpenMP 'target' are not clear. */
2656 "cannot apply %<%s%> to %qD, which has also been"
2657 " marked with an OpenMP 'declare target' directive",
2658 routine_str
, fndecl
);
2663 /* If a "#pragma acc routine" has already been applied, just verify
2664 this one for compatibility. */
2665 /* Collect previous directive's clauses. */
2666 tree c_level_p
= NULL_TREE
;
2667 tree c_nohost_p
= NULL_TREE
;
2668 for (tree c
= TREE_VALUE (attr
); c
; c
= OMP_CLAUSE_CHAIN (c
))
2669 switch (OMP_CLAUSE_CODE (c
))
2671 case OMP_CLAUSE_GANG
:
2672 case OMP_CLAUSE_WORKER
:
2673 case OMP_CLAUSE_VECTOR
:
2674 case OMP_CLAUSE_SEQ
:
2675 gcc_checking_assert (c_level_p
== NULL_TREE
);
2678 case OMP_CLAUSE_NOHOST
:
2679 gcc_checking_assert (c_nohost_p
== NULL_TREE
);
2685 gcc_checking_assert (c_level_p
!= NULL_TREE
);
2686 /* ..., and compare to current directive's, which we've already collected
2690 /* Matching level of parallelism? */
2691 if (OMP_CLAUSE_CODE (c_level
) != OMP_CLAUSE_CODE (c_level_p
))
2694 c_diag_p
= c_level_p
;
2697 /* Matching 'nohost' clauses? */
2698 if ((c_nohost
== NULL_TREE
) != (c_nohost_p
== NULL_TREE
))
2701 c_diag_p
= c_nohost_p
;
2708 if (c_diag
!= NULL_TREE
)
2709 error_at (OMP_CLAUSE_LOCATION (c_diag
),
2710 "incompatible %qs clause when applying"
2711 " %<%s%> to %qD, which has already been"
2712 " marked with an OpenACC 'routine' directive",
2713 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)],
2714 routine_str
, fndecl
);
2715 else if (c_diag_p
!= NULL_TREE
)
2717 "missing %qs clause when applying"
2718 " %<%s%> to %qD, which has already been"
2719 " marked with an OpenACC 'routine' directive",
2720 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)],
2721 routine_str
, fndecl
);
2724 if (c_diag_p
!= NULL_TREE
)
2725 inform (OMP_CLAUSE_LOCATION (c_diag_p
),
2726 "... with %qs clause here",
2727 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag_p
)]);
2730 /* In the front ends, we don't preserve location information for the
2731 OpenACC routine directive itself. However, that of c_level_p
2733 location_t loc_routine
= OMP_CLAUSE_LOCATION (c_level_p
);
2734 inform (loc_routine
, "... without %qs clause near to here",
2735 omp_clause_code_name
[OMP_CLAUSE_CODE (c_diag
)]);
2744 /* Process the OpenACC 'routine' directive clauses to generate an attribute
2745 for the level of parallelism. All dimensions have a size of zero
2746 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
2747 can have a loop partitioned on it. non-zero indicates
2748 yes, zero indicates no. By construction once a non-zero has been
2749 reached, further inner dimensions must also be non-zero. We set
2750 TREE_VALUE to zero for the dimensions that may be partitioned and
2751 1 for the other ones -- if a loop is (erroneously) spawned at
2752 an outer level, we don't want to try and partition it. */
2755 oacc_build_routine_dims (tree clauses
)
2757 /* Must match GOMP_DIM ordering. */
2758 static const omp_clause_code ids
[]
2759 = {OMP_CLAUSE_GANG
, OMP_CLAUSE_WORKER
, OMP_CLAUSE_VECTOR
, OMP_CLAUSE_SEQ
};
2763 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
2764 for (ix
= GOMP_DIM_MAX
+ 1; ix
--;)
2765 if (OMP_CLAUSE_CODE (clauses
) == ids
[ix
])
2770 gcc_checking_assert (level
>= 0);
2772 tree dims
= NULL_TREE
;
2774 for (ix
= GOMP_DIM_MAX
; ix
--;)
2775 dims
= tree_cons (build_int_cst (boolean_type_node
, ix
>= level
),
2776 build_int_cst (integer_type_node
, ix
< level
), dims
);
2781 /* Retrieve the oacc function attrib and return it. Non-oacc
2782 functions will return NULL. */
2785 oacc_get_fn_attrib (tree fn
)
2787 return lookup_attribute (OACC_FN_ATTRIB
, DECL_ATTRIBUTES (fn
));
2790 /* Return true if FN is an OpenMP or OpenACC offloading function. */
2793 offloading_function_p (tree fn
)
2795 tree attrs
= DECL_ATTRIBUTES (fn
);
2796 return (lookup_attribute ("omp declare target", attrs
)
2797 || lookup_attribute ("omp target entrypoint", attrs
));
2800 /* Extract an oacc execution dimension from FN. FN must be an
2801 offloaded function or routine that has already had its execution
2802 dimensions lowered to the target-specific values. */
2805 oacc_get_fn_dim_size (tree fn
, int axis
)
2807 tree attrs
= oacc_get_fn_attrib (fn
);
2809 gcc_assert (axis
< GOMP_DIM_MAX
);
2811 tree dims
= TREE_VALUE (attrs
);
2813 dims
= TREE_CHAIN (dims
);
2815 int size
= TREE_INT_CST_LOW (TREE_VALUE (dims
));
2820 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
2821 IFN_GOACC_DIM_SIZE call. */
2824 oacc_get_ifn_dim_arg (const gimple
*stmt
)
2826 gcc_checking_assert (gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_SIZE
2827 || gimple_call_internal_fn (stmt
) == IFN_GOACC_DIM_POS
);
2828 tree arg
= gimple_call_arg (stmt
, 0);
2829 HOST_WIDE_INT axis
= TREE_INT_CST_LOW (arg
);
2831 gcc_checking_assert (axis
>= 0 && axis
< GOMP_DIM_MAX
);
2835 #include "gt-omp-general.h"