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