Darwin: Update quotes in driver warning messages.
[official-gcc.git] / gcc / omp-general.c
blob3e5ca94c2a7f91206f873c75932d841e8819d836
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"
47 #include "opts.h"
49 enum omp_requires omp_requires_mask;
51 tree
52 omp_find_clause (tree clauses, enum omp_clause_code kind)
54 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55 if (OMP_CLAUSE_CODE (clauses) == kind)
56 return clauses;
58 return NULL_TREE;
61 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
62 allocatable or pointer attribute. */
63 bool
64 omp_is_allocatable_or_ptr (tree decl)
66 return lang_hooks.decls.omp_is_allocatable_or_ptr (decl);
69 /* Check whether this DECL belongs to a Fortran optional argument.
70 With 'for_present_check' set to false, decls which are optional parameters
71 themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
72 always pointers. With 'for_present_check' set to true, the decl for checking
73 whether an argument is present is returned; for arguments with value
74 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
75 unrelated to optional arguments, NULL_TREE is returned. */
77 tree
78 omp_check_optional_argument (tree decl, bool for_present_check)
80 return lang_hooks.decls.omp_check_optional_argument (decl, for_present_check);
83 /* True if OpenMP should privatize what this DECL points to rather
84 than the DECL itself. */
86 bool
87 omp_privatize_by_reference (tree decl)
89 return lang_hooks.decls.omp_privatize_by_reference (decl);
92 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or GT_EXPR,
93 given that V is the loop index variable and STEP is loop step. */
95 void
96 omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2,
97 tree v, tree step)
99 switch (*cond_code)
101 case LT_EXPR:
102 case GT_EXPR:
103 break;
105 case NE_EXPR:
106 gcc_assert (TREE_CODE (step) == INTEGER_CST);
107 if (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE)
109 if (integer_onep (step))
110 *cond_code = LT_EXPR;
111 else
113 gcc_assert (integer_minus_onep (step));
114 *cond_code = GT_EXPR;
117 else
119 tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
120 gcc_assert (TREE_CODE (unit) == INTEGER_CST);
121 if (tree_int_cst_equal (unit, step))
122 *cond_code = LT_EXPR;
123 else
125 gcc_assert (wi::neg (wi::to_widest (unit))
126 == wi::to_widest (step));
127 *cond_code = GT_EXPR;
131 break;
133 case LE_EXPR:
134 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
135 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
136 else
137 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
138 build_int_cst (TREE_TYPE (*n2), 1));
139 *cond_code = LT_EXPR;
140 break;
141 case GE_EXPR:
142 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
143 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
144 else
145 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
146 build_int_cst (TREE_TYPE (*n2), 1));
147 *cond_code = GT_EXPR;
148 break;
149 default:
150 gcc_unreachable ();
154 /* Return the looping step from INCR, extracted from the step of a gimple omp
155 for statement. */
157 tree
158 omp_get_for_step_from_incr (location_t loc, tree incr)
160 tree step;
161 switch (TREE_CODE (incr))
163 case PLUS_EXPR:
164 step = TREE_OPERAND (incr, 1);
165 break;
166 case POINTER_PLUS_EXPR:
167 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
168 break;
169 case MINUS_EXPR:
170 step = TREE_OPERAND (incr, 1);
171 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
172 break;
173 default:
174 gcc_unreachable ();
176 return step;
179 /* Extract the header elements of parallel loop FOR_STMT and store
180 them into *FD. */
182 void
183 omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
184 struct omp_for_data_loop *loops)
186 tree t, var, *collapse_iter, *collapse_count;
187 tree count = NULL_TREE, iter_type = long_integer_type_node;
188 struct omp_for_data_loop *loop;
189 int i;
190 struct omp_for_data_loop dummy_loop;
191 location_t loc = gimple_location (for_stmt);
192 bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
193 bool distribute = gimple_omp_for_kind (for_stmt)
194 == GF_OMP_FOR_KIND_DISTRIBUTE;
195 bool taskloop = gimple_omp_for_kind (for_stmt)
196 == GF_OMP_FOR_KIND_TASKLOOP;
197 bool order_reproducible = false;
198 tree iterv, countv;
200 fd->for_stmt = for_stmt;
201 fd->pre = NULL;
202 fd->have_nowait = distribute || simd;
203 fd->have_ordered = false;
204 fd->have_reductemp = false;
205 fd->have_pointer_condtemp = false;
206 fd->have_scantemp = false;
207 fd->have_nonctrl_scantemp = false;
208 fd->non_rect = false;
209 fd->lastprivate_conditional = 0;
210 fd->tiling = NULL_TREE;
211 fd->collapse = 1;
212 fd->ordered = 0;
213 fd->first_nonrect = -1;
214 fd->last_nonrect = -1;
215 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
216 fd->sched_modifiers = 0;
217 fd->chunk_size = NULL_TREE;
218 fd->simd_schedule = false;
219 fd->first_inner_iterations = NULL_TREE;
220 fd->factor = NULL_TREE;
221 fd->adjn1 = NULL_TREE;
222 collapse_iter = NULL;
223 collapse_count = NULL;
225 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
226 switch (OMP_CLAUSE_CODE (t))
228 case OMP_CLAUSE_NOWAIT:
229 fd->have_nowait = true;
230 break;
231 case OMP_CLAUSE_ORDERED:
232 fd->have_ordered = true;
233 if (OMP_CLAUSE_ORDERED_EXPR (t))
234 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
235 break;
236 case OMP_CLAUSE_SCHEDULE:
237 gcc_assert (!distribute && !taskloop);
238 fd->sched_kind
239 = (enum omp_clause_schedule_kind)
240 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
241 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
242 & ~OMP_CLAUSE_SCHEDULE_MASK);
243 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
244 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
245 break;
246 case OMP_CLAUSE_DIST_SCHEDULE:
247 gcc_assert (distribute);
248 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
249 break;
250 case OMP_CLAUSE_COLLAPSE:
251 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
252 if (fd->collapse > 1)
254 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
255 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
257 break;
258 case OMP_CLAUSE_TILE:
259 fd->tiling = OMP_CLAUSE_TILE_LIST (t);
260 fd->collapse = list_length (fd->tiling);
261 gcc_assert (fd->collapse);
262 collapse_iter = &OMP_CLAUSE_TILE_ITERVAR (t);
263 collapse_count = &OMP_CLAUSE_TILE_COUNT (t);
264 break;
265 case OMP_CLAUSE__REDUCTEMP_:
266 fd->have_reductemp = true;
267 break;
268 case OMP_CLAUSE_LASTPRIVATE:
269 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
270 fd->lastprivate_conditional++;
271 break;
272 case OMP_CLAUSE__CONDTEMP_:
273 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
274 fd->have_pointer_condtemp = true;
275 break;
276 case OMP_CLAUSE__SCANTEMP_:
277 fd->have_scantemp = true;
278 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t)
279 && !OMP_CLAUSE__SCANTEMP__CONTROL (t))
280 fd->have_nonctrl_scantemp = true;
281 break;
282 case OMP_CLAUSE_ORDER:
283 /* FIXME: For OpenMP 5.2 this should change to
284 if (OMP_CLAUSE_ORDER_REPRODUCIBLE (t))
285 (with the exception of loop construct but that lowers to
286 no schedule/dist_schedule clauses currently). */
287 if (!OMP_CLAUSE_ORDER_UNCONSTRAINED (t))
288 order_reproducible = true;
289 default:
290 break;
293 /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
294 we have either the option to expensively remember at runtime how we've
295 distributed work from first loop and reuse that in following loops with
296 the same number of iterations and schedule, or just force static schedule.
297 OpenMP API calls etc. aren't allowed in order(concurrent) bodies so
298 users can't observe it easily anyway. */
299 if (order_reproducible)
300 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
301 if (fd->collapse > 1 || fd->tiling)
302 fd->loops = loops;
303 else
304 fd->loops = &fd->loop;
306 if (fd->ordered && fd->collapse == 1 && loops != NULL)
308 fd->loops = loops;
309 iterv = NULL_TREE;
310 countv = NULL_TREE;
311 collapse_iter = &iterv;
312 collapse_count = &countv;
315 /* FIXME: for now map schedule(auto) to schedule(static).
316 There should be analysis to determine whether all iterations
317 are approximately the same amount of work (then schedule(static)
318 is best) or if it varies (then schedule(dynamic,N) is better). */
319 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
321 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
322 gcc_assert (fd->chunk_size == NULL);
324 gcc_assert ((fd->collapse == 1 && !fd->tiling) || collapse_iter != NULL);
325 if (taskloop)
326 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
327 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
328 gcc_assert (fd->chunk_size == NULL);
329 else if (fd->chunk_size == NULL)
331 /* We only need to compute a default chunk size for ordered
332 static loops and dynamic loops. */
333 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
334 || fd->have_ordered)
335 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
336 ? integer_zero_node : integer_one_node;
339 int cnt = fd->ordered ? fd->ordered : fd->collapse;
340 int single_nonrect = -1;
341 tree single_nonrect_count = NULL_TREE;
342 enum tree_code single_nonrect_cond_code = ERROR_MARK;
343 for (i = 1; i < cnt; i++)
345 tree n1 = gimple_omp_for_initial (for_stmt, i);
346 tree n2 = gimple_omp_for_final (for_stmt, i);
347 if (TREE_CODE (n1) == TREE_VEC)
349 if (fd->non_rect)
351 single_nonrect = -1;
352 break;
354 for (int j = i - 1; j >= 0; j--)
355 if (TREE_VEC_ELT (n1, 0) == gimple_omp_for_index (for_stmt, j))
357 single_nonrect = j;
358 break;
360 fd->non_rect = true;
362 else if (TREE_CODE (n2) == TREE_VEC)
364 if (fd->non_rect)
366 single_nonrect = -1;
367 break;
369 for (int j = i - 1; j >= 0; j--)
370 if (TREE_VEC_ELT (n2, 0) == gimple_omp_for_index (for_stmt, j))
372 single_nonrect = j;
373 break;
375 fd->non_rect = true;
378 for (i = 0; i < cnt; i++)
380 if (i == 0
381 && fd->collapse == 1
382 && !fd->tiling
383 && (fd->ordered == 0 || loops == NULL))
384 loop = &fd->loop;
385 else if (loops != NULL)
386 loop = loops + i;
387 else
388 loop = &dummy_loop;
390 loop->v = gimple_omp_for_index (for_stmt, i);
391 gcc_assert (SSA_VAR_P (loop->v));
392 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
393 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
394 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
395 loop->n1 = gimple_omp_for_initial (for_stmt, i);
396 loop->m1 = NULL_TREE;
397 loop->m2 = NULL_TREE;
398 loop->outer = 0;
399 loop->non_rect_referenced = false;
400 if (TREE_CODE (loop->n1) == TREE_VEC)
402 for (int j = i - 1; j >= 0; j--)
403 if (TREE_VEC_ELT (loop->n1, 0) == gimple_omp_for_index (for_stmt, j))
405 loop->outer = i - j;
406 if (loops != NULL)
407 loops[j].non_rect_referenced = true;
408 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
409 fd->first_nonrect = j;
410 break;
412 gcc_assert (loop->outer);
413 loop->m1 = TREE_VEC_ELT (loop->n1, 1);
414 loop->n1 = TREE_VEC_ELT (loop->n1, 2);
415 fd->non_rect = true;
416 fd->last_nonrect = i;
419 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
420 loop->n2 = gimple_omp_for_final (for_stmt, i);
421 gcc_assert (loop->cond_code != NE_EXPR
422 || (gimple_omp_for_kind (for_stmt)
423 != GF_OMP_FOR_KIND_OACC_LOOP));
424 if (TREE_CODE (loop->n2) == TREE_VEC)
426 if (loop->outer)
427 gcc_assert (TREE_VEC_ELT (loop->n2, 0)
428 == gimple_omp_for_index (for_stmt, i - loop->outer));
429 else
430 for (int j = i - 1; j >= 0; j--)
431 if (TREE_VEC_ELT (loop->n2, 0) == gimple_omp_for_index (for_stmt, j))
433 loop->outer = i - j;
434 if (loops != NULL)
435 loops[j].non_rect_referenced = true;
436 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
437 fd->first_nonrect = j;
438 break;
440 gcc_assert (loop->outer);
441 loop->m2 = TREE_VEC_ELT (loop->n2, 1);
442 loop->n2 = TREE_VEC_ELT (loop->n2, 2);
443 fd->non_rect = true;
444 fd->last_nonrect = i;
447 t = gimple_omp_for_incr (for_stmt, i);
448 gcc_assert (TREE_OPERAND (t, 0) == var);
449 loop->step = omp_get_for_step_from_incr (loc, t);
451 omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2, loop->v,
452 loop->step);
454 if (simd
455 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
456 && !fd->have_ordered))
458 if (fd->collapse == 1 && !fd->tiling)
459 iter_type = TREE_TYPE (loop->v);
460 else if (i == 0
461 || TYPE_PRECISION (iter_type)
462 < TYPE_PRECISION (TREE_TYPE (loop->v)))
463 iter_type
464 = build_nonstandard_integer_type
465 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
467 else if (iter_type != long_long_unsigned_type_node)
469 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
470 iter_type = long_long_unsigned_type_node;
471 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
472 && TYPE_PRECISION (TREE_TYPE (loop->v))
473 >= TYPE_PRECISION (iter_type))
475 tree n;
477 if (loop->cond_code == LT_EXPR)
478 n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
479 loop->n2, loop->step);
480 else
481 n = loop->n1;
482 if (loop->m1
483 || loop->m2
484 || TREE_CODE (n) != INTEGER_CST
485 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
486 iter_type = long_long_unsigned_type_node;
488 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
489 > TYPE_PRECISION (iter_type))
491 tree n1, n2;
493 if (loop->cond_code == LT_EXPR)
495 n1 = loop->n1;
496 n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
497 loop->n2, loop->step);
499 else
501 n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
502 loop->n2, loop->step);
503 n2 = loop->n1;
505 if (loop->m1
506 || loop->m2
507 || TREE_CODE (n1) != INTEGER_CST
508 || TREE_CODE (n2) != INTEGER_CST
509 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
510 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
511 iter_type = long_long_unsigned_type_node;
515 if (i >= fd->collapse)
516 continue;
518 if (collapse_count && *collapse_count == NULL)
520 if (count && integer_zerop (count))
521 continue;
522 tree n1first = NULL_TREE, n2first = NULL_TREE;
523 tree n1last = NULL_TREE, n2last = NULL_TREE;
524 tree ostep = NULL_TREE;
525 if (loop->m1 || loop->m2)
527 if (count == NULL_TREE)
528 continue;
529 if (single_nonrect == -1
530 || (loop->m1 && TREE_CODE (loop->m1) != INTEGER_CST)
531 || (loop->m2 && TREE_CODE (loop->m2) != INTEGER_CST)
532 || TREE_CODE (loop->n1) != INTEGER_CST
533 || TREE_CODE (loop->n2) != INTEGER_CST
534 || TREE_CODE (loop->step) != INTEGER_CST)
536 count = NULL_TREE;
537 continue;
539 tree var = gimple_omp_for_initial (for_stmt, single_nonrect);
540 tree itype = TREE_TYPE (var);
541 tree first = gimple_omp_for_initial (for_stmt, single_nonrect);
542 t = gimple_omp_for_incr (for_stmt, single_nonrect);
543 ostep = omp_get_for_step_from_incr (loc, t);
544 t = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
545 single_nonrect_count,
546 build_one_cst (long_long_unsigned_type_node));
547 t = fold_convert (itype, t);
548 first = fold_convert (itype, first);
549 ostep = fold_convert (itype, ostep);
550 tree last = fold_binary (PLUS_EXPR, itype, first,
551 fold_binary (MULT_EXPR, itype, t,
552 ostep));
553 if (TREE_CODE (first) != INTEGER_CST
554 || TREE_CODE (last) != INTEGER_CST)
556 count = NULL_TREE;
557 continue;
559 if (loop->m1)
561 tree m1 = fold_convert (itype, loop->m1);
562 tree n1 = fold_convert (itype, loop->n1);
563 n1first = fold_binary (PLUS_EXPR, itype,
564 fold_binary (MULT_EXPR, itype,
565 first, m1), n1);
566 n1last = fold_binary (PLUS_EXPR, itype,
567 fold_binary (MULT_EXPR, itype,
568 last, m1), n1);
570 else
571 n1first = n1last = loop->n1;
572 if (loop->m2)
574 tree n2 = fold_convert (itype, loop->n2);
575 tree m2 = fold_convert (itype, loop->m2);
576 n2first = fold_binary (PLUS_EXPR, itype,
577 fold_binary (MULT_EXPR, itype,
578 first, m2), n2);
579 n2last = fold_binary (PLUS_EXPR, itype,
580 fold_binary (MULT_EXPR, itype,
581 last, m2), n2);
583 else
584 n2first = n2last = loop->n2;
585 n1first = fold_convert (TREE_TYPE (loop->v), n1first);
586 n2first = fold_convert (TREE_TYPE (loop->v), n2first);
587 n1last = fold_convert (TREE_TYPE (loop->v), n1last);
588 n2last = fold_convert (TREE_TYPE (loop->v), n2last);
589 t = fold_binary (loop->cond_code, boolean_type_node,
590 n1first, n2first);
591 tree t2 = fold_binary (loop->cond_code, boolean_type_node,
592 n1last, n2last);
593 if (t && t2 && integer_nonzerop (t) && integer_nonzerop (t2))
594 /* All outer loop iterators have at least one inner loop
595 iteration. Try to compute the count at compile time. */
596 t = NULL_TREE;
597 else if (t && t2 && integer_zerop (t) && integer_zerop (t2))
598 /* No iterations of the inner loop. count will be set to
599 zero cst below. */;
600 else if (TYPE_UNSIGNED (itype)
601 || t == NULL_TREE
602 || t2 == NULL_TREE
603 || TREE_CODE (t) != INTEGER_CST
604 || TREE_CODE (t2) != INTEGER_CST)
606 /* Punt (for now). */
607 count = NULL_TREE;
608 continue;
610 else
612 /* Some iterations of the outer loop have zero iterations
613 of the inner loop, while others have at least one.
614 In this case, we need to adjust one of those outer
615 loop bounds. If ADJ_FIRST, we need to adjust outer n1
616 (first), otherwise outer n2 (last). */
617 bool adj_first = integer_zerop (t);
618 tree n1 = fold_convert (itype, loop->n1);
619 tree n2 = fold_convert (itype, loop->n2);
620 tree m1 = loop->m1 ? fold_convert (itype, loop->m1)
621 : build_zero_cst (itype);
622 tree m2 = loop->m2 ? fold_convert (itype, loop->m2)
623 : build_zero_cst (itype);
624 t = fold_binary (MINUS_EXPR, itype, n1, n2);
625 t2 = fold_binary (MINUS_EXPR, itype, m2, m1);
626 t = fold_binary (TRUNC_DIV_EXPR, itype, t, t2);
627 t2 = fold_binary (MINUS_EXPR, itype, t, first);
628 t2 = fold_binary (TRUNC_MOD_EXPR, itype, t2, ostep);
629 t = fold_binary (MINUS_EXPR, itype, t, t2);
630 tree n1cur
631 = fold_binary (PLUS_EXPR, itype, n1,
632 fold_binary (MULT_EXPR, itype, m1, t));
633 tree n2cur
634 = fold_binary (PLUS_EXPR, itype, n2,
635 fold_binary (MULT_EXPR, itype, m2, t));
636 t2 = fold_binary (loop->cond_code, boolean_type_node,
637 n1cur, n2cur);
638 tree t3 = fold_binary (MULT_EXPR, itype, m1, ostep);
639 tree t4 = fold_binary (MULT_EXPR, itype, m2, ostep);
640 tree diff;
641 if (adj_first)
643 tree new_first;
644 if (integer_nonzerop (t2))
646 new_first = t;
647 n1first = n1cur;
648 n2first = n2cur;
649 if (flag_checking)
651 t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
652 t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
653 t3 = fold_binary (loop->cond_code,
654 boolean_type_node, t3, t4);
655 gcc_assert (integer_zerop (t3));
658 else
660 t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
661 t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
662 new_first = fold_binary (PLUS_EXPR, itype, t, ostep);
663 n1first = t3;
664 n2first = t4;
665 if (flag_checking)
667 t3 = fold_binary (loop->cond_code,
668 boolean_type_node, t3, t4);
669 gcc_assert (integer_nonzerop (t3));
672 diff = fold_binary (MINUS_EXPR, itype, new_first, first);
673 first = new_first;
674 fd->adjn1 = first;
676 else
678 tree new_last;
679 if (integer_zerop (t2))
681 t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
682 t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
683 new_last = fold_binary (MINUS_EXPR, itype, t, ostep);
684 n1last = t3;
685 n2last = t4;
686 if (flag_checking)
688 t3 = fold_binary (loop->cond_code,
689 boolean_type_node, t3, t4);
690 gcc_assert (integer_nonzerop (t3));
693 else
695 new_last = t;
696 n1last = n1cur;
697 n2last = n2cur;
698 if (flag_checking)
700 t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
701 t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
702 t3 = fold_binary (loop->cond_code,
703 boolean_type_node, t3, t4);
704 gcc_assert (integer_zerop (t3));
707 diff = fold_binary (MINUS_EXPR, itype, last, new_last);
709 if (TYPE_UNSIGNED (itype)
710 && single_nonrect_cond_code == GT_EXPR)
711 diff = fold_binary (TRUNC_DIV_EXPR, itype,
712 fold_unary (NEGATE_EXPR, itype, diff),
713 fold_unary (NEGATE_EXPR, itype,
714 ostep));
715 else
716 diff = fold_binary (TRUNC_DIV_EXPR, itype, diff, ostep);
717 diff = fold_convert (long_long_unsigned_type_node, diff);
718 single_nonrect_count
719 = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
720 single_nonrect_count, diff);
721 t = NULL_TREE;
724 else
725 t = fold_binary (loop->cond_code, boolean_type_node,
726 fold_convert (TREE_TYPE (loop->v), loop->n1),
727 fold_convert (TREE_TYPE (loop->v), loop->n2));
728 if (t && integer_zerop (t))
729 count = build_zero_cst (long_long_unsigned_type_node);
730 else if ((i == 0 || count != NULL_TREE)
731 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
732 && TREE_CONSTANT (loop->n1)
733 && TREE_CONSTANT (loop->n2)
734 && TREE_CODE (loop->step) == INTEGER_CST)
736 tree itype = TREE_TYPE (loop->v);
738 if (POINTER_TYPE_P (itype))
739 itype = signed_type_for (itype);
740 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
741 t = fold_build2 (PLUS_EXPR, itype,
742 fold_convert (itype, loop->step), t);
743 tree n1 = loop->n1;
744 tree n2 = loop->n2;
745 if (loop->m1 || loop->m2)
747 gcc_assert (single_nonrect != -1);
748 n1 = n1first;
749 n2 = n2first;
751 t = fold_build2 (PLUS_EXPR, itype, t, fold_convert (itype, n2));
752 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
753 tree step = fold_convert_loc (loc, itype, loop->step);
754 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
755 t = fold_build2 (TRUNC_DIV_EXPR, itype,
756 fold_build1 (NEGATE_EXPR, itype, t),
757 fold_build1 (NEGATE_EXPR, itype, step));
758 else
759 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
760 tree llutype = long_long_unsigned_type_node;
761 t = fold_convert (llutype, t);
762 if (loop->m1 || loop->m2)
764 /* t is number of iterations of inner loop at either first
765 or last value of the outer iterator (the one with fewer
766 iterations).
767 Compute t2 = ((m2 - m1) * ostep) / step
768 and niters = outer_count * t
769 + t2 * ((outer_count - 1) * outer_count / 2)
771 tree m1 = loop->m1 ? loop->m1 : integer_zero_node;
772 tree m2 = loop->m2 ? loop->m2 : integer_zero_node;
773 m1 = fold_convert (itype, m1);
774 m2 = fold_convert (itype, m2);
775 tree t2 = fold_build2 (MINUS_EXPR, itype, m2, m1);
776 t2 = fold_build2 (MULT_EXPR, itype, t2, ostep);
777 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
778 t2 = fold_build2 (TRUNC_DIV_EXPR, itype,
779 fold_build1 (NEGATE_EXPR, itype, t2),
780 fold_build1 (NEGATE_EXPR, itype, step));
781 else
782 t2 = fold_build2 (TRUNC_DIV_EXPR, itype, t2, step);
783 t2 = fold_convert (llutype, t2);
784 fd->first_inner_iterations = t;
785 fd->factor = t2;
786 t = fold_build2 (MULT_EXPR, llutype, t,
787 single_nonrect_count);
788 tree t3 = fold_build2 (MINUS_EXPR, llutype,
789 single_nonrect_count,
790 build_one_cst (llutype));
791 t3 = fold_build2 (MULT_EXPR, llutype, t3,
792 single_nonrect_count);
793 t3 = fold_build2 (TRUNC_DIV_EXPR, llutype, t3,
794 build_int_cst (llutype, 2));
795 t2 = fold_build2 (MULT_EXPR, llutype, t2, t3);
796 t = fold_build2 (PLUS_EXPR, llutype, t, t2);
798 if (i == single_nonrect)
800 if (integer_zerop (t) || TREE_CODE (t) != INTEGER_CST)
801 count = t;
802 else
804 single_nonrect_count = t;
805 single_nonrect_cond_code = loop->cond_code;
806 if (count == NULL_TREE)
807 count = build_one_cst (llutype);
810 else if (count != NULL_TREE)
811 count = fold_build2 (MULT_EXPR, llutype, count, t);
812 else
813 count = t;
814 if (TREE_CODE (count) != INTEGER_CST)
815 count = NULL_TREE;
817 else if (count && !integer_zerop (count))
818 count = NULL_TREE;
822 if (count
823 && !simd
824 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
825 || fd->have_ordered))
827 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
828 iter_type = long_long_unsigned_type_node;
829 else
830 iter_type = long_integer_type_node;
832 else if (collapse_iter && *collapse_iter != NULL)
833 iter_type = TREE_TYPE (*collapse_iter);
834 fd->iter_type = iter_type;
835 if (collapse_iter && *collapse_iter == NULL)
836 *collapse_iter = create_tmp_var (iter_type, ".iter");
837 if (collapse_count && *collapse_count == NULL)
839 if (count)
841 *collapse_count = fold_convert_loc (loc, iter_type, count);
842 if (fd->first_inner_iterations && fd->factor)
844 t = make_tree_vec (4);
845 TREE_VEC_ELT (t, 0) = *collapse_count;
846 TREE_VEC_ELT (t, 1) = fd->first_inner_iterations;
847 TREE_VEC_ELT (t, 2) = fd->factor;
848 TREE_VEC_ELT (t, 3) = fd->adjn1;
849 *collapse_count = t;
852 else
853 *collapse_count = create_tmp_var (iter_type, ".count");
856 if (fd->collapse > 1 || fd->tiling || (fd->ordered && loops))
858 fd->loop.v = *collapse_iter;
859 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
860 fd->loop.n2 = *collapse_count;
861 if (TREE_CODE (fd->loop.n2) == TREE_VEC)
863 gcc_assert (fd->non_rect);
864 fd->first_inner_iterations = TREE_VEC_ELT (fd->loop.n2, 1);
865 fd->factor = TREE_VEC_ELT (fd->loop.n2, 2);
866 fd->adjn1 = TREE_VEC_ELT (fd->loop.n2, 3);
867 fd->loop.n2 = TREE_VEC_ELT (fd->loop.n2, 0);
869 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
870 fd->loop.m1 = NULL_TREE;
871 fd->loop.m2 = NULL_TREE;
872 fd->loop.outer = 0;
873 fd->loop.cond_code = LT_EXPR;
875 else if (loops)
876 loops[0] = fd->loop;
879 /* Build a call to GOMP_barrier. */
881 gimple *
882 omp_build_barrier (tree lhs)
884 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
885 : BUILT_IN_GOMP_BARRIER);
886 gcall *g = gimple_build_call (fndecl, 0);
887 if (lhs)
888 gimple_call_set_lhs (g, lhs);
889 return g;
892 /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
893 array, pdata[0] non-NULL if there is anything non-trivial in between,
894 pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
895 of OMP_FOR in between if any and pdata[3] is address of the inner
896 OMP_FOR/OMP_SIMD. */
898 tree
899 find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
901 tree **pdata = (tree **) data;
902 *walk_subtrees = 0;
903 switch (TREE_CODE (*tp))
905 case OMP_FOR:
906 if (OMP_FOR_INIT (*tp) != NULL_TREE)
908 pdata[3] = tp;
909 return *tp;
911 pdata[2] = tp;
912 *walk_subtrees = 1;
913 break;
914 case OMP_SIMD:
915 if (OMP_FOR_INIT (*tp) != NULL_TREE)
917 pdata[3] = tp;
918 return *tp;
920 break;
921 case BIND_EXPR:
922 if (BIND_EXPR_VARS (*tp)
923 || (BIND_EXPR_BLOCK (*tp)
924 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
925 pdata[0] = tp;
926 *walk_subtrees = 1;
927 break;
928 case STATEMENT_LIST:
929 if (!tsi_one_before_end_p (tsi_start (*tp)))
930 pdata[0] = tp;
931 *walk_subtrees = 1;
932 break;
933 case TRY_FINALLY_EXPR:
934 pdata[0] = tp;
935 *walk_subtrees = 1;
936 break;
937 case OMP_PARALLEL:
938 pdata[1] = tp;
939 *walk_subtrees = 1;
940 break;
941 default:
942 break;
944 return NULL_TREE;
947 /* Return maximum possible vectorization factor for the target. */
949 poly_uint64
950 omp_max_vf (void)
952 if (!optimize
953 || optimize_debug
954 || !flag_tree_loop_optimize
955 || (!flag_tree_loop_vectorize
956 && OPTION_SET_P (flag_tree_loop_vectorize)))
957 return 1;
959 auto_vector_modes modes;
960 targetm.vectorize.autovectorize_vector_modes (&modes, true);
961 if (!modes.is_empty ())
963 poly_uint64 vf = 0;
964 for (unsigned int i = 0; i < modes.length (); ++i)
965 /* The returned modes use the smallest element size (and thus
966 the largest nunits) for the vectorization approach that they
967 represent. */
968 vf = ordered_max (vf, GET_MODE_NUNITS (modes[i]));
969 return vf;
972 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
973 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
974 return GET_MODE_NUNITS (vqimode);
976 return 1;
979 /* Return maximum SIMT width if offloading may target SIMT hardware. */
982 omp_max_simt_vf (void)
984 if (!optimize)
985 return 0;
986 if (ENABLE_OFFLOADING)
987 for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
989 if (startswith (c, "nvptx"))
990 return 32;
991 else if ((c = strchr (c, ':')))
992 c++;
994 return 0;
997 /* Store the construct selectors as tree codes from last to first,
998 return their number. */
1001 omp_constructor_traits_to_codes (tree ctx, enum tree_code *constructs)
1003 int nconstructs = list_length (ctx);
1004 int i = nconstructs - 1;
1005 for (tree t2 = ctx; t2; t2 = TREE_CHAIN (t2), i--)
1007 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
1008 if (!strcmp (sel, "target"))
1009 constructs[i] = OMP_TARGET;
1010 else if (!strcmp (sel, "teams"))
1011 constructs[i] = OMP_TEAMS;
1012 else if (!strcmp (sel, "parallel"))
1013 constructs[i] = OMP_PARALLEL;
1014 else if (!strcmp (sel, "for") || !strcmp (sel, "do"))
1015 constructs[i] = OMP_FOR;
1016 else if (!strcmp (sel, "simd"))
1017 constructs[i] = OMP_SIMD;
1018 else
1019 gcc_unreachable ();
1021 gcc_assert (i == -1);
1022 return nconstructs;
1025 /* Return true if PROP is possibly present in one of the offloading target's
1026 OpenMP contexts. The format of PROPS string is always offloading target's
1027 name terminated by '\0', followed by properties for that offloading
1028 target separated by '\0' and terminated by another '\0'. The strings
1029 are created from omp-device-properties installed files of all configured
1030 offloading targets. */
1032 static bool
1033 omp_offload_device_kind_arch_isa (const char *props, const char *prop)
1035 const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1036 if (names == NULL || *names == '\0')
1037 return false;
1038 while (*props != '\0')
1040 size_t name_len = strlen (props);
1041 bool matches = false;
1042 for (const char *c = names; c; )
1044 if (strncmp (props, c, name_len) == 0
1045 && (c[name_len] == '\0'
1046 || c[name_len] == ':'
1047 || c[name_len] == '='))
1049 matches = true;
1050 break;
1052 else if ((c = strchr (c, ':')))
1053 c++;
1055 props = props + name_len + 1;
1056 while (*props != '\0')
1058 if (matches && strcmp (props, prop) == 0)
1059 return true;
1060 props = strchr (props, '\0') + 1;
1062 props++;
1064 return false;
1067 /* Return true if the current code location is or might be offloaded.
1068 Return true in declare target functions, or when nested in a target
1069 region or when unsure, return false otherwise. */
1071 static bool
1072 omp_maybe_offloaded (void)
1074 if (!ENABLE_OFFLOADING)
1075 return false;
1076 const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1077 if (names == NULL || *names == '\0')
1078 return false;
1080 if (symtab->state == PARSING)
1081 /* Maybe. */
1082 return true;
1083 if (cfun && cfun->after_inlining)
1084 return false;
1085 if (current_function_decl
1086 && lookup_attribute ("omp declare target",
1087 DECL_ATTRIBUTES (current_function_decl)))
1088 return true;
1089 if (cfun && (cfun->curr_properties & PROP_gimple_any) == 0)
1091 enum tree_code construct = OMP_TARGET;
1092 if (omp_construct_selector_matches (&construct, 1, NULL))
1093 return true;
1095 return false;
1098 /* Return a name from PROP, a property in selectors accepting
1099 name lists. */
1101 static const char *
1102 omp_context_name_list_prop (tree prop)
1104 if (TREE_PURPOSE (prop))
1105 return IDENTIFIER_POINTER (TREE_PURPOSE (prop));
1106 else
1108 const char *ret = TREE_STRING_POINTER (TREE_VALUE (prop));
1109 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop)) == strlen (ret) + 1)
1110 return ret;
1111 return NULL;
1115 /* Return 1 if context selector matches the current OpenMP context, 0
1116 if it does not and -1 if it is unknown and need to be determined later.
1117 Some properties can be checked right away during parsing (this routine),
1118 others need to wait until the whole TU is parsed, others need to wait until
1119 IPA, others until vectorization. */
1122 omp_context_selector_matches (tree ctx)
1124 int ret = 1;
1125 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1127 char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0];
1128 if (set == 'c')
1130 /* For now, ignore the construct set. While something can be
1131 determined already during parsing, we don't know until end of TU
1132 whether additional constructs aren't added through declare variant
1133 unless "omp declare variant variant" attribute exists already
1134 (so in most of the cases), and we'd need to maintain set of
1135 surrounding OpenMP constructs, which is better handled during
1136 gimplification. */
1137 if (symtab->state == PARSING)
1139 ret = -1;
1140 continue;
1143 enum tree_code constructs[5];
1144 int nconstructs
1145 = omp_constructor_traits_to_codes (TREE_VALUE (t1), constructs);
1147 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1149 if (!cfun->after_inlining)
1151 ret = -1;
1152 continue;
1154 int i;
1155 for (i = 0; i < nconstructs; ++i)
1156 if (constructs[i] == OMP_SIMD)
1157 break;
1158 if (i < nconstructs)
1160 ret = -1;
1161 continue;
1163 /* If there is no simd, assume it is ok after IPA,
1164 constructs should have been checked before. */
1165 continue;
1168 int r = omp_construct_selector_matches (constructs, nconstructs,
1169 NULL);
1170 if (r == 0)
1171 return 0;
1172 if (r == -1)
1173 ret = -1;
1174 continue;
1176 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1178 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
1179 switch (*sel)
1181 case 'v':
1182 if (set == 'i' && !strcmp (sel, "vendor"))
1183 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1185 const char *prop = omp_context_name_list_prop (t3);
1186 if (prop == NULL)
1187 return 0;
1188 if ((!strcmp (prop, " score") && TREE_PURPOSE (t3))
1189 || !strcmp (prop, "gnu"))
1190 continue;
1191 return 0;
1193 break;
1194 case 'e':
1195 if (set == 'i' && !strcmp (sel, "extension"))
1196 /* We don't support any extensions right now. */
1197 return 0;
1198 break;
1199 case 'a':
1200 if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
1202 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1203 break;
1205 enum omp_memory_order omo
1206 = ((enum omp_memory_order)
1207 (omp_requires_mask
1208 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER));
1209 if (omo == OMP_MEMORY_ORDER_UNSPECIFIED)
1211 /* We don't know yet, until end of TU. */
1212 if (symtab->state == PARSING)
1214 ret = -1;
1215 break;
1217 else
1218 omo = OMP_MEMORY_ORDER_RELAXED;
1220 tree t3 = TREE_VALUE (t2);
1221 const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
1222 if (!strcmp (prop, " score"))
1224 t3 = TREE_CHAIN (t3);
1225 prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
1227 if (!strcmp (prop, "relaxed")
1228 && omo != OMP_MEMORY_ORDER_RELAXED)
1229 return 0;
1230 else if (!strcmp (prop, "seq_cst")
1231 && omo != OMP_MEMORY_ORDER_SEQ_CST)
1232 return 0;
1233 else if (!strcmp (prop, "acq_rel")
1234 && omo != OMP_MEMORY_ORDER_ACQ_REL)
1235 return 0;
1237 if (set == 'd' && !strcmp (sel, "arch"))
1238 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1240 const char *arch = omp_context_name_list_prop (t3);
1241 if (arch == NULL)
1242 return 0;
1243 int r = 0;
1244 if (targetm.omp.device_kind_arch_isa != NULL)
1245 r = targetm.omp.device_kind_arch_isa (omp_device_arch,
1246 arch);
1247 if (r == 0 || (r == -1 && symtab->state != PARSING))
1249 /* If we are or might be in a target region or
1250 declare target function, need to take into account
1251 also offloading values. */
1252 if (!omp_maybe_offloaded ())
1253 return 0;
1254 if (ENABLE_OFFLOADING)
1256 const char *arches = omp_offload_device_arch;
1257 if (omp_offload_device_kind_arch_isa (arches,
1258 arch))
1260 ret = -1;
1261 continue;
1264 return 0;
1266 else if (r == -1)
1267 ret = -1;
1268 /* If arch matches on the host, it still might not match
1269 in the offloading region. */
1270 else if (omp_maybe_offloaded ())
1271 ret = -1;
1273 break;
1274 case 'u':
1275 if (set == 'i' && !strcmp (sel, "unified_address"))
1277 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1278 break;
1280 if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
1282 if (symtab->state == PARSING)
1283 ret = -1;
1284 else
1285 return 0;
1287 break;
1289 if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
1291 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1292 break;
1294 if ((omp_requires_mask
1295 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
1297 if (symtab->state == PARSING)
1298 ret = -1;
1299 else
1300 return 0;
1302 break;
1304 break;
1305 case 'd':
1306 if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
1308 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1309 break;
1311 if ((omp_requires_mask
1312 & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1314 if (symtab->state == PARSING)
1315 ret = -1;
1316 else
1317 return 0;
1319 break;
1321 break;
1322 case 'r':
1323 if (set == 'i' && !strcmp (sel, "reverse_offload"))
1325 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1326 break;
1328 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
1330 if (symtab->state == PARSING)
1331 ret = -1;
1332 else
1333 return 0;
1335 break;
1337 break;
1338 case 'k':
1339 if (set == 'd' && !strcmp (sel, "kind"))
1340 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1342 const char *prop = omp_context_name_list_prop (t3);
1343 if (prop == NULL)
1344 return 0;
1345 if (!strcmp (prop, "any"))
1346 continue;
1347 if (!strcmp (prop, "host"))
1349 if (omp_maybe_offloaded ())
1350 ret = -1;
1351 continue;
1353 if (!strcmp (prop, "nohost"))
1355 if (omp_maybe_offloaded ())
1356 ret = -1;
1357 else
1358 return 0;
1359 continue;
1361 int r = 0;
1362 if (targetm.omp.device_kind_arch_isa != NULL)
1363 r = targetm.omp.device_kind_arch_isa (omp_device_kind,
1364 prop);
1365 else
1366 r = strcmp (prop, "cpu") == 0;
1367 if (r == 0 || (r == -1 && symtab->state != PARSING))
1369 /* If we are or might be in a target region or
1370 declare target function, need to take into account
1371 also offloading values. */
1372 if (!omp_maybe_offloaded ())
1373 return 0;
1374 if (ENABLE_OFFLOADING)
1376 const char *kinds = omp_offload_device_kind;
1377 if (omp_offload_device_kind_arch_isa (kinds, prop))
1379 ret = -1;
1380 continue;
1383 return 0;
1385 else if (r == -1)
1386 ret = -1;
1387 /* If kind matches on the host, it still might not match
1388 in the offloading region. */
1389 else if (omp_maybe_offloaded ())
1390 ret = -1;
1392 break;
1393 case 'i':
1394 if (set == 'd' && !strcmp (sel, "isa"))
1395 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1397 const char *isa = omp_context_name_list_prop (t3);
1398 if (isa == NULL)
1399 return 0;
1400 int r = 0;
1401 if (targetm.omp.device_kind_arch_isa != NULL)
1402 r = targetm.omp.device_kind_arch_isa (omp_device_isa,
1403 isa);
1404 if (r == 0 || (r == -1 && symtab->state != PARSING))
1406 /* If isa is valid on the target, but not in the
1407 current function and current function has
1408 #pragma omp declare simd on it, some simd clones
1409 might have the isa added later on. */
1410 if (r == -1
1411 && targetm.simd_clone.compute_vecsize_and_simdlen
1412 && (cfun == NULL || !cfun->after_inlining))
1414 tree attrs
1415 = DECL_ATTRIBUTES (current_function_decl);
1416 if (lookup_attribute ("omp declare simd", attrs))
1418 ret = -1;
1419 continue;
1422 /* If we are or might be in a target region or
1423 declare target function, need to take into account
1424 also offloading values. */
1425 if (!omp_maybe_offloaded ())
1426 return 0;
1427 if (ENABLE_OFFLOADING)
1429 const char *isas = omp_offload_device_isa;
1430 if (omp_offload_device_kind_arch_isa (isas, isa))
1432 ret = -1;
1433 continue;
1436 return 0;
1438 else if (r == -1)
1439 ret = -1;
1440 /* If isa matches on the host, it still might not match
1441 in the offloading region. */
1442 else if (omp_maybe_offloaded ())
1443 ret = -1;
1445 break;
1446 case 'c':
1447 if (set == 'u' && !strcmp (sel, "condition"))
1448 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1449 if (TREE_PURPOSE (t3) == NULL_TREE)
1451 if (integer_zerop (TREE_VALUE (t3)))
1452 return 0;
1453 if (integer_nonzerop (TREE_VALUE (t3)))
1454 break;
1455 ret = -1;
1457 break;
1458 default:
1459 break;
1463 return ret;
1466 /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1467 in omp_context_selector_set_compare. */
1469 static int
1470 omp_construct_simd_compare (tree clauses1, tree clauses2)
1472 if (clauses1 == NULL_TREE)
1473 return clauses2 == NULL_TREE ? 0 : -1;
1474 if (clauses2 == NULL_TREE)
1475 return 1;
1477 int r = 0;
1478 struct declare_variant_simd_data {
1479 bool inbranch, notinbranch;
1480 tree simdlen;
1481 auto_vec<tree,16> data_sharing;
1482 auto_vec<tree,16> aligned;
1483 declare_variant_simd_data ()
1484 : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
1485 } data[2];
1486 unsigned int i;
1487 for (i = 0; i < 2; i++)
1488 for (tree c = i ? clauses2 : clauses1; c; c = OMP_CLAUSE_CHAIN (c))
1490 vec<tree> *v;
1491 switch (OMP_CLAUSE_CODE (c))
1493 case OMP_CLAUSE_INBRANCH:
1494 data[i].inbranch = true;
1495 continue;
1496 case OMP_CLAUSE_NOTINBRANCH:
1497 data[i].notinbranch = true;
1498 continue;
1499 case OMP_CLAUSE_SIMDLEN:
1500 data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
1501 continue;
1502 case OMP_CLAUSE_UNIFORM:
1503 case OMP_CLAUSE_LINEAR:
1504 v = &data[i].data_sharing;
1505 break;
1506 case OMP_CLAUSE_ALIGNED:
1507 v = &data[i].aligned;
1508 break;
1509 default:
1510 gcc_unreachable ();
1512 unsigned HOST_WIDE_INT argno = tree_to_uhwi (OMP_CLAUSE_DECL (c));
1513 if (argno >= v->length ())
1514 v->safe_grow_cleared (argno + 1, true);
1515 (*v)[argno] = c;
1517 /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1518 CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1519 doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1520 -1, r == 2 implies 1 and r == 0 implies 0. */
1521 if (data[0].inbranch != data[1].inbranch)
1522 r |= data[0].inbranch ? 2 : 1;
1523 if (data[0].notinbranch != data[1].notinbranch)
1524 r |= data[0].notinbranch ? 2 : 1;
1525 if (!simple_cst_equal (data[0].simdlen, data[1].simdlen))
1527 if (data[0].simdlen && data[1].simdlen)
1528 return 2;
1529 r |= data[0].simdlen ? 2 : 1;
1531 if (data[0].data_sharing.length () < data[1].data_sharing.length ()
1532 || data[0].aligned.length () < data[1].aligned.length ())
1533 r |= 1;
1534 tree c1, c2;
1535 FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
1537 c2 = (i < data[1].data_sharing.length ()
1538 ? data[1].data_sharing[i] : NULL_TREE);
1539 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
1541 r |= c1 != NULL_TREE ? 2 : 1;
1542 continue;
1544 if (c1 == NULL_TREE)
1545 continue;
1546 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
1547 return 2;
1548 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
1549 continue;
1550 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
1551 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
1552 return 2;
1553 if (OMP_CLAUSE_LINEAR_KIND (c1) != OMP_CLAUSE_LINEAR_KIND (c2))
1554 return 2;
1555 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
1556 OMP_CLAUSE_LINEAR_STEP (c2)))
1557 return 2;
1559 FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
1561 c2 = i < data[1].aligned.length () ? data[1].aligned[i] : NULL_TREE;
1562 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
1564 r |= c1 != NULL_TREE ? 2 : 1;
1565 continue;
1567 if (c1 == NULL_TREE)
1568 continue;
1569 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
1570 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
1571 return 2;
1573 switch (r)
1575 case 0: return 0;
1576 case 1: return -1;
1577 case 2: return 1;
1578 case 3: return 2;
1579 default: gcc_unreachable ();
1583 /* Compare properties of selectors SEL from SET other than construct.
1584 Return 0/-1/1/2 as in omp_context_selector_set_compare.
1585 Unlike set names or selector names, properties can have duplicates. */
1587 static int
1588 omp_context_selector_props_compare (const char *set, const char *sel,
1589 tree ctx1, tree ctx2)
1591 int ret = 0;
1592 for (int pass = 0; pass < 2; pass++)
1593 for (tree t1 = pass ? ctx2 : ctx1; t1; t1 = TREE_CHAIN (t1))
1595 tree t2;
1596 for (t2 = pass ? ctx1 : ctx2; t2; t2 = TREE_CHAIN (t2))
1597 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1599 if (TREE_PURPOSE (t1) == NULL_TREE)
1601 if (set[0] == 'u' && strcmp (sel, "condition") == 0)
1603 if (integer_zerop (TREE_VALUE (t1))
1604 != integer_zerop (TREE_VALUE (t2)))
1605 return 2;
1606 break;
1608 if (simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1609 break;
1611 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
1612 " score") == 0)
1614 if (!simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1615 return 2;
1616 break;
1618 else
1619 break;
1621 else if (TREE_PURPOSE (t1)
1622 && TREE_PURPOSE (t2) == NULL_TREE
1623 && TREE_CODE (TREE_VALUE (t2)) == STRING_CST)
1625 const char *p1 = omp_context_name_list_prop (t1);
1626 const char *p2 = omp_context_name_list_prop (t2);
1627 if (p2
1628 && strcmp (p1, p2) == 0
1629 && strcmp (p1, " score"))
1630 break;
1632 else if (TREE_PURPOSE (t1) == NULL_TREE
1633 && TREE_PURPOSE (t2)
1634 && TREE_CODE (TREE_VALUE (t1)) == STRING_CST)
1636 const char *p1 = omp_context_name_list_prop (t1);
1637 const char *p2 = omp_context_name_list_prop (t2);
1638 if (p1
1639 && strcmp (p1, p2) == 0
1640 && strcmp (p1, " score"))
1641 break;
1643 if (t2 == NULL_TREE)
1645 int r = pass ? -1 : 1;
1646 if (ret && ret != r)
1647 return 2;
1648 else if (pass)
1649 return r;
1650 else
1652 ret = r;
1653 break;
1657 return ret;
1660 /* Compare single context selector sets CTX1 and CTX2 with SET name.
1661 Return 0 if CTX1 is equal to CTX2,
1662 -1 if CTX1 is a strict subset of CTX2,
1663 1 if CTX2 is a strict subset of CTX1, or
1664 2 if neither context is a subset of another one. */
1667 omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
1669 bool swapped = false;
1670 int ret = 0;
1671 int len1 = list_length (ctx1);
1672 int len2 = list_length (ctx2);
1673 int cnt = 0;
1674 if (len1 < len2)
1676 swapped = true;
1677 std::swap (ctx1, ctx2);
1678 std::swap (len1, len2);
1680 if (set[0] == 'c')
1682 tree t1;
1683 tree t2 = ctx2;
1684 tree simd = get_identifier ("simd");
1685 /* Handle construct set specially. In this case the order
1686 of the selector matters too. */
1687 for (t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1688 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1690 int r = 0;
1691 if (TREE_PURPOSE (t1) == simd)
1692 r = omp_construct_simd_compare (TREE_VALUE (t1),
1693 TREE_VALUE (t2));
1694 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1695 return 2;
1696 if (ret == 0)
1697 ret = r;
1698 t2 = TREE_CHAIN (t2);
1699 if (t2 == NULL_TREE)
1701 t1 = TREE_CHAIN (t1);
1702 break;
1705 else if (ret < 0)
1706 return 2;
1707 else
1708 ret = 1;
1709 if (t2 != NULL_TREE)
1710 return 2;
1711 if (t1 != NULL_TREE)
1713 if (ret < 0)
1714 return 2;
1715 ret = 1;
1717 if (ret == 0)
1718 return 0;
1719 return swapped ? -ret : ret;
1721 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1723 tree t2;
1724 for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
1725 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1727 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
1728 int r = omp_context_selector_props_compare (set, sel,
1729 TREE_VALUE (t1),
1730 TREE_VALUE (t2));
1731 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1732 return 2;
1733 if (ret == 0)
1734 ret = r;
1735 cnt++;
1736 break;
1738 if (t2 == NULL_TREE)
1740 if (ret == -1)
1741 return 2;
1742 ret = 1;
1745 if (cnt < len2)
1746 return 2;
1747 if (ret == 0)
1748 return 0;
1749 return swapped ? -ret : ret;
1752 /* Compare whole context selector specification CTX1 and CTX2.
1753 Return 0 if CTX1 is equal to CTX2,
1754 -1 if CTX1 is a strict subset of CTX2,
1755 1 if CTX2 is a strict subset of CTX1, or
1756 2 if neither context is a subset of another one. */
1758 static int
1759 omp_context_selector_compare (tree ctx1, tree ctx2)
1761 bool swapped = false;
1762 int ret = 0;
1763 int len1 = list_length (ctx1);
1764 int len2 = list_length (ctx2);
1765 int cnt = 0;
1766 if (len1 < len2)
1768 swapped = true;
1769 std::swap (ctx1, ctx2);
1770 std::swap (len1, len2);
1772 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1774 tree t2;
1775 for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
1776 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1778 const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
1779 int r = omp_context_selector_set_compare (set, TREE_VALUE (t1),
1780 TREE_VALUE (t2));
1781 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1782 return 2;
1783 if (ret == 0)
1784 ret = r;
1785 cnt++;
1786 break;
1788 if (t2 == NULL_TREE)
1790 if (ret == -1)
1791 return 2;
1792 ret = 1;
1795 if (cnt < len2)
1796 return 2;
1797 if (ret == 0)
1798 return 0;
1799 return swapped ? -ret : ret;
1802 /* From context selector CTX, return trait-selector with name SEL in
1803 trait-selector-set with name SET if any, or NULL_TREE if not found.
1804 If SEL is NULL, return the list of trait-selectors in SET. */
1806 tree
1807 omp_get_context_selector (tree ctx, const char *set, const char *sel)
1809 tree setid = get_identifier (set);
1810 tree selid = sel ? get_identifier (sel) : NULL_TREE;
1811 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1812 if (TREE_PURPOSE (t1) == setid)
1814 if (sel == NULL)
1815 return TREE_VALUE (t1);
1816 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1817 if (TREE_PURPOSE (t2) == selid)
1818 return t2;
1820 return NULL_TREE;
1823 /* Compute *SCORE for context selector CTX. Return true if the score
1824 would be different depending on whether it is a declare simd clone or
1825 not. DECLARE_SIMD should be true for the case when it would be
1826 a declare simd clone. */
1828 static bool
1829 omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
1831 tree construct = omp_get_context_selector (ctx, "construct", NULL);
1832 bool has_kind = omp_get_context_selector (ctx, "device", "kind");
1833 bool has_arch = omp_get_context_selector (ctx, "device", "arch");
1834 bool has_isa = omp_get_context_selector (ctx, "device", "isa");
1835 bool ret = false;
1836 *score = 1;
1837 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1838 if (TREE_VALUE (t1) != construct)
1839 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1840 if (tree t3 = TREE_VALUE (t2))
1841 if (TREE_PURPOSE (t3)
1842 && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)), " score") == 0
1843 && TREE_CODE (TREE_VALUE (t3)) == INTEGER_CST)
1844 *score += wi::to_widest (TREE_VALUE (t3));
1845 if (construct || has_kind || has_arch || has_isa)
1847 int scores[12];
1848 enum tree_code constructs[5];
1849 int nconstructs = 0;
1850 if (construct)
1851 nconstructs = omp_constructor_traits_to_codes (construct, constructs);
1852 if (omp_construct_selector_matches (constructs, nconstructs, scores)
1853 == 2)
1854 ret = true;
1855 int b = declare_simd ? nconstructs + 1 : 0;
1856 if (scores[b + nconstructs] + 4U < score->get_precision ())
1858 for (int n = 0; n < nconstructs; ++n)
1860 if (scores[b + n] < 0)
1862 *score = -1;
1863 return ret;
1865 *score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
1867 if (has_kind)
1868 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs],
1869 1, false);
1870 if (has_arch)
1871 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 1,
1872 1, false);
1873 if (has_isa)
1874 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 2,
1875 1, false);
1877 else /* FIXME: Implement this. */
1878 gcc_unreachable ();
1880 return ret;
1883 /* Class describing a single variant. */
1884 struct GTY(()) omp_declare_variant_entry {
1885 /* NODE of the variant. */
1886 cgraph_node *variant;
1887 /* Score if not in declare simd clone. */
1888 widest_int score;
1889 /* Score if in declare simd clone. */
1890 widest_int score_in_declare_simd_clone;
1891 /* Context selector for the variant. */
1892 tree ctx;
1893 /* True if the context selector is known to match already. */
1894 bool matches;
1897 /* Class describing a function with variants. */
1898 struct GTY((for_user)) omp_declare_variant_base_entry {
1899 /* NODE of the base function. */
1900 cgraph_node *base;
1901 /* NODE of the artificial function created for the deferred variant
1902 resolution. */
1903 cgraph_node *node;
1904 /* Vector of the variants. */
1905 vec<omp_declare_variant_entry, va_gc> *variants;
1908 struct omp_declare_variant_hasher
1909 : ggc_ptr_hash<omp_declare_variant_base_entry> {
1910 static hashval_t hash (omp_declare_variant_base_entry *);
1911 static bool equal (omp_declare_variant_base_entry *,
1912 omp_declare_variant_base_entry *);
1915 hashval_t
1916 omp_declare_variant_hasher::hash (omp_declare_variant_base_entry *x)
1918 inchash::hash hstate;
1919 hstate.add_int (DECL_UID (x->base->decl));
1920 hstate.add_int (x->variants->length ());
1921 omp_declare_variant_entry *variant;
1922 unsigned int i;
1923 FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
1925 hstate.add_int (DECL_UID (variant->variant->decl));
1926 hstate.add_wide_int (variant->score);
1927 hstate.add_wide_int (variant->score_in_declare_simd_clone);
1928 hstate.add_ptr (variant->ctx);
1929 hstate.add_int (variant->matches);
1931 return hstate.end ();
1934 bool
1935 omp_declare_variant_hasher::equal (omp_declare_variant_base_entry *x,
1936 omp_declare_variant_base_entry *y)
1938 if (x->base != y->base
1939 || x->variants->length () != y->variants->length ())
1940 return false;
1941 omp_declare_variant_entry *variant;
1942 unsigned int i;
1943 FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
1944 if (variant->variant != (*y->variants)[i].variant
1945 || variant->score != (*y->variants)[i].score
1946 || (variant->score_in_declare_simd_clone
1947 != (*y->variants)[i].score_in_declare_simd_clone)
1948 || variant->ctx != (*y->variants)[i].ctx
1949 || variant->matches != (*y->variants)[i].matches)
1950 return false;
1951 return true;
1954 static GTY(()) hash_table<omp_declare_variant_hasher> *omp_declare_variants;
1956 struct omp_declare_variant_alt_hasher
1957 : ggc_ptr_hash<omp_declare_variant_base_entry> {
1958 static hashval_t hash (omp_declare_variant_base_entry *);
1959 static bool equal (omp_declare_variant_base_entry *,
1960 omp_declare_variant_base_entry *);
1963 hashval_t
1964 omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry *x)
1966 return DECL_UID (x->node->decl);
1969 bool
1970 omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry *x,
1971 omp_declare_variant_base_entry *y)
1973 return x->node == y->node;
1976 static GTY(()) hash_table<omp_declare_variant_alt_hasher>
1977 *omp_declare_variant_alt;
1979 /* Try to resolve declare variant after gimplification. */
1981 static tree
1982 omp_resolve_late_declare_variant (tree alt)
1984 cgraph_node *node = cgraph_node::get (alt);
1985 cgraph_node *cur_node = cgraph_node::get (cfun->decl);
1986 if (node == NULL
1987 || !node->declare_variant_alt
1988 || !cfun->after_inlining)
1989 return alt;
1991 omp_declare_variant_base_entry entry;
1992 entry.base = NULL;
1993 entry.node = node;
1994 entry.variants = NULL;
1995 omp_declare_variant_base_entry *entryp
1996 = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (alt));
1998 unsigned int i, j;
1999 omp_declare_variant_entry *varentry1, *varentry2;
2000 auto_vec <bool, 16> matches;
2001 unsigned int nmatches = 0;
2002 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2004 if (varentry1->matches)
2006 /* This has been checked to be ok already. */
2007 matches.safe_push (true);
2008 nmatches++;
2009 continue;
2011 switch (omp_context_selector_matches (varentry1->ctx))
2013 case 0:
2014 matches.safe_push (false);
2015 break;
2016 case -1:
2017 return alt;
2018 default:
2019 matches.safe_push (true);
2020 nmatches++;
2021 break;
2025 if (nmatches == 0)
2026 return entryp->base->decl;
2028 /* A context selector that is a strict subset of another context selector
2029 has a score of zero. */
2030 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2031 if (matches[i])
2033 for (j = i + 1;
2034 vec_safe_iterate (entryp->variants, j, &varentry2); ++j)
2035 if (matches[j])
2037 int r = omp_context_selector_compare (varentry1->ctx,
2038 varentry2->ctx);
2039 if (r == -1)
2041 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2042 matches[i] = false;
2043 break;
2045 else if (r == 1)
2046 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2047 matches[j] = false;
2051 widest_int max_score = -1;
2052 varentry2 = NULL;
2053 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2054 if (matches[i])
2056 widest_int score
2057 = (cur_node->simdclone ? varentry1->score_in_declare_simd_clone
2058 : varentry1->score);
2059 if (score > max_score)
2061 max_score = score;
2062 varentry2 = varentry1;
2065 return varentry2->variant->decl;
2068 /* Hook to adjust hash tables on cgraph_node removal. */
2070 static void
2071 omp_declare_variant_remove_hook (struct cgraph_node *node, void *)
2073 if (!node->declare_variant_alt)
2074 return;
2076 /* Drop this hash table completely. */
2077 omp_declare_variants = NULL;
2078 /* And remove node from the other hash table. */
2079 if (omp_declare_variant_alt)
2081 omp_declare_variant_base_entry entry;
2082 entry.base = NULL;
2083 entry.node = node;
2084 entry.variants = NULL;
2085 omp_declare_variant_alt->remove_elt_with_hash (&entry,
2086 DECL_UID (node->decl));
2090 /* Try to resolve declare variant, return the variant decl if it should
2091 be used instead of base, or base otherwise. */
2093 tree
2094 omp_resolve_declare_variant (tree base)
2096 tree variant1 = NULL_TREE, variant2 = NULL_TREE;
2097 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
2098 return omp_resolve_late_declare_variant (base);
2100 auto_vec <tree, 16> variants;
2101 auto_vec <bool, 16> defer;
2102 bool any_deferred = false;
2103 for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
2105 attr = lookup_attribute ("omp declare variant base", attr);
2106 if (attr == NULL_TREE)
2107 break;
2108 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr))) != FUNCTION_DECL)
2109 continue;
2110 cgraph_node *node = cgraph_node::get (base);
2111 /* If this is already a magic decl created by this function,
2112 don't process it again. */
2113 if (node && node->declare_variant_alt)
2114 return base;
2115 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr))))
2117 case 0:
2118 /* No match, ignore. */
2119 break;
2120 case -1:
2121 /* Needs to be deferred. */
2122 any_deferred = true;
2123 variants.safe_push (attr);
2124 defer.safe_push (true);
2125 break;
2126 default:
2127 variants.safe_push (attr);
2128 defer.safe_push (false);
2129 break;
2132 if (variants.length () == 0)
2133 return base;
2135 if (any_deferred)
2137 widest_int max_score1 = 0;
2138 widest_int max_score2 = 0;
2139 bool first = true;
2140 unsigned int i;
2141 tree attr1, attr2;
2142 omp_declare_variant_base_entry entry;
2143 entry.base = cgraph_node::get_create (base);
2144 entry.node = NULL;
2145 vec_alloc (entry.variants, variants.length ());
2146 FOR_EACH_VEC_ELT (variants, i, attr1)
2148 widest_int score1;
2149 widest_int score2;
2150 bool need_two;
2151 tree ctx = TREE_VALUE (TREE_VALUE (attr1));
2152 need_two = omp_context_compute_score (ctx, &score1, false);
2153 if (need_two)
2154 omp_context_compute_score (ctx, &score2, true);
2155 else
2156 score2 = score1;
2157 if (first)
2159 first = false;
2160 max_score1 = score1;
2161 max_score2 = score2;
2162 if (!defer[i])
2164 variant1 = attr1;
2165 variant2 = attr1;
2168 else
2170 if (max_score1 == score1)
2171 variant1 = NULL_TREE;
2172 else if (score1 > max_score1)
2174 max_score1 = score1;
2175 variant1 = defer[i] ? NULL_TREE : attr1;
2177 if (max_score2 == score2)
2178 variant2 = NULL_TREE;
2179 else if (score2 > max_score2)
2181 max_score2 = score2;
2182 variant2 = defer[i] ? NULL_TREE : attr1;
2185 omp_declare_variant_entry varentry;
2186 varentry.variant
2187 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1)));
2188 varentry.score = score1;
2189 varentry.score_in_declare_simd_clone = score2;
2190 varentry.ctx = ctx;
2191 varentry.matches = !defer[i];
2192 entry.variants->quick_push (varentry);
2195 /* If there is a clear winner variant with the score which is not
2196 deferred, verify it is not a strict subset of any other context
2197 selector and if it is not, it is the best alternative no matter
2198 whether the others do or don't match. */
2199 if (variant1 && variant1 == variant2)
2201 tree ctx1 = TREE_VALUE (TREE_VALUE (variant1));
2202 FOR_EACH_VEC_ELT (variants, i, attr2)
2204 if (attr2 == variant1)
2205 continue;
2206 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2207 int r = omp_context_selector_compare (ctx1, ctx2);
2208 if (r == -1)
2210 /* The winner is a strict subset of ctx2, can't
2211 decide now. */
2212 variant1 = NULL_TREE;
2213 break;
2216 if (variant1)
2218 vec_free (entry.variants);
2219 return TREE_PURPOSE (TREE_VALUE (variant1));
2223 static struct cgraph_node_hook_list *node_removal_hook_holder;
2224 if (!node_removal_hook_holder)
2225 node_removal_hook_holder
2226 = symtab->add_cgraph_removal_hook (omp_declare_variant_remove_hook,
2227 NULL);
2229 if (omp_declare_variants == NULL)
2230 omp_declare_variants
2231 = hash_table<omp_declare_variant_hasher>::create_ggc (64);
2232 omp_declare_variant_base_entry **slot
2233 = omp_declare_variants->find_slot (&entry, INSERT);
2234 if (*slot != NULL)
2236 vec_free (entry.variants);
2237 return (*slot)->node->decl;
2240 *slot = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
2241 (*slot)->base = entry.base;
2242 (*slot)->node = entry.base;
2243 (*slot)->variants = entry.variants;
2244 tree alt = build_decl (DECL_SOURCE_LOCATION (base), FUNCTION_DECL,
2245 DECL_NAME (base), TREE_TYPE (base));
2246 DECL_ARTIFICIAL (alt) = 1;
2247 DECL_IGNORED_P (alt) = 1;
2248 TREE_STATIC (alt) = 1;
2249 tree attributes = DECL_ATTRIBUTES (base);
2250 if (lookup_attribute ("noipa", attributes) == NULL)
2252 attributes = tree_cons (get_identifier ("noipa"), NULL, attributes);
2253 if (lookup_attribute ("noinline", attributes) == NULL)
2254 attributes = tree_cons (get_identifier ("noinline"), NULL,
2255 attributes);
2256 if (lookup_attribute ("noclone", attributes) == NULL)
2257 attributes = tree_cons (get_identifier ("noclone"), NULL,
2258 attributes);
2259 if (lookup_attribute ("no_icf", attributes) == NULL)
2260 attributes = tree_cons (get_identifier ("no_icf"), NULL,
2261 attributes);
2263 DECL_ATTRIBUTES (alt) = attributes;
2264 DECL_INITIAL (alt) = error_mark_node;
2265 (*slot)->node = cgraph_node::create (alt);
2266 (*slot)->node->declare_variant_alt = 1;
2267 (*slot)->node->create_reference (entry.base, IPA_REF_ADDR);
2268 omp_declare_variant_entry *varentry;
2269 FOR_EACH_VEC_SAFE_ELT (entry.variants, i, varentry)
2270 (*slot)->node->create_reference (varentry->variant, IPA_REF_ADDR);
2271 if (omp_declare_variant_alt == NULL)
2272 omp_declare_variant_alt
2273 = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
2274 *omp_declare_variant_alt->find_slot_with_hash (*slot, DECL_UID (alt),
2275 INSERT) = *slot;
2276 return alt;
2279 if (variants.length () == 1)
2280 return TREE_PURPOSE (TREE_VALUE (variants[0]));
2282 /* A context selector that is a strict subset of another context selector
2283 has a score of zero. */
2284 tree attr1, attr2;
2285 unsigned int i, j;
2286 FOR_EACH_VEC_ELT (variants, i, attr1)
2287 if (attr1)
2289 tree ctx1 = TREE_VALUE (TREE_VALUE (attr1));
2290 FOR_EACH_VEC_ELT_FROM (variants, j, attr2, i + 1)
2291 if (attr2)
2293 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2294 int r = omp_context_selector_compare (ctx1, ctx2);
2295 if (r == -1)
2297 /* ctx1 is a strict subset of ctx2, remove
2298 attr1 from the vector. */
2299 variants[i] = NULL_TREE;
2300 break;
2302 else if (r == 1)
2303 /* ctx2 is a strict subset of ctx1, remove attr2
2304 from the vector. */
2305 variants[j] = NULL_TREE;
2308 widest_int max_score1 = 0;
2309 widest_int max_score2 = 0;
2310 bool first = true;
2311 FOR_EACH_VEC_ELT (variants, i, attr1)
2312 if (attr1)
2314 if (variant1)
2316 widest_int score1;
2317 widest_int score2;
2318 bool need_two;
2319 tree ctx;
2320 if (first)
2322 first = false;
2323 ctx = TREE_VALUE (TREE_VALUE (variant1));
2324 need_two = omp_context_compute_score (ctx, &max_score1, false);
2325 if (need_two)
2326 omp_context_compute_score (ctx, &max_score2, true);
2327 else
2328 max_score2 = max_score1;
2330 ctx = TREE_VALUE (TREE_VALUE (attr1));
2331 need_two = omp_context_compute_score (ctx, &score1, false);
2332 if (need_two)
2333 omp_context_compute_score (ctx, &score2, true);
2334 else
2335 score2 = score1;
2336 if (score1 > max_score1)
2338 max_score1 = score1;
2339 variant1 = attr1;
2341 if (score2 > max_score2)
2343 max_score2 = score2;
2344 variant2 = attr1;
2347 else
2349 variant1 = attr1;
2350 variant2 = attr1;
2353 /* If there is a disagreement on which variant has the highest score
2354 depending on whether it will be in a declare simd clone or not,
2355 punt for now and defer until after IPA where we will know that. */
2356 return ((variant1 && variant1 == variant2)
2357 ? TREE_PURPOSE (TREE_VALUE (variant1)) : base);
2360 void
2361 omp_lto_output_declare_variant_alt (lto_simple_output_block *ob,
2362 cgraph_node *node,
2363 lto_symtab_encoder_t encoder)
2365 gcc_assert (node->declare_variant_alt);
2367 omp_declare_variant_base_entry entry;
2368 entry.base = NULL;
2369 entry.node = node;
2370 entry.variants = NULL;
2371 omp_declare_variant_base_entry *entryp
2372 = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (node->decl));
2373 gcc_assert (entryp);
2375 int nbase = lto_symtab_encoder_lookup (encoder, entryp->base);
2376 gcc_assert (nbase != LCC_NOT_FOUND);
2377 streamer_write_hwi_stream (ob->main_stream, nbase);
2379 streamer_write_hwi_stream (ob->main_stream, entryp->variants->length ());
2381 unsigned int i;
2382 omp_declare_variant_entry *varentry;
2383 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry)
2385 int nvar = lto_symtab_encoder_lookup (encoder, varentry->variant);
2386 gcc_assert (nvar != LCC_NOT_FOUND);
2387 streamer_write_hwi_stream (ob->main_stream, nvar);
2389 for (widest_int *w = &varentry->score; ;
2390 w = &varentry->score_in_declare_simd_clone)
2392 unsigned len = w->get_len ();
2393 streamer_write_hwi_stream (ob->main_stream, len);
2394 const HOST_WIDE_INT *val = w->get_val ();
2395 for (unsigned j = 0; j < len; j++)
2396 streamer_write_hwi_stream (ob->main_stream, val[j]);
2397 if (w == &varentry->score_in_declare_simd_clone)
2398 break;
2401 HOST_WIDE_INT cnt = -1;
2402 HOST_WIDE_INT i = varentry->matches ? 1 : 0;
2403 for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
2404 attr; attr = TREE_CHAIN (attr), i += 2)
2406 attr = lookup_attribute ("omp declare variant base", attr);
2407 if (attr == NULL_TREE)
2408 break;
2410 if (varentry->ctx == TREE_VALUE (TREE_VALUE (attr)))
2412 cnt = i;
2413 break;
2417 gcc_assert (cnt != -1);
2418 streamer_write_hwi_stream (ob->main_stream, cnt);
2422 void
2423 omp_lto_input_declare_variant_alt (lto_input_block *ib, cgraph_node *node,
2424 vec<symtab_node *> nodes)
2426 gcc_assert (node->declare_variant_alt);
2427 omp_declare_variant_base_entry *entryp
2428 = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
2429 entryp->base = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
2430 entryp->node = node;
2431 unsigned int len = streamer_read_hwi (ib);
2432 vec_alloc (entryp->variants, len);
2434 for (unsigned int i = 0; i < len; i++)
2436 omp_declare_variant_entry varentry;
2437 varentry.variant
2438 = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
2439 for (widest_int *w = &varentry.score; ;
2440 w = &varentry.score_in_declare_simd_clone)
2442 unsigned len2 = streamer_read_hwi (ib);
2443 HOST_WIDE_INT arr[WIDE_INT_MAX_ELTS];
2444 gcc_assert (len2 <= WIDE_INT_MAX_ELTS);
2445 for (unsigned int j = 0; j < len2; j++)
2446 arr[j] = streamer_read_hwi (ib);
2447 *w = widest_int::from_array (arr, len2, true);
2448 if (w == &varentry.score_in_declare_simd_clone)
2449 break;
2452 HOST_WIDE_INT cnt = streamer_read_hwi (ib);
2453 HOST_WIDE_INT j = 0;
2454 varentry.ctx = NULL_TREE;
2455 varentry.matches = (cnt & 1) ? true : false;
2456 cnt &= ~HOST_WIDE_INT_1;
2457 for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
2458 attr; attr = TREE_CHAIN (attr), j += 2)
2460 attr = lookup_attribute ("omp declare variant base", attr);
2461 if (attr == NULL_TREE)
2462 break;
2464 if (cnt == j)
2466 varentry.ctx = TREE_VALUE (TREE_VALUE (attr));
2467 break;
2470 gcc_assert (varentry.ctx != NULL_TREE);
2471 entryp->variants->quick_push (varentry);
2473 if (omp_declare_variant_alt == NULL)
2474 omp_declare_variant_alt
2475 = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
2476 *omp_declare_variant_alt->find_slot_with_hash (entryp, DECL_UID (node->decl),
2477 INSERT) = entryp;
2480 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2481 macro on gomp-constants.h. We do not check for overflow. */
2483 tree
2484 oacc_launch_pack (unsigned code, tree device, unsigned op)
2486 tree res;
2488 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
2489 if (device)
2491 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
2492 device, build_int_cst (unsigned_type_node,
2493 GOMP_LAUNCH_DEVICE_SHIFT));
2494 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
2496 return res;
2499 /* FIXME: What is the following comment for? */
2500 /* Look for compute grid dimension clauses and convert to an attribute
2501 attached to FN. This permits the target-side code to (a) massage
2502 the dimensions, (b) emit that data and (c) optimize. Non-constant
2503 dimensions are pushed onto ARGS.
2505 The attribute value is a TREE_LIST. A set of dimensions is
2506 represented as a list of INTEGER_CST. Those that are runtime
2507 exprs are represented as an INTEGER_CST of zero.
2509 TODO: Normally the attribute will just contain a single such list. If
2510 however it contains a list of lists, this will represent the use of
2511 device_type. Each member of the outer list is an assoc list of
2512 dimensions, keyed by the device type. The first entry will be the
2513 default. Well, that's the plan. */
2515 /* Replace any existing oacc fn attribute with updated dimensions. */
2517 /* Variant working on a list of attributes. */
2519 tree
2520 oacc_replace_fn_attrib_attr (tree attribs, tree dims)
2522 tree ident = get_identifier (OACC_FN_ATTRIB);
2524 /* If we happen to be present as the first attrib, drop it. */
2525 if (attribs && TREE_PURPOSE (attribs) == ident)
2526 attribs = TREE_CHAIN (attribs);
2527 return tree_cons (ident, dims, attribs);
2530 /* Variant working on a function decl. */
2532 void
2533 oacc_replace_fn_attrib (tree fn, tree dims)
2535 DECL_ATTRIBUTES (fn)
2536 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn), dims);
2539 /* Scan CLAUSES for launch dimensions and attach them to the oacc
2540 function attribute. Push any that are non-constant onto the ARGS
2541 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
2543 void
2544 oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
2546 /* Must match GOMP_DIM ordering. */
2547 static const omp_clause_code ids[]
2548 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
2549 OMP_CLAUSE_VECTOR_LENGTH };
2550 unsigned ix;
2551 tree dims[GOMP_DIM_MAX];
2553 tree attr = NULL_TREE;
2554 unsigned non_const = 0;
2556 for (ix = GOMP_DIM_MAX; ix--;)
2558 tree clause = omp_find_clause (clauses, ids[ix]);
2559 tree dim = NULL_TREE;
2561 if (clause)
2562 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
2563 dims[ix] = dim;
2564 if (dim && TREE_CODE (dim) != INTEGER_CST)
2566 dim = integer_zero_node;
2567 non_const |= GOMP_DIM_MASK (ix);
2569 attr = tree_cons (NULL_TREE, dim, attr);
2572 oacc_replace_fn_attrib (fn, attr);
2574 if (non_const)
2576 /* Push a dynamic argument set. */
2577 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
2578 NULL_TREE, non_const));
2579 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
2580 if (non_const & GOMP_DIM_MASK (ix))
2581 args->safe_push (dims[ix]);
2585 /* Verify OpenACC routine clauses.
2587 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
2588 if it has already been marked in compatible way, and -1 if incompatible.
2589 Upon returning, the chain of clauses will contain exactly one clause
2590 specifying the level of parallelism. */
2593 oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc,
2594 const char *routine_str)
2596 tree c_level = NULL_TREE;
2597 tree c_nohost = NULL_TREE;
2598 tree c_p = NULL_TREE;
2599 for (tree c = *clauses; c; c_p = c, c = OMP_CLAUSE_CHAIN (c))
2600 switch (OMP_CLAUSE_CODE (c))
2602 case OMP_CLAUSE_GANG:
2603 case OMP_CLAUSE_WORKER:
2604 case OMP_CLAUSE_VECTOR:
2605 case OMP_CLAUSE_SEQ:
2606 if (c_level == NULL_TREE)
2607 c_level = c;
2608 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_CODE (c_level))
2610 /* This has already been diagnosed in the front ends. */
2611 /* Drop the duplicate clause. */
2612 gcc_checking_assert (c_p != NULL_TREE);
2613 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
2614 c = c_p;
2616 else
2618 error_at (OMP_CLAUSE_LOCATION (c),
2619 "%qs specifies a conflicting level of parallelism",
2620 omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
2621 inform (OMP_CLAUSE_LOCATION (c_level),
2622 "... to the previous %qs clause here",
2623 omp_clause_code_name[OMP_CLAUSE_CODE (c_level)]);
2624 /* Drop the conflicting clause. */
2625 gcc_checking_assert (c_p != NULL_TREE);
2626 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
2627 c = c_p;
2629 break;
2630 case OMP_CLAUSE_NOHOST:
2631 /* Don't worry about duplicate clauses here. */
2632 c_nohost = c;
2633 break;
2634 default:
2635 gcc_unreachable ();
2637 if (c_level == NULL_TREE)
2639 /* Default to an implicit 'seq' clause. */
2640 c_level = build_omp_clause (loc, OMP_CLAUSE_SEQ);
2641 OMP_CLAUSE_CHAIN (c_level) = *clauses;
2642 *clauses = c_level;
2644 /* In *clauses, we now have exactly one clause specifying the level of
2645 parallelism. */
2647 tree attr
2648 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl));
2649 if (attr != NULL_TREE)
2651 /* Diagnose if "#pragma omp declare target" has also been applied. */
2652 if (TREE_VALUE (attr) == NULL_TREE)
2654 /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
2655 OpenACC and OpenMP 'target' are not clear. */
2656 error_at (loc,
2657 "cannot apply %<%s%> to %qD, which has also been"
2658 " marked with an OpenMP 'declare target' directive",
2659 routine_str, fndecl);
2660 /* Incompatible. */
2661 return -1;
2664 /* If a "#pragma acc routine" has already been applied, just verify
2665 this one for compatibility. */
2666 /* Collect previous directive's clauses. */
2667 tree c_level_p = NULL_TREE;
2668 tree c_nohost_p = NULL_TREE;
2669 for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c))
2670 switch (OMP_CLAUSE_CODE (c))
2672 case OMP_CLAUSE_GANG:
2673 case OMP_CLAUSE_WORKER:
2674 case OMP_CLAUSE_VECTOR:
2675 case OMP_CLAUSE_SEQ:
2676 gcc_checking_assert (c_level_p == NULL_TREE);
2677 c_level_p = c;
2678 break;
2679 case OMP_CLAUSE_NOHOST:
2680 gcc_checking_assert (c_nohost_p == NULL_TREE);
2681 c_nohost_p = c;
2682 break;
2683 default:
2684 gcc_unreachable ();
2686 gcc_checking_assert (c_level_p != NULL_TREE);
2687 /* ..., and compare to current directive's, which we've already collected
2688 above. */
2689 tree c_diag;
2690 tree c_diag_p;
2691 /* Matching level of parallelism? */
2692 if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
2694 c_diag = c_level;
2695 c_diag_p = c_level_p;
2696 goto incompatible;
2698 /* Matching 'nohost' clauses? */
2699 if ((c_nohost == NULL_TREE) != (c_nohost_p == NULL_TREE))
2701 c_diag = c_nohost;
2702 c_diag_p = c_nohost_p;
2703 goto incompatible;
2705 /* Compatible. */
2706 return 1;
2708 incompatible:
2709 if (c_diag != NULL_TREE)
2710 error_at (OMP_CLAUSE_LOCATION (c_diag),
2711 "incompatible %qs clause when applying"
2712 " %<%s%> to %qD, which has already been"
2713 " marked with an OpenACC 'routine' directive",
2714 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)],
2715 routine_str, fndecl);
2716 else if (c_diag_p != NULL_TREE)
2717 error_at (loc,
2718 "missing %qs clause when applying"
2719 " %<%s%> to %qD, which has already been"
2720 " marked with an OpenACC 'routine' directive",
2721 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)],
2722 routine_str, fndecl);
2723 else
2724 gcc_unreachable ();
2725 if (c_diag_p != NULL_TREE)
2726 inform (OMP_CLAUSE_LOCATION (c_diag_p),
2727 "... with %qs clause here",
2728 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]);
2729 else
2731 /* In the front ends, we don't preserve location information for the
2732 OpenACC routine directive itself. However, that of c_level_p
2733 should be close. */
2734 location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p);
2735 inform (loc_routine, "... without %qs clause near to here",
2736 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]);
2738 /* Incompatible. */
2739 return -1;
2742 return 0;
2745 /* Process the OpenACC 'routine' directive clauses to generate an attribute
2746 for the level of parallelism. All dimensions have a size of zero
2747 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
2748 can have a loop partitioned on it. non-zero indicates
2749 yes, zero indicates no. By construction once a non-zero has been
2750 reached, further inner dimensions must also be non-zero. We set
2751 TREE_VALUE to zero for the dimensions that may be partitioned and
2752 1 for the other ones -- if a loop is (erroneously) spawned at
2753 an outer level, we don't want to try and partition it. */
2755 tree
2756 oacc_build_routine_dims (tree clauses)
2758 /* Must match GOMP_DIM ordering. */
2759 static const omp_clause_code ids[]
2760 = {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
2761 int ix;
2762 int level = -1;
2764 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
2765 for (ix = GOMP_DIM_MAX + 1; ix--;)
2766 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
2768 level = ix;
2769 break;
2771 gcc_checking_assert (level >= 0);
2773 tree dims = NULL_TREE;
2775 for (ix = GOMP_DIM_MAX; ix--;)
2776 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
2777 build_int_cst (integer_type_node, ix < level), dims);
2779 return dims;
2782 /* Retrieve the oacc function attrib and return it. Non-oacc
2783 functions will return NULL. */
2785 tree
2786 oacc_get_fn_attrib (tree fn)
2788 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
2791 /* Return true if FN is an OpenMP or OpenACC offloading function. */
2793 bool
2794 offloading_function_p (tree fn)
2796 tree attrs = DECL_ATTRIBUTES (fn);
2797 return (lookup_attribute ("omp declare target", attrs)
2798 || lookup_attribute ("omp target entrypoint", attrs));
2801 /* Extract an oacc execution dimension from FN. FN must be an
2802 offloaded function or routine that has already had its execution
2803 dimensions lowered to the target-specific values. */
2806 oacc_get_fn_dim_size (tree fn, int axis)
2808 tree attrs = oacc_get_fn_attrib (fn);
2810 gcc_assert (axis < GOMP_DIM_MAX);
2812 tree dims = TREE_VALUE (attrs);
2813 while (axis--)
2814 dims = TREE_CHAIN (dims);
2816 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
2818 return size;
2821 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
2822 IFN_GOACC_DIM_SIZE call. */
2825 oacc_get_ifn_dim_arg (const gimple *stmt)
2827 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
2828 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
2829 tree arg = gimple_call_arg (stmt, 0);
2830 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
2832 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
2833 return (int) axis;
2836 #include "gt-omp-general.h"