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