Default to dwarf version 4 on hppa64-hpux
[official-gcc.git] / gcc / omp-general.c
blob1e4c0b2553154c7123f6824bf9ec3aee252a5658
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
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"
45 #include "data-streamer.h"
46 #include "streamer-hooks.h"
48 enum omp_requires omp_requires_mask;
50 tree
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)
55 return clauses;
57 return NULL_TREE;
60 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
61 allocatable or pointer attribute. */
62 bool
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. */
76 tree
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. */
85 bool
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. */
94 void
95 omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2,
96 tree v, tree step)
98 switch (*cond_code)
100 case LT_EXPR:
101 case GT_EXPR:
102 break;
104 case NE_EXPR:
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;
110 else
112 gcc_assert (integer_minus_onep (step));
113 *cond_code = GT_EXPR;
116 else
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;
122 else
124 gcc_assert (wi::neg (wi::to_widest (unit))
125 == wi::to_widest (step));
126 *cond_code = GT_EXPR;
130 break;
132 case LE_EXPR:
133 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
134 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
135 else
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;
139 break;
140 case GE_EXPR:
141 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
142 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
143 else
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;
147 break;
148 default:
149 gcc_unreachable ();
153 /* Return the looping step from INCR, extracted from the step of a gimple omp
154 for statement. */
156 tree
157 omp_get_for_step_from_incr (location_t loc, tree incr)
159 tree step;
160 switch (TREE_CODE (incr))
162 case PLUS_EXPR:
163 step = TREE_OPERAND (incr, 1);
164 break;
165 case POINTER_PLUS_EXPR:
166 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
167 break;
168 case MINUS_EXPR:
169 step = TREE_OPERAND (incr, 1);
170 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
171 break;
172 default:
173 gcc_unreachable ();
175 return step;
178 /* Extract the header elements of parallel loop FOR_STMT and store
179 them into *FD. */
181 void
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;
188 int i;
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;
197 tree iterv, countv;
199 fd->for_stmt = for_stmt;
200 fd->pre = NULL;
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;
210 fd->collapse = 1;
211 fd->ordered = 0;
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;
229 break;
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));
234 break;
235 case OMP_CLAUSE_SCHEDULE:
236 gcc_assert (!distribute && !taskloop);
237 fd->sched_kind
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);
244 break;
245 case OMP_CLAUSE_DIST_SCHEDULE:
246 gcc_assert (distribute);
247 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
248 break;
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);
256 break;
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);
263 break;
264 case OMP_CLAUSE__REDUCTEMP_:
265 fd->have_reductemp = true;
266 break;
267 case OMP_CLAUSE_LASTPRIVATE:
268 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
269 fd->lastprivate_conditional++;
270 break;
271 case OMP_CLAUSE__CONDTEMP_:
272 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
273 fd->have_pointer_condtemp = true;
274 break;
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;
280 break;
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;
288 default:
289 break;
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)
301 fd->loops = loops;
302 else
303 fd->loops = &fd->loop;
305 if (fd->ordered && fd->collapse == 1 && loops != NULL)
307 fd->loops = loops;
308 iterv = NULL_TREE;
309 countv = NULL_TREE;
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);
324 if (taskloop)
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
333 || fd->have_ordered)
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)
348 if (fd->non_rect)
350 single_nonrect = -1;
351 break;
353 for (int j = i - 1; j >= 0; j--)
354 if (TREE_VEC_ELT (n1, 0) == gimple_omp_for_index (for_stmt, j))
356 single_nonrect = j;
357 break;
359 fd->non_rect = true;
361 else if (TREE_CODE (n2) == TREE_VEC)
363 if (fd->non_rect)
365 single_nonrect = -1;
366 break;
368 for (int j = i - 1; j >= 0; j--)
369 if (TREE_VEC_ELT (n2, 0) == gimple_omp_for_index (for_stmt, j))
371 single_nonrect = j;
372 break;
374 fd->non_rect = true;
377 for (i = 0; i < cnt; i++)
379 if (i == 0
380 && fd->collapse == 1
381 && !fd->tiling
382 && (fd->ordered == 0 || loops == NULL))
383 loop = &fd->loop;
384 else if (loops != NULL)
385 loop = loops + i;
386 else
387 loop = &dummy_loop;
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;
397 loop->outer = 0;
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))
404 loop->outer = i - j;
405 if (loops != NULL)
406 loops[j].non_rect_referenced = true;
407 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
408 fd->first_nonrect = j;
409 break;
411 gcc_assert (loop->outer);
412 loop->m1 = TREE_VEC_ELT (loop->n1, 1);
413 loop->n1 = TREE_VEC_ELT (loop->n1, 2);
414 fd->non_rect = true;
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)
425 if (loop->outer)
426 gcc_assert (TREE_VEC_ELT (loop->n2, 0)
427 == gimple_omp_for_index (for_stmt, i - loop->outer));
428 else
429 for (int j = i - 1; j >= 0; j--)
430 if (TREE_VEC_ELT (loop->n2, 0) == gimple_omp_for_index (for_stmt, j))
432 loop->outer = i - j;
433 if (loops != NULL)
434 loops[j].non_rect_referenced = true;
435 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
436 fd->first_nonrect = j;
437 break;
439 gcc_assert (loop->outer);
440 loop->m2 = TREE_VEC_ELT (loop->n2, 1);
441 loop->n2 = TREE_VEC_ELT (loop->n2, 2);
442 fd->non_rect = true;
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,
451 loop->step);
453 if (simd
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);
459 else if (i == 0
460 || TYPE_PRECISION (iter_type)
461 < TYPE_PRECISION (TREE_TYPE (loop->v)))
462 iter_type
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))
474 tree n;
476 if (loop->cond_code == LT_EXPR)
477 n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
478 loop->n2, loop->step);
479 else
480 n = loop->n1;
481 if (loop->m1
482 || loop->m2
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))
490 tree n1, n2;
492 if (loop->cond_code == LT_EXPR)
494 n1 = loop->n1;
495 n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
496 loop->n2, loop->step);
498 else
500 n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
501 loop->n2, loop->step);
502 n2 = loop->n1;
504 if (loop->m1
505 || loop->m2
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)
515 continue;
517 if (collapse_count && *collapse_count == NULL)
519 if (count && integer_zerop (count))
520 continue;
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)
527 continue;
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)
535 count = NULL_TREE;
536 continue;
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,
551 ostep));
552 if (TREE_CODE (first) != INTEGER_CST
553 || TREE_CODE (last) != INTEGER_CST)
555 count = NULL_TREE;
556 continue;
558 if (loop->m1)
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,
564 first, m1), n1);
565 n1last = fold_binary (PLUS_EXPR, itype,
566 fold_binary (MULT_EXPR, itype,
567 last, m1), n1);
569 else
570 n1first = n1last = loop->n1;
571 if (loop->m2)
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,
577 first, m2), n2);
578 n2last = fold_binary (PLUS_EXPR, itype,
579 fold_binary (MULT_EXPR, itype,
580 last, m2), n2);
582 else
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,
589 n1first, n2first);
590 tree t2 = fold_binary (loop->cond_code, boolean_type_node,
591 n1last, n2last);
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. */
595 t = NULL_TREE;
596 else if (t && t2 && integer_zerop (t) && integer_zerop (t2))
597 /* No iterations of the inner loop. count will be set to
598 zero cst below. */;
599 else if (TYPE_UNSIGNED (itype)
600 || t == NULL_TREE
601 || t2 == NULL_TREE
602 || TREE_CODE (t) != INTEGER_CST
603 || TREE_CODE (t2) != INTEGER_CST)
605 /* Punt (for now). */
606 count = NULL_TREE;
607 continue;
609 else
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);
629 tree n1cur
630 = fold_binary (PLUS_EXPR, itype, n1,
631 fold_binary (MULT_EXPR, itype, m1, t));
632 tree n2cur
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,
636 n1cur, n2cur);
637 tree t3 = fold_binary (MULT_EXPR, itype, m1, ostep);
638 tree t4 = fold_binary (MULT_EXPR, itype, m2, ostep);
639 tree diff;
640 if (adj_first)
642 tree new_first;
643 if (integer_nonzerop (t2))
645 new_first = t;
646 n1first = n1cur;
647 n2first = n2cur;
648 if (flag_checking)
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));
657 else
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);
662 n1first = t3;
663 n2first = t4;
664 if (flag_checking)
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);
672 first = new_first;
673 fd->adjn1 = first;
675 else
677 tree new_last;
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);
683 n1last = t3;
684 n2last = t4;
685 if (flag_checking)
687 t3 = fold_binary (loop->cond_code,
688 boolean_type_node, t3, t4);
689 gcc_assert (integer_nonzerop (t3));
692 else
694 new_last = t;
695 n1last = n1cur;
696 n2last = n2cur;
697 if (flag_checking)
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,
713 ostep));
714 else
715 diff = fold_binary (TRUNC_DIV_EXPR, itype, diff, ostep);
716 diff = fold_convert (long_long_unsigned_type_node, diff);
717 single_nonrect_count
718 = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
719 single_nonrect_count, diff);
720 t = NULL_TREE;
723 else
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);
742 tree n1 = loop->n1;
743 tree n2 = loop->n2;
744 if (loop->m1 || loop->m2)
746 gcc_assert (single_nonrect != -1);
747 n1 = n1first;
748 n2 = n2first;
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));
757 else
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
765 iterations).
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));
780 else
781 t2 = fold_build2 (TRUNC_DIV_EXPR, itype, t2, step);
782 t2 = fold_convert (llutype, t2);
783 fd->first_inner_iterations = t;
784 fd->factor = t2;
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)
800 count = t;
801 else
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);
811 else
812 count = t;
813 if (TREE_CODE (count) != INTEGER_CST)
814 count = NULL_TREE;
816 else if (count && !integer_zerop (count))
817 count = NULL_TREE;
821 if (count
822 && !simd
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;
828 else
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)
838 if (count)
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;
848 *collapse_count = t;
851 else
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;
871 fd->loop.outer = 0;
872 fd->loop.cond_code = LT_EXPR;
874 else if (loops)
875 loops[0] = fd->loop;
878 /* Build a call to GOMP_barrier. */
880 gimple *
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);
886 if (lhs)
887 gimple_call_set_lhs (g, lhs);
888 return g;
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
895 OMP_FOR/OMP_SIMD. */
897 tree
898 find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
900 tree **pdata = (tree **) data;
901 *walk_subtrees = 0;
902 switch (TREE_CODE (*tp))
904 case OMP_FOR:
905 if (OMP_FOR_INIT (*tp) != NULL_TREE)
907 pdata[3] = tp;
908 return *tp;
910 pdata[2] = tp;
911 *walk_subtrees = 1;
912 break;
913 case OMP_SIMD:
914 if (OMP_FOR_INIT (*tp) != NULL_TREE)
916 pdata[3] = tp;
917 return *tp;
919 break;
920 case BIND_EXPR:
921 if (BIND_EXPR_VARS (*tp)
922 || (BIND_EXPR_BLOCK (*tp)
923 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
924 pdata[0] = tp;
925 *walk_subtrees = 1;
926 break;
927 case STATEMENT_LIST:
928 if (!tsi_one_before_end_p (tsi_start (*tp)))
929 pdata[0] = tp;
930 *walk_subtrees = 1;
931 break;
932 case TRY_FINALLY_EXPR:
933 pdata[0] = tp;
934 *walk_subtrees = 1;
935 break;
936 case OMP_PARALLEL:
937 pdata[1] = tp;
938 *walk_subtrees = 1;
939 break;
940 default:
941 break;
943 return NULL_TREE;
946 /* Return maximum possible vectorization factor for the target. */
948 poly_uint64
949 omp_max_vf (void)
951 if (!optimize
952 || optimize_debug
953 || !flag_tree_loop_optimize
954 || (!flag_tree_loop_vectorize
955 && global_options_set.x_flag_tree_loop_vectorize))
956 return 1;
958 auto_vector_modes modes;
959 targetm.vectorize.autovectorize_vector_modes (&modes, true);
960 if (!modes.is_empty ())
962 poly_uint64 vf = 0;
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
966 represent. */
967 vf = ordered_max (vf, GET_MODE_NUNITS (modes[i]));
968 return vf;
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);
975 return 1;
978 /* Return maximum SIMT width if offloading may target SIMT hardware. */
981 omp_max_simt_vf (void)
983 if (!optimize)
984 return 0;
985 if (ENABLE_OFFLOADING)
986 for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
988 if (startswith (c, "nvptx"))
989 return 32;
990 else if ((c = strchr (c, ':')))
991 c++;
993 return 0;
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;
1017 else
1018 gcc_unreachable ();
1020 gcc_assert (i == -1);
1021 return nconstructs;
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. */
1031 static bool
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')
1036 return false;
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] == '='))
1048 matches = true;
1049 break;
1051 else if ((c = strchr (c, ':')))
1052 c++;
1054 props = props + name_len + 1;
1055 while (*props != '\0')
1057 if (matches && strcmp (props, prop) == 0)
1058 return true;
1059 props = strchr (props, '\0') + 1;
1061 props++;
1063 return false;
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. */
1070 static bool
1071 omp_maybe_offloaded (void)
1073 if (!ENABLE_OFFLOADING)
1074 return false;
1075 const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1076 if (names == NULL || *names == '\0')
1077 return false;
1079 if (symtab->state == PARSING)
1080 /* Maybe. */
1081 return true;
1082 if (cfun && cfun->after_inlining)
1083 return false;
1084 if (current_function_decl
1085 && lookup_attribute ("omp declare target",
1086 DECL_ATTRIBUTES (current_function_decl)))
1087 return true;
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))
1092 return true;
1094 return false;
1097 /* Return a name from PROP, a property in selectors accepting
1098 name lists. */
1100 static const char *
1101 omp_context_name_list_prop (tree prop)
1103 if (TREE_PURPOSE (prop))
1104 return IDENTIFIER_POINTER (TREE_PURPOSE (prop));
1105 else
1107 const char *ret = TREE_STRING_POINTER (TREE_VALUE (prop));
1108 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop)) == strlen (ret) + 1)
1109 return ret;
1110 return NULL;
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)
1123 int ret = 1;
1124 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1126 char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0];
1127 if (set == 'c')
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
1135 gimplification. */
1136 if (symtab->state == PARSING)
1138 ret = -1;
1139 continue;
1142 enum tree_code constructs[5];
1143 int nconstructs
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)
1150 ret = -1;
1151 continue;
1153 int i;
1154 for (i = 0; i < nconstructs; ++i)
1155 if (constructs[i] == OMP_SIMD)
1156 break;
1157 if (i < nconstructs)
1159 ret = -1;
1160 continue;
1162 /* If there is no simd, assume it is ok after IPA,
1163 constructs should have been checked before. */
1164 continue;
1167 int r = omp_construct_selector_matches (constructs, nconstructs,
1168 NULL);
1169 if (r == 0)
1170 return 0;
1171 if (r == -1)
1172 ret = -1;
1173 continue;
1175 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1177 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
1178 switch (*sel)
1180 case 'v':
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);
1185 if (prop == NULL)
1186 return 0;
1187 if ((!strcmp (prop, " score") && TREE_PURPOSE (t3))
1188 || !strcmp (prop, "gnu"))
1189 continue;
1190 return 0;
1192 break;
1193 case 'e':
1194 if (set == 'i' && !strcmp (sel, "extension"))
1195 /* We don't support any extensions right now. */
1196 return 0;
1197 break;
1198 case 'a':
1199 if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
1201 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1202 break;
1204 enum omp_memory_order omo
1205 = ((enum omp_memory_order)
1206 (omp_requires_mask
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)
1213 ret = -1;
1214 break;
1216 else
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)
1228 return 0;
1229 else if (!strcmp (prop, "seq_cst")
1230 && omo != OMP_MEMORY_ORDER_SEQ_CST)
1231 return 0;
1232 else if (!strcmp (prop, "acq_rel")
1233 && omo != OMP_MEMORY_ORDER_ACQ_REL)
1234 return 0;
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);
1240 if (arch == NULL)
1241 return 0;
1242 int r = 0;
1243 if (targetm.omp.device_kind_arch_isa != NULL)
1244 r = targetm.omp.device_kind_arch_isa (omp_device_arch,
1245 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 ())
1252 return 0;
1253 if (ENABLE_OFFLOADING)
1255 const char *arches = omp_offload_device_arch;
1256 if (omp_offload_device_kind_arch_isa (arches,
1257 arch))
1259 ret = -1;
1260 continue;
1263 return 0;
1265 else if (r == -1)
1266 ret = -1;
1267 /* If arch matches on the host, it still might not match
1268 in the offloading region. */
1269 else if (omp_maybe_offloaded ())
1270 ret = -1;
1272 break;
1273 case 'u':
1274 if (set == 'i' && !strcmp (sel, "unified_address"))
1276 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1277 break;
1279 if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
1281 if (symtab->state == PARSING)
1282 ret = -1;
1283 else
1284 return 0;
1286 break;
1288 if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
1290 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1291 break;
1293 if ((omp_requires_mask
1294 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
1296 if (symtab->state == PARSING)
1297 ret = -1;
1298 else
1299 return 0;
1301 break;
1303 break;
1304 case 'd':
1305 if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
1307 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1308 break;
1310 if ((omp_requires_mask
1311 & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1313 if (symtab->state == PARSING)
1314 ret = -1;
1315 else
1316 return 0;
1318 break;
1320 break;
1321 case 'r':
1322 if (set == 'i' && !strcmp (sel, "reverse_offload"))
1324 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1325 break;
1327 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
1329 if (symtab->state == PARSING)
1330 ret = -1;
1331 else
1332 return 0;
1334 break;
1336 break;
1337 case 'k':
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);
1342 if (prop == NULL)
1343 return 0;
1344 if (!strcmp (prop, "any"))
1345 continue;
1346 if (!strcmp (prop, "host"))
1348 if (omp_maybe_offloaded ())
1349 ret = -1;
1350 continue;
1352 if (!strcmp (prop, "nohost"))
1354 if (omp_maybe_offloaded ())
1355 ret = -1;
1356 else
1357 return 0;
1358 continue;
1360 int r = 0;
1361 if (targetm.omp.device_kind_arch_isa != NULL)
1362 r = targetm.omp.device_kind_arch_isa (omp_device_kind,
1363 prop);
1364 else
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 ())
1372 return 0;
1373 if (ENABLE_OFFLOADING)
1375 const char *kinds = omp_offload_device_kind;
1376 if (omp_offload_device_kind_arch_isa (kinds, prop))
1378 ret = -1;
1379 continue;
1382 return 0;
1384 else if (r == -1)
1385 ret = -1;
1386 /* If kind matches on the host, it still might not match
1387 in the offloading region. */
1388 else if (omp_maybe_offloaded ())
1389 ret = -1;
1391 break;
1392 case 'i':
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);
1397 if (isa == NULL)
1398 return 0;
1399 int r = 0;
1400 if (targetm.omp.device_kind_arch_isa != NULL)
1401 r = targetm.omp.device_kind_arch_isa (omp_device_isa,
1402 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. */
1409 if (r == -1
1410 && targetm.simd_clone.compute_vecsize_and_simdlen
1411 && (cfun == NULL || !cfun->after_inlining))
1413 tree attrs
1414 = DECL_ATTRIBUTES (current_function_decl);
1415 if (lookup_attribute ("omp declare simd", attrs))
1417 ret = -1;
1418 continue;
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 ())
1425 return 0;
1426 if (ENABLE_OFFLOADING)
1428 const char *isas = omp_offload_device_isa;
1429 if (omp_offload_device_kind_arch_isa (isas, isa))
1431 ret = -1;
1432 continue;
1435 return 0;
1437 else if (r == -1)
1438 ret = -1;
1439 /* If isa matches on the host, it still might not match
1440 in the offloading region. */
1441 else if (omp_maybe_offloaded ())
1442 ret = -1;
1444 break;
1445 case 'c':
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)))
1451 return 0;
1452 if (integer_nonzerop (TREE_VALUE (t3)))
1453 break;
1454 ret = -1;
1456 break;
1457 default:
1458 break;
1462 return ret;
1465 /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1466 in omp_context_selector_set_compare. */
1468 static int
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)
1474 return 1;
1476 int r = 0;
1477 struct declare_variant_simd_data {
1478 bool inbranch, notinbranch;
1479 tree simdlen;
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) {}
1484 } data[2];
1485 unsigned int i;
1486 for (i = 0; i < 2; i++)
1487 for (tree c = i ? clauses2 : clauses1; c; c = OMP_CLAUSE_CHAIN (c))
1489 vec<tree> *v;
1490 switch (OMP_CLAUSE_CODE (c))
1492 case OMP_CLAUSE_INBRANCH:
1493 data[i].inbranch = true;
1494 continue;
1495 case OMP_CLAUSE_NOTINBRANCH:
1496 data[i].notinbranch = true;
1497 continue;
1498 case OMP_CLAUSE_SIMDLEN:
1499 data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
1500 continue;
1501 case OMP_CLAUSE_UNIFORM:
1502 case OMP_CLAUSE_LINEAR:
1503 v = &data[i].data_sharing;
1504 break;
1505 case OMP_CLAUSE_ALIGNED:
1506 v = &data[i].aligned;
1507 break;
1508 default:
1509 gcc_unreachable ();
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);
1514 (*v)[argno] = c;
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)
1527 return 2;
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 ())
1532 r |= 1;
1533 tree c1, c2;
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;
1541 continue;
1543 if (c1 == NULL_TREE)
1544 continue;
1545 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
1546 return 2;
1547 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
1548 continue;
1549 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
1550 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
1551 return 2;
1552 if (OMP_CLAUSE_LINEAR_KIND (c1) != OMP_CLAUSE_LINEAR_KIND (c2))
1553 return 2;
1554 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
1555 OMP_CLAUSE_LINEAR_STEP (c2)))
1556 return 2;
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;
1564 continue;
1566 if (c1 == NULL_TREE)
1567 continue;
1568 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
1569 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
1570 return 2;
1572 switch (r)
1574 case 0: return 0;
1575 case 1: return -1;
1576 case 2: return 1;
1577 case 3: return 2;
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. */
1586 static int
1587 omp_context_selector_props_compare (const char *set, const char *sel,
1588 tree ctx1, tree ctx2)
1590 int ret = 0;
1591 for (int pass = 0; pass < 2; pass++)
1592 for (tree t1 = pass ? ctx2 : ctx1; t1; t1 = TREE_CHAIN (t1))
1594 tree t2;
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)))
1604 return 2;
1605 break;
1607 if (simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1608 break;
1610 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
1611 " score") == 0)
1613 if (!simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1614 return 2;
1615 break;
1617 else
1618 break;
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);
1626 if (p2
1627 && strcmp (p1, p2) == 0
1628 && strcmp (p1, " score"))
1629 break;
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);
1637 if (p1
1638 && strcmp (p1, p2) == 0
1639 && strcmp (p1, " score"))
1640 break;
1642 if (t2 == NULL_TREE)
1644 int r = pass ? -1 : 1;
1645 if (ret && ret != r)
1646 return 2;
1647 else if (pass)
1648 return r;
1649 else
1651 ret = r;
1652 break;
1656 return ret;
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;
1669 int ret = 0;
1670 int len1 = list_length (ctx1);
1671 int len2 = list_length (ctx2);
1672 int cnt = 0;
1673 if (len1 < len2)
1675 swapped = true;
1676 std::swap (ctx1, ctx2);
1677 std::swap (len1, len2);
1679 if (set[0] == 'c')
1681 tree t1;
1682 tree t2 = ctx2;
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))
1689 int r = 0;
1690 if (TREE_PURPOSE (t1) == simd)
1691 r = omp_construct_simd_compare (TREE_VALUE (t1),
1692 TREE_VALUE (t2));
1693 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1694 return 2;
1695 if (ret == 0)
1696 ret = r;
1697 t2 = TREE_CHAIN (t2);
1698 if (t2 == NULL_TREE)
1700 t1 = TREE_CHAIN (t1);
1701 break;
1704 else if (ret < 0)
1705 return 2;
1706 else
1707 ret = 1;
1708 if (t2 != NULL_TREE)
1709 return 2;
1710 if (t1 != NULL_TREE)
1712 if (ret < 0)
1713 return 2;
1714 ret = 1;
1716 if (ret == 0)
1717 return 0;
1718 return swapped ? -ret : ret;
1720 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1722 tree t2;
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,
1728 TREE_VALUE (t1),
1729 TREE_VALUE (t2));
1730 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1731 return 2;
1732 if (ret == 0)
1733 ret = r;
1734 cnt++;
1735 break;
1737 if (t2 == NULL_TREE)
1739 if (ret == -1)
1740 return 2;
1741 ret = 1;
1744 if (cnt < len2)
1745 return 2;
1746 if (ret == 0)
1747 return 0;
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. */
1757 static int
1758 omp_context_selector_compare (tree ctx1, tree ctx2)
1760 bool swapped = false;
1761 int ret = 0;
1762 int len1 = list_length (ctx1);
1763 int len2 = list_length (ctx2);
1764 int cnt = 0;
1765 if (len1 < len2)
1767 swapped = true;
1768 std::swap (ctx1, ctx2);
1769 std::swap (len1, len2);
1771 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1773 tree t2;
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),
1779 TREE_VALUE (t2));
1780 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1781 return 2;
1782 if (ret == 0)
1783 ret = r;
1784 cnt++;
1785 break;
1787 if (t2 == NULL_TREE)
1789 if (ret == -1)
1790 return 2;
1791 ret = 1;
1794 if (cnt < len2)
1795 return 2;
1796 if (ret == 0)
1797 return 0;
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. */
1805 tree
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)
1813 if (sel == NULL)
1814 return TREE_VALUE (t1);
1815 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1816 if (TREE_PURPOSE (t2) == selid)
1817 return t2;
1819 return NULL_TREE;
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. */
1827 static bool
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");
1834 bool ret = false;
1835 *score = 1;
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)
1846 int scores[12];
1847 enum tree_code constructs[5];
1848 int nconstructs = 0;
1849 if (construct)
1850 nconstructs = omp_constructor_traits_to_codes (construct, constructs);
1851 if (omp_construct_selector_matches (constructs, nconstructs, scores)
1852 == 2)
1853 ret = true;
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)
1861 *score = -1;
1862 return ret;
1864 *score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
1866 if (has_kind)
1867 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs],
1868 1, false);
1869 if (has_arch)
1870 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 1,
1871 1, false);
1872 if (has_isa)
1873 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 2,
1874 1, false);
1876 else /* FIXME: Implement this. */
1877 gcc_unreachable ();
1879 return ret;
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. */
1887 widest_int score;
1888 /* Score if in declare simd clone. */
1889 widest_int score_in_declare_simd_clone;
1890 /* Context selector for the variant. */
1891 tree ctx;
1892 /* True if the context selector is known to match already. */
1893 bool matches;
1896 /* Class describing a function with variants. */
1897 struct GTY((for_user)) omp_declare_variant_base_entry {
1898 /* NODE of the base function. */
1899 cgraph_node *base;
1900 /* NODE of the artificial function created for the deferred variant
1901 resolution. */
1902 cgraph_node *node;
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 *);
1914 hashval_t
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;
1921 unsigned int i;
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 ();
1933 bool
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 ())
1939 return false;
1940 omp_declare_variant_entry *variant;
1941 unsigned int i;
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)
1949 return false;
1950 return true;
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 *);
1962 hashval_t
1963 omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry *x)
1965 return DECL_UID (x->node->decl);
1968 bool
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. */
1980 static tree
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);
1985 if (node == NULL
1986 || !node->declare_variant_alt
1987 || !cfun->after_inlining)
1988 return alt;
1990 omp_declare_variant_base_entry entry;
1991 entry.base = NULL;
1992 entry.node = node;
1993 entry.variants = NULL;
1994 omp_declare_variant_base_entry *entryp
1995 = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (alt));
1997 unsigned int i, j;
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);
2007 nmatches++;
2008 continue;
2010 switch (omp_context_selector_matches (varentry1->ctx))
2012 case 0:
2013 matches.safe_push (false);
2014 break;
2015 case -1:
2016 return alt;
2017 default:
2018 matches.safe_push (true);
2019 nmatches++;
2020 break;
2024 if (nmatches == 0)
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)
2030 if (matches[i])
2032 for (j = i + 1;
2033 vec_safe_iterate (entryp->variants, j, &varentry2); ++j)
2034 if (matches[j])
2036 int r = omp_context_selector_compare (varentry1->ctx,
2037 varentry2->ctx);
2038 if (r == -1)
2040 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2041 matches[i] = false;
2042 break;
2044 else if (r == 1)
2045 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2046 matches[j] = false;
2050 widest_int max_score = -1;
2051 varentry2 = NULL;
2052 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2053 if (matches[i])
2055 widest_int score
2056 = (cur_node->simdclone ? varentry1->score_in_declare_simd_clone
2057 : varentry1->score);
2058 if (score > max_score)
2060 max_score = score;
2061 varentry2 = varentry1;
2064 return varentry2->variant->decl;
2067 /* Hook to adjust hash tables on cgraph_node removal. */
2069 static void
2070 omp_declare_variant_remove_hook (struct cgraph_node *node, void *)
2072 if (!node->declare_variant_alt)
2073 return;
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;
2081 entry.base = NULL;
2082 entry.node = node;
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. */
2092 tree
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)
2106 break;
2107 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr))) != FUNCTION_DECL)
2108 continue;
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)
2113 return base;
2114 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr))))
2116 case 0:
2117 /* No match, ignore. */
2118 break;
2119 case -1:
2120 /* Needs to be deferred. */
2121 any_deferred = true;
2122 variants.safe_push (attr);
2123 defer.safe_push (true);
2124 break;
2125 default:
2126 variants.safe_push (attr);
2127 defer.safe_push (false);
2128 break;
2131 if (variants.length () == 0)
2132 return base;
2134 if (any_deferred)
2136 widest_int max_score1 = 0;
2137 widest_int max_score2 = 0;
2138 bool first = true;
2139 unsigned int i;
2140 tree attr1, attr2;
2141 omp_declare_variant_base_entry entry;
2142 entry.base = cgraph_node::get_create (base);
2143 entry.node = NULL;
2144 vec_alloc (entry.variants, variants.length ());
2145 FOR_EACH_VEC_ELT (variants, i, attr1)
2147 widest_int score1;
2148 widest_int score2;
2149 bool need_two;
2150 tree ctx = TREE_VALUE (TREE_VALUE (attr1));
2151 need_two = omp_context_compute_score (ctx, &score1, false);
2152 if (need_two)
2153 omp_context_compute_score (ctx, &score2, true);
2154 else
2155 score2 = score1;
2156 if (first)
2158 first = false;
2159 max_score1 = score1;
2160 max_score2 = score2;
2161 if (!defer[i])
2163 variant1 = attr1;
2164 variant2 = attr1;
2167 else
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;
2185 varentry.variant
2186 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1)));
2187 varentry.score = score1;
2188 varentry.score_in_declare_simd_clone = score2;
2189 varentry.ctx = ctx;
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)
2204 continue;
2205 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2206 int r = omp_context_selector_compare (ctx1, ctx2);
2207 if (r == -1)
2209 /* The winner is a strict subset of ctx2, can't
2210 decide now. */
2211 variant1 = NULL_TREE;
2212 break;
2215 if (variant1)
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,
2226 NULL);
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);
2233 if (*slot != NULL)
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,
2254 attributes);
2255 if (lookup_attribute ("noclone", attributes) == NULL)
2256 attributes = tree_cons (get_identifier ("noclone"), NULL,
2257 attributes);
2258 if (lookup_attribute ("no_icf", attributes) == NULL)
2259 attributes = tree_cons (get_identifier ("no_icf"), NULL,
2260 attributes);
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),
2274 INSERT) = *slot;
2275 return 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. */
2283 tree attr1, attr2;
2284 unsigned int i, j;
2285 FOR_EACH_VEC_ELT (variants, i, attr1)
2286 if (attr1)
2288 tree ctx1 = TREE_VALUE (TREE_VALUE (attr1));
2289 FOR_EACH_VEC_ELT_FROM (variants, j, attr2, i + 1)
2290 if (attr2)
2292 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2293 int r = omp_context_selector_compare (ctx1, ctx2);
2294 if (r == -1)
2296 /* ctx1 is a strict subset of ctx2, remove
2297 attr1 from the vector. */
2298 variants[i] = NULL_TREE;
2299 break;
2301 else if (r == 1)
2302 /* ctx2 is a strict subset of ctx1, remove attr2
2303 from the vector. */
2304 variants[j] = NULL_TREE;
2307 widest_int max_score1 = 0;
2308 widest_int max_score2 = 0;
2309 bool first = true;
2310 FOR_EACH_VEC_ELT (variants, i, attr1)
2311 if (attr1)
2313 if (variant1)
2315 widest_int score1;
2316 widest_int score2;
2317 bool need_two;
2318 tree ctx;
2319 if (first)
2321 first = false;
2322 ctx = TREE_VALUE (TREE_VALUE (variant1));
2323 need_two = omp_context_compute_score (ctx, &max_score1, false);
2324 if (need_two)
2325 omp_context_compute_score (ctx, &max_score2, true);
2326 else
2327 max_score2 = max_score1;
2329 ctx = TREE_VALUE (TREE_VALUE (attr1));
2330 need_two = omp_context_compute_score (ctx, &score1, false);
2331 if (need_two)
2332 omp_context_compute_score (ctx, &score2, true);
2333 else
2334 score2 = score1;
2335 if (score1 > max_score1)
2337 max_score1 = score1;
2338 variant1 = attr1;
2340 if (score2 > max_score2)
2342 max_score2 = score2;
2343 variant2 = attr1;
2346 else
2348 variant1 = attr1;
2349 variant2 = attr1;
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);
2359 void
2360 omp_lto_output_declare_variant_alt (lto_simple_output_block *ob,
2361 cgraph_node *node,
2362 lto_symtab_encoder_t encoder)
2364 gcc_assert (node->declare_variant_alt);
2366 omp_declare_variant_base_entry entry;
2367 entry.base = NULL;
2368 entry.node = node;
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 ());
2380 unsigned int i;
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)
2397 break;
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)
2407 break;
2409 if (varentry->ctx == TREE_VALUE (TREE_VALUE (attr)))
2411 cnt = i;
2412 break;
2416 gcc_assert (cnt != -1);
2417 streamer_write_hwi_stream (ob->main_stream, cnt);
2421 void
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;
2436 varentry.variant
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)
2448 break;
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)
2461 break;
2463 if (cnt == j)
2465 varentry.ctx = TREE_VALUE (TREE_VALUE (attr));
2466 break;
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),
2476 INSERT) = entryp;
2479 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2480 macro on gomp-constants.h. We do not check for overflow. */
2482 tree
2483 oacc_launch_pack (unsigned code, tree device, unsigned op)
2485 tree res;
2487 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
2488 if (device)
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);
2495 return res;
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. */
2518 tree
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. */
2531 void
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. */
2542 void
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 };
2549 unsigned ix;
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;
2560 if (clause)
2561 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
2562 dims[ix] = dim;
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);
2573 if (non_const)
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)
2606 c_level = c;
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);
2613 c = c_p;
2615 else
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);
2626 c = c_p;
2628 break;
2629 case OMP_CLAUSE_NOHOST:
2630 /* Don't worry about duplicate clauses here. */
2631 c_nohost = c;
2632 break;
2633 default:
2634 gcc_unreachable ();
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;
2641 *clauses = c_level;
2643 /* In *clauses, we now have exactly one clause specifying the level of
2644 parallelism. */
2646 tree attr
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. */
2655 error_at (loc,
2656 "cannot apply %<%s%> to %qD, which has also been"
2657 " marked with an OpenMP 'declare target' directive",
2658 routine_str, fndecl);
2659 /* Incompatible. */
2660 return -1;
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);
2676 c_level_p = c;
2677 break;
2678 case OMP_CLAUSE_NOHOST:
2679 gcc_checking_assert (c_nohost_p == NULL_TREE);
2680 c_nohost_p = c;
2681 break;
2682 default:
2683 gcc_unreachable ();
2685 gcc_checking_assert (c_level_p != NULL_TREE);
2686 /* ..., and compare to current directive's, which we've already collected
2687 above. */
2688 tree c_diag;
2689 tree c_diag_p;
2690 /* Matching level of parallelism? */
2691 if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
2693 c_diag = c_level;
2694 c_diag_p = c_level_p;
2695 goto incompatible;
2697 /* Matching 'nohost' clauses? */
2698 if ((c_nohost == NULL_TREE) != (c_nohost_p == NULL_TREE))
2700 c_diag = c_nohost;
2701 c_diag_p = c_nohost_p;
2702 goto incompatible;
2704 /* Compatible. */
2705 return 1;
2707 incompatible:
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)
2716 error_at (loc,
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);
2722 else
2723 gcc_unreachable ();
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)]);
2728 else
2730 /* In the front ends, we don't preserve location information for the
2731 OpenACC routine directive itself. However, that of c_level_p
2732 should be close. */
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)]);
2737 /* Incompatible. */
2738 return -1;
2741 return 0;
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. */
2754 tree
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};
2760 int ix;
2761 int level = -1;
2763 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
2764 for (ix = GOMP_DIM_MAX + 1; ix--;)
2765 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
2767 level = ix;
2768 break;
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);
2778 return dims;
2781 /* Retrieve the oacc function attrib and return it. Non-oacc
2782 functions will return NULL. */
2784 tree
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. */
2792 bool
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);
2812 while (axis--)
2813 dims = TREE_CHAIN (dims);
2815 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
2817 return size;
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);
2832 return (int) axis;
2835 #include "gt-omp-general.h"