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