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