]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-general.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / omp-general.c
CommitLineData
629b3d75
MJ
1/* General types and functions that are uselful for processing of OpenMP,
2 OpenACC and similar directivers at various stages of compilation.
3
99dee823 4 Copyright (C) 2005-2021 Free Software Foundation, Inc.
629b3d75
MJ
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22/* Find an OMP clause of type KIND within CLAUSES. */
23
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"
314e6352
ML
36#include "stringpool.h"
37#include "attribs.h"
135df52c
JJ
38#include "gimplify.h"
39#include "cgraph.h"
a895e6d7 40#include "alloc-pool.h"
135df52c 41#include "symbol-summary.h"
135df52c 42#include "tree-pass.h"
9ba66bf5 43#include "omp-device-properties.h"
f1f862ae 44#include "tree-iterator.h"
f165ef89
JJ
45#include "data-streamer.h"
46#include "streamer-hooks.h"
629b3d75 47
28567c40
JJ
48enum omp_requires omp_requires_mask;
49
629b3d75
MJ
50tree
51omp_find_clause (tree clauses, enum omp_clause_code kind)
52{
53 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
54 if (OMP_CLAUSE_CODE (clauses) == kind)
55 return clauses;
56
57 return NULL_TREE;
58}
59
08c14aaa
TB
60/* True if OpenMP should regard this DECL as being a scalar which has Fortran's
61 allocatable or pointer attribute. */
62bool
63omp_is_allocatable_or_ptr (tree decl)
64{
65 return lang_hooks.decls.omp_is_allocatable_or_ptr (decl);
66}
67
a2c26c50
TB
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. */
73a28634 75
a2c26c50
TB
76tree
77omp_check_optional_argument (tree decl, bool for_present_check)
73a28634 78{
a2c26c50 79 return lang_hooks.decls.omp_check_optional_argument (decl, for_present_check);
73a28634
KCY
80}
81
22e6b327
TS
82/* True if OpenMP should privatize what this DECL points to rather
83 than the DECL itself. */
629b3d75
MJ
84
85bool
22e6b327 86omp_privatize_by_reference (tree decl)
629b3d75
MJ
87{
88 return lang_hooks.decls.omp_privatize_by_reference (decl);
89}
90
031c5c8b
MJ
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. */
629b3d75
MJ
93
94void
031c5c8b
MJ
95omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2,
96 tree v, tree step)
629b3d75
MJ
97{
98 switch (*cond_code)
99 {
100 case LT_EXPR:
101 case GT_EXPR:
031c5c8b
MJ
102 break;
103
629b3d75 104 case NE_EXPR:
031c5c8b
MJ
105 gcc_assert (TREE_CODE (step) == INTEGER_CST);
106 if (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE)
107 {
108 if (integer_onep (step))
109 *cond_code = LT_EXPR;
110 else
111 {
112 gcc_assert (integer_minus_onep (step));
113 *cond_code = GT_EXPR;
114 }
115 }
116 else
117 {
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
123 {
124 gcc_assert (wi::neg (wi::to_widest (unit))
125 == wi::to_widest (step));
126 *cond_code = GT_EXPR;
127 }
128 }
129
629b3d75 130 break;
031c5c8b 131
629b3d75
MJ
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 ();
150 }
151}
152
153/* Return the looping step from INCR, extracted from the step of a gimple omp
154 for statement. */
155
156tree
157omp_get_for_step_from_incr (location_t loc, tree incr)
158{
159 tree step;
160 switch (TREE_CODE (incr))
161 {
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 ();
174 }
175 return step;
176}
177
178/* Extract the header elements of parallel loop FOR_STMT and store
179 them into *FD. */
180
181void
182omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
183 struct omp_for_data_loop *loops)
184{
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);
dfa6e5b4 191 bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
629b3d75
MJ
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 tree iterv, countv;
197
198 fd->for_stmt = for_stmt;
199 fd->pre = NULL;
629b3d75
MJ
200 fd->have_nowait = distribute || simd;
201 fd->have_ordered = false;
28567c40 202 fd->have_reductemp = false;
8221c30b 203 fd->have_pointer_condtemp = false;
2f6bb511
JJ
204 fd->have_scantemp = false;
205 fd->have_nonctrl_scantemp = false;
1160ec9a 206 fd->non_rect = false;
6c7ae8c5 207 fd->lastprivate_conditional = 0;
02889d23 208 fd->tiling = NULL_TREE;
629b3d75
MJ
209 fd->collapse = 1;
210 fd->ordered = 0;
aed3ab25
JJ
211 fd->first_nonrect = -1;
212 fd->last_nonrect = -1;
629b3d75
MJ
213 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
214 fd->sched_modifiers = 0;
215 fd->chunk_size = NULL_TREE;
216 fd->simd_schedule = false;
79c12969 217 fd->first_inner_iterations = NULL_TREE;
5acef69f 218 fd->factor = NULL_TREE;
f418bd4b 219 fd->adjn1 = NULL_TREE;
629b3d75
MJ
220 collapse_iter = NULL;
221 collapse_count = NULL;
222
223 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
224 switch (OMP_CLAUSE_CODE (t))
225 {
226 case OMP_CLAUSE_NOWAIT:
227 fd->have_nowait = true;
228 break;
229 case OMP_CLAUSE_ORDERED:
230 fd->have_ordered = true;
231 if (OMP_CLAUSE_ORDERED_EXPR (t))
232 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
233 break;
234 case OMP_CLAUSE_SCHEDULE:
235 gcc_assert (!distribute && !taskloop);
236 fd->sched_kind
237 = (enum omp_clause_schedule_kind)
238 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
239 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
240 & ~OMP_CLAUSE_SCHEDULE_MASK);
241 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
242 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
243 break;
244 case OMP_CLAUSE_DIST_SCHEDULE:
245 gcc_assert (distribute);
246 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
247 break;
248 case OMP_CLAUSE_COLLAPSE:
249 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
250 if (fd->collapse > 1)
251 {
252 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
253 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
254 }
255 break;
02889d23
CLT
256 case OMP_CLAUSE_TILE:
257 fd->tiling = OMP_CLAUSE_TILE_LIST (t);
258 fd->collapse = list_length (fd->tiling);
259 gcc_assert (fd->collapse);
260 collapse_iter = &OMP_CLAUSE_TILE_ITERVAR (t);
261 collapse_count = &OMP_CLAUSE_TILE_COUNT (t);
262 break;
28567c40
JJ
263 case OMP_CLAUSE__REDUCTEMP_:
264 fd->have_reductemp = true;
6c7ae8c5
JJ
265 break;
266 case OMP_CLAUSE_LASTPRIVATE:
267 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
268 fd->lastprivate_conditional++;
269 break;
8221c30b
JJ
270 case OMP_CLAUSE__CONDTEMP_:
271 if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
272 fd->have_pointer_condtemp = true;
273 break;
2f6bb511
JJ
274 case OMP_CLAUSE__SCANTEMP_:
275 fd->have_scantemp = true;
276 if (!OMP_CLAUSE__SCANTEMP__ALLOC (t)
277 && !OMP_CLAUSE__SCANTEMP__CONTROL (t))
278 fd->have_nonctrl_scantemp = true;
279 break;
629b3d75
MJ
280 default:
281 break;
282 }
02889d23
CLT
283
284 if (fd->collapse > 1 || fd->tiling)
285 fd->loops = loops;
286 else
287 fd->loops = &fd->loop;
288
629b3d75
MJ
289 if (fd->ordered && fd->collapse == 1 && loops != NULL)
290 {
291 fd->loops = loops;
292 iterv = NULL_TREE;
293 countv = NULL_TREE;
294 collapse_iter = &iterv;
295 collapse_count = &countv;
296 }
297
298 /* FIXME: for now map schedule(auto) to schedule(static).
299 There should be analysis to determine whether all iterations
300 are approximately the same amount of work (then schedule(static)
301 is best) or if it varies (then schedule(dynamic,N) is better). */
302 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
303 {
304 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
305 gcc_assert (fd->chunk_size == NULL);
306 }
02889d23 307 gcc_assert ((fd->collapse == 1 && !fd->tiling) || collapse_iter != NULL);
629b3d75
MJ
308 if (taskloop)
309 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
310 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
311 gcc_assert (fd->chunk_size == NULL);
312 else if (fd->chunk_size == NULL)
313 {
314 /* We only need to compute a default chunk size for ordered
315 static loops and dynamic loops. */
316 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
317 || fd->have_ordered)
318 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
319 ? integer_zero_node : integer_one_node;
320 }
321
322 int cnt = fd->ordered ? fd->ordered : fd->collapse;
c154b8bc
JJ
323 int single_nonrect = -1;
324 tree single_nonrect_count = NULL_TREE;
325 enum tree_code single_nonrect_cond_code = ERROR_MARK;
326 for (i = 1; i < cnt; i++)
327 {
328 tree n1 = gimple_omp_for_initial (for_stmt, i);
329 tree n2 = gimple_omp_for_final (for_stmt, i);
330 if (TREE_CODE (n1) == TREE_VEC)
331 {
332 if (fd->non_rect)
333 {
334 single_nonrect = -1;
335 break;
336 }
337 for (int j = i - 1; j >= 0; j--)
338 if (TREE_VEC_ELT (n1, 0) == gimple_omp_for_index (for_stmt, j))
339 {
340 single_nonrect = j;
341 break;
342 }
343 fd->non_rect = true;
344 }
345 else if (TREE_CODE (n2) == TREE_VEC)
346 {
347 if (fd->non_rect)
348 {
349 single_nonrect = -1;
350 break;
351 }
352 for (int j = i - 1; j >= 0; j--)
353 if (TREE_VEC_ELT (n2, 0) == gimple_omp_for_index (for_stmt, j))
354 {
355 single_nonrect = j;
356 break;
357 }
358 fd->non_rect = true;
359 }
360 }
629b3d75
MJ
361 for (i = 0; i < cnt; i++)
362 {
02889d23
CLT
363 if (i == 0
364 && fd->collapse == 1
365 && !fd->tiling
366 && (fd->ordered == 0 || loops == NULL))
629b3d75
MJ
367 loop = &fd->loop;
368 else if (loops != NULL)
369 loop = loops + i;
370 else
371 loop = &dummy_loop;
372
373 loop->v = gimple_omp_for_index (for_stmt, i);
374 gcc_assert (SSA_VAR_P (loop->v));
375 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
376 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
377 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
378 loop->n1 = gimple_omp_for_initial (for_stmt, i);
1160ec9a
JJ
379 loop->m1 = NULL_TREE;
380 loop->m2 = NULL_TREE;
381 loop->outer = 0;
aed3ab25 382 loop->non_rect_referenced = false;
1160ec9a
JJ
383 if (TREE_CODE (loop->n1) == TREE_VEC)
384 {
385 for (int j = i - 1; j >= 0; j--)
386 if (TREE_VEC_ELT (loop->n1, 0) == gimple_omp_for_index (for_stmt, j))
387 {
388 loop->outer = i - j;
aed3ab25
JJ
389 if (loops != NULL)
390 loops[j].non_rect_referenced = true;
391 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
392 fd->first_nonrect = j;
1160ec9a
JJ
393 break;
394 }
395 gcc_assert (loop->outer);
396 loop->m1 = TREE_VEC_ELT (loop->n1, 1);
397 loop->n1 = TREE_VEC_ELT (loop->n1, 2);
398 fd->non_rect = true;
aed3ab25 399 fd->last_nonrect = i;
1160ec9a 400 }
629b3d75
MJ
401
402 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
403 loop->n2 = gimple_omp_for_final (for_stmt, i);
28567c40
JJ
404 gcc_assert (loop->cond_code != NE_EXPR
405 || (gimple_omp_for_kind (for_stmt)
406 != GF_OMP_FOR_KIND_OACC_LOOP));
1160ec9a
JJ
407 if (TREE_CODE (loop->n2) == TREE_VEC)
408 {
409 if (loop->outer)
410 gcc_assert (TREE_VEC_ELT (loop->n2, 0)
411 == gimple_omp_for_index (for_stmt, i - loop->outer));
412 else
413 for (int j = i - 1; j >= 0; j--)
414 if (TREE_VEC_ELT (loop->n2, 0) == gimple_omp_for_index (for_stmt, j))
415 {
416 loop->outer = i - j;
aed3ab25
JJ
417 if (loops != NULL)
418 loops[j].non_rect_referenced = true;
419 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
420 fd->first_nonrect = j;
1160ec9a
JJ
421 break;
422 }
423 gcc_assert (loop->outer);
424 loop->m2 = TREE_VEC_ELT (loop->n2, 1);
425 loop->n2 = TREE_VEC_ELT (loop->n2, 2);
426 fd->non_rect = true;
aed3ab25 427 fd->last_nonrect = i;
1160ec9a 428 }
629b3d75
MJ
429
430 t = gimple_omp_for_incr (for_stmt, i);
431 gcc_assert (TREE_OPERAND (t, 0) == var);
432 loop->step = omp_get_for_step_from_incr (loc, t);
433
031c5c8b
MJ
434 omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2, loop->v,
435 loop->step);
28567c40 436
629b3d75
MJ
437 if (simd
438 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
439 && !fd->have_ordered))
440 {
02889d23 441 if (fd->collapse == 1 && !fd->tiling)
629b3d75
MJ
442 iter_type = TREE_TYPE (loop->v);
443 else if (i == 0
444 || TYPE_PRECISION (iter_type)
445 < TYPE_PRECISION (TREE_TYPE (loop->v)))
446 iter_type
447 = build_nonstandard_integer_type
448 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
449 }
450 else if (iter_type != long_long_unsigned_type_node)
451 {
452 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
453 iter_type = long_long_unsigned_type_node;
454 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
455 && TYPE_PRECISION (TREE_TYPE (loop->v))
456 >= TYPE_PRECISION (iter_type))
457 {
458 tree n;
459
460 if (loop->cond_code == LT_EXPR)
28567c40
JJ
461 n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
462 loop->n2, loop->step);
629b3d75
MJ
463 else
464 n = loop->n1;
2e47c8c6
JJ
465 if (loop->m1
466 || loop->m2
467 || TREE_CODE (n) != INTEGER_CST
629b3d75
MJ
468 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
469 iter_type = long_long_unsigned_type_node;
470 }
471 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
472 > TYPE_PRECISION (iter_type))
473 {
474 tree n1, n2;
475
476 if (loop->cond_code == LT_EXPR)
477 {
478 n1 = loop->n1;
28567c40
JJ
479 n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
480 loop->n2, loop->step);
629b3d75
MJ
481 }
482 else
483 {
28567c40
JJ
484 n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
485 loop->n2, loop->step);
629b3d75
MJ
486 n2 = loop->n1;
487 }
2e47c8c6
JJ
488 if (loop->m1
489 || loop->m2
490 || TREE_CODE (n1) != INTEGER_CST
629b3d75
MJ
491 || TREE_CODE (n2) != INTEGER_CST
492 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
493 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
494 iter_type = long_long_unsigned_type_node;
495 }
496 }
497
498 if (i >= fd->collapse)
499 continue;
500
501 if (collapse_count && *collapse_count == NULL)
502 {
c154b8bc
JJ
503 if (count && integer_zerop (count))
504 continue;
505 tree n1first = NULL_TREE, n2first = NULL_TREE;
506 tree n1last = NULL_TREE, n2last = NULL_TREE;
507 tree ostep = NULL_TREE;
1160ec9a 508 if (loop->m1 || loop->m2)
c154b8bc
JJ
509 {
510 if (count == NULL_TREE)
511 continue;
512 if (single_nonrect == -1
513 || (loop->m1 && TREE_CODE (loop->m1) != INTEGER_CST)
f418bd4b
JJ
514 || (loop->m2 && TREE_CODE (loop->m2) != INTEGER_CST)
515 || TREE_CODE (loop->n1) != INTEGER_CST
516 || TREE_CODE (loop->n2) != INTEGER_CST
517 || TREE_CODE (loop->step) != INTEGER_CST)
c154b8bc
JJ
518 {
519 count = NULL_TREE;
520 continue;
521 }
522 tree var = gimple_omp_for_initial (for_stmt, single_nonrect);
523 tree itype = TREE_TYPE (var);
524 tree first = gimple_omp_for_initial (for_stmt, single_nonrect);
525 t = gimple_omp_for_incr (for_stmt, single_nonrect);
526 ostep = omp_get_for_step_from_incr (loc, t);
527 t = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
528 single_nonrect_count,
529 build_one_cst (long_long_unsigned_type_node));
530 t = fold_convert (itype, t);
531 first = fold_convert (itype, first);
532 ostep = fold_convert (itype, ostep);
533 tree last = fold_binary (PLUS_EXPR, itype, first,
534 fold_binary (MULT_EXPR, itype, t,
535 ostep));
536 if (TREE_CODE (first) != INTEGER_CST
537 || TREE_CODE (last) != INTEGER_CST)
538 {
539 count = NULL_TREE;
540 continue;
541 }
542 if (loop->m1)
543 {
544 tree m1 = fold_convert (itype, loop->m1);
545 tree n1 = fold_convert (itype, loop->n1);
546 n1first = fold_binary (PLUS_EXPR, itype,
547 fold_binary (MULT_EXPR, itype,
548 first, m1), n1);
549 n1last = fold_binary (PLUS_EXPR, itype,
550 fold_binary (MULT_EXPR, itype,
551 last, m1), n1);
552 }
553 else
554 n1first = n1last = loop->n1;
555 if (loop->m2)
556 {
557 tree n2 = fold_convert (itype, loop->n2);
558 tree m2 = fold_convert (itype, loop->m2);
559 n2first = fold_binary (PLUS_EXPR, itype,
560 fold_binary (MULT_EXPR, itype,
561 first, m2), n2);
562 n2last = fold_binary (PLUS_EXPR, itype,
563 fold_binary (MULT_EXPR, itype,
564 last, m2), n2);
565 }
566 else
567 n2first = n2last = loop->n2;
568 n1first = fold_convert (TREE_TYPE (loop->v), n1first);
569 n2first = fold_convert (TREE_TYPE (loop->v), n2first);
570 n1last = fold_convert (TREE_TYPE (loop->v), n1last);
571 n2last = fold_convert (TREE_TYPE (loop->v), n2last);
572 t = fold_binary (loop->cond_code, boolean_type_node,
573 n1first, n2first);
574 tree t2 = fold_binary (loop->cond_code, boolean_type_node,
575 n1last, n2last);
576 if (t && t2 && integer_nonzerop (t) && integer_nonzerop (t2))
577 /* All outer loop iterators have at least one inner loop
578 iteration. Try to compute the count at compile time. */
579 t = NULL_TREE;
580 else if (t && t2 && integer_zerop (t) && integer_zerop (t2))
581 /* No iterations of the inner loop. count will be set to
582 zero cst below. */;
f418bd4b
JJ
583 else if (TYPE_UNSIGNED (itype)
584 || t == NULL_TREE
585 || t2 == NULL_TREE
586 || TREE_CODE (t) != INTEGER_CST
587 || TREE_CODE (t2) != INTEGER_CST)
c154b8bc
JJ
588 {
589 /* Punt (for now). */
590 count = NULL_TREE;
591 continue;
592 }
f418bd4b
JJ
593 else
594 {
595 /* Some iterations of the outer loop have zero iterations
596 of the inner loop, while others have at least one.
597 In this case, we need to adjust one of those outer
598 loop bounds. If ADJ_FIRST, we need to adjust outer n1
599 (first), otherwise outer n2 (last). */
600 bool adj_first = integer_zerop (t);
601 tree n1 = fold_convert (itype, loop->n1);
602 tree n2 = fold_convert (itype, loop->n2);
603 tree m1 = loop->m1 ? fold_convert (itype, loop->m1)
604 : build_zero_cst (itype);
605 tree m2 = loop->m2 ? fold_convert (itype, loop->m2)
606 : build_zero_cst (itype);
607 t = fold_binary (MINUS_EXPR, itype, n1, n2);
608 t2 = fold_binary (MINUS_EXPR, itype, m2, m1);
609 t = fold_binary (TRUNC_DIV_EXPR, itype, t, t2);
610 t2 = fold_binary (MINUS_EXPR, itype, t, first);
611 t2 = fold_binary (TRUNC_MOD_EXPR, itype, t2, ostep);
612 t = fold_binary (MINUS_EXPR, itype, t, t2);
613 tree n1cur
614 = fold_binary (PLUS_EXPR, itype, n1,
615 fold_binary (MULT_EXPR, itype, m1, t));
616 tree n2cur
617 = fold_binary (PLUS_EXPR, itype, n2,
618 fold_binary (MULT_EXPR, itype, m2, t));
619 t2 = fold_binary (loop->cond_code, boolean_type_node,
620 n1cur, n2cur);
621 tree t3 = fold_binary (MULT_EXPR, itype, m1, ostep);
622 tree t4 = fold_binary (MULT_EXPR, itype, m2, ostep);
623 tree diff;
624 if (adj_first)
625 {
626 tree new_first;
627 if (integer_nonzerop (t2))
628 {
629 new_first = t;
630 n1first = n1cur;
631 n2first = n2cur;
632 if (flag_checking)
633 {
634 t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
635 t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
636 t3 = fold_binary (loop->cond_code,
637 boolean_type_node, t3, t4);
638 gcc_assert (integer_zerop (t3));
639 }
640 }
641 else
642 {
643 t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
644 t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
645 new_first = fold_binary (PLUS_EXPR, itype, t, ostep);
646 n1first = t3;
647 n2first = t4;
648 if (flag_checking)
649 {
650 t3 = fold_binary (loop->cond_code,
651 boolean_type_node, t3, t4);
652 gcc_assert (integer_nonzerop (t3));
653 }
654 }
655 diff = fold_binary (MINUS_EXPR, itype, new_first, first);
656 first = new_first;
657 fd->adjn1 = first;
658 }
659 else
660 {
661 tree new_last;
662 if (integer_zerop (t2))
663 {
664 t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
665 t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
666 new_last = fold_binary (MINUS_EXPR, itype, t, ostep);
667 n1last = t3;
668 n2last = t4;
669 if (flag_checking)
670 {
671 t3 = fold_binary (loop->cond_code,
672 boolean_type_node, t3, t4);
673 gcc_assert (integer_nonzerop (t3));
674 }
675 }
676 else
677 {
678 new_last = t;
679 n1last = n1cur;
680 n2last = n2cur;
681 if (flag_checking)
682 {
683 t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
684 t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
685 t3 = fold_binary (loop->cond_code,
686 boolean_type_node, t3, t4);
687 gcc_assert (integer_zerop (t3));
688 }
689 }
690 diff = fold_binary (MINUS_EXPR, itype, last, new_last);
691 }
692 if (TYPE_UNSIGNED (itype)
693 && single_nonrect_cond_code == GT_EXPR)
694 diff = fold_binary (TRUNC_DIV_EXPR, itype,
695 fold_unary (NEGATE_EXPR, itype, diff),
696 fold_unary (NEGATE_EXPR, itype,
697 ostep));
698 else
699 diff = fold_binary (TRUNC_DIV_EXPR, itype, diff, ostep);
700 diff = fold_convert (long_long_unsigned_type_node, diff);
701 single_nonrect_count
702 = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
703 single_nonrect_count, diff);
704 t = NULL_TREE;
705 }
c154b8bc 706 }
1160ec9a
JJ
707 else
708 t = fold_binary (loop->cond_code, boolean_type_node,
709 fold_convert (TREE_TYPE (loop->v), loop->n1),
710 fold_convert (TREE_TYPE (loop->v), loop->n2));
629b3d75
MJ
711 if (t && integer_zerop (t))
712 count = build_zero_cst (long_long_unsigned_type_node);
713 else if ((i == 0 || count != NULL_TREE)
714 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
715 && TREE_CONSTANT (loop->n1)
716 && TREE_CONSTANT (loop->n2)
717 && TREE_CODE (loop->step) == INTEGER_CST)
718 {
719 tree itype = TREE_TYPE (loop->v);
720
721 if (POINTER_TYPE_P (itype))
722 itype = signed_type_for (itype);
723 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
c154b8bc
JJ
724 t = fold_build2 (PLUS_EXPR, itype,
725 fold_convert (itype, loop->step), t);
726 tree n1 = loop->n1;
727 tree n2 = loop->n2;
728 if (loop->m1 || loop->m2)
28567c40 729 {
c154b8bc 730 gcc_assert (single_nonrect != -1);
79c12969
JJ
731 n1 = n1first;
732 n2 = n2first;
28567c40 733 }
c154b8bc
JJ
734 t = fold_build2 (PLUS_EXPR, itype, t, fold_convert (itype, n2));
735 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
736 tree step = fold_convert_loc (loc, itype, loop->step);
737 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
738 t = fold_build2 (TRUNC_DIV_EXPR, itype,
739 fold_build1 (NEGATE_EXPR, itype, t),
740 fold_build1 (NEGATE_EXPR, itype, step));
629b3d75 741 else
c154b8bc
JJ
742 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
743 tree llutype = long_long_unsigned_type_node;
744 t = fold_convert (llutype, t);
745 if (loop->m1 || loop->m2)
746 {
747 /* t is number of iterations of inner loop at either first
748 or last value of the outer iterator (the one with fewer
749 iterations).
750 Compute t2 = ((m2 - m1) * ostep) / step
c154b8bc
JJ
751 and niters = outer_count * t
752 + t2 * ((outer_count - 1) * outer_count / 2)
753 */
754 tree m1 = loop->m1 ? loop->m1 : integer_zero_node;
755 tree m2 = loop->m2 ? loop->m2 : integer_zero_node;
756 m1 = fold_convert (itype, m1);
757 m2 = fold_convert (itype, m2);
79c12969 758 tree t2 = fold_build2 (MINUS_EXPR, itype, m2, m1);
c154b8bc
JJ
759 t2 = fold_build2 (MULT_EXPR, itype, t2, ostep);
760 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
761 t2 = fold_build2 (TRUNC_DIV_EXPR, itype,
762 fold_build1 (NEGATE_EXPR, itype, t2),
763 fold_build1 (NEGATE_EXPR, itype, step));
764 else
765 t2 = fold_build2 (TRUNC_DIV_EXPR, itype, t2, step);
766 t2 = fold_convert (llutype, t2);
79c12969 767 fd->first_inner_iterations = t;
5acef69f 768 fd->factor = t2;
c154b8bc
JJ
769 t = fold_build2 (MULT_EXPR, llutype, t,
770 single_nonrect_count);
771 tree t3 = fold_build2 (MINUS_EXPR, llutype,
772 single_nonrect_count,
773 build_one_cst (llutype));
774 t3 = fold_build2 (MULT_EXPR, llutype, t3,
775 single_nonrect_count);
776 t3 = fold_build2 (TRUNC_DIV_EXPR, llutype, t3,
777 build_int_cst (llutype, 2));
778 t2 = fold_build2 (MULT_EXPR, llutype, t2, t3);
779 t = fold_build2 (PLUS_EXPR, llutype, t, t2);
780 }
781 if (i == single_nonrect)
782 {
783 if (integer_zerop (t) || TREE_CODE (t) != INTEGER_CST)
784 count = t;
785 else
786 {
787 single_nonrect_count = t;
788 single_nonrect_cond_code = loop->cond_code;
789 if (count == NULL_TREE)
790 count = build_one_cst (llutype);
791 }
792 }
793 else if (count != NULL_TREE)
794 count = fold_build2 (MULT_EXPR, llutype, count, t);
629b3d75
MJ
795 else
796 count = t;
797 if (TREE_CODE (count) != INTEGER_CST)
798 count = NULL_TREE;
799 }
800 else if (count && !integer_zerop (count))
801 count = NULL_TREE;
802 }
803 }
804
805 if (count
806 && !simd
807 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
808 || fd->have_ordered))
809 {
810 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
811 iter_type = long_long_unsigned_type_node;
812 else
813 iter_type = long_integer_type_node;
814 }
815 else if (collapse_iter && *collapse_iter != NULL)
816 iter_type = TREE_TYPE (*collapse_iter);
817 fd->iter_type = iter_type;
818 if (collapse_iter && *collapse_iter == NULL)
819 *collapse_iter = create_tmp_var (iter_type, ".iter");
820 if (collapse_count && *collapse_count == NULL)
821 {
822 if (count)
5acef69f
JJ
823 {
824 *collapse_count = fold_convert_loc (loc, iter_type, count);
79c12969 825 if (fd->first_inner_iterations && fd->factor)
5acef69f 826 {
f418bd4b 827 t = make_tree_vec (4);
5acef69f 828 TREE_VEC_ELT (t, 0) = *collapse_count;
79c12969 829 TREE_VEC_ELT (t, 1) = fd->first_inner_iterations;
5acef69f 830 TREE_VEC_ELT (t, 2) = fd->factor;
f418bd4b 831 TREE_VEC_ELT (t, 3) = fd->adjn1;
5acef69f
JJ
832 *collapse_count = t;
833 }
834 }
629b3d75
MJ
835 else
836 *collapse_count = create_tmp_var (iter_type, ".count");
837 }
838
02889d23 839 if (fd->collapse > 1 || fd->tiling || (fd->ordered && loops))
629b3d75
MJ
840 {
841 fd->loop.v = *collapse_iter;
842 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
843 fd->loop.n2 = *collapse_count;
5acef69f
JJ
844 if (TREE_CODE (fd->loop.n2) == TREE_VEC)
845 {
846 gcc_assert (fd->non_rect);
79c12969 847 fd->first_inner_iterations = TREE_VEC_ELT (fd->loop.n2, 1);
5acef69f 848 fd->factor = TREE_VEC_ELT (fd->loop.n2, 2);
f418bd4b 849 fd->adjn1 = TREE_VEC_ELT (fd->loop.n2, 3);
5acef69f
JJ
850 fd->loop.n2 = TREE_VEC_ELT (fd->loop.n2, 0);
851 }
629b3d75 852 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
1160ec9a
JJ
853 fd->loop.m1 = NULL_TREE;
854 fd->loop.m2 = NULL_TREE;
855 fd->loop.outer = 0;
629b3d75
MJ
856 fd->loop.cond_code = LT_EXPR;
857 }
858 else if (loops)
859 loops[0] = fd->loop;
860}
861
862/* Build a call to GOMP_barrier. */
863
864gimple *
865omp_build_barrier (tree lhs)
866{
867 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
868 : BUILT_IN_GOMP_BARRIER);
869 gcall *g = gimple_build_call (fndecl, 0);
870 if (lhs)
871 gimple_call_set_lhs (g, lhs);
872 return g;
873}
874
f1f862ae
JJ
875/* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT. Also, fill in pdata
876 array, pdata[0] non-NULL if there is anything non-trivial in between,
877 pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
878 of OMP_FOR in between if any and pdata[3] is address of the inner
879 OMP_FOR/OMP_SIMD. */
880
881tree
882find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
883{
884 tree **pdata = (tree **) data;
885 *walk_subtrees = 0;
886 switch (TREE_CODE (*tp))
887 {
888 case OMP_FOR:
889 if (OMP_FOR_INIT (*tp) != NULL_TREE)
890 {
891 pdata[3] = tp;
892 return *tp;
893 }
894 pdata[2] = tp;
895 *walk_subtrees = 1;
896 break;
897 case OMP_SIMD:
898 if (OMP_FOR_INIT (*tp) != NULL_TREE)
899 {
900 pdata[3] = tp;
901 return *tp;
902 }
903 break;
904 case BIND_EXPR:
905 if (BIND_EXPR_VARS (*tp)
906 || (BIND_EXPR_BLOCK (*tp)
907 && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
908 pdata[0] = tp;
909 *walk_subtrees = 1;
910 break;
911 case STATEMENT_LIST:
912 if (!tsi_one_before_end_p (tsi_start (*tp)))
913 pdata[0] = tp;
914 *walk_subtrees = 1;
915 break;
916 case TRY_FINALLY_EXPR:
917 pdata[0] = tp;
918 *walk_subtrees = 1;
919 break;
920 case OMP_PARALLEL:
921 pdata[1] = tp;
922 *walk_subtrees = 1;
923 break;
924 default:
925 break;
926 }
927 return NULL_TREE;
928}
929
629b3d75
MJ
930/* Return maximum possible vectorization factor for the target. */
931
9d2f08ab 932poly_uint64
629b3d75
MJ
933omp_max_vf (void)
934{
935 if (!optimize
936 || optimize_debug
937 || !flag_tree_loop_optimize
938 || (!flag_tree_loop_vectorize
26d476cd 939 && global_options_set.x_flag_tree_loop_vectorize))
629b3d75
MJ
940 return 1;
941
e021fb86
RS
942 auto_vector_modes modes;
943 targetm.vectorize.autovectorize_vector_modes (&modes, true);
944 if (!modes.is_empty ())
629b3d75 945 {
86e36728 946 poly_uint64 vf = 0;
e021fb86
RS
947 for (unsigned int i = 0; i < modes.length (); ++i)
948 /* The returned modes use the smallest element size (and thus
949 the largest nunits) for the vectorization approach that they
950 represent. */
951 vf = ordered_max (vf, GET_MODE_NUNITS (modes[i]));
86e36728 952 return vf;
629b3d75 953 }
86e36728
RS
954
955 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
956 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
957 return GET_MODE_NUNITS (vqimode);
958
959 return 1;
629b3d75
MJ
960}
961
962/* Return maximum SIMT width if offloading may target SIMT hardware. */
963
964int
965omp_max_simt_vf (void)
966{
967 if (!optimize)
968 return 0;
969 if (ENABLE_OFFLOADING)
01914336 970 for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
629b3d75 971 {
6ba3079d 972 if (startswith (c, "nvptx"))
629b3d75 973 return 32;
9ba66bf5 974 else if ((c = strchr (c, ':')))
629b3d75
MJ
975 c++;
976 }
977 return 0;
978}
979
135df52c
JJ
980/* Store the construct selectors as tree codes from last to first,
981 return their number. */
982
983int
984omp_constructor_traits_to_codes (tree ctx, enum tree_code *constructs)
985{
986 int nconstructs = list_length (ctx);
987 int i = nconstructs - 1;
988 for (tree t2 = ctx; t2; t2 = TREE_CHAIN (t2), i--)
989 {
990 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
991 if (!strcmp (sel, "target"))
992 constructs[i] = OMP_TARGET;
993 else if (!strcmp (sel, "teams"))
994 constructs[i] = OMP_TEAMS;
995 else if (!strcmp (sel, "parallel"))
996 constructs[i] = OMP_PARALLEL;
997 else if (!strcmp (sel, "for") || !strcmp (sel, "do"))
998 constructs[i] = OMP_FOR;
999 else if (!strcmp (sel, "simd"))
1000 constructs[i] = OMP_SIMD;
1001 else
1002 gcc_unreachable ();
1003 }
1004 gcc_assert (i == -1);
1005 return nconstructs;
1006}
1007
9ba66bf5
JJ
1008/* Return true if PROP is possibly present in one of the offloading target's
1009 OpenMP contexts. The format of PROPS string is always offloading target's
1010 name terminated by '\0', followed by properties for that offloading
1011 target separated by '\0' and terminated by another '\0'. The strings
1012 are created from omp-device-properties installed files of all configured
1013 offloading targets. */
1014
1015static bool
1016omp_offload_device_kind_arch_isa (const char *props, const char *prop)
1017{
1018 const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1019 if (names == NULL || *names == '\0')
1020 return false;
1021 while (*props != '\0')
1022 {
1023 size_t name_len = strlen (props);
1024 bool matches = false;
1025 for (const char *c = names; c; )
1026 {
1027 if (strncmp (props, c, name_len) == 0
1028 && (c[name_len] == '\0'
1029 || c[name_len] == ':'
1030 || c[name_len] == '='))
1031 {
1032 matches = true;
1033 break;
1034 }
1035 else if ((c = strchr (c, ':')))
1036 c++;
1037 }
1038 props = props + name_len + 1;
1039 while (*props != '\0')
1040 {
1041 if (matches && strcmp (props, prop) == 0)
1042 return true;
1043 props = strchr (props, '\0') + 1;
1044 }
1045 props++;
1046 }
1047 return false;
1048}
1049
1050/* Return true if the current code location is or might be offloaded.
1051 Return true in declare target functions, or when nested in a target
1052 region or when unsure, return false otherwise. */
1053
1054static bool
1055omp_maybe_offloaded (void)
1056{
c56684fd
MJ
1057 if (!ENABLE_OFFLOADING)
1058 return false;
1059 const char *names = getenv ("OFFLOAD_TARGET_NAMES");
1060 if (names == NULL || *names == '\0')
1061 return false;
1062
9ba66bf5
JJ
1063 if (symtab->state == PARSING)
1064 /* Maybe. */
1065 return true;
7a50e708
JJ
1066 if (cfun && cfun->after_inlining)
1067 return false;
9ba66bf5
JJ
1068 if (current_function_decl
1069 && lookup_attribute ("omp declare target",
1070 DECL_ATTRIBUTES (current_function_decl)))
1071 return true;
1072 if (cfun && (cfun->curr_properties & PROP_gimple_any) == 0)
1073 {
1074 enum tree_code construct = OMP_TARGET;
d0c464d2 1075 if (omp_construct_selector_matches (&construct, 1, NULL))
9ba66bf5
JJ
1076 return true;
1077 }
1078 return false;
1079}
1080
b2417b59
JJ
1081/* Return a name from PROP, a property in selectors accepting
1082 name lists. */
1083
1084static const char *
1085omp_context_name_list_prop (tree prop)
1086{
1087 if (TREE_PURPOSE (prop))
1088 return IDENTIFIER_POINTER (TREE_PURPOSE (prop));
1089 else
1090 {
1091 const char *ret = TREE_STRING_POINTER (TREE_VALUE (prop));
1092 if ((size_t) TREE_STRING_LENGTH (TREE_VALUE (prop)) == strlen (ret) + 1)
1093 return ret;
1094 return NULL;
1095 }
1096}
1097
135df52c
JJ
1098/* Return 1 if context selector matches the current OpenMP context, 0
1099 if it does not and -1 if it is unknown and need to be determined later.
1100 Some properties can be checked right away during parsing (this routine),
1101 others need to wait until the whole TU is parsed, others need to wait until
1102 IPA, others until vectorization. */
1103
1104int
1105omp_context_selector_matches (tree ctx)
1106{
1107 int ret = 1;
1108 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1109 {
1110 char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0];
1111 if (set == 'c')
1112 {
1113 /* For now, ignore the construct set. While something can be
1114 determined already during parsing, we don't know until end of TU
1115 whether additional constructs aren't added through declare variant
1116 unless "omp declare variant variant" attribute exists already
1117 (so in most of the cases), and we'd need to maintain set of
1118 surrounding OpenMP constructs, which is better handled during
1119 gimplification. */
7a50e708 1120 if (symtab->state == PARSING)
135df52c
JJ
1121 {
1122 ret = -1;
1123 continue;
1124 }
1125
1126 enum tree_code constructs[5];
1127 int nconstructs
1128 = omp_constructor_traits_to_codes (TREE_VALUE (t1), constructs);
7a50e708
JJ
1129
1130 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1131 {
1132 if (!cfun->after_inlining)
1133 {
1134 ret = -1;
1135 continue;
1136 }
1137 int i;
1138 for (i = 0; i < nconstructs; ++i)
1139 if (constructs[i] == OMP_SIMD)
1140 break;
1141 if (i < nconstructs)
1142 {
1143 ret = -1;
1144 continue;
1145 }
1146 /* If there is no simd, assume it is ok after IPA,
1147 constructs should have been checked before. */
1148 continue;
1149 }
1150
d0c464d2
JJ
1151 int r = omp_construct_selector_matches (constructs, nconstructs,
1152 NULL);
135df52c
JJ
1153 if (r == 0)
1154 return 0;
1155 if (r == -1)
1156 ret = -1;
1157 continue;
1158 }
1159 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1160 {
1161 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
1162 switch (*sel)
1163 {
1164 case 'v':
1165 if (set == 'i' && !strcmp (sel, "vendor"))
1166 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1167 {
b2417b59
JJ
1168 const char *prop = omp_context_name_list_prop (t3);
1169 if (prop == NULL)
1170 return 0;
1171 if ((!strcmp (prop, " score") && TREE_PURPOSE (t3))
1172 || !strcmp (prop, "gnu"))
135df52c
JJ
1173 continue;
1174 return 0;
1175 }
1176 break;
1177 case 'e':
1178 if (set == 'i' && !strcmp (sel, "extension"))
1179 /* We don't support any extensions right now. */
1180 return 0;
1181 break;
1182 case 'a':
1183 if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
1184 {
7a50e708
JJ
1185 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1186 break;
1187
135df52c
JJ
1188 enum omp_memory_order omo
1189 = ((enum omp_memory_order)
1190 (omp_requires_mask
1191 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER));
1192 if (omo == OMP_MEMORY_ORDER_UNSPECIFIED)
1193 {
1194 /* We don't know yet, until end of TU. */
1195 if (symtab->state == PARSING)
1196 {
1197 ret = -1;
1198 break;
1199 }
1200 else
1201 omo = OMP_MEMORY_ORDER_RELAXED;
1202 }
1203 tree t3 = TREE_VALUE (t2);
1204 const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
1205 if (!strcmp (prop, " score"))
1206 {
1207 t3 = TREE_CHAIN (t3);
1208 prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
1209 }
1210 if (!strcmp (prop, "relaxed")
1211 && omo != OMP_MEMORY_ORDER_RELAXED)
1212 return 0;
1213 else if (!strcmp (prop, "seq_cst")
1214 && omo != OMP_MEMORY_ORDER_SEQ_CST)
1215 return 0;
1216 else if (!strcmp (prop, "acq_rel")
1217 && omo != OMP_MEMORY_ORDER_ACQ_REL)
1218 return 0;
1219 }
1220 if (set == 'd' && !strcmp (sel, "arch"))
9ba66bf5
JJ
1221 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1222 {
b2417b59
JJ
1223 const char *arch = omp_context_name_list_prop (t3);
1224 if (arch == NULL)
1225 return 0;
9ba66bf5
JJ
1226 int r = 0;
1227 if (targetm.omp.device_kind_arch_isa != NULL)
1228 r = targetm.omp.device_kind_arch_isa (omp_device_arch,
1229 arch);
1230 if (r == 0 || (r == -1 && symtab->state != PARSING))
1231 {
1232 /* If we are or might be in a target region or
1233 declare target function, need to take into account
1234 also offloading values. */
1235 if (!omp_maybe_offloaded ())
1236 return 0;
9ba66bf5
JJ
1237 if (ENABLE_OFFLOADING)
1238 {
1239 const char *arches = omp_offload_device_arch;
1240 if (omp_offload_device_kind_arch_isa (arches,
1241 arch))
1242 {
1243 ret = -1;
1244 continue;
1245 }
1246 }
1247 return 0;
1248 }
1249 else if (r == -1)
1250 ret = -1;
1251 /* If arch matches on the host, it still might not match
1252 in the offloading region. */
1253 else if (omp_maybe_offloaded ())
1254 ret = -1;
1255 }
135df52c
JJ
1256 break;
1257 case 'u':
1258 if (set == 'i' && !strcmp (sel, "unified_address"))
1259 {
7a50e708
JJ
1260 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1261 break;
1262
135df52c
JJ
1263 if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
1264 {
1265 if (symtab->state == PARSING)
1266 ret = -1;
1267 else
1268 return 0;
1269 }
1270 break;
1271 }
1272 if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
1273 {
7a50e708
JJ
1274 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1275 break;
1276
135df52c
JJ
1277 if ((omp_requires_mask
1278 & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
1279 {
1280 if (symtab->state == PARSING)
1281 ret = -1;
1282 else
1283 return 0;
1284 }
1285 break;
1286 }
1287 break;
1288 case 'd':
1289 if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
1290 {
7a50e708
JJ
1291 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1292 break;
1293
135df52c
JJ
1294 if ((omp_requires_mask
1295 & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1296 {
1297 if (symtab->state == PARSING)
1298 ret = -1;
1299 else
1300 return 0;
1301 }
1302 break;
1303 }
1304 break;
1305 case 'r':
1306 if (set == 'i' && !strcmp (sel, "reverse_offload"))
1307 {
7a50e708
JJ
1308 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
1309 break;
1310
135df52c
JJ
1311 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
1312 {
1313 if (symtab->state == PARSING)
1314 ret = -1;
1315 else
1316 return 0;
1317 }
1318 break;
1319 }
1320 break;
1321 case 'k':
1322 if (set == 'd' && !strcmp (sel, "kind"))
1323 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1324 {
b2417b59
JJ
1325 const char *prop = omp_context_name_list_prop (t3);
1326 if (prop == NULL)
1327 return 0;
135df52c
JJ
1328 if (!strcmp (prop, "any"))
1329 continue;
135df52c
JJ
1330 if (!strcmp (prop, "host"))
1331 {
9ba66bf5 1332 if (omp_maybe_offloaded ())
135df52c
JJ
1333 ret = -1;
1334 continue;
1335 }
1336 if (!strcmp (prop, "nohost"))
1337 {
9ba66bf5 1338 if (omp_maybe_offloaded ())
135df52c
JJ
1339 ret = -1;
1340 else
1341 return 0;
1342 continue;
1343 }
9ba66bf5
JJ
1344 int r = 0;
1345 if (targetm.omp.device_kind_arch_isa != NULL)
1346 r = targetm.omp.device_kind_arch_isa (omp_device_kind,
1347 prop);
1348 else
1349 r = strcmp (prop, "cpu") == 0;
1350 if (r == 0 || (r == -1 && symtab->state != PARSING))
135df52c 1351 {
9ba66bf5
JJ
1352 /* If we are or might be in a target region or
1353 declare target function, need to take into account
1354 also offloading values. */
1355 if (!omp_maybe_offloaded ())
1356 return 0;
9ba66bf5
JJ
1357 if (ENABLE_OFFLOADING)
1358 {
1359 const char *kinds = omp_offload_device_kind;
1360 if (omp_offload_device_kind_arch_isa (kinds, prop))
1361 {
1362 ret = -1;
1363 continue;
1364 }
1365 }
1366 return 0;
135df52c 1367 }
9ba66bf5
JJ
1368 else if (r == -1)
1369 ret = -1;
1370 /* If kind matches on the host, it still might not match
1371 in the offloading region. */
1372 else if (omp_maybe_offloaded ())
1373 ret = -1;
135df52c
JJ
1374 }
1375 break;
1376 case 'i':
1377 if (set == 'd' && !strcmp (sel, "isa"))
9ba66bf5
JJ
1378 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1379 {
b2417b59
JJ
1380 const char *isa = omp_context_name_list_prop (t3);
1381 if (isa == NULL)
1382 return 0;
9ba66bf5
JJ
1383 int r = 0;
1384 if (targetm.omp.device_kind_arch_isa != NULL)
1385 r = targetm.omp.device_kind_arch_isa (omp_device_isa,
1386 isa);
1387 if (r == 0 || (r == -1 && symtab->state != PARSING))
1388 {
0227ffa9
JJ
1389 /* If isa is valid on the target, but not in the
1390 current function and current function has
1391 #pragma omp declare simd on it, some simd clones
1392 might have the isa added later on. */
1393 if (r == -1
7a50e708
JJ
1394 && targetm.simd_clone.compute_vecsize_and_simdlen
1395 && (cfun == NULL || !cfun->after_inlining))
0227ffa9
JJ
1396 {
1397 tree attrs
1398 = DECL_ATTRIBUTES (current_function_decl);
1399 if (lookup_attribute ("omp declare simd", attrs))
1400 {
1401 ret = -1;
1402 continue;
1403 }
1404 }
9ba66bf5
JJ
1405 /* If we are or might be in a target region or
1406 declare target function, need to take into account
1407 also offloading values. */
1408 if (!omp_maybe_offloaded ())
1409 return 0;
1410 if (ENABLE_OFFLOADING)
1411 {
1412 const char *isas = omp_offload_device_isa;
1413 if (omp_offload_device_kind_arch_isa (isas, isa))
1414 {
1415 ret = -1;
1416 continue;
1417 }
1418 }
1419 return 0;
1420 }
1421 else if (r == -1)
1422 ret = -1;
1423 /* If isa matches on the host, it still might not match
1424 in the offloading region. */
1425 else if (omp_maybe_offloaded ())
1426 ret = -1;
1427 }
135df52c
JJ
1428 break;
1429 case 'c':
1430 if (set == 'u' && !strcmp (sel, "condition"))
1431 for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
1432 if (TREE_PURPOSE (t3) == NULL_TREE)
1433 {
1434 if (integer_zerop (TREE_VALUE (t3)))
1435 return 0;
1436 if (integer_nonzerop (TREE_VALUE (t3)))
1437 break;
1438 ret = -1;
1439 }
1440 break;
1441 default:
1442 break;
1443 }
1444 }
1445 }
1446 return ret;
1447}
1448
917dd789
JJ
1449/* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
1450 in omp_context_selector_set_compare. */
1451
1452static int
1453omp_construct_simd_compare (tree clauses1, tree clauses2)
1454{
1455 if (clauses1 == NULL_TREE)
1456 return clauses2 == NULL_TREE ? 0 : -1;
1457 if (clauses2 == NULL_TREE)
1458 return 1;
1459
1460 int r = 0;
1461 struct declare_variant_simd_data {
1462 bool inbranch, notinbranch;
1463 tree simdlen;
1464 auto_vec<tree,16> data_sharing;
1465 auto_vec<tree,16> aligned;
1466 declare_variant_simd_data ()
1467 : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
1468 } data[2];
1469 unsigned int i;
1470 for (i = 0; i < 2; i++)
1471 for (tree c = i ? clauses2 : clauses1; c; c = OMP_CLAUSE_CHAIN (c))
1472 {
1473 vec<tree> *v;
1474 switch (OMP_CLAUSE_CODE (c))
1475 {
1476 case OMP_CLAUSE_INBRANCH:
1477 data[i].inbranch = true;
1478 continue;
1479 case OMP_CLAUSE_NOTINBRANCH:
1480 data[i].notinbranch = true;
1481 continue;
1482 case OMP_CLAUSE_SIMDLEN:
1483 data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
1484 continue;
1485 case OMP_CLAUSE_UNIFORM:
1486 case OMP_CLAUSE_LINEAR:
1487 v = &data[i].data_sharing;
1488 break;
1489 case OMP_CLAUSE_ALIGNED:
1490 v = &data[i].aligned;
1491 break;
1492 default:
1493 gcc_unreachable ();
1494 }
1495 unsigned HOST_WIDE_INT argno = tree_to_uhwi (OMP_CLAUSE_DECL (c));
1496 if (argno >= v->length ())
cb3874dc 1497 v->safe_grow_cleared (argno + 1, true);
917dd789
JJ
1498 (*v)[argno] = c;
1499 }
1500 /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
1501 CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
1502 doesn't. Thus, r == 3 implies return value 2, r == 1 implies
1503 -1, r == 2 implies 1 and r == 0 implies 0. */
1504 if (data[0].inbranch != data[1].inbranch)
1505 r |= data[0].inbranch ? 2 : 1;
1506 if (data[0].notinbranch != data[1].notinbranch)
1507 r |= data[0].notinbranch ? 2 : 1;
1508 if (!simple_cst_equal (data[0].simdlen, data[1].simdlen))
1509 {
1510 if (data[0].simdlen && data[1].simdlen)
1511 return 2;
1512 r |= data[0].simdlen ? 2 : 1;
1513 }
1514 if (data[0].data_sharing.length () < data[1].data_sharing.length ()
1515 || data[0].aligned.length () < data[1].aligned.length ())
1516 r |= 1;
1517 tree c1, c2;
1518 FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
1519 {
1520 c2 = (i < data[1].data_sharing.length ()
1521 ? data[1].data_sharing[i] : NULL_TREE);
1522 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
1523 {
1524 r |= c1 != NULL_TREE ? 2 : 1;
1525 continue;
1526 }
1527 if (c1 == NULL_TREE)
1528 continue;
1529 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
1530 return 2;
1531 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
1532 continue;
1533 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
1534 != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
1535 return 2;
1536 if (OMP_CLAUSE_LINEAR_KIND (c1) != OMP_CLAUSE_LINEAR_KIND (c2))
1537 return 2;
1538 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
1539 OMP_CLAUSE_LINEAR_STEP (c2)))
1540 return 2;
1541 }
1542 FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
1543 {
1544 c2 = i < data[1].aligned.length () ? data[1].aligned[i] : NULL_TREE;
1545 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
1546 {
1547 r |= c1 != NULL_TREE ? 2 : 1;
1548 continue;
1549 }
1550 if (c1 == NULL_TREE)
1551 continue;
1552 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
1553 OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
1554 return 2;
1555 }
1556 switch (r)
1557 {
1558 case 0: return 0;
1559 case 1: return -1;
1560 case 2: return 1;
1561 case 3: return 2;
1562 default: gcc_unreachable ();
1563 }
1564}
1565
1566/* Compare properties of selectors SEL from SET other than construct.
1567 Return 0/-1/1/2 as in omp_context_selector_set_compare.
1568 Unlike set names or selector names, properties can have duplicates. */
1569
1570static int
1571omp_context_selector_props_compare (const char *set, const char *sel,
1572 tree ctx1, tree ctx2)
1573{
1574 int ret = 0;
1575 for (int pass = 0; pass < 2; pass++)
1576 for (tree t1 = pass ? ctx2 : ctx1; t1; t1 = TREE_CHAIN (t1))
1577 {
1578 tree t2;
1579 for (t2 = pass ? ctx1 : ctx2; t2; t2 = TREE_CHAIN (t2))
1580 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1581 {
1582 if (TREE_PURPOSE (t1) == NULL_TREE)
1583 {
1584 if (set[0] == 'u' && strcmp (sel, "condition") == 0)
1585 {
1586 if (integer_zerop (TREE_VALUE (t1))
1587 != integer_zerop (TREE_VALUE (t2)))
1588 return 2;
1589 break;
1590 }
1591 if (simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1592 break;
1593 }
1594 else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
1595 " score") == 0)
1596 {
1597 if (!simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
1598 return 2;
1599 break;
1600 }
1601 else
1602 break;
1603 }
b2417b59
JJ
1604 else if (TREE_PURPOSE (t1)
1605 && TREE_PURPOSE (t2) == NULL_TREE
1606 && TREE_CODE (TREE_VALUE (t2)) == STRING_CST)
1607 {
1608 const char *p1 = omp_context_name_list_prop (t1);
1609 const char *p2 = omp_context_name_list_prop (t2);
1610 if (p2
1611 && strcmp (p1, p2) == 0
1612 && strcmp (p1, " score"))
1613 break;
1614 }
1615 else if (TREE_PURPOSE (t1) == NULL_TREE
1616 && TREE_PURPOSE (t2)
1617 && TREE_CODE (TREE_VALUE (t1)) == STRING_CST)
1618 {
1619 const char *p1 = omp_context_name_list_prop (t1);
1620 const char *p2 = omp_context_name_list_prop (t2);
1621 if (p1
1622 && strcmp (p1, p2) == 0
1623 && strcmp (p1, " score"))
1624 break;
1625 }
917dd789
JJ
1626 if (t2 == NULL_TREE)
1627 {
1628 int r = pass ? -1 : 1;
1629 if (ret && ret != r)
1630 return 2;
1631 else if (pass)
1632 return r;
1633 else
1634 {
1635 ret = r;
1636 break;
1637 }
1638 }
1639 }
1640 return ret;
1641}
1642
1643/* Compare single context selector sets CTX1 and CTX2 with SET name.
1644 Return 0 if CTX1 is equal to CTX2,
1645 -1 if CTX1 is a strict subset of CTX2,
1646 1 if CTX2 is a strict subset of CTX1, or
1647 2 if neither context is a subset of another one. */
1648
1649int
1650omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
1651{
1652 bool swapped = false;
1653 int ret = 0;
1654 int len1 = list_length (ctx1);
1655 int len2 = list_length (ctx2);
1656 int cnt = 0;
1657 if (len1 < len2)
1658 {
1659 swapped = true;
1660 std::swap (ctx1, ctx2);
1661 std::swap (len1, len2);
1662 }
1663 if (set[0] == 'c')
1664 {
1665 tree t1;
1666 tree t2 = ctx2;
1667 tree simd = get_identifier ("simd");
1668 /* Handle construct set specially. In this case the order
1669 of the selector matters too. */
1670 for (t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1671 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1672 {
1673 int r = 0;
1674 if (TREE_PURPOSE (t1) == simd)
1675 r = omp_construct_simd_compare (TREE_VALUE (t1),
1676 TREE_VALUE (t2));
1677 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1678 return 2;
1679 if (ret == 0)
1680 ret = r;
1681 t2 = TREE_CHAIN (t2);
1682 if (t2 == NULL_TREE)
1683 {
1684 t1 = TREE_CHAIN (t1);
1685 break;
1686 }
1687 }
1688 else if (ret < 0)
1689 return 2;
1690 else
1691 ret = 1;
1692 if (t2 != NULL_TREE)
1693 return 2;
1694 if (t1 != NULL_TREE)
1695 {
1696 if (ret < 0)
1697 return 2;
1698 ret = 1;
1699 }
1700 if (ret == 0)
1701 return 0;
1702 return swapped ? -ret : ret;
1703 }
1704 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1705 {
1706 tree t2;
1707 for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
1708 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1709 {
1710 const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
1711 int r = omp_context_selector_props_compare (set, sel,
1712 TREE_VALUE (t1),
1713 TREE_VALUE (t2));
1714 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1715 return 2;
1716 if (ret == 0)
1717 ret = r;
1718 cnt++;
1719 break;
1720 }
1721 if (t2 == NULL_TREE)
1722 {
1723 if (ret == -1)
1724 return 2;
1725 ret = 1;
1726 }
1727 }
1728 if (cnt < len2)
1729 return 2;
1730 if (ret == 0)
1731 return 0;
1732 return swapped ? -ret : ret;
1733}
1734
1735/* Compare whole context selector specification CTX1 and CTX2.
1736 Return 0 if CTX1 is equal to CTX2,
1737 -1 if CTX1 is a strict subset of CTX2,
1738 1 if CTX2 is a strict subset of CTX1, or
1739 2 if neither context is a subset of another one. */
1740
1741static int
1742omp_context_selector_compare (tree ctx1, tree ctx2)
1743{
1744 bool swapped = false;
1745 int ret = 0;
1746 int len1 = list_length (ctx1);
1747 int len2 = list_length (ctx2);
1748 int cnt = 0;
1749 if (len1 < len2)
1750 {
1751 swapped = true;
1752 std::swap (ctx1, ctx2);
1753 std::swap (len1, len2);
1754 }
1755 for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
1756 {
1757 tree t2;
1758 for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
1759 if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
1760 {
1761 const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
1762 int r = omp_context_selector_set_compare (set, TREE_VALUE (t1),
1763 TREE_VALUE (t2));
1764 if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
1765 return 2;
1766 if (ret == 0)
1767 ret = r;
1768 cnt++;
1769 break;
1770 }
1771 if (t2 == NULL_TREE)
1772 {
1773 if (ret == -1)
1774 return 2;
1775 ret = 1;
1776 }
1777 }
1778 if (cnt < len2)
1779 return 2;
1780 if (ret == 0)
1781 return 0;
1782 return swapped ? -ret : ret;
1783}
1784
d0c464d2
JJ
1785/* From context selector CTX, return trait-selector with name SEL in
1786 trait-selector-set with name SET if any, or NULL_TREE if not found.
1787 If SEL is NULL, return the list of trait-selectors in SET. */
1788
1789tree
1790omp_get_context_selector (tree ctx, const char *set, const char *sel)
1791{
1792 tree setid = get_identifier (set);
1793 tree selid = sel ? get_identifier (sel) : NULL_TREE;
1794 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
1795 if (TREE_PURPOSE (t1) == setid)
1796 {
1797 if (sel == NULL)
1798 return TREE_VALUE (t1);
1799 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1800 if (TREE_PURPOSE (t2) == selid)
1801 return t2;
1802 }
1803 return NULL_TREE;
1804}
1805
1806/* Compute *SCORE for context selector CTX. Return true if the score
1807 would be different depending on whether it is a declare simd clone or
1808 not. DECLARE_SIMD should be true for the case when it would be
1809 a declare simd clone. */
1810
1811static bool
1812omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
1813{
1814 tree construct = omp_get_context_selector (ctx, "construct", NULL);
1815 bool has_kind = omp_get_context_selector (ctx, "device", "kind");
1816 bool has_arch = omp_get_context_selector (ctx, "device", "arch");
1817 bool has_isa = omp_get_context_selector (ctx, "device", "isa");
1818 bool ret = false;
1819 *score = 1;
1820 for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
0227ffa9
JJ
1821 if (TREE_VALUE (t1) != construct)
1822 for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
1823 if (tree t3 = TREE_VALUE (t2))
1824 if (TREE_PURPOSE (t3)
1825 && strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)), " score") == 0
1826 && TREE_CODE (TREE_VALUE (t3)) == INTEGER_CST)
1827 *score += wi::to_widest (TREE_VALUE (t3));
d0c464d2
JJ
1828 if (construct || has_kind || has_arch || has_isa)
1829 {
1830 int scores[12];
1831 enum tree_code constructs[5];
1832 int nconstructs = 0;
1833 if (construct)
1834 nconstructs = omp_constructor_traits_to_codes (construct, constructs);
1835 if (omp_construct_selector_matches (constructs, nconstructs, scores)
1836 == 2)
1837 ret = true;
1838 int b = declare_simd ? nconstructs + 1 : 0;
1839 if (scores[b + nconstructs] + 4U < score->get_precision ())
1840 {
1841 for (int n = 0; n < nconstructs; ++n)
1842 {
1843 if (scores[b + n] < 0)
1844 {
0227ffa9 1845 *score = -1;
d0c464d2
JJ
1846 return ret;
1847 }
1848 *score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
1849 }
1850 if (has_kind)
1851 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs],
1852 1, false);
1853 if (has_arch)
1854 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 1,
1855 1, false);
1856 if (has_isa)
1857 *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 2,
1858 1, false);
1859 }
1860 else /* FIXME: Implement this. */
1861 gcc_unreachable ();
1862 }
1863 return ret;
1864}
1865
7a50e708
JJ
1866/* Class describing a single variant. */
1867struct GTY(()) omp_declare_variant_entry {
1868 /* NODE of the variant. */
1869 cgraph_node *variant;
1870 /* Score if not in declare simd clone. */
1871 widest_int score;
1872 /* Score if in declare simd clone. */
1873 widest_int score_in_declare_simd_clone;
1874 /* Context selector for the variant. */
1875 tree ctx;
1876 /* True if the context selector is known to match already. */
1877 bool matches;
1878};
1879
1880/* Class describing a function with variants. */
1881struct GTY((for_user)) omp_declare_variant_base_entry {
1882 /* NODE of the base function. */
1883 cgraph_node *base;
1884 /* NODE of the artificial function created for the deferred variant
1885 resolution. */
1886 cgraph_node *node;
1887 /* Vector of the variants. */
1888 vec<omp_declare_variant_entry, va_gc> *variants;
1889};
1890
1891struct omp_declare_variant_hasher
1892 : ggc_ptr_hash<omp_declare_variant_base_entry> {
1893 static hashval_t hash (omp_declare_variant_base_entry *);
1894 static bool equal (omp_declare_variant_base_entry *,
1895 omp_declare_variant_base_entry *);
1896};
1897
1898hashval_t
1899omp_declare_variant_hasher::hash (omp_declare_variant_base_entry *x)
1900{
1901 inchash::hash hstate;
1902 hstate.add_int (DECL_UID (x->base->decl));
1903 hstate.add_int (x->variants->length ());
1904 omp_declare_variant_entry *variant;
1905 unsigned int i;
1906 FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
1907 {
1908 hstate.add_int (DECL_UID (variant->variant->decl));
1909 hstate.add_wide_int (variant->score);
1910 hstate.add_wide_int (variant->score_in_declare_simd_clone);
1911 hstate.add_ptr (variant->ctx);
1912 hstate.add_int (variant->matches);
1913 }
1914 return hstate.end ();
1915}
1916
1917bool
1918omp_declare_variant_hasher::equal (omp_declare_variant_base_entry *x,
1919 omp_declare_variant_base_entry *y)
1920{
1921 if (x->base != y->base
1922 || x->variants->length () != y->variants->length ())
1923 return false;
1924 omp_declare_variant_entry *variant;
1925 unsigned int i;
1926 FOR_EACH_VEC_SAFE_ELT (x->variants, i, variant)
1927 if (variant->variant != (*y->variants)[i].variant
1928 || variant->score != (*y->variants)[i].score
1929 || (variant->score_in_declare_simd_clone
1930 != (*y->variants)[i].score_in_declare_simd_clone)
1931 || variant->ctx != (*y->variants)[i].ctx
1932 || variant->matches != (*y->variants)[i].matches)
1933 return false;
1934 return true;
1935}
1936
1937static GTY(()) hash_table<omp_declare_variant_hasher> *omp_declare_variants;
1938
1939struct omp_declare_variant_alt_hasher
1940 : ggc_ptr_hash<omp_declare_variant_base_entry> {
1941 static hashval_t hash (omp_declare_variant_base_entry *);
1942 static bool equal (omp_declare_variant_base_entry *,
1943 omp_declare_variant_base_entry *);
1944};
1945
1946hashval_t
1947omp_declare_variant_alt_hasher::hash (omp_declare_variant_base_entry *x)
1948{
1949 return DECL_UID (x->node->decl);
1950}
1951
1952bool
1953omp_declare_variant_alt_hasher::equal (omp_declare_variant_base_entry *x,
1954 omp_declare_variant_base_entry *y)
1955{
1956 return x->node == y->node;
1957}
1958
1959static GTY(()) hash_table<omp_declare_variant_alt_hasher>
1960 *omp_declare_variant_alt;
1961
1962/* Try to resolve declare variant after gimplification. */
1963
1964static tree
1965omp_resolve_late_declare_variant (tree alt)
1966{
1967 cgraph_node *node = cgraph_node::get (alt);
1968 cgraph_node *cur_node = cgraph_node::get (cfun->decl);
1969 if (node == NULL
1970 || !node->declare_variant_alt
1971 || !cfun->after_inlining)
1972 return alt;
1973
1974 omp_declare_variant_base_entry entry;
1975 entry.base = NULL;
1976 entry.node = node;
1977 entry.variants = NULL;
1978 omp_declare_variant_base_entry *entryp
1979 = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (alt));
1980
1981 unsigned int i, j;
1982 omp_declare_variant_entry *varentry1, *varentry2;
1983 auto_vec <bool, 16> matches;
1984 unsigned int nmatches = 0;
1985 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
1986 {
1987 if (varentry1->matches)
1988 {
1989 /* This has been checked to be ok already. */
1990 matches.safe_push (true);
1991 nmatches++;
1992 continue;
1993 }
1994 switch (omp_context_selector_matches (varentry1->ctx))
1995 {
1996 case 0:
1997 matches.safe_push (false);
1998 break;
1999 case -1:
2000 return alt;
2001 default:
2002 matches.safe_push (true);
2003 nmatches++;
2004 break;
2005 }
2006 }
2007
2008 if (nmatches == 0)
2009 return entryp->base->decl;
2010
2011 /* A context selector that is a strict subset of another context selector
2012 has a score of zero. */
2013 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2014 if (matches[i])
2015 {
2016 for (j = i + 1;
2017 vec_safe_iterate (entryp->variants, j, &varentry2); ++j)
2018 if (matches[j])
2019 {
2020 int r = omp_context_selector_compare (varentry1->ctx,
2021 varentry2->ctx);
2022 if (r == -1)
2023 {
2024 /* ctx1 is a strict subset of ctx2, ignore ctx1. */
2025 matches[i] = false;
2026 break;
2027 }
2028 else if (r == 1)
2029 /* ctx2 is a strict subset of ctx1, remove ctx2. */
2030 matches[j] = false;
2031 }
2032 }
2033
2034 widest_int max_score = -1;
2035 varentry2 = NULL;
2036 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
2037 if (matches[i])
2038 {
2039 widest_int score
2040 = (cur_node->simdclone ? varentry1->score_in_declare_simd_clone
2041 : varentry1->score);
2042 if (score > max_score)
2043 {
2044 max_score = score;
2045 varentry2 = varentry1;
2046 }
2047 }
2048 return varentry2->variant->decl;
2049}
2050
baff22c4
JJ
2051/* Hook to adjust hash tables on cgraph_node removal. */
2052
2053static void
2054omp_declare_variant_remove_hook (struct cgraph_node *node, void *)
2055{
2056 if (!node->declare_variant_alt)
2057 return;
2058
2059 /* Drop this hash table completely. */
2060 omp_declare_variants = NULL;
2061 /* And remove node from the other hash table. */
2062 if (omp_declare_variant_alt)
2063 {
2064 omp_declare_variant_base_entry entry;
2065 entry.base = NULL;
2066 entry.node = node;
2067 entry.variants = NULL;
2068 omp_declare_variant_alt->remove_elt_with_hash (&entry,
2069 DECL_UID (node->decl));
2070 }
2071}
2072
135df52c
JJ
2073/* Try to resolve declare variant, return the variant decl if it should
2074 be used instead of base, or base otherwise. */
2075
2076tree
2077omp_resolve_declare_variant (tree base)
2078{
d0c464d2 2079 tree variant1 = NULL_TREE, variant2 = NULL_TREE;
7a50e708
JJ
2080 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
2081 return omp_resolve_late_declare_variant (base);
2082
917dd789 2083 auto_vec <tree, 16> variants;
0227ffa9
JJ
2084 auto_vec <bool, 16> defer;
2085 bool any_deferred = false;
135df52c
JJ
2086 for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
2087 {
2088 attr = lookup_attribute ("omp declare variant base", attr);
2089 if (attr == NULL_TREE)
2090 break;
917dd789
JJ
2091 if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr))) != FUNCTION_DECL)
2092 continue;
baff22c4
JJ
2093 cgraph_node *node = cgraph_node::get (base);
2094 /* If this is already a magic decl created by this function,
2095 don't process it again. */
2096 if (node && node->declare_variant_alt)
2097 return base;
135df52c
JJ
2098 switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr))))
2099 {
2100 case 0:
2101 /* No match, ignore. */
2102 break;
2103 case -1:
2104 /* Needs to be deferred. */
0227ffa9
JJ
2105 any_deferred = true;
2106 variants.safe_push (attr);
2107 defer.safe_push (true);
2108 break;
135df52c 2109 default:
917dd789 2110 variants.safe_push (attr);
0227ffa9
JJ
2111 defer.safe_push (false);
2112 break;
135df52c
JJ
2113 }
2114 }
917dd789
JJ
2115 if (variants.length () == 0)
2116 return base;
0227ffa9
JJ
2117
2118 if (any_deferred)
2119 {
2120 widest_int max_score1 = 0;
2121 widest_int max_score2 = 0;
2122 bool first = true;
2123 unsigned int i;
2124 tree attr1, attr2;
7a50e708
JJ
2125 omp_declare_variant_base_entry entry;
2126 entry.base = cgraph_node::get_create (base);
2127 entry.node = NULL;
2128 vec_alloc (entry.variants, variants.length ());
0227ffa9
JJ
2129 FOR_EACH_VEC_ELT (variants, i, attr1)
2130 {
2131 widest_int score1;
2132 widest_int score2;
2133 bool need_two;
2134 tree ctx = TREE_VALUE (TREE_VALUE (attr1));
2135 need_two = omp_context_compute_score (ctx, &score1, false);
2136 if (need_two)
2137 omp_context_compute_score (ctx, &score2, true);
2138 else
2139 score2 = score1;
2140 if (first)
2141 {
2142 first = false;
2143 max_score1 = score1;
2144 max_score2 = score2;
2145 if (!defer[i])
2146 {
2147 variant1 = attr1;
2148 variant2 = attr1;
2149 }
2150 }
2151 else
2152 {
2153 if (max_score1 == score1)
2154 variant1 = NULL_TREE;
2155 else if (score1 > max_score1)
2156 {
2157 max_score1 = score1;
2158 variant1 = defer[i] ? NULL_TREE : attr1;
2159 }
2160 if (max_score2 == score2)
2161 variant2 = NULL_TREE;
2162 else if (score2 > max_score2)
2163 {
2164 max_score2 = score2;
2165 variant2 = defer[i] ? NULL_TREE : attr1;
2166 }
2167 }
7a50e708
JJ
2168 omp_declare_variant_entry varentry;
2169 varentry.variant
2170 = cgraph_node::get_create (TREE_PURPOSE (TREE_VALUE (attr1)));
2171 varentry.score = score1;
2172 varentry.score_in_declare_simd_clone = score2;
2173 varentry.ctx = ctx;
2174 varentry.matches = !defer[i];
2175 entry.variants->quick_push (varentry);
0227ffa9
JJ
2176 }
2177
2178 /* If there is a clear winner variant with the score which is not
2179 deferred, verify it is not a strict subset of any other context
2180 selector and if it is not, it is the best alternative no matter
2181 whether the others do or don't match. */
2182 if (variant1 && variant1 == variant2)
2183 {
2184 tree ctx1 = TREE_VALUE (TREE_VALUE (variant1));
2185 FOR_EACH_VEC_ELT (variants, i, attr2)
2186 {
2187 if (attr2 == variant1)
2188 continue;
2189 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2190 int r = omp_context_selector_compare (ctx1, ctx2);
2191 if (r == -1)
2192 {
2193 /* The winner is a strict subset of ctx2, can't
2194 decide now. */
2195 variant1 = NULL_TREE;
2196 break;
2197 }
2198 }
2199 if (variant1)
7a50e708
JJ
2200 {
2201 vec_free (entry.variants);
2202 return TREE_PURPOSE (TREE_VALUE (variant1));
2203 }
2204 }
2205
baff22c4 2206 static struct cgraph_node_hook_list *node_removal_hook_holder;
3d0675f3 2207 if (!node_removal_hook_holder)
baff22c4
JJ
2208 node_removal_hook_holder
2209 = symtab->add_cgraph_removal_hook (omp_declare_variant_remove_hook,
2210 NULL);
2211
7a50e708
JJ
2212 if (omp_declare_variants == NULL)
2213 omp_declare_variants
2214 = hash_table<omp_declare_variant_hasher>::create_ggc (64);
2215 omp_declare_variant_base_entry **slot
2216 = omp_declare_variants->find_slot (&entry, INSERT);
2217 if (*slot != NULL)
2218 {
2219 vec_free (entry.variants);
2220 return (*slot)->node->decl;
0227ffa9
JJ
2221 }
2222
7a50e708
JJ
2223 *slot = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
2224 (*slot)->base = entry.base;
2225 (*slot)->node = entry.base;
2226 (*slot)->variants = entry.variants;
2227 tree alt = build_decl (DECL_SOURCE_LOCATION (base), FUNCTION_DECL,
2228 DECL_NAME (base), TREE_TYPE (base));
2229 DECL_ARTIFICIAL (alt) = 1;
2230 DECL_IGNORED_P (alt) = 1;
2231 TREE_STATIC (alt) = 1;
2232 tree attributes = DECL_ATTRIBUTES (base);
2233 if (lookup_attribute ("noipa", attributes) == NULL)
2234 {
2235 attributes = tree_cons (get_identifier ("noipa"), NULL, attributes);
2236 if (lookup_attribute ("noinline", attributes) == NULL)
2237 attributes = tree_cons (get_identifier ("noinline"), NULL,
2238 attributes);
2239 if (lookup_attribute ("noclone", attributes) == NULL)
2240 attributes = tree_cons (get_identifier ("noclone"), NULL,
2241 attributes);
2242 if (lookup_attribute ("no_icf", attributes) == NULL)
2243 attributes = tree_cons (get_identifier ("no_icf"), NULL,
2244 attributes);
2245 }
2246 DECL_ATTRIBUTES (alt) = attributes;
2247 DECL_INITIAL (alt) = error_mark_node;
2248 (*slot)->node = cgraph_node::create (alt);
2249 (*slot)->node->declare_variant_alt = 1;
2250 (*slot)->node->create_reference (entry.base, IPA_REF_ADDR);
2251 omp_declare_variant_entry *varentry;
2252 FOR_EACH_VEC_SAFE_ELT (entry.variants, i, varentry)
2253 (*slot)->node->create_reference (varentry->variant, IPA_REF_ADDR);
2254 if (omp_declare_variant_alt == NULL)
2255 omp_declare_variant_alt
2256 = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
2257 *omp_declare_variant_alt->find_slot_with_hash (*slot, DECL_UID (alt),
2258 INSERT) = *slot;
2259 return alt;
0227ffa9
JJ
2260 }
2261
917dd789
JJ
2262 if (variants.length () == 1)
2263 return TREE_PURPOSE (TREE_VALUE (variants[0]));
2264
7a50e708
JJ
2265 /* A context selector that is a strict subset of another context selector
2266 has a score of zero. */
917dd789
JJ
2267 tree attr1, attr2;
2268 unsigned int i, j;
2269 FOR_EACH_VEC_ELT (variants, i, attr1)
2270 if (attr1)
2271 {
2272 tree ctx1 = TREE_VALUE (TREE_VALUE (attr1));
2273 FOR_EACH_VEC_ELT_FROM (variants, j, attr2, i + 1)
2274 if (attr2)
2275 {
2276 tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
2277 int r = omp_context_selector_compare (ctx1, ctx2);
2278 if (r == -1)
2279 {
2280 /* ctx1 is a strict subset of ctx2, remove
2281 attr1 from the vector. */
2282 variants[i] = NULL_TREE;
2283 break;
2284 }
2285 else if (r == 1)
2286 /* ctx2 is a strict subset of ctx1, remove attr2
2287 from the vector. */
2288 variants[j] = NULL_TREE;
2289 }
2290 }
d0c464d2
JJ
2291 widest_int max_score1 = 0;
2292 widest_int max_score2 = 0;
2293 bool first = true;
917dd789
JJ
2294 FOR_EACH_VEC_ELT (variants, i, attr1)
2295 if (attr1)
2296 {
d0c464d2
JJ
2297 if (variant1)
2298 {
2299 widest_int score1;
2300 widest_int score2;
2301 bool need_two;
2302 tree ctx;
2303 if (first)
2304 {
2305 first = false;
2306 ctx = TREE_VALUE (TREE_VALUE (variant1));
2307 need_two = omp_context_compute_score (ctx, &max_score1, false);
2308 if (need_two)
2309 omp_context_compute_score (ctx, &max_score2, true);
2310 else
2311 max_score2 = max_score1;
2312 }
2313 ctx = TREE_VALUE (TREE_VALUE (attr1));
2314 need_two = omp_context_compute_score (ctx, &score1, false);
2315 if (need_two)
2316 omp_context_compute_score (ctx, &score2, true);
2317 else
2318 score2 = score1;
2319 if (score1 > max_score1)
2320 {
2321 max_score1 = score1;
2322 variant1 = attr1;
2323 }
2324 if (score2 > max_score2)
2325 {
2326 max_score2 = score2;
2327 variant2 = attr1;
2328 }
2329 }
2330 else
2331 {
2332 variant1 = attr1;
2333 variant2 = attr1;
2334 }
917dd789 2335 }
d0c464d2
JJ
2336 /* If there is a disagreement on which variant has the highest score
2337 depending on whether it will be in a declare simd clone or not,
2338 punt for now and defer until after IPA where we will know that. */
2339 return ((variant1 && variant1 == variant2)
2340 ? TREE_PURPOSE (TREE_VALUE (variant1)) : base);
135df52c
JJ
2341}
2342
f165ef89
JJ
2343void
2344omp_lto_output_declare_variant_alt (lto_simple_output_block *ob,
2345 cgraph_node *node,
2346 lto_symtab_encoder_t encoder)
2347{
2348 gcc_assert (node->declare_variant_alt);
2349
2350 omp_declare_variant_base_entry entry;
2351 entry.base = NULL;
2352 entry.node = node;
2353 entry.variants = NULL;
2354 omp_declare_variant_base_entry *entryp
2355 = omp_declare_variant_alt->find_with_hash (&entry, DECL_UID (node->decl));
2356 gcc_assert (entryp);
2357
2358 int nbase = lto_symtab_encoder_lookup (encoder, entryp->base);
2359 gcc_assert (nbase != LCC_NOT_FOUND);
2360 streamer_write_hwi_stream (ob->main_stream, nbase);
2361
2362 streamer_write_hwi_stream (ob->main_stream, entryp->variants->length ());
2363
2364 unsigned int i;
2365 omp_declare_variant_entry *varentry;
2366 FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry)
2367 {
2368 int nvar = lto_symtab_encoder_lookup (encoder, varentry->variant);
2369 gcc_assert (nvar != LCC_NOT_FOUND);
2370 streamer_write_hwi_stream (ob->main_stream, nvar);
2371
2372 for (widest_int *w = &varentry->score; ;
2373 w = &varentry->score_in_declare_simd_clone)
2374 {
2375 unsigned len = w->get_len ();
2376 streamer_write_hwi_stream (ob->main_stream, len);
2377 const HOST_WIDE_INT *val = w->get_val ();
2378 for (unsigned j = 0; j < len; j++)
2379 streamer_write_hwi_stream (ob->main_stream, val[j]);
2380 if (w == &varentry->score_in_declare_simd_clone)
2381 break;
2382 }
2383
2384 HOST_WIDE_INT cnt = -1;
2385 HOST_WIDE_INT i = varentry->matches ? 1 : 0;
2386 for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
2387 attr; attr = TREE_CHAIN (attr), i += 2)
2388 {
2389 attr = lookup_attribute ("omp declare variant base", attr);
2390 if (attr == NULL_TREE)
2391 break;
2392
2393 if (varentry->ctx == TREE_VALUE (TREE_VALUE (attr)))
2394 {
2395 cnt = i;
2396 break;
2397 }
2398 }
2399
2400 gcc_assert (cnt != -1);
2401 streamer_write_hwi_stream (ob->main_stream, cnt);
2402 }
2403}
2404
2405void
2406omp_lto_input_declare_variant_alt (lto_input_block *ib, cgraph_node *node,
2407 vec<symtab_node *> nodes)
2408{
2409 gcc_assert (node->declare_variant_alt);
2410 omp_declare_variant_base_entry *entryp
2411 = ggc_cleared_alloc<omp_declare_variant_base_entry> ();
2412 entryp->base = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
2413 entryp->node = node;
2414 unsigned int len = streamer_read_hwi (ib);
2415 vec_alloc (entryp->variants, len);
2416
2417 for (unsigned int i = 0; i < len; i++)
2418 {
2419 omp_declare_variant_entry varentry;
2420 varentry.variant
2421 = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
2422 for (widest_int *w = &varentry.score; ;
2423 w = &varentry.score_in_declare_simd_clone)
2424 {
2425 unsigned len2 = streamer_read_hwi (ib);
2426 HOST_WIDE_INT arr[WIDE_INT_MAX_ELTS];
2427 gcc_assert (len2 <= WIDE_INT_MAX_ELTS);
2428 for (unsigned int j = 0; j < len2; j++)
2429 arr[j] = streamer_read_hwi (ib);
2430 *w = widest_int::from_array (arr, len2, true);
2431 if (w == &varentry.score_in_declare_simd_clone)
2432 break;
2433 }
2434
2435 HOST_WIDE_INT cnt = streamer_read_hwi (ib);
2436 HOST_WIDE_INT j = 0;
2437 varentry.ctx = NULL_TREE;
2438 varentry.matches = (cnt & 1) ? true : false;
2439 cnt &= ~HOST_WIDE_INT_1;
2440 for (tree attr = DECL_ATTRIBUTES (entryp->base->decl);
2441 attr; attr = TREE_CHAIN (attr), j += 2)
2442 {
2443 attr = lookup_attribute ("omp declare variant base", attr);
2444 if (attr == NULL_TREE)
2445 break;
2446
2447 if (cnt == j)
2448 {
2449 varentry.ctx = TREE_VALUE (TREE_VALUE (attr));
2450 break;
2451 }
2452 }
2453 gcc_assert (varentry.ctx != NULL_TREE);
2454 entryp->variants->quick_push (varentry);
2455 }
2456 if (omp_declare_variant_alt == NULL)
2457 omp_declare_variant_alt
2458 = hash_table<omp_declare_variant_alt_hasher>::create_ggc (64);
2459 *omp_declare_variant_alt->find_slot_with_hash (entryp, DECL_UID (node->decl),
2460 INSERT) = entryp;
2461}
135df52c 2462
629b3d75
MJ
2463/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
2464 macro on gomp-constants.h. We do not check for overflow. */
2465
2466tree
2467oacc_launch_pack (unsigned code, tree device, unsigned op)
2468{
2469 tree res;
2470
2471 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
2472 if (device)
2473 {
2474 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
2475 device, build_int_cst (unsigned_type_node,
2476 GOMP_LAUNCH_DEVICE_SHIFT));
2477 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
2478 }
2479 return res;
2480}
2481
2482/* FIXME: What is the following comment for? */
2483/* Look for compute grid dimension clauses and convert to an attribute
2484 attached to FN. This permits the target-side code to (a) massage
2485 the dimensions, (b) emit that data and (c) optimize. Non-constant
2486 dimensions are pushed onto ARGS.
2487
2488 The attribute value is a TREE_LIST. A set of dimensions is
2489 represented as a list of INTEGER_CST. Those that are runtime
2490 exprs are represented as an INTEGER_CST of zero.
2491
01914336 2492 TODO: Normally the attribute will just contain a single such list. If
629b3d75
MJ
2493 however it contains a list of lists, this will represent the use of
2494 device_type. Each member of the outer list is an assoc list of
2495 dimensions, keyed by the device type. The first entry will be the
2496 default. Well, that's the plan. */
2497
2498/* Replace any existing oacc fn attribute with updated dimensions. */
2499
68034b1b
TS
2500/* Variant working on a list of attributes. */
2501
2502tree
2503oacc_replace_fn_attrib_attr (tree attribs, tree dims)
629b3d75
MJ
2504{
2505 tree ident = get_identifier (OACC_FN_ATTRIB);
629b3d75
MJ
2506
2507 /* If we happen to be present as the first attrib, drop it. */
2508 if (attribs && TREE_PURPOSE (attribs) == ident)
2509 attribs = TREE_CHAIN (attribs);
68034b1b
TS
2510 return tree_cons (ident, dims, attribs);
2511}
2512
2513/* Variant working on a function decl. */
2514
2515void
2516oacc_replace_fn_attrib (tree fn, tree dims)
2517{
2518 DECL_ATTRIBUTES (fn)
2519 = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn), dims);
629b3d75
MJ
2520}
2521
2522/* Scan CLAUSES for launch dimensions and attach them to the oacc
2523 function attribute. Push any that are non-constant onto the ARGS
25651634 2524 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
629b3d75
MJ
2525
2526void
25651634 2527oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
629b3d75
MJ
2528{
2529 /* Must match GOMP_DIM ordering. */
2530 static const omp_clause_code ids[]
2531 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
2532 OMP_CLAUSE_VECTOR_LENGTH };
2533 unsigned ix;
2534 tree dims[GOMP_DIM_MAX];
2535
2536 tree attr = NULL_TREE;
2537 unsigned non_const = 0;
2538
2539 for (ix = GOMP_DIM_MAX; ix--;)
2540 {
2541 tree clause = omp_find_clause (clauses, ids[ix]);
2542 tree dim = NULL_TREE;
2543
2544 if (clause)
2545 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
2546 dims[ix] = dim;
2547 if (dim && TREE_CODE (dim) != INTEGER_CST)
2548 {
2549 dim = integer_zero_node;
2550 non_const |= GOMP_DIM_MASK (ix);
2551 }
2552 attr = tree_cons (NULL_TREE, dim, attr);
629b3d75
MJ
2553 }
2554
2555 oacc_replace_fn_attrib (fn, attr);
2556
2557 if (non_const)
2558 {
2559 /* Push a dynamic argument set. */
2560 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
2561 NULL_TREE, non_const));
2562 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
2563 if (non_const & GOMP_DIM_MASK (ix))
2564 args->safe_push (dims[ix]);
2565 }
2566}
2567
5bf04509
TS
2568/* Verify OpenACC routine clauses.
2569
b48f44bf
TS
2570 Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
2571 if it has already been marked in compatible way, and -1 if incompatible.
5bf04509
TS
2572 Upon returning, the chain of clauses will contain exactly one clause
2573 specifying the level of parallelism. */
2574
b48f44bf
TS
2575int
2576oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc,
2577 const char *routine_str)
5bf04509
TS
2578{
2579 tree c_level = NULL_TREE;
a61f6afb 2580 tree c_nohost = NULL_TREE;
5bf04509
TS
2581 tree c_p = NULL_TREE;
2582 for (tree c = *clauses; c; c_p = c, c = OMP_CLAUSE_CHAIN (c))
2583 switch (OMP_CLAUSE_CODE (c))
2584 {
2585 case OMP_CLAUSE_GANG:
2586 case OMP_CLAUSE_WORKER:
2587 case OMP_CLAUSE_VECTOR:
2588 case OMP_CLAUSE_SEQ:
2589 if (c_level == NULL_TREE)
2590 c_level = c;
2591 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_CODE (c_level))
2592 {
2593 /* This has already been diagnosed in the front ends. */
2594 /* Drop the duplicate clause. */
2595 gcc_checking_assert (c_p != NULL_TREE);
2596 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
2597 c = c_p;
2598 }
2599 else
2600 {
2601 error_at (OMP_CLAUSE_LOCATION (c),
2602 "%qs specifies a conflicting level of parallelism",
2603 omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
2604 inform (OMP_CLAUSE_LOCATION (c_level),
2605 "... to the previous %qs clause here",
2606 omp_clause_code_name[OMP_CLAUSE_CODE (c_level)]);
2607 /* Drop the conflicting clause. */
2608 gcc_checking_assert (c_p != NULL_TREE);
2609 OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
2610 c = c_p;
2611 }
2612 break;
a61f6afb
TS
2613 case OMP_CLAUSE_NOHOST:
2614 /* Don't worry about duplicate clauses here. */
2615 c_nohost = c;
2616 break;
5bf04509
TS
2617 default:
2618 gcc_unreachable ();
2619 }
2620 if (c_level == NULL_TREE)
2621 {
2622 /* Default to an implicit 'seq' clause. */
2623 c_level = build_omp_clause (loc, OMP_CLAUSE_SEQ);
2624 OMP_CLAUSE_CHAIN (c_level) = *clauses;
2625 *clauses = c_level;
2626 }
b48f44bf
TS
2627 /* In *clauses, we now have exactly one clause specifying the level of
2628 parallelism. */
2629
2630 tree attr
2631 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl));
2632 if (attr != NULL_TREE)
2633 {
ff3f862b
TS
2634 /* Diagnose if "#pragma omp declare target" has also been applied. */
2635 if (TREE_VALUE (attr) == NULL_TREE)
2636 {
2637 /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
2638 OpenACC and OpenMP 'target' are not clear. */
2639 error_at (loc,
2640 "cannot apply %<%s%> to %qD, which has also been"
2641 " marked with an OpenMP 'declare target' directive",
2642 routine_str, fndecl);
2643 /* Incompatible. */
2644 return -1;
2645 }
2646
b48f44bf
TS
2647 /* If a "#pragma acc routine" has already been applied, just verify
2648 this one for compatibility. */
2649 /* Collect previous directive's clauses. */
2650 tree c_level_p = NULL_TREE;
a61f6afb 2651 tree c_nohost_p = NULL_TREE;
b48f44bf
TS
2652 for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c))
2653 switch (OMP_CLAUSE_CODE (c))
2654 {
2655 case OMP_CLAUSE_GANG:
2656 case OMP_CLAUSE_WORKER:
2657 case OMP_CLAUSE_VECTOR:
2658 case OMP_CLAUSE_SEQ:
2659 gcc_checking_assert (c_level_p == NULL_TREE);
2660 c_level_p = c;
2661 break;
a61f6afb
TS
2662 case OMP_CLAUSE_NOHOST:
2663 gcc_checking_assert (c_nohost_p == NULL_TREE);
2664 c_nohost_p = c;
2665 break;
b48f44bf
TS
2666 default:
2667 gcc_unreachable ();
2668 }
2669 gcc_checking_assert (c_level_p != NULL_TREE);
2670 /* ..., and compare to current directive's, which we've already collected
2671 above. */
2672 tree c_diag;
2673 tree c_diag_p;
2674 /* Matching level of parallelism? */
2675 if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
2676 {
2677 c_diag = c_level;
2678 c_diag_p = c_level_p;
2679 goto incompatible;
2680 }
a61f6afb
TS
2681 /* Matching 'nohost' clauses? */
2682 if ((c_nohost == NULL_TREE) != (c_nohost_p == NULL_TREE))
2683 {
2684 c_diag = c_nohost;
2685 c_diag_p = c_nohost_p;
2686 goto incompatible;
2687 }
b48f44bf
TS
2688 /* Compatible. */
2689 return 1;
2690
2691 incompatible:
2692 if (c_diag != NULL_TREE)
2693 error_at (OMP_CLAUSE_LOCATION (c_diag),
2694 "incompatible %qs clause when applying"
2695 " %<%s%> to %qD, which has already been"
2696 " marked with an OpenACC 'routine' directive",
2697 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)],
2698 routine_str, fndecl);
2699 else if (c_diag_p != NULL_TREE)
2700 error_at (loc,
2701 "missing %qs clause when applying"
2702 " %<%s%> to %qD, which has already been"
2703 " marked with an OpenACC 'routine' directive",
2704 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)],
2705 routine_str, fndecl);
2706 else
2707 gcc_unreachable ();
2708 if (c_diag_p != NULL_TREE)
2709 inform (OMP_CLAUSE_LOCATION (c_diag_p),
2710 "... with %qs clause here",
2711 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]);
2712 else
2713 {
2714 /* In the front ends, we don't preserve location information for the
2715 OpenACC routine directive itself. However, that of c_level_p
2716 should be close. */
2717 location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p);
2718 inform (loc_routine, "... without %qs clause near to here",
2719 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]);
2720 }
2721 /* Incompatible. */
2722 return -1;
2723 }
2724
2725 return 0;
5bf04509
TS
2726}
2727
2728/* Process the OpenACC 'routine' directive clauses to generate an attribute
2729 for the level of parallelism. All dimensions have a size of zero
629b3d75
MJ
2730 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
2731 can have a loop partitioned on it. non-zero indicates
2732 yes, zero indicates no. By construction once a non-zero has been
2733 reached, further inner dimensions must also be non-zero. We set
2734 TREE_VALUE to zero for the dimensions that may be partitioned and
2735 1 for the other ones -- if a loop is (erroneously) spawned at
2736 an outer level, we don't want to try and partition it. */
2737
2738tree
2739oacc_build_routine_dims (tree clauses)
2740{
2741 /* Must match GOMP_DIM ordering. */
01914336
MJ
2742 static const omp_clause_code ids[]
2743 = {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
629b3d75
MJ
2744 int ix;
2745 int level = -1;
2746
2747 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
2748 for (ix = GOMP_DIM_MAX + 1; ix--;)
2749 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
2750 {
629b3d75
MJ
2751 level = ix;
2752 break;
2753 }
5bf04509 2754 gcc_checking_assert (level >= 0);
629b3d75
MJ
2755
2756 tree dims = NULL_TREE;
2757
2758 for (ix = GOMP_DIM_MAX; ix--;)
2759 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
2760 build_int_cst (integer_type_node, ix < level), dims);
2761
2762 return dims;
2763}
2764
2765/* Retrieve the oacc function attrib and return it. Non-oacc
2766 functions will return NULL. */
2767
2768tree
2769oacc_get_fn_attrib (tree fn)
2770{
2771 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
2772}
2773
46dbeb40
TV
2774/* Return true if FN is an OpenMP or OpenACC offloading function. */
2775
2776bool
2777offloading_function_p (tree fn)
2778{
2779 tree attrs = DECL_ATTRIBUTES (fn);
2780 return (lookup_attribute ("omp declare target", attrs)
2781 || lookup_attribute ("omp target entrypoint", attrs));
2782}
2783
629b3d75
MJ
2784/* Extract an oacc execution dimension from FN. FN must be an
2785 offloaded function or routine that has already had its execution
2786 dimensions lowered to the target-specific values. */
2787
2788int
2789oacc_get_fn_dim_size (tree fn, int axis)
2790{
2791 tree attrs = oacc_get_fn_attrib (fn);
2792
2793 gcc_assert (axis < GOMP_DIM_MAX);
2794
2795 tree dims = TREE_VALUE (attrs);
2796 while (axis--)
2797 dims = TREE_CHAIN (dims);
2798
2799 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
2800
2801 return size;
2802}
2803
2804/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
2805 IFN_GOACC_DIM_SIZE call. */
2806
2807int
2808oacc_get_ifn_dim_arg (const gimple *stmt)
2809{
2810 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
2811 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
2812 tree arg = gimple_call_arg (stmt, 0);
2813 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
2814
2815 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
2816 return (int) axis;
2817}
7a50e708
JJ
2818
2819#include "gt-omp-general.h"