[RS6000] dg-do !compile and scan-assembler
[official-gcc.git] / gcc / omp-general.c
blobb70e3e31352c06b8a9fa5690c7132ea2e7cc21c9
1 /* General types and functions that are uselful for processing of OpenMP,
2 OpenACC and similar directivers at various stages of compilation.
4 Copyright (C) 2005-2020 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
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
16 for more details.
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. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "backend.h"
28 #include "target.h"
29 #include "tree.h"
30 #include "gimple.h"
31 #include "ssa.h"
32 #include "diagnostic-core.h"
33 #include "fold-const.h"
34 #include "langhooks.h"
35 #include "omp-general.h"
36 #include "stringpool.h"
37 #include "attribs.h"
38 #include "gimplify.h"
39 #include "cgraph.h"
40 #include "alloc-pool.h"
41 #include "symbol-summary.h"
42 #include "tree-pass.h"
43 #include "omp-device-properties.h"
44 #include "tree-iterator.h"
46 enum omp_requires omp_requires_mask;
48 tree
49 omp_find_clause (tree clauses, enum omp_clause_code kind)
51 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
52 if (OMP_CLAUSE_CODE (clauses) == kind)
53 return clauses;
55 return NULL_TREE;
58 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
59 allocatable or pointer attribute. */
60 bool
61 omp_is_allocatable_or_ptr (tree decl)
63 return lang_hooks.decls.omp_is_allocatable_or_ptr (decl);
66 /* Check whether this DECL belongs to a Fortran optional argument.
67 With 'for_present_check' set to false, decls which are optional parameters
68 themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
69 always pointers. With 'for_present_check' set to true, the decl for checking
70 whether an argument is present is returned; for arguments with value
71 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
72 unrelated to optional arguments, NULL_TREE is returned. */
74 tree
75 omp_check_optional_argument (tree decl, bool for_present_check)
77 return lang_hooks.decls.omp_check_optional_argument (decl, for_present_check);
80 /* Return true if DECL is a reference type. */
82 bool
83 omp_is_reference (tree decl)
85 return lang_hooks.decls.omp_privatize_by_reference (decl);
88 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
89 given that V is the loop index variable and STEP is loop step. */
91 void
92 omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2,
93 tree v, tree step)
95 switch (*cond_code)
97 case LT_EXPR:
98 case GT_EXPR:
99 break;
101 case NE_EXPR:
102 gcc_assert (TREE_CODE (step) == INTEGER_CST);
103 if (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE)
105 if (integer_onep (step))
106 *cond_code = LT_EXPR;
107 else
109 gcc_assert (integer_minus_onep (step));
110 *cond_code = GT_EXPR;
113 else
115 tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
116 gcc_assert (TREE_CODE (unit) == INTEGER_CST);
117 if (tree_int_cst_equal (unit, step))
118 *cond_code = LT_EXPR;
119 else
121 gcc_assert (wi::neg (wi::to_widest (unit))
122 == wi::to_widest (step));
123 *cond_code = GT_EXPR;
127 break;
129 case LE_EXPR:
130 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
131 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
132 else
133 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
134 build_int_cst (TREE_TYPE (*n2), 1));
135 *cond_code = LT_EXPR;
136 break;
137 case GE_EXPR:
138 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
139 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
140 else
141 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
142 build_int_cst (TREE_TYPE (*n2), 1));
143 *cond_code = GT_EXPR;
144 break;
145 default:
146 gcc_unreachable ();
150 /* Return the looping step from INCR, extracted from the step of a gimple omp
151 for statement. */
153 tree
154 omp_get_for_step_from_incr (location_t loc, tree incr)
156 tree step;
157 switch (TREE_CODE (incr))
159 case PLUS_EXPR:
160 step = TREE_OPERAND (incr, 1);
161 break;
162 case POINTER_PLUS_EXPR:
163 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
164 break;
165 case MINUS_EXPR:
166 step = TREE_OPERAND (incr, 1);
167 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
168 break;
169 default:
170 gcc_unreachable ();
172 return step;
175 /* Extract the header elements of parallel loop FOR_STMT and store
176 them into *FD. */
178 void
179 omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
180 struct omp_for_data_loop *loops)
182 tree t, var, *collapse_iter, *collapse_count;
183 tree count = NULL_TREE, iter_type = long_integer_type_node;
184 struct omp_for_data_loop *loop;
185 int i;
186 struct omp_for_data_loop dummy_loop;
187 location_t loc = gimple_location (for_stmt);
188 bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
189 bool distribute = gimple_omp_for_kind (for_stmt)
190 == GF_OMP_FOR_KIND_DISTRIBUTE;
191 bool taskloop = gimple_omp_for_kind (for_stmt)
192 == GF_OMP_FOR_KIND_TASKLOOP;
193 tree iterv, countv;
195 fd->for_stmt = for_stmt;
196 fd->pre = NULL;
197 fd->have_nowait = distribute || simd;
198 fd->have_ordered = false;
199 fd->have_reductemp = false;
200 fd->have_pointer_condtemp = false;
201 fd->have_scantemp = false;
202 fd->have_nonctrl_scantemp = false;
203 fd->non_rect = false;
204 fd->lastprivate_conditional = 0;
205 fd->tiling = NULL_TREE;
206 fd->collapse = 1;
207 fd->ordered = 0;
208 fd->first_nonrect = -1;
209 fd->last_nonrect = -1;
210 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
211 fd->sched_modifiers = 0;
212 fd->chunk_size = NULL_TREE;
213 fd->simd_schedule = false;
214 fd->first_inner_iterations = NULL_TREE;
215 fd->factor = NULL_TREE;
216 fd->adjn1 = NULL_TREE;
217 collapse_iter = NULL;
218 collapse_count = NULL;
220 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
221 switch (OMP_CLAUSE_CODE (t))
223 case OMP_CLAUSE_NOWAIT:
224 fd->have_nowait = true;
225 break;
226 case OMP_CLAUSE_ORDERED:
227 fd->have_ordered = true;
228 if (OMP_CLAUSE_ORDERED_EXPR (t))
229 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
230 break;
231 case OMP_CLAUSE_SCHEDULE:
232 gcc_assert (!distribute && !taskloop);
233 fd->sched_kind
234 = (enum omp_clause_schedule_kind)
235 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
236 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
237 & ~OMP_CLAUSE_SCHEDULE_MASK);
238 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
239 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
240 break;
241 case OMP_CLAUSE_DIST_SCHEDULE:
242 gcc_assert (distribute);
243 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
244 break;
245 case OMP_CLAUSE_COLLAPSE:
246 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
247 if (fd->collapse > 1)
249 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
250 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
252 break;
253 case OMP_CLAUSE_TILE:
254 fd->tiling = OMP_CLAUSE_TILE_LIST (t);
255 fd->collapse = list_length (fd->tiling);
256 gcc_assert (fd->collapse);
257 collapse_iter = &OMP_CLAUSE_TILE_ITERVAR (t);
258 collapse_count = &OMP_CLAUSE_TILE_COUNT (t);
259 break;
260 case OMP_CLAUSE__REDUCTEMP_:
261 fd->have_reductemp = true;
262 break;
263 case OMP_CLAUSE_LASTPRIVATE:
264 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
265 fd->lastprivate_conditional++;
266 break;
267 case OMP_CLAUSE__CONDTEMP_:
268 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
269 fd->have_pointer_condtemp = true;
270 break;
271 case OMP_CLAUSE__SCANTEMP_:
272 fd->have_scantemp = true;
273 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t)
274 && !OMP_CLAUSE__SCANTEMP__CONTROL (t))
275 fd->have_nonctrl_scantemp = true;
276 break;
277 default:
278 break;
281 if (fd->collapse > 1 || fd->tiling)
282 fd->loops = loops;
283 else
284 fd->loops = &fd->loop;
286 if (fd->ordered && fd->collapse == 1 && loops != NULL)
288 fd->loops = loops;
289 iterv = NULL_TREE;
290 countv = NULL_TREE;
291 collapse_iter = &iterv;
292 collapse_count = &countv;
295 /* FIXME: for now map schedule(auto) to schedule(static).
296 There should be analysis to determine whether all iterations
297 are approximately the same amount of work (then schedule(static)
298 is best) or if it varies (then schedule(dynamic,N) is better). */
299 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
301 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
302 gcc_assert (fd->chunk_size == NULL);
304 gcc_assert ((fd->collapse == 1 && !fd->tiling) || collapse_iter != NULL);
305 if (taskloop)
306 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
307 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
308 gcc_assert (fd->chunk_size == NULL);
309 else if (fd->chunk_size == NULL)
311 /* We only need to compute a default chunk size for ordered
312 static loops and dynamic loops. */
313 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
314 || fd->have_ordered)
315 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
316 ? integer_zero_node : integer_one_node;
319 int cnt = fd->ordered ? fd->ordered : fd->collapse;
320 int single_nonrect = -1;
321 tree single_nonrect_count = NULL_TREE;
322 enum tree_code single_nonrect_cond_code = ERROR_MARK;
323 for (i = 1; i < cnt; i++)
325 tree n1 = gimple_omp_for_initial (for_stmt, i);
326 tree n2 = gimple_omp_for_final (for_stmt, i);
327 if (TREE_CODE (n1) == TREE_VEC)
329 if (fd->non_rect)
331 single_nonrect = -1;
332 break;
334 for (int j = i - 1; j >= 0; j--)
335 if (TREE_VEC_ELT (n1, 0) == gimple_omp_for_index (for_stmt, j))
337 single_nonrect = j;
338 break;
340 fd->non_rect = true;
342 else if (TREE_CODE (n2) == TREE_VEC)
344 if (fd->non_rect)
346 single_nonrect = -1;
347 break;
349 for (int j = i - 1; j >= 0; j--)
350 if (TREE_VEC_ELT (n2, 0) == gimple_omp_for_index (for_stmt, j))
352 single_nonrect = j;
353 break;
355 fd->non_rect = true;
358 for (i = 0; i < cnt; i++)
360 if (i == 0
361 && fd->collapse == 1
362 && !fd->tiling
363 && (fd->ordered == 0 || loops == NULL))
364 loop = &fd->loop;
365 else if (loops != NULL)
366 loop = loops + i;
367 else
368 loop = &dummy_loop;
370 loop->v = gimple_omp_for_index (for_stmt, i);
371 gcc_assert (SSA_VAR_P (loop->v));
372 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
373 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
374 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
375 loop->n1 = gimple_omp_for_initial (for_stmt, i);
376 loop->m1 = NULL_TREE;
377 loop->m2 = NULL_TREE;
378 loop->outer = 0;
379 loop->non_rect_referenced = false;
380 if (TREE_CODE (loop->n1) == TREE_VEC)
382 for (int j = i - 1; j >= 0; j--)
383 if (TREE_VEC_ELT (loop->n1, 0) == gimple_omp_for_index (for_stmt, j))
385 loop->outer = i - j;
386 if (loops != NULL)
387 loops[j].non_rect_referenced = true;
388 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
389 fd->first_nonrect = j;
390 break;
392 gcc_assert (loop->outer);
393 loop->m1 = TREE_VEC_ELT (loop->n1, 1);
394 loop->n1 = TREE_VEC_ELT (loop->n1, 2);
395 fd->non_rect = true;
396 fd->last_nonrect = i;
399 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
400 loop->n2 = gimple_omp_for_final (for_stmt, i);
401 gcc_assert (loop->cond_code != NE_EXPR
402 || (gimple_omp_for_kind (for_stmt)
403 != GF_OMP_FOR_KIND_OACC_LOOP));
404 if (TREE_CODE (loop->n2) == TREE_VEC)
406 if (loop->outer)
407 gcc_assert (TREE_VEC_ELT (loop->n2, 0)
408 == gimple_omp_for_index (for_stmt, i - loop->outer));
409 else
410 for (int j = i - 1; j >= 0; j--)
411 if (TREE_VEC_ELT (loop->n2, 0) == gimple_omp_for_index (for_stmt, j))
413 loop->outer = i - j;
414 if (loops != NULL)
415 loops[j].non_rect_referenced = true;
416 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
417 fd->first_nonrect = j;
418 break;
420 gcc_assert (loop->outer);
421 loop->m2 = TREE_VEC_ELT (loop->n2, 1);
422 loop->n2 = TREE_VEC_ELT (loop->n2, 2);
423 fd->non_rect = true;
424 fd->last_nonrect = i;
427 t = gimple_omp_for_incr (for_stmt, i);
428 gcc_assert (TREE_OPERAND (t, 0) == var);
429 loop->step = omp_get_for_step_from_incr (loc, t);
431 omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2, loop->v,
432 loop->step);
434 if (simd
435 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
436 && !fd->have_ordered))
438 if (fd->collapse == 1 && !fd->tiling)
439 iter_type = TREE_TYPE (loop->v);
440 else if (i == 0
441 || TYPE_PRECISION (iter_type)
442 < TYPE_PRECISION (TREE_TYPE (loop->v)))
443 iter_type
444 = build_nonstandard_integer_type
445 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
447 else if (iter_type != long_long_unsigned_type_node)
449 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
450 iter_type = long_long_unsigned_type_node;
451 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
452 && TYPE_PRECISION (TREE_TYPE (loop->v))
453 >= TYPE_PRECISION (iter_type))
455 tree n;
457 if (loop->cond_code == LT_EXPR)
458 n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
459 loop->n2, loop->step);
460 else
461 n = loop->n1;
462 if (loop->m1
463 || loop->m2
464 || TREE_CODE (n) != INTEGER_CST
465 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
466 iter_type = long_long_unsigned_type_node;
468 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
469 > TYPE_PRECISION (iter_type))
471 tree n1, n2;
473 if (loop->cond_code == LT_EXPR)
475 n1 = loop->n1;
476 n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
477 loop->n2, loop->step);
479 else
481 n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
482 loop->n2, loop->step);
483 n2 = loop->n1;
485 if (loop->m1
486 || loop->m2
487 || TREE_CODE (n1) != INTEGER_CST
488 || TREE_CODE (n2) != INTEGER_CST
489 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
490 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
491 iter_type = long_long_unsigned_type_node;
495 if (i >= fd->collapse)
496 continue;
498 if (collapse_count && *collapse_count == NULL)
500 if (count && integer_zerop (count))
501 continue;
502 tree n1first = NULL_TREE, n2first = NULL_TREE;
503 tree n1last = NULL_TREE, n2last = NULL_TREE;
504 tree ostep = NULL_TREE;
505 if (loop->m1 || loop->m2)
507 if (count == NULL_TREE)
508 continue;
509 if (single_nonrect == -1
510 || (loop->m1 && TREE_CODE (loop->m1) != INTEGER_CST)
511 || (loop->m2 && TREE_CODE (loop->m2) != INTEGER_CST)
512 || TREE_CODE (loop->n1) != INTEGER_CST
513 || TREE_CODE (loop->n2) != INTEGER_CST
514 || TREE_CODE (loop->step) != INTEGER_CST)
516 count = NULL_TREE;
517 continue;
519 tree var = gimple_omp_for_initial (for_stmt, single_nonrect);
520 tree itype = TREE_TYPE (var);
521 tree first = gimple_omp_for_initial (for_stmt, single_nonrect);
522 t = gimple_omp_for_incr (for_stmt, single_nonrect);
523 ostep = omp_get_for_step_from_incr (loc, t);
524 t = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
525 single_nonrect_count,
526 build_one_cst (long_long_unsigned_type_node));
527 t = fold_convert (itype, t);
528 first = fold_convert (itype, first);
529 ostep = fold_convert (itype, ostep);
530 tree last = fold_binary (PLUS_EXPR, itype, first,
531 fold_binary (MULT_EXPR, itype, t,
532 ostep));
533 if (TREE_CODE (first) != INTEGER_CST
534 || TREE_CODE (last) != INTEGER_CST)
536 count = NULL_TREE;
537 continue;
539 if (loop->m1)
541 tree m1 = fold_convert (itype, loop->m1);
542 tree n1 = fold_convert (itype, loop->n1);
543 n1first = fold_binary (PLUS_EXPR, itype,
544 fold_binary (MULT_EXPR, itype,
545 first, m1), n1);
546 n1last = fold_binary (PLUS_EXPR, itype,
547 fold_binary (MULT_EXPR, itype,
548 last, m1), n1);
550 else
551 n1first = n1last = loop->n1;
552 if (loop->m2)
554 tree n2 = fold_convert (itype, loop->n2);
555 tree m2 = fold_convert (itype, loop->m2);
556 n2first = fold_binary (PLUS_EXPR, itype,
557 fold_binary (MULT_EXPR, itype,
558 first, m2), n2);
559 n2last = fold_binary (PLUS_EXPR, itype,
560 fold_binary (MULT_EXPR, itype,
561 last, m2), n2);
563 else
564 n2first = n2last = loop->n2;
565 n1first = fold_convert (TREE_TYPE (loop->v), n1first);
566 n2first = fold_convert (TREE_TYPE (loop->v), n2first);
567 n1last = fold_convert (TREE_TYPE (loop->v), n1last);
568 n2last = fold_convert (TREE_TYPE (loop->v), n2last);
569 t = fold_binary (loop->cond_code, boolean_type_node,
570 n1first, n2first);
571 tree t2 = fold_binary (loop->cond_code, boolean_type_node,
572 n1last, n2last);
573 if (t && t2 && integer_nonzerop (t) && integer_nonzerop (t2))
574 /* All outer loop iterators have at least one inner loop
575 iteration. Try to compute the count at compile time. */
576 t = NULL_TREE;
577 else if (t && t2 && integer_zerop (t) && integer_zerop (t2))
578 /* No iterations of the inner loop. count will be set to
579 zero cst below. */;
580 else if (TYPE_UNSIGNED (itype)
581 || t == NULL_TREE
582 || t2 == NULL_TREE
583 || TREE_CODE (t) != INTEGER_CST
584 || TREE_CODE (t2) != INTEGER_CST)
586 /* Punt (for now). */
587 count = NULL_TREE;
588 continue;
590 else
592 /* Some iterations of the outer loop have zero iterations
593 of the inner loop, while others have at least one.
594 In this case, we need to adjust one of those outer
595 loop bounds. If ADJ_FIRST, we need to adjust outer n1
596 (first), otherwise outer n2 (last). */
597 bool adj_first = integer_zerop (t);
598 tree n1 = fold_convert (itype, loop->n1);
599 tree n2 = fold_convert (itype, loop->n2);
600 tree m1 = loop->m1 ? fold_convert (itype, loop->m1)
601 : build_zero_cst (itype);
602 tree m2 = loop->m2 ? fold_convert (itype, loop->m2)
603 : build_zero_cst (itype);
604 t = fold_binary (MINUS_EXPR, itype, n1, n2);
605 t2 = fold_binary (MINUS_EXPR, itype, m2, m1);
606 t = fold_binary (TRUNC_DIV_EXPR, itype, t, t2);
607 t2 = fold_binary (MINUS_EXPR, itype, t, first);
608 t2 = fold_binary (TRUNC_MOD_EXPR, itype, t2, ostep);
609 t = fold_binary (MINUS_EXPR, itype, t, t2);
610 tree n1cur
611 = fold_binary (PLUS_EXPR, itype, n1,
612 fold_binary (MULT_EXPR, itype, m1, t));
613 tree n2cur
614 = fold_binary (PLUS_EXPR, itype, n2,
615 fold_binary (MULT_EXPR, itype, m2, t));
616 t2 = fold_binary (loop->cond_code, boolean_type_node,
617 n1cur, n2cur);
618 tree t3 = fold_binary (MULT_EXPR, itype, m1, ostep);
619 tree t4 = fold_binary (MULT_EXPR, itype, m2, ostep);
620 tree diff;
621 if (adj_first)
623 tree new_first;
624 if (integer_nonzerop (t2))
626 new_first = t;
627 n1first = n1cur;
628 n2first = n2cur;
629 if (flag_checking)
631 t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
632 t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
633 t3 = fold_binary (loop->cond_code,
634 boolean_type_node, t3, t4);
635 gcc_assert (integer_zerop (t3));
638 else
640 t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
641 t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
642 new_first = fold_binary (PLUS_EXPR, itype, t, ostep);
643 n1first = t3;
644 n2first = t4;
645 if (flag_checking)
647 t3 = fold_binary (loop->cond_code,
648 boolean_type_node, t3, t4);
649 gcc_assert (integer_nonzerop (t3));
652 diff = fold_binary (MINUS_EXPR, itype, new_first, first);
653 first = new_first;
654 fd->adjn1 = first;
656 else
658 tree new_last;
659 if (integer_zerop (t2))
661 t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
662 t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
663 new_last = fold_binary (MINUS_EXPR, itype, t, ostep);
664 n1last = t3;
665 n2last = t4;
666 if (flag_checking)
668 t3 = fold_binary (loop->cond_code,
669 boolean_type_node, t3, t4);
670 gcc_assert (integer_nonzerop (t3));
673 else
675 new_last = t;
676 n1last = n1cur;
677 n2last = n2cur;
678 if (flag_checking)
680 t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
681 t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
682 t3 = fold_binary (loop->cond_code,
683 boolean_type_node, t3, t4);
684 gcc_assert (integer_zerop (t3));
687 diff = fold_binary (MINUS_EXPR, itype, last, new_last);
689 if (TYPE_UNSIGNED (itype)
690 && single_nonrect_cond_code == GT_EXPR)
691 diff = fold_binary (TRUNC_DIV_EXPR, itype,
692 fold_unary (NEGATE_EXPR, itype, diff),
693 fold_unary (NEGATE_EXPR, itype,
694 ostep));
695 else
696 diff = fold_binary (TRUNC_DIV_EXPR, itype, diff, ostep);
697 diff = fold_convert (long_long_unsigned_type_node, diff);
698 single_nonrect_count
699 = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
700 single_nonrect_count, diff);
701 t = NULL_TREE;
704 else
705 t = fold_binary (loop->cond_code, boolean_type_node,
706 fold_convert (TREE_TYPE (loop->v), loop->n1),
707 fold_convert (TREE_TYPE (loop->v), loop->n2));
708 if (t && integer_zerop (t))
709 count = build_zero_cst (long_long_unsigned_type_node);
710 else if ((i == 0 || count != NULL_TREE)
711 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
712 && TREE_CONSTANT (loop->n1)
713 && TREE_CONSTANT (loop->n2)
714 && TREE_CODE (loop->step) == INTEGER_CST)
716 tree itype = TREE_TYPE (loop->v);
718 if (POINTER_TYPE_P (itype))
719 itype = signed_type_for (itype);
720 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
721 t = fold_build2 (PLUS_EXPR, itype,
722 fold_convert (itype, loop->step), t);
723 tree n1 = loop->n1;
724 tree n2 = loop->n2;
725 if (loop->m1 || loop->m2)
727 gcc_assert (single_nonrect != -1);
728 n1 = n1first;
729 n2 = n2first;
731 t = fold_build2 (PLUS_EXPR, itype, t, fold_convert (itype, n2));
732 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
733 tree step = fold_convert_loc (loc, itype, loop->step);
734 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
735 t = fold_build2 (TRUNC_DIV_EXPR, itype,
736 fold_build1 (NEGATE_EXPR, itype, t),
737 fold_build1 (NEGATE_EXPR, itype, step));
738 else
739 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
740 tree llutype = long_long_unsigned_type_node;
741 t = fold_convert (llutype, t);
742 if (loop->m1 || loop->m2)
744 /* t is number of iterations of inner loop at either first
745 or last value of the outer iterator (the one with fewer
746 iterations).
747 Compute t2 = ((m2 - m1) * ostep) / step
748 and niters = outer_count * t
749 + t2 * ((outer_count - 1) * outer_count / 2)
751 tree m1 = loop->m1 ? loop->m1 : integer_zero_node;
752 tree m2 = loop->m2 ? loop->m2 : integer_zero_node;
753 m1 = fold_convert (itype, m1);
754 m2 = fold_convert (itype, m2);
755 tree t2 = fold_build2 (MINUS_EXPR, itype, m2, m1);
756 t2 = fold_build2 (MULT_EXPR, itype, t2, ostep);
757 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
758 t2 = fold_build2 (TRUNC_DIV_EXPR, itype,
759 fold_build1 (NEGATE_EXPR, itype, t2),
760 fold_build1 (NEGATE_EXPR, itype, step));
761 else
762 t2 = fold_build2 (TRUNC_DIV_EXPR, itype, t2, step);
763 t2 = fold_convert (llutype, t2);
764 fd->first_inner_iterations = t;
765 fd->factor = t2;
766 t = fold_build2 (MULT_EXPR, llutype, t,
767 single_nonrect_count);
768 tree t3 = fold_build2 (MINUS_EXPR, llutype,
769 single_nonrect_count,
770 build_one_cst (llutype));
771 t3 = fold_build2 (MULT_EXPR, llutype, t3,
772 single_nonrect_count);
773 t3 = fold_build2 (TRUNC_DIV_EXPR, llutype, t3,
774 build_int_cst (llutype, 2));
775 t2 = fold_build2 (MULT_EXPR, llutype, t2, t3);
776 t = fold_build2 (PLUS_EXPR, llutype, t, t2);
778 if (i == single_nonrect)
780 if (integer_zerop (t) || TREE_CODE (t) != INTEGER_CST)
781 count = t;
782 else
784 single_nonrect_count = t;
785 single_nonrect_cond_code = loop->cond_code;
786 if (count == NULL_TREE)
787 count = build_one_cst (llutype);
790 else if (count != NULL_TREE)
791 count = fold_build2 (MULT_EXPR, llutype, count, t);
792 else
793 count = t;
794 if (TREE_CODE (count) != INTEGER_CST)
795 count = NULL_TREE;
797 else if (count && !integer_zerop (count))
798 count = NULL_TREE;
802 if (count
803 && !simd
804 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
805 || fd->have_ordered))
807 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
808 iter_type = long_long_unsigned_type_node;
809 else
810 iter_type = long_integer_type_node;
812 else if (collapse_iter && *collapse_iter != NULL)
813 iter_type = TREE_TYPE (*collapse_iter);
814 fd->iter_type = iter_type;
815 if (collapse_iter && *collapse_iter == NULL)
816 *collapse_iter = create_tmp_var (iter_type, ".iter");
817 if (collapse_count && *collapse_count == NULL)
819 if (count)
821 *collapse_count = fold_convert_loc (loc, iter_type, count);
822 if (fd->first_inner_iterations && fd->factor)
824 t = make_tree_vec (4);
825 TREE_VEC_ELT (t, 0) = *collapse_count;
826 TREE_VEC_ELT (t, 1) = fd->first_inner_iterations;
827 TREE_VEC_ELT (t, 2) = fd->factor;
828 TREE_VEC_ELT (t, 3) = fd->adjn1;
829 *collapse_count = t;
832 else
833 *collapse_count = create_tmp_var (iter_type, ".count");
836 if (fd->collapse > 1 || fd->tiling || (fd->ordered && loops))
838 fd->loop.v = *collapse_iter;
839 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
840 fd->loop.n2 = *collapse_count;
841 if (TREE_CODE (fd->loop.n2) == TREE_VEC)
843 gcc_assert (fd->non_rect);
844 fd->first_inner_iterations = TREE_VEC_ELT (fd->loop.n2, 1);
845 fd->factor = TREE_VEC_ELT (fd->loop.n2, 2);
846 fd->adjn1 = TREE_VEC_ELT (fd->loop.n2, 3);
847 fd->loop.n2 = TREE_VEC_ELT (fd->loop.n2, 0);
849 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
850 fd->loop.m1 = NULL_TREE;
851 fd->loop.m2 = NULL_TREE;
852 fd->loop.outer = 0;
853 fd->loop.cond_code = LT_EXPR;
855 else if (loops)
856 loops[0] = fd->loop;
859 /* Build a call to GOMP_barrier. */
861 gimple *
862 omp_build_barrier (tree lhs)
864 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
865 : BUILT_IN_GOMP_BARRIER);
866 gcall *g = gimple_build_call (fndecl, 0);
867 if (lhs)
868 gimple_call_set_lhs (g, lhs);
869 return g;
872 /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
873 array, pdata[0] non-NULL if there is anything non-trivial in between,
874 pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
875 of OMP_FOR in between if any and pdata[3] is address of the inner
876 OMP_FOR/OMP_SIMD. */
878 tree
879 find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
881 tree **pdata = (tree **) data;
882 *walk_subtrees = 0;
883 switch (TREE_CODE (*tp))
885 case OMP_FOR:
886 if (OMP_FOR_INIT (*tp) != NULL_TREE)
888 pdata[3] = tp;
889 return *tp;
891 pdata[2] = tp;
892 *walk_subtrees = 1;
893 break;
894 case OMP_SIMD:
895 if (OMP_FOR_INIT (*tp) != NULL_TREE)
897 pdata[3] = tp;
898 return *tp;
900 break;
901 case BIND_EXPR:
902 if (BIND_EXPR_VARS (*tp)
903 || (BIND_EXPR_BLOCK (*tp)
904 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
905 pdata[0] = tp;
906 *walk_subtrees = 1;
907 break;
908 case STATEMENT_LIST:
909 if (!tsi_one_before_end_p (tsi_start (*tp)))
910 pdata[0] = tp;
911 *walk_subtrees = 1;
912 break;
913 case TRY_FINALLY_EXPR:
914 pdata[0] = tp;
915 *walk_subtrees = 1;
916 break;
917 case OMP_PARALLEL:
918 pdata[1] = tp;
919 *walk_subtrees = 1;
920 break;
921 default:
922 break;
924 return NULL_TREE;
927 /* Return maximum possible vectorization factor for the target. */
929 poly_uint64
930 omp_max_vf (void)
932 if (!optimize
933 || optimize_debug
934 || !flag_tree_loop_optimize
935 || (!flag_tree_loop_vectorize
936 && global_options_set.x_flag_tree_loop_vectorize))
937 return 1;
939 auto_vector_modes modes;
940 targetm.vectorize.autovectorize_vector_modes (&modes, true);
941 if (!modes.is_empty ())
943 poly_uint64 vf = 0;
944 for (unsigned int i = 0; i < modes.length (); ++i)
945 /* The returned modes use the smallest element size (and thus
946 the largest nunits) for the vectorization approach that they
947 represent. */
948 vf = ordered_max (vf, GET_MODE_NUNITS (modes[i]));
949 return vf;
952 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
953 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
954 return GET_MODE_NUNITS (vqimode);
956 return 1;
959 /* Return maximum SIMT width if offloading may target SIMT hardware. */
962 omp_max_simt_vf (void)
964 if (!optimize)
965 return 0;
966 if (ENABLE_OFFLOADING)
967 for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
969 if (!strncmp (c, "nvptx", strlen ("nvptx")))
970 return 32;
971 else if ((c = strchr (c, ':')))
972 c++;
974 return 0;
977 /* Store the construct selectors as tree codes from last to first,
978 return their number. */
981 omp_constructor_traits_to_codes (tree ctx, enum tree_code *constructs)
983 int nconstructs = list_length (ctx);
984 int i = nconstructs - 1;
985 for (tree t2 = ctx; t2; t2 = TREE_CHAIN (t2), i--)
987 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
988 if (!strcmp (sel, "target"))
989 constructs[i] = OMP_TARGET;
990 else if (!strcmp (sel, "teams"))
991 constructs[i] = OMP_TEAMS;
992 else if (!strcmp (sel, "parallel"))
993 constructs[i] = OMP_PARALLEL;
994 else if (!strcmp (sel, "for") || !strcmp (sel, "do"))
995 constructs[i] = OMP_FOR;
996 else if (!strcmp (sel, "simd"))
997 constructs[i] = OMP_SIMD;
998 else
999 gcc_unreachable ();
1001 gcc_assert (i == -1);
1002 return nconstructs;
1005 /* Return true if PROP is possibly present in one of the offloading target's
1006 OpenMP contexts. The format of PROPS string is always offloading target's
1007 name terminated by '\0', followed by properties for that offloading
1008 target separated by '\0' and terminated by another '\0'. The strings
1009 are created from omp-device-properties installed files of all configured
1010 offloading targets. */
1012 static bool
1013 omp_offload_device_kind_arch_isa (const char *props, const char *prop)
1015 const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1016 if (names == NULL || *names == '\0')
1017 return false;
1018 while (*props != '\0')
1020 size_t name_len = strlen (props);
1021 bool matches = false;
1022 for (const char *c = names; c; )
1024 if (strncmp (props, c, name_len) == 0
1025 && (c[name_len] == '\0'
1026 || c[name_len] == ':'
1027 || c[name_len] == '='))
1029 matches = true;
1030 break;
1032 else if ((c = strchr (c, ':')))
1033 c++;
1035 props = props + name_len + 1;
1036 while (*props != '\0')
1038 if (matches && strcmp (props, prop) == 0)
1039 return true;
1040 props = strchr (props, '\0') + 1;
1042 props++;
1044 return false;
1047 /* Return true if the current code location is or might be offloaded.
1048 Return true in declare target functions, or when nested in a target
1049 region or when unsure, return false otherwise. */
1051 static bool
1052 omp_maybe_offloaded (void)
1054 if (!ENABLE_OFFLOADING)
1055 return false;
1056 const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1057 if (names == NULL || *names == '\0')
1058 return false;
1060 if (symtab->state == PARSING)
1061 /* Maybe. */
1062 return true;
1063 if (cfun && cfun->after_inlining)
1064 return false;
1065 if (current_function_decl
1066 && lookup_attribute ("omp declare target",
1067 DECL_ATTRIBUTES (current_function_decl)))
1068 return true;
1069 if (cfun && (cfun->curr_properties & PROP_gimple_any) == 0)
1071 enum tree_code construct = OMP_TARGET;
1072 if (omp_construct_selector_matches (&construct, 1, NULL))
1073 return true;
1075 return false;
1078 /* Return a name from PROP, a property in selectors accepting
1079 name lists. */
1081 static const char *
1082 omp_context_name_list_prop (tree prop)
1084 if (TREE_PURPOSE (prop))
1085 return IDENTIFIER_POINTER (TREE_PURPOSE (prop));
1086 else
1088 const char *ret = TREE_STRING_POINTER (TREE_VALUE (prop));
1089 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop)) == strlen (ret) + 1)
1090 return ret;
1091 return NULL;
1095 /* Return 1 if context selector matches the current OpenMP context, 0
1096 if it does not and -1 if it is unknown and need to be determined later.
1097 Some properties can be checked right away during parsing (this routine),
1098 others need to wait until the whole TU is parsed, others need to wait until
1099 IPA, others until vectorization. */
1102 omp_context_selector_matches (tree ctx)
1104 int ret = 1;
1105 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1107 char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0];
1108 if (set == 'c')
1110 /* For now, ignore the construct set. While something can be
1111 determined already during parsing, we don't know until end of TU
1112 whether additional constructs aren't added through declare variant
1113 unless "omp declare variant variant" attribute exists already
1114 (so in most of the cases), and we'd need to maintain set of
1115 surrounding OpenMP constructs, which is better handled during
1116 gimplification. */
1117 if (symtab->state == PARSING)
1119 ret = -1;
1120 continue;
1123 enum tree_code constructs[5];
1124 int nconstructs
1125 = omp_constructor_traits_to_codes (TREE_VALUE (t1), constructs);
1127 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1129 if (!cfun->after_inlining)
1131 ret = -1;
1132 continue;
1134 int i;
1135 for (i = 0; i < nconstructs; ++i)
1136 if (constructs[i] == OMP_SIMD)
1137 break;
1138 if (i < nconstructs)
1140 ret = -1;
1141 continue;
1143 /* If there is no simd, assume it is ok after IPA,
1144 constructs should have been checked before. */
1145 continue;
1148 int r = omp_construct_selector_matches (constructs, nconstructs,
1149 NULL);
1150 if (r == 0)
1151 return 0;
1152 if (r == -1)
1153 ret = -1;
1154 continue;
1156 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1158 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
1159 switch (*sel)
1161 case 'v':
1162 if (set == 'i' && !strcmp (sel, "vendor"))
1163 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1165 const char *prop = omp_context_name_list_prop (t3);
1166 if (prop == NULL)
1167 return 0;
1168 if ((!strcmp (prop, " score") && TREE_PURPOSE (t3))
1169 || !strcmp (prop, "gnu"))
1170 continue;
1171 return 0;
1173 break;
1174 case 'e':
1175 if (set == 'i' && !strcmp (sel, "extension"))
1176 /* We don't support any extensions right now. */
1177 return 0;
1178 break;
1179 case 'a':
1180 if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
1182 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1183 break;
1185 enum omp_memory_order omo
1186 = ((enum omp_memory_order)
1187 (omp_requires_mask
1188 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER));
1189 if (omo == OMP_MEMORY_ORDER_UNSPECIFIED)
1191 /* We don't know yet, until end of TU. */
1192 if (symtab->state == PARSING)
1194 ret = -1;
1195 break;
1197 else
1198 omo = OMP_MEMORY_ORDER_RELAXED;
1200 tree t3 = TREE_VALUE (t2);
1201 const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
1202 if (!strcmp (prop, " score"))
1204 t3 = TREE_CHAIN (t3);
1205 prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
1207 if (!strcmp (prop, "relaxed")
1208 && omo != OMP_MEMORY_ORDER_RELAXED)
1209 return 0;
1210 else if (!strcmp (prop, "seq_cst")
1211 && omo != OMP_MEMORY_ORDER_SEQ_CST)
1212 return 0;
1213 else if (!strcmp (prop, "acq_rel")
1214 && omo != OMP_MEMORY_ORDER_ACQ_REL)
1215 return 0;
1217 if (set == 'd' && !strcmp (sel, "arch"))
1218 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1220 const char *arch = omp_context_name_list_prop (t3);
1221 if (arch == NULL)
1222 return 0;
1223 int r = 0;
1224 if (targetm.omp.device_kind_arch_isa != NULL)
1225 r = targetm.omp.device_kind_arch_isa (omp_device_arch,
1226 arch);
1227 if (r == 0 || (r == -1 && symtab->state != PARSING))
1229 /* If we are or might be in a target region or
1230 declare target function, need to take into account
1231 also offloading values. */
1232 if (!omp_maybe_offloaded ())
1233 return 0;
1234 if (ENABLE_OFFLOADING)
1236 const char *arches = omp_offload_device_arch;
1237 if (omp_offload_device_kind_arch_isa (arches,
1238 arch))
1240 ret = -1;
1241 continue;
1244 return 0;
1246 else if (r == -1)
1247 ret = -1;
1248 /* If arch matches on the host, it still might not match
1249 in the offloading region. */
1250 else if (omp_maybe_offloaded ())
1251 ret = -1;
1253 break;
1254 case 'u':
1255 if (set == 'i' && !strcmp (sel, "unified_address"))
1257 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1258 break;
1260 if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
1262 if (symtab->state == PARSING)
1263 ret = -1;
1264 else
1265 return 0;
1267 break;
1269 if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
1271 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1272 break;
1274 if ((omp_requires_mask
1275 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
1277 if (symtab->state == PARSING)
1278 ret = -1;
1279 else
1280 return 0;
1282 break;
1284 break;
1285 case 'd':
1286 if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
1288 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1289 break;
1291 if ((omp_requires_mask
1292 & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1294 if (symtab->state == PARSING)
1295 ret = -1;
1296 else
1297 return 0;
1299 break;
1301 break;
1302 case 'r':
1303 if (set == 'i' && !strcmp (sel, "reverse_offload"))
1305 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1306 break;
1308 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
1310 if (symtab->state == PARSING)
1311 ret = -1;
1312 else
1313 return 0;
1315 break;
1317 break;
1318 case 'k':
1319 if (set == 'd' && !strcmp (sel, "kind"))
1320 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1322 const char *prop = omp_context_name_list_prop (t3);
1323 if (prop == NULL)
1324 return 0;
1325 if (!strcmp (prop, "any"))
1326 continue;
1327 if (!strcmp (prop, "host"))
1329 if (omp_maybe_offloaded ())
1330 ret = -1;
1331 continue;
1333 if (!strcmp (prop, "nohost"))
1335 if (omp_maybe_offloaded ())
1336 ret = -1;
1337 else
1338 return 0;
1339 continue;
1341 int r = 0;
1342 if (targetm.omp.device_kind_arch_isa != NULL)
1343 r = targetm.omp.device_kind_arch_isa (omp_device_kind,
1344 prop);
1345 else
1346 r = strcmp (prop, "cpu") == 0;
1347 if (r == 0 || (r == -1 && symtab->state != PARSING))
1349 /* If we are or might be in a target region or
1350 declare target function, need to take into account
1351 also offloading values. */
1352 if (!omp_maybe_offloaded ())
1353 return 0;
1354 if (ENABLE_OFFLOADING)
1356 const char *kinds = omp_offload_device_kind;
1357 if (omp_offload_device_kind_arch_isa (kinds, prop))
1359 ret = -1;
1360 continue;
1363 return 0;
1365 else if (r == -1)
1366 ret = -1;
1367 /* If kind matches on the host, it still might not match
1368 in the offloading region. */
1369 else if (omp_maybe_offloaded ())
1370 ret = -1;
1372 break;
1373 case 'i':
1374 if (set == 'd' && !strcmp (sel, "isa"))
1375 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1377 const char *isa = omp_context_name_list_prop (t3);
1378 if (isa == NULL)
1379 return 0;
1380 int r = 0;
1381 if (targetm.omp.device_kind_arch_isa != NULL)
1382 r = targetm.omp.device_kind_arch_isa (omp_device_isa,
1383 isa);
1384 if (r == 0 || (r == -1 && symtab->state != PARSING))
1386 /* If isa is valid on the target, but not in the
1387 current function and current function has
1388 #pragma omp declare simd on it, some simd clones
1389 might have the isa added later on. */
1390 if (r == -1
1391 && targetm.simd_clone.compute_vecsize_and_simdlen
1392 && (cfun == NULL || !cfun->after_inlining))
1394 tree attrs
1395 = DECL_ATTRIBUTES (current_function_decl);
1396 if (lookup_attribute ("omp declare simd", attrs))
1398 ret = -1;
1399 continue;
1402 /* If we are or might be in a target region or
1403 declare target function, need to take into account
1404 also offloading values. */
1405 if (!omp_maybe_offloaded ())
1406 return 0;
1407 if (ENABLE_OFFLOADING)
1409 const char *isas = omp_offload_device_isa;
1410 if (omp_offload_device_kind_arch_isa (isas, isa))
1412 ret = -1;
1413 continue;
1416 return 0;
1418 else if (r == -1)
1419 ret = -1;
1420 /* If isa matches on the host, it still might not match
1421 in the offloading region. */
1422 else if (omp_maybe_offloaded ())
1423 ret = -1;
1425 break;
1426 case 'c':
1427 if (set == 'u' && !strcmp (sel, "condition"))
1428 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1429 if (TREE_PURPOSE (t3) == NULL_TREE)
1431 if (integer_zerop (TREE_VALUE (t3)))
1432 return 0;
1433 if (integer_nonzerop (TREE_VALUE (t3)))
1434 break;
1435 ret = -1;
1437 break;
1438 default:
1439 break;
1443 return ret;
1446 /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1447 in omp_context_selector_set_compare. */
1449 static int
1450 omp_construct_simd_compare (tree clauses1, tree clauses2)
1452 if (clauses1 == NULL_TREE)
1453 return clauses2 == NULL_TREE ? 0 : -1;
1454 if (clauses2 == NULL_TREE)
1455 return 1;
1457 int r = 0;
1458 struct declare_variant_simd_data {
1459 bool inbranch, notinbranch;
1460 tree simdlen;
1461 auto_vec<tree,16> data_sharing;
1462 auto_vec<tree,16> aligned;
1463 declare_variant_simd_data ()
1464 : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
1465 } data[2];
1466 unsigned int i;
1467 for (i = 0; i < 2; i++)
1468 for (tree c = i ? clauses2 : clauses1; c; c = OMP_CLAUSE_CHAIN (c))
1470 vec<tree> *v;
1471 switch (OMP_CLAUSE_CODE (c))
1473 case OMP_CLAUSE_INBRANCH:
1474 data[i].inbranch = true;
1475 continue;
1476 case OMP_CLAUSE_NOTINBRANCH:
1477 data[i].notinbranch = true;
1478 continue;
1479 case OMP_CLAUSE_SIMDLEN:
1480 data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
1481 continue;
1482 case OMP_CLAUSE_UNIFORM:
1483 case OMP_CLAUSE_LINEAR:
1484 v = &data[i].data_sharing;
1485 break;
1486 case OMP_CLAUSE_ALIGNED:
1487 v = &data[i].aligned;
1488 break;
1489 default:
1490 gcc_unreachable ();
1492 unsigned HOST_WIDE_INT argno = tree_to_uhwi (OMP_CLAUSE_DECL (c));
1493 if (argno >= v->length ())
1494 v->safe_grow_cleared (argno + 1, true);
1495 (*v)[argno] = c;
1497 /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1498 CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1499 doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1500 -1, r == 2 implies 1 and r == 0 implies 0. */
1501 if (data[0].inbranch != data[1].inbranch)
1502 r |= data[0].inbranch ? 2 : 1;
1503 if (data[0].notinbranch != data[1].notinbranch)
1504 r |= data[0].notinbranch ? 2 : 1;
1505 if (!simple_cst_equal (data[0].simdlen, data[1].simdlen))
1507 if (data[0].simdlen && data[1].simdlen)
1508 return 2;
1509 r |= data[0].simdlen ? 2 : 1;
1511 if (data[0].data_sharing.length () < data[1].data_sharing.length ()
1512 || data[0].aligned.length () < data[1].aligned.length ())
1513 r |= 1;
1514 tree c1, c2;
1515 FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
1517 c2 = (i < data[1].data_sharing.length ()
1518 ? data[1].data_sharing[i] : NULL_TREE);
1519 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
1521 r |= c1 != NULL_TREE ? 2 : 1;
1522 continue;
1524 if (c1 == NULL_TREE)
1525 continue;
1526 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
1527 return 2;
1528 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
1529 continue;
1530 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
1531 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
1532 return 2;
1533 if (OMP_CLAUSE_LINEAR_KIND (c1) != OMP_CLAUSE_LINEAR_KIND (c2))
1534 return 2;
1535 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
1536 OMP_CLAUSE_LINEAR_STEP (c2)))
1537 return 2;
1539 FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
1541 c2 = i < data[1].aligned.length () ? data[1].aligned[i] : NULL_TREE;
1542 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
1544 r |= c1 != NULL_TREE ? 2 : 1;
1545 continue;
1547 if (c1 == NULL_TREE)
1548 continue;
1549 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
1550 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
1551 return 2;
1553 switch (r)
1555 case 0: return 0;
1556 case 1: return -1;
1557 case 2: return 1;
1558 case 3: return 2;
1559 default: gcc_unreachable ();
1563 /* Compare properties of selectors SEL from SET other than construct.
1564 Return 0/-1/1/2 as in omp_context_selector_set_compare.
1565 Unlike set names or selector names, properties can have duplicates. */
1567 static int
1568 omp_context_selector_props_compare (const char *set, const char *sel,
1569 tree ctx1, tree ctx2)
1571 int ret = 0;
1572 for (int pass = 0; pass < 2; pass++)
1573 for (tree t1 = pass ? ctx2 : ctx1; t1; t1 = TREE_CHAIN (t1))
1575 tree t2;
1576 for (t2 = pass ? ctx1 : ctx2; t2; t2 = TREE_CHAIN (t2))
1577 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1579 if (TREE_PURPOSE (t1) == NULL_TREE)
1581 if (set[0] == 'u' && strcmp (sel, "condition") == 0)
1583 if (integer_zerop (TREE_VALUE (t1))
1584 != integer_zerop (TREE_VALUE (t2)))
1585 return 2;
1586 break;
1588 if (simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1589 break;
1591 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
1592 " score") == 0)
1594 if (!simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1595 return 2;
1596 break;
1598 else
1599 break;
1601 else if (TREE_PURPOSE (t1)
1602 && TREE_PURPOSE (t2) == NULL_TREE
1603 && TREE_CODE (TREE_VALUE (t2)) == STRING_CST)
1605 const char *p1 = omp_context_name_list_prop (t1);
1606 const char *p2 = omp_context_name_list_prop (t2);
1607 if (p2
1608 && strcmp (p1, p2) == 0
1609 && strcmp (p1, " score"))
1610 break;
1612 else if (TREE_PURPOSE (t1) == NULL_TREE
1613 && TREE_PURPOSE (t2)
1614 && TREE_CODE (TREE_VALUE (t1)) == STRING_CST)
1616 const char *p1 = omp_context_name_list_prop (t1);
1617 const char *p2 = omp_context_name_list_prop (t2);
1618 if (p1
1619 && strcmp (p1, p2) == 0
1620 && strcmp (p1, " score"))
1621 break;
1623 if (t2 == NULL_TREE)
1625 int r = pass ? -1 : 1;
1626 if (ret && ret != r)
1627 return 2;
1628 else if (pass)
1629 return r;
1630 else
1632 ret = r;
1633 break;
1637 return ret;
1640 /* Compare single context selector sets CTX1 and CTX2 with SET name.
1641 Return 0 if CTX1 is equal to CTX2,
1642 -1 if CTX1 is a strict subset of CTX2,
1643 1 if CTX2 is a strict subset of CTX1, or
1644 2 if neither context is a subset of another one. */
1647 omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
1649 bool swapped = false;
1650 int ret = 0;
1651 int len1 = list_length (ctx1);
1652 int len2 = list_length (ctx2);
1653 int cnt = 0;
1654 if (len1 < len2)
1656 swapped = true;
1657 std::swap (ctx1, ctx2);
1658 std::swap (len1, len2);
1660 if (set[0] == 'c')
1662 tree t1;
1663 tree t2 = ctx2;
1664 tree simd = get_identifier ("simd");
1665 /* Handle construct set specially. In this case the order
1666 of the selector matters too. */
1667 for (t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1668 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1670 int r = 0;
1671 if (TREE_PURPOSE (t1) == simd)
1672 r = omp_construct_simd_compare (TREE_VALUE (t1),
1673 TREE_VALUE (t2));
1674 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1675 return 2;
1676 if (ret == 0)
1677 ret = r;
1678 t2 = TREE_CHAIN (t2);
1679 if (t2 == NULL_TREE)
1681 t1 = TREE_CHAIN (t1);
1682 break;
1685 else if (ret < 0)
1686 return 2;
1687 else
1688 ret = 1;
1689 if (t2 != NULL_TREE)
1690 return 2;
1691 if (t1 != NULL_TREE)
1693 if (ret < 0)
1694 return 2;
1695 ret = 1;
1697 if (ret == 0)
1698 return 0;
1699 return swapped ? -ret : ret;
1701 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1703 tree t2;
1704 for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
1705 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1707 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
1708 int r = omp_context_selector_props_compare (set, sel,
1709 TREE_VALUE (t1),
1710 TREE_VALUE (t2));
1711 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1712 return 2;
1713 if (ret == 0)
1714 ret = r;
1715 cnt++;
1716 break;
1718 if (t2 == NULL_TREE)
1720 if (ret == -1)
1721 return 2;
1722 ret = 1;
1725 if (cnt < len2)
1726 return 2;
1727 if (ret == 0)
1728 return 0;
1729 return swapped ? -ret : ret;
1732 /* Compare whole context selector specification CTX1 and CTX2.
1733 Return 0 if CTX1 is equal to CTX2,
1734 -1 if CTX1 is a strict subset of CTX2,
1735 1 if CTX2 is a strict subset of CTX1, or
1736 2 if neither context is a subset of another one. */
1738 static int
1739 omp_context_selector_compare (tree ctx1, tree ctx2)
1741 bool swapped = false;
1742 int ret = 0;
1743 int len1 = list_length (ctx1);
1744 int len2 = list_length (ctx2);
1745 int cnt = 0;
1746 if (len1 < len2)
1748 swapped = true;
1749 std::swap (ctx1, ctx2);
1750 std::swap (len1, len2);
1752 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1754 tree t2;
1755 for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
1756 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1758 const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
1759 int r = omp_context_selector_set_compare (set, TREE_VALUE (t1),
1760 TREE_VALUE (t2));
1761 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1762 return 2;
1763 if (ret == 0)
1764 ret = r;
1765 cnt++;
1766 break;
1768 if (t2 == NULL_TREE)
1770 if (ret == -1)
1771 return 2;
1772 ret = 1;
1775 if (cnt < len2)
1776 return 2;
1777 if (ret == 0)
1778 return 0;
1779 return swapped ? -ret : ret;
1782 /* From context selector CTX, return trait-selector with name SEL in
1783 trait-selector-set with name SET if any, or NULL_TREE if not found.
1784 If SEL is NULL, return the list of trait-selectors in SET. */
1786 tree
1787 omp_get_context_selector (tree ctx, const char *set, const char *sel)
1789 tree setid = get_identifier (set);
1790 tree selid = sel ? get_identifier (sel) : NULL_TREE;
1791 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1792 if (TREE_PURPOSE (t1) == setid)
1794 if (sel == NULL)
1795 return TREE_VALUE (t1);
1796 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1797 if (TREE_PURPOSE (t2) == selid)
1798 return t2;
1800 return NULL_TREE;
1803 /* Compute *SCORE for context selector CTX. Return true if the score
1804 would be different depending on whether it is a declare simd clone or
1805 not. DECLARE_SIMD should be true for the case when it would be
1806 a declare simd clone. */
1808 static bool
1809 omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
1811 tree construct = omp_get_context_selector (ctx, "construct", NULL);
1812 bool has_kind = omp_get_context_selector (ctx, "device", "kind");
1813 bool has_arch = omp_get_context_selector (ctx, "device", "arch");
1814 bool has_isa = omp_get_context_selector (ctx, "device", "isa");
1815 bool ret = false;
1816 *score = 1;
1817 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1818 if (TREE_VALUE (t1) != construct)
1819 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1820 if (tree t3 = TREE_VALUE (t2))
1821 if (TREE_PURPOSE (t3)
1822 && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)), " score") == 0
1823 && TREE_CODE (TREE_VALUE (t3)) == INTEGER_CST)
1824 *score += wi::to_widest (TREE_VALUE (t3));
1825 if (construct || has_kind || has_arch || has_isa)
1827 int scores[12];
1828 enum tree_code constructs[5];
1829 int nconstructs = 0;
1830 if (construct)
1831 nconstructs = omp_constructor_traits_to_codes (construct, constructs);
1832 if (omp_construct_selector_matches (constructs, nconstructs, scores)
1833 == 2)
1834 ret = true;
1835 int b = declare_simd ? nconstructs + 1 : 0;
1836 if (scores[b + nconstructs] + 4U < score->get_precision ())
1838 for (int n = 0; n < nconstructs; ++n)
1840 if (scores[b + n] < 0)
1842 *score = -1;
1843 return ret;
1845 *score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
1847 if (has_kind)
1848 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs],
1849 1, false);
1850 if (has_arch)
1851 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 1,
1852 1, false);
1853 if (has_isa)
1854 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 2,
1855 1, false);
1857 else /* FIXME: Implement this. */
1858 gcc_unreachable ();
1860 return ret;
1863 /* Class describing a single variant. */
1864 struct GTY(()) omp_declare_variant_entry {
1865 /* NODE of the variant. */
1866 cgraph_node *variant;
1867 /* Score if not in declare simd clone. */
1868 widest_int score;
1869 /* Score if in declare simd clone. */
1870 widest_int score_in_declare_simd_clone;
1871 /* Context selector for the variant. */
1872 tree ctx;
1873 /* True if the context selector is known to match already. */
1874 bool matches;
1877 /* Class describing a function with variants. */
1878 struct GTY((for_user)) omp_declare_variant_base_entry {
1879 /* NODE of the base function. */
1880 cgraph_node *base;
1881 /* NODE of the artificial function created for the deferred variant
1882 resolution. */
1883 cgraph_node *node;
1884 /* Vector of the variants. */
1885 vec<omp_declare_variant_entry, va_gc> *variants;
1888 struct omp_declare_variant_hasher
1889 : ggc_ptr_hash<omp_declare_variant_base_entry> {
1890 static hashval_t hash (omp_declare_variant_base_entry *);
1891 static bool equal (omp_declare_variant_base_entry *,
1892 omp_declare_variant_base_entry *);
1895 hashval_t
1896 omp_declare_variant_hasher::hash (omp_declare_variant_base_entry *x)
1898 inchash::hash hstate;
1899 hstate.add_int (DECL_UID (x->base->decl));
1900 hstate.add_int (x->variants->length ());
1901 omp_declare_variant_entry *variant;
1902 unsigned int i;
1903 FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
1905 hstate.add_int (DECL_UID (variant->variant->decl));
1906 hstate.add_wide_int (variant->score);
1907 hstate.add_wide_int (variant->score_in_declare_simd_clone);
1908 hstate.add_ptr (variant->ctx);
1909 hstate.add_int (variant->matches);
1911 return hstate.end ();
1914 bool
1915 omp_declare_variant_hasher::equal (omp_declare_variant_base_entry *x,
1916 omp_declare_variant_base_entry *y)
1918 if (x->base != y->base
1919 || x->variants->length () != y->variants->length ())
1920 return false;
1921 omp_declare_variant_entry *variant;
1922 unsigned int i;
1923 FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
1924 if (variant->variant != (*y->variants)[i].variant
1925 || variant->score != (*y->variants)[i].score
1926 || (variant->score_in_declare_simd_clone
1927 != (*y->variants)[i].score_in_declare_simd_clone)
1928 || variant->ctx != (*y->variants)[i].ctx
1929 || variant->matches != (*y->variants)[i].matches)
1930 return false;
1931 return true;
1934 static GTY(()) hash_table<omp_declare_variant_hasher> *omp_declare_variants;
1936 struct omp_declare_variant_alt_hasher
1937 : ggc_ptr_hash<omp_declare_variant_base_entry> {
1938 static hashval_t hash (omp_declare_variant_base_entry *);
1939 static bool equal (omp_declare_variant_base_entry *,
1940 omp_declare_variant_base_entry *);
1943 hashval_t
1944 omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry *x)
1946 return DECL_UID (x->node->decl);
1949 bool
1950 omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry *x,
1951 omp_declare_variant_base_entry *y)
1953 return x->node == y->node;
1956 static GTY(()) hash_table<omp_declare_variant_alt_hasher>
1957 *omp_declare_variant_alt;
1959 /* Try to resolve declare variant after gimplification. */
1961 static tree
1962 omp_resolve_late_declare_variant (tree alt)
1964 cgraph_node *node = cgraph_node::get (alt);
1965 cgraph_node *cur_node = cgraph_node::get (cfun->decl);
1966 if (node == NULL
1967 || !node->declare_variant_alt
1968 || !cfun->after_inlining)
1969 return alt;
1971 omp_declare_variant_base_entry entry;
1972 entry.base = NULL;
1973 entry.node = node;
1974 entry.variants = NULL;
1975 omp_declare_variant_base_entry *entryp
1976 = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (alt));
1978 unsigned int i, j;
1979 omp_declare_variant_entry *varentry1, *varentry2;
1980 auto_vec <bool, 16> matches;
1981 unsigned int nmatches = 0;
1982 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
1984 if (varentry1->matches)
1986 /* This has been checked to be ok already. */
1987 matches.safe_push (true);
1988 nmatches++;
1989 continue;
1991 switch (omp_context_selector_matches (varentry1->ctx))
1993 case 0:
1994 matches.safe_push (false);
1995 break;
1996 case -1:
1997 return alt;
1998 default:
1999 matches.safe_push (true);
2000 nmatches++;
2001 break;
2005 if (nmatches == 0)
2006 return entryp->base->decl;
2008 /* A context selector that is a strict subset of another context selector
2009 has a score of zero. */
2010 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2011 if (matches[i])
2013 for (j = i + 1;
2014 vec_safe_iterate (entryp->variants, j, &varentry2); ++j)
2015 if (matches[j])
2017 int r = omp_context_selector_compare (varentry1->ctx,
2018 varentry2->ctx);
2019 if (r == -1)
2021 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2022 matches[i] = false;
2023 break;
2025 else if (r == 1)
2026 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2027 matches[j] = false;
2031 widest_int max_score = -1;
2032 varentry2 = NULL;
2033 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2034 if (matches[i])
2036 widest_int score
2037 = (cur_node->simdclone ? varentry1->score_in_declare_simd_clone
2038 : varentry1->score);
2039 if (score > max_score)
2041 max_score = score;
2042 varentry2 = varentry1;
2045 return varentry2->variant->decl;
2048 /* Hook to adjust hash tables on cgraph_node removal. */
2050 static void
2051 omp_declare_variant_remove_hook (struct cgraph_node *node, void *)
2053 if (!node->declare_variant_alt)
2054 return;
2056 /* Drop this hash table completely. */
2057 omp_declare_variants = NULL;
2058 /* And remove node from the other hash table. */
2059 if (omp_declare_variant_alt)
2061 omp_declare_variant_base_entry entry;
2062 entry.base = NULL;
2063 entry.node = node;
2064 entry.variants = NULL;
2065 omp_declare_variant_alt->remove_elt_with_hash (&entry,
2066 DECL_UID (node->decl));
2070 /* Try to resolve declare variant, return the variant decl if it should
2071 be used instead of base, or base otherwise. */
2073 tree
2074 omp_resolve_declare_variant (tree base)
2076 tree variant1 = NULL_TREE, variant2 = NULL_TREE;
2077 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
2078 return omp_resolve_late_declare_variant (base);
2080 auto_vec <tree, 16> variants;
2081 auto_vec <bool, 16> defer;
2082 bool any_deferred = false;
2083 for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
2085 attr = lookup_attribute ("omp declare variant base", attr);
2086 if (attr == NULL_TREE)
2087 break;
2088 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr))) != FUNCTION_DECL)
2089 continue;
2090 cgraph_node *node = cgraph_node::get (base);
2091 /* If this is already a magic decl created by this function,
2092 don't process it again. */
2093 if (node && node->declare_variant_alt)
2094 return base;
2095 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr))))
2097 case 0:
2098 /* No match, ignore. */
2099 break;
2100 case -1:
2101 /* Needs to be deferred. */
2102 any_deferred = true;
2103 variants.safe_push (attr);
2104 defer.safe_push (true);
2105 break;
2106 default:
2107 variants.safe_push (attr);
2108 defer.safe_push (false);
2109 break;
2112 if (variants.length () == 0)
2113 return base;
2115 if (any_deferred)
2117 widest_int max_score1 = 0;
2118 widest_int max_score2 = 0;
2119 bool first = true;
2120 unsigned int i;
2121 tree attr1, attr2;
2122 omp_declare_variant_base_entry entry;
2123 entry.base = cgraph_node::get_create (base);
2124 entry.node = NULL;
2125 vec_alloc (entry.variants, variants.length ());
2126 FOR_EACH_VEC_ELT (variants, i, attr1)
2128 widest_int score1;
2129 widest_int score2;
2130 bool need_two;
2131 tree ctx = TREE_VALUE (TREE_VALUE (attr1));
2132 need_two = omp_context_compute_score (ctx, &score1, false);
2133 if (need_two)
2134 omp_context_compute_score (ctx, &score2, true);
2135 else
2136 score2 = score1;
2137 if (first)
2139 first = false;
2140 max_score1 = score1;
2141 max_score2 = score2;
2142 if (!defer[i])
2144 variant1 = attr1;
2145 variant2 = attr1;
2148 else
2150 if (max_score1 == score1)
2151 variant1 = NULL_TREE;
2152 else if (score1 > max_score1)
2154 max_score1 = score1;
2155 variant1 = defer[i] ? NULL_TREE : attr1;
2157 if (max_score2 == score2)
2158 variant2 = NULL_TREE;
2159 else if (score2 > max_score2)
2161 max_score2 = score2;
2162 variant2 = defer[i] ? NULL_TREE : attr1;
2165 omp_declare_variant_entry varentry;
2166 varentry.variant
2167 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1)));
2168 varentry.score = score1;
2169 varentry.score_in_declare_simd_clone = score2;
2170 varentry.ctx = ctx;
2171 varentry.matches = !defer[i];
2172 entry.variants->quick_push (varentry);
2175 /* If there is a clear winner variant with the score which is not
2176 deferred, verify it is not a strict subset of any other context
2177 selector and if it is not, it is the best alternative no matter
2178 whether the others do or don't match. */
2179 if (variant1 && variant1 == variant2)
2181 tree ctx1 = TREE_VALUE (TREE_VALUE (variant1));
2182 FOR_EACH_VEC_ELT (variants, i, attr2)
2184 if (attr2 == variant1)
2185 continue;
2186 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2187 int r = omp_context_selector_compare (ctx1, ctx2);
2188 if (r == -1)
2190 /* The winner is a strict subset of ctx2, can't
2191 decide now. */
2192 variant1 = NULL_TREE;
2193 break;
2196 if (variant1)
2198 vec_free (entry.variants);
2199 return TREE_PURPOSE (TREE_VALUE (variant1));
2203 static struct cgraph_node_hook_list *node_removal_hook_holder;
2204 if (!node_removal_hook_holder)
2205 node_removal_hook_holder
2206 = symtab->add_cgraph_removal_hook (omp_declare_variant_remove_hook,
2207 NULL);
2209 if (omp_declare_variants == NULL)
2210 omp_declare_variants
2211 = hash_table<omp_declare_variant_hasher>::create_ggc (64);
2212 omp_declare_variant_base_entry **slot
2213 = omp_declare_variants->find_slot (&entry, INSERT);
2214 if (*slot != NULL)
2216 vec_free (entry.variants);
2217 return (*slot)->node->decl;
2220 *slot = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
2221 (*slot)->base = entry.base;
2222 (*slot)->node = entry.base;
2223 (*slot)->variants = entry.variants;
2224 tree alt = build_decl (DECL_SOURCE_LOCATION (base), FUNCTION_DECL,
2225 DECL_NAME (base), TREE_TYPE (base));
2226 DECL_ARTIFICIAL (alt) = 1;
2227 DECL_IGNORED_P (alt) = 1;
2228 TREE_STATIC (alt) = 1;
2229 tree attributes = DECL_ATTRIBUTES (base);
2230 if (lookup_attribute ("noipa", attributes) == NULL)
2232 attributes = tree_cons (get_identifier ("noipa"), NULL, attributes);
2233 if (lookup_attribute ("noinline", attributes) == NULL)
2234 attributes = tree_cons (get_identifier ("noinline"), NULL,
2235 attributes);
2236 if (lookup_attribute ("noclone", attributes) == NULL)
2237 attributes = tree_cons (get_identifier ("noclone"), NULL,
2238 attributes);
2239 if (lookup_attribute ("no_icf", attributes) == NULL)
2240 attributes = tree_cons (get_identifier ("no_icf"), NULL,
2241 attributes);
2243 DECL_ATTRIBUTES (alt) = attributes;
2244 DECL_INITIAL (alt) = error_mark_node;
2245 (*slot)->node = cgraph_node::create (alt);
2246 (*slot)->node->declare_variant_alt = 1;
2247 (*slot)->node->create_reference (entry.base, IPA_REF_ADDR);
2248 omp_declare_variant_entry *varentry;
2249 FOR_EACH_VEC_SAFE_ELT (entry.variants, i, varentry)
2250 (*slot)->node->create_reference (varentry->variant, IPA_REF_ADDR);
2251 if (omp_declare_variant_alt == NULL)
2252 omp_declare_variant_alt
2253 = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
2254 *omp_declare_variant_alt->find_slot_with_hash (*slot, DECL_UID (alt),
2255 INSERT) = *slot;
2256 return alt;
2259 if (variants.length () == 1)
2260 return TREE_PURPOSE (TREE_VALUE (variants[0]));
2262 /* A context selector that is a strict subset of another context selector
2263 has a score of zero. */
2264 tree attr1, attr2;
2265 unsigned int i, j;
2266 FOR_EACH_VEC_ELT (variants, i, attr1)
2267 if (attr1)
2269 tree ctx1 = TREE_VALUE (TREE_VALUE (attr1));
2270 FOR_EACH_VEC_ELT_FROM (variants, j, attr2, i + 1)
2271 if (attr2)
2273 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2274 int r = omp_context_selector_compare (ctx1, ctx2);
2275 if (r == -1)
2277 /* ctx1 is a strict subset of ctx2, remove
2278 attr1 from the vector. */
2279 variants[i] = NULL_TREE;
2280 break;
2282 else if (r == 1)
2283 /* ctx2 is a strict subset of ctx1, remove attr2
2284 from the vector. */
2285 variants[j] = NULL_TREE;
2288 widest_int max_score1 = 0;
2289 widest_int max_score2 = 0;
2290 bool first = true;
2291 FOR_EACH_VEC_ELT (variants, i, attr1)
2292 if (attr1)
2294 if (variant1)
2296 widest_int score1;
2297 widest_int score2;
2298 bool need_two;
2299 tree ctx;
2300 if (first)
2302 first = false;
2303 ctx = TREE_VALUE (TREE_VALUE (variant1));
2304 need_two = omp_context_compute_score (ctx, &max_score1, false);
2305 if (need_two)
2306 omp_context_compute_score (ctx, &max_score2, true);
2307 else
2308 max_score2 = max_score1;
2310 ctx = TREE_VALUE (TREE_VALUE (attr1));
2311 need_two = omp_context_compute_score (ctx, &score1, false);
2312 if (need_two)
2313 omp_context_compute_score (ctx, &score2, true);
2314 else
2315 score2 = score1;
2316 if (score1 > max_score1)
2318 max_score1 = score1;
2319 variant1 = attr1;
2321 if (score2 > max_score2)
2323 max_score2 = score2;
2324 variant2 = attr1;
2327 else
2329 variant1 = attr1;
2330 variant2 = attr1;
2333 /* If there is a disagreement on which variant has the highest score
2334 depending on whether it will be in a declare simd clone or not,
2335 punt for now and defer until after IPA where we will know that. */
2336 return ((variant1 && variant1 == variant2)
2337 ? TREE_PURPOSE (TREE_VALUE (variant1)) : base);
2341 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2342 macro on gomp-constants.h. We do not check for overflow. */
2344 tree
2345 oacc_launch_pack (unsigned code, tree device, unsigned op)
2347 tree res;
2349 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
2350 if (device)
2352 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
2353 device, build_int_cst (unsigned_type_node,
2354 GOMP_LAUNCH_DEVICE_SHIFT));
2355 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
2357 return res;
2360 /* FIXME: What is the following comment for? */
2361 /* Look for compute grid dimension clauses and convert to an attribute
2362 attached to FN. This permits the target-side code to (a) massage
2363 the dimensions, (b) emit that data and (c) optimize. Non-constant
2364 dimensions are pushed onto ARGS.
2366 The attribute value is a TREE_LIST. A set of dimensions is
2367 represented as a list of INTEGER_CST. Those that are runtime
2368 exprs are represented as an INTEGER_CST of zero.
2370 TODO: Normally the attribute will just contain a single such list. If
2371 however it contains a list of lists, this will represent the use of
2372 device_type. Each member of the outer list is an assoc list of
2373 dimensions, keyed by the device type. The first entry will be the
2374 default. Well, that's the plan. */
2376 /* Replace any existing oacc fn attribute with updated dimensions. */
2378 /* Variant working on a list of attributes. */
2380 tree
2381 oacc_replace_fn_attrib_attr (tree attribs, tree dims)
2383 tree ident = get_identifier (OACC_FN_ATTRIB);
2385 /* If we happen to be present as the first attrib, drop it. */
2386 if (attribs && TREE_PURPOSE (attribs) == ident)
2387 attribs = TREE_CHAIN (attribs);
2388 return tree_cons (ident, dims, attribs);
2391 /* Variant working on a function decl. */
2393 void
2394 oacc_replace_fn_attrib (tree fn, tree dims)
2396 DECL_ATTRIBUTES (fn)
2397 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn), dims);
2400 /* Scan CLAUSES for launch dimensions and attach them to the oacc
2401 function attribute. Push any that are non-constant onto the ARGS
2402 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
2404 void
2405 oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
2407 /* Must match GOMP_DIM ordering. */
2408 static const omp_clause_code ids[]
2409 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
2410 OMP_CLAUSE_VECTOR_LENGTH };
2411 unsigned ix;
2412 tree dims[GOMP_DIM_MAX];
2414 tree attr = NULL_TREE;
2415 unsigned non_const = 0;
2417 for (ix = GOMP_DIM_MAX; ix--;)
2419 tree clause = omp_find_clause (clauses, ids[ix]);
2420 tree dim = NULL_TREE;
2422 if (clause)
2423 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
2424 dims[ix] = dim;
2425 if (dim && TREE_CODE (dim) != INTEGER_CST)
2427 dim = integer_zero_node;
2428 non_const |= GOMP_DIM_MASK (ix);
2430 attr = tree_cons (NULL_TREE, dim, attr);
2433 oacc_replace_fn_attrib (fn, attr);
2435 if (non_const)
2437 /* Push a dynamic argument set. */
2438 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
2439 NULL_TREE, non_const));
2440 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
2441 if (non_const & GOMP_DIM_MASK (ix))
2442 args->safe_push (dims[ix]);
2446 /* Verify OpenACC routine clauses.
2448 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
2449 if it has already been marked in compatible way, and -1 if incompatible.
2450 Upon returning, the chain of clauses will contain exactly one clause
2451 specifying the level of parallelism. */
2454 oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc,
2455 const char *routine_str)
2457 tree c_level = NULL_TREE;
2458 tree c_p = NULL_TREE;
2459 for (tree c = *clauses; c; c_p = c, c = OMP_CLAUSE_CHAIN (c))
2460 switch (OMP_CLAUSE_CODE (c))
2462 case OMP_CLAUSE_GANG:
2463 case OMP_CLAUSE_WORKER:
2464 case OMP_CLAUSE_VECTOR:
2465 case OMP_CLAUSE_SEQ:
2466 if (c_level == NULL_TREE)
2467 c_level = c;
2468 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_CODE (c_level))
2470 /* This has already been diagnosed in the front ends. */
2471 /* Drop the duplicate clause. */
2472 gcc_checking_assert (c_p != NULL_TREE);
2473 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
2474 c = c_p;
2476 else
2478 error_at (OMP_CLAUSE_LOCATION (c),
2479 "%qs specifies a conflicting level of parallelism",
2480 omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
2481 inform (OMP_CLAUSE_LOCATION (c_level),
2482 "... to the previous %qs clause here",
2483 omp_clause_code_name[OMP_CLAUSE_CODE (c_level)]);
2484 /* Drop the conflicting clause. */
2485 gcc_checking_assert (c_p != NULL_TREE);
2486 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
2487 c = c_p;
2489 break;
2490 default:
2491 gcc_unreachable ();
2493 if (c_level == NULL_TREE)
2495 /* Default to an implicit 'seq' clause. */
2496 c_level = build_omp_clause (loc, OMP_CLAUSE_SEQ);
2497 OMP_CLAUSE_CHAIN (c_level) = *clauses;
2498 *clauses = c_level;
2500 /* In *clauses, we now have exactly one clause specifying the level of
2501 parallelism. */
2503 tree attr
2504 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl));
2505 if (attr != NULL_TREE)
2507 /* Diagnose if "#pragma omp declare target" has also been applied. */
2508 if (TREE_VALUE (attr) == NULL_TREE)
2510 /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
2511 OpenACC and OpenMP 'target' are not clear. */
2512 error_at (loc,
2513 "cannot apply %<%s%> to %qD, which has also been"
2514 " marked with an OpenMP 'declare target' directive",
2515 routine_str, fndecl);
2516 /* Incompatible. */
2517 return -1;
2520 /* If a "#pragma acc routine" has already been applied, just verify
2521 this one for compatibility. */
2522 /* Collect previous directive's clauses. */
2523 tree c_level_p = NULL_TREE;
2524 for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c))
2525 switch (OMP_CLAUSE_CODE (c))
2527 case OMP_CLAUSE_GANG:
2528 case OMP_CLAUSE_WORKER:
2529 case OMP_CLAUSE_VECTOR:
2530 case OMP_CLAUSE_SEQ:
2531 gcc_checking_assert (c_level_p == NULL_TREE);
2532 c_level_p = c;
2533 break;
2534 default:
2535 gcc_unreachable ();
2537 gcc_checking_assert (c_level_p != NULL_TREE);
2538 /* ..., and compare to current directive's, which we've already collected
2539 above. */
2540 tree c_diag;
2541 tree c_diag_p;
2542 /* Matching level of parallelism? */
2543 if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
2545 c_diag = c_level;
2546 c_diag_p = c_level_p;
2547 goto incompatible;
2549 /* Compatible. */
2550 return 1;
2552 incompatible:
2553 if (c_diag != NULL_TREE)
2554 error_at (OMP_CLAUSE_LOCATION (c_diag),
2555 "incompatible %qs clause when applying"
2556 " %<%s%> to %qD, which has already been"
2557 " marked with an OpenACC 'routine' directive",
2558 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)],
2559 routine_str, fndecl);
2560 else if (c_diag_p != NULL_TREE)
2561 error_at (loc,
2562 "missing %qs clause when applying"
2563 " %<%s%> to %qD, which has already been"
2564 " marked with an OpenACC 'routine' directive",
2565 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)],
2566 routine_str, fndecl);
2567 else
2568 gcc_unreachable ();
2569 if (c_diag_p != NULL_TREE)
2570 inform (OMP_CLAUSE_LOCATION (c_diag_p),
2571 "... with %qs clause here",
2572 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]);
2573 else
2575 /* In the front ends, we don't preserve location information for the
2576 OpenACC routine directive itself. However, that of c_level_p
2577 should be close. */
2578 location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p);
2579 inform (loc_routine, "... without %qs clause near to here",
2580 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]);
2582 /* Incompatible. */
2583 return -1;
2586 return 0;
2589 /* Process the OpenACC 'routine' directive clauses to generate an attribute
2590 for the level of parallelism. All dimensions have a size of zero
2591 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
2592 can have a loop partitioned on it. non-zero indicates
2593 yes, zero indicates no. By construction once a non-zero has been
2594 reached, further inner dimensions must also be non-zero. We set
2595 TREE_VALUE to zero for the dimensions that may be partitioned and
2596 1 for the other ones -- if a loop is (erroneously) spawned at
2597 an outer level, we don't want to try and partition it. */
2599 tree
2600 oacc_build_routine_dims (tree clauses)
2602 /* Must match GOMP_DIM ordering. */
2603 static const omp_clause_code ids[]
2604 = {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
2605 int ix;
2606 int level = -1;
2608 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
2609 for (ix = GOMP_DIM_MAX + 1; ix--;)
2610 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
2612 level = ix;
2613 break;
2615 gcc_checking_assert (level >= 0);
2617 tree dims = NULL_TREE;
2619 for (ix = GOMP_DIM_MAX; ix--;)
2620 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
2621 build_int_cst (integer_type_node, ix < level), dims);
2623 return dims;
2626 /* Retrieve the oacc function attrib and return it. Non-oacc
2627 functions will return NULL. */
2629 tree
2630 oacc_get_fn_attrib (tree fn)
2632 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
2635 /* Return true if FN is an OpenMP or OpenACC offloading function. */
2637 bool
2638 offloading_function_p (tree fn)
2640 tree attrs = DECL_ATTRIBUTES (fn);
2641 return (lookup_attribute ("omp declare target", attrs)
2642 || lookup_attribute ("omp target entrypoint", attrs));
2645 /* Extract an oacc execution dimension from FN. FN must be an
2646 offloaded function or routine that has already had its execution
2647 dimensions lowered to the target-specific values. */
2650 oacc_get_fn_dim_size (tree fn, int axis)
2652 tree attrs = oacc_get_fn_attrib (fn);
2654 gcc_assert (axis < GOMP_DIM_MAX);
2656 tree dims = TREE_VALUE (attrs);
2657 while (axis--)
2658 dims = TREE_CHAIN (dims);
2660 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
2662 return size;
2665 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
2666 IFN_GOACC_DIM_SIZE call. */
2669 oacc_get_ifn_dim_arg (const gimple *stmt)
2671 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
2672 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
2673 tree arg = gimple_call_arg (stmt, 0);
2674 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
2676 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
2677 return (int) axis;
2680 #include "gt-omp-general.h"