LCOV - code coverage report
Current view: top level - gcc - omp-general.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 90.2 % 2374 2141
Test Date: 2026-07-11 15:47:05 Functions: 95.3 % 86 82
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* General types and functions that are useful for processing of OpenMP,
       2              :    OpenACC and similar directives at various stages of compilation.
       3              : 
       4              :    Copyright (C) 2005-2026 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              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "backend.h"
      26              : #include "target.h"
      27              : #include "tree.h"
      28              : #include "gimple.h"
      29              : #include "ssa.h"
      30              : #include "diagnostic-core.h"
      31              : #include "fold-const.h"
      32              : #include "langhooks.h"
      33              : #include "omp-general.h"
      34              : #include "stringpool.h"
      35              : #include "attribs.h"
      36              : #include "gimplify.h"
      37              : #include "cgraph.h"
      38              : #include "alloc-pool.h"
      39              : #include "symbol-summary.h"
      40              : #include "tree-pass.h"
      41              : #include "omp-device-properties.h"
      42              : #include "tree-iterator.h"
      43              : #include "data-streamer.h"
      44              : #include "streamer-hooks.h"
      45              : #include "opts.h"
      46              : #include "tree-pretty-print.h"
      47              : 
      48              : enum omp_requires omp_requires_mask;
      49              : 
      50              : /* Find an OMP clause of type KIND within CLAUSES.  */
      51              : tree
      52      1222193 : omp_find_clause (tree clauses, enum omp_clause_code kind)
      53              : {
      54      4494026 :   for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
      55      3528400 :     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        15434 : omp_is_allocatable_or_ptr (tree decl)
      65              : {
      66        15434 :   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              :    themselves 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        13288 : omp_check_optional_argument (tree decl, bool for_present_check)
      79              : {
      80        13288 :   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        58765 : omp_mappable_type (tree type)
      87              : {
      88              :   /* Mappable type has to be complete.  */
      89        58765 :   if (type == error_mark_node || !COMPLETE_TYPE_P (type))
      90          190 :     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      5026635 : omp_privatize_by_reference (tree decl)
      99              : {
     100      5026635 :   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       196508 : omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2,
     108              :                           tree v, tree step)
     109              : {
     110       196508 :   switch (*cond_code)
     111              :     {
     112              :     case LT_EXPR:
     113              :     case GT_EXPR:
     114              :       break;
     115              : 
     116        29865 :     case NE_EXPR:
     117        29865 :       gcc_assert (TREE_CODE (step) == INTEGER_CST);
     118        29865 :       if (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE
     119        29865 :           || TREE_CODE (TREE_TYPE (v)) == BITINT_TYPE)
     120              :         {
     121        25021 :           if (integer_onep (step))
     122        17737 :             *cond_code = LT_EXPR;
     123              :           else
     124              :             {
     125         7284 :               gcc_assert (integer_minus_onep (step));
     126         7284 :               *cond_code = GT_EXPR;
     127              :             }
     128              :         }
     129              :       else
     130              :         {
     131         4844 :           tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
     132         4844 :           gcc_assert (TREE_CODE (unit) == INTEGER_CST);
     133         4844 :           if (tree_int_cst_equal (unit, step))
     134         3358 :             *cond_code = LT_EXPR;
     135              :           else
     136              :             {
     137         1486 :               gcc_assert (wi::neg (wi::to_widest (unit))
     138              :                           == wi::to_widest (step));
     139         1486 :               *cond_code = GT_EXPR;
     140              :             }
     141              :         }
     142              : 
     143              :       break;
     144              : 
     145        28283 :     case LE_EXPR:
     146        28283 :       if (POINTER_TYPE_P (TREE_TYPE (*n2)))
     147              :         {
     148          123 :           tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
     149          123 :           gcc_assert (TREE_CODE (unit) == INTEGER_CST);
     150          123 :           *n2 = fold_build_pointer_plus_loc (loc, *n2, unit);
     151              :         }
     152              :       else
     153        28160 :         *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
     154        28160 :                                build_int_cst (TREE_TYPE (*n2), 1));
     155        28283 :       *cond_code = LT_EXPR;
     156        28283 :       break;
     157         1808 :     case GE_EXPR:
     158         1808 :       if (POINTER_TYPE_P (TREE_TYPE (*n2)))
     159              :         {
     160          137 :           tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v)));
     161          137 :           gcc_assert (TREE_CODE (unit) == INTEGER_CST);
     162          137 :           unit = convert_to_ptrofftype_loc (loc, unit);
     163          137 :           unit = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (unit),
     164              :                                   unit);
     165          137 :           *n2 = fold_build_pointer_plus_loc (loc, *n2, unit);
     166              :         }
     167              :       else
     168         1671 :         *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
     169         1671 :                                build_int_cst (TREE_TYPE (*n2), 1));
     170         1808 :       *cond_code = GT_EXPR;
     171         1808 :       break;
     172            0 :     default:
     173            0 :       gcc_unreachable ();
     174              :     }
     175       196508 : }
     176              : 
     177              : /* Return the looping step from INCR, extracted from the step of a gimple omp
     178              :    for statement.  */
     179              : 
     180              : tree
     181       195344 : omp_get_for_step_from_incr (location_t loc, tree incr)
     182              : {
     183       195344 :   tree step;
     184       195344 :   switch (TREE_CODE (incr))
     185              :     {
     186       173096 :     case PLUS_EXPR:
     187       173096 :       step = TREE_OPERAND (incr, 1);
     188       173096 :       break;
     189        16144 :     case POINTER_PLUS_EXPR:
     190        16144 :       step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
     191        16144 :       break;
     192         6104 :     case MINUS_EXPR:
     193         6104 :       step = TREE_OPERAND (incr, 1);
     194         6104 :       step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
     195         6104 :       break;
     196            0 :     default:
     197            0 :       gcc_unreachable ();
     198              :     }
     199       195344 :   return step;
     200              : }
     201              : 
     202              : /* Extract the header elements of parallel loop FOR_STMT and store
     203              :    them into *FD.  */
     204              : 
     205              : void
     206       129291 : omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
     207              :                       struct omp_for_data_loop *loops)
     208              : {
     209       129291 :   tree t, var, *collapse_iter, *collapse_count;
     210       129291 :   tree count = NULL_TREE, iter_type = long_integer_type_node;
     211       129291 :   struct omp_for_data_loop *loop;
     212       129291 :   int i;
     213       129291 :   struct omp_for_data_loop dummy_loop;
     214       129291 :   location_t loc = gimple_location (for_stmt);
     215       129291 :   bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
     216       129291 :   bool distribute = gimple_omp_for_kind (for_stmt)
     217       129291 :                     == GF_OMP_FOR_KIND_DISTRIBUTE;
     218       129291 :   bool taskloop = gimple_omp_for_kind (for_stmt)
     219       129291 :                   == GF_OMP_FOR_KIND_TASKLOOP;
     220       129291 :   bool order_reproducible = false;
     221       129291 :   tree iterv, countv;
     222              : 
     223       129291 :   fd->for_stmt = for_stmt;
     224       129291 :   fd->pre = NULL;
     225       129291 :   fd->have_nowait = distribute || simd;
     226       129291 :   fd->have_ordered = false;
     227       129291 :   fd->have_reductemp = false;
     228       129291 :   fd->have_pointer_condtemp = false;
     229       129291 :   fd->have_scantemp = false;
     230       129291 :   fd->have_nonctrl_scantemp = false;
     231       129291 :   fd->non_rect = false;
     232       129291 :   fd->lastprivate_conditional = 0;
     233       129291 :   fd->tiling = NULL_TREE;
     234       129291 :   fd->collapse = 1;
     235       129291 :   fd->ordered = 0;
     236       129291 :   fd->first_nonrect = -1;
     237       129291 :   fd->last_nonrect = -1;
     238       129291 :   fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
     239       129291 :   fd->sched_modifiers = 0;
     240       129291 :   fd->chunk_size = NULL_TREE;
     241       129291 :   fd->simd_schedule = false;
     242       129291 :   fd->first_inner_iterations = NULL_TREE;
     243       129291 :   fd->factor = NULL_TREE;
     244       129291 :   fd->adjn1 = NULL_TREE;
     245       129291 :   collapse_iter = NULL;
     246       129291 :   collapse_count = NULL;
     247              : 
     248       647742 :   for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
     249       518451 :     switch (OMP_CLAUSE_CODE (t))
     250              :       {
     251        45031 :       case OMP_CLAUSE_NOWAIT:
     252        45031 :         fd->have_nowait = true;
     253        45031 :         break;
     254         1399 :       case OMP_CLAUSE_ORDERED:
     255         1399 :         fd->have_ordered = true;
     256         1399 :         if (OMP_CLAUSE_ORDERED_DOACROSS (t))
     257              :           {
     258          700 :             if (OMP_CLAUSE_ORDERED_EXPR (t))
     259          680 :               fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
     260              :             else
     261           20 :               fd->ordered = -1;
     262              :           }
     263              :         break;
     264        30488 :       case OMP_CLAUSE_SCHEDULE:
     265        30488 :         gcc_assert (!distribute && !taskloop);
     266        30488 :         fd->sched_kind
     267        30488 :           = (enum omp_clause_schedule_kind)
     268        30488 :             (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
     269        30488 :         fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
     270        30488 :                                & ~OMP_CLAUSE_SCHEDULE_MASK);
     271        30488 :         fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
     272        30488 :         fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
     273        30488 :         break;
     274         7026 :       case OMP_CLAUSE_DIST_SCHEDULE:
     275         7026 :         gcc_assert (distribute);
     276         7026 :         fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
     277         7026 :         break;
     278        41507 :       case OMP_CLAUSE_COLLAPSE:
     279        41507 :         fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
     280        41507 :         if (fd->collapse > 1)
     281              :           {
     282        33914 :             collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
     283        33914 :             collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
     284              :           }
     285              :         break;
     286          354 :       case OMP_CLAUSE_TILE:
     287          354 :         fd->tiling = OMP_CLAUSE_TILE_LIST (t);
     288          354 :         fd->collapse = list_length (fd->tiling);
     289          354 :         gcc_assert (fd->collapse);
     290          354 :         collapse_iter = &OMP_CLAUSE_TILE_ITERVAR (t);
     291          354 :         collapse_count = &OMP_CLAUSE_TILE_COUNT (t);
     292          354 :         break;
     293          482 :       case OMP_CLAUSE__REDUCTEMP_:
     294          482 :         fd->have_reductemp = true;
     295          482 :         break;
     296        40463 :       case OMP_CLAUSE_LASTPRIVATE:
     297        40463 :         if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
     298         1480 :           fd->lastprivate_conditional++;
     299              :         break;
     300         1526 :       case OMP_CLAUSE__CONDTEMP_:
     301         1526 :         if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
     302          185 :           fd->have_pointer_condtemp = true;
     303              :         break;
     304         1126 :       case OMP_CLAUSE__SCANTEMP_:
     305         1126 :         fd->have_scantemp = true;
     306         1126 :         if (!OMP_CLAUSE__SCANTEMP__ALLOC (t)
     307         1126 :             && !OMP_CLAUSE__SCANTEMP__CONTROL (t))
     308          209 :           fd->have_nonctrl_scantemp = true;
     309              :         break;
     310         7718 :       case OMP_CLAUSE_ORDER:
     311              :         /* FIXME: For OpenMP 5.2 this should change to
     312              :            if (OMP_CLAUSE_ORDER_REPRODUCIBLE (t))
     313              :            (with the exception of loop construct but that lowers to
     314              :            no schedule/dist_schedule clauses currently).  */
     315         7718 :         if (!OMP_CLAUSE_ORDER_UNCONSTRAINED (t))
     316       518451 :           order_reproducible = true;
     317              :       default:
     318              :         break;
     319              :       }
     320              : 
     321       129291 :   if (fd->ordered == -1)
     322           20 :     fd->ordered = fd->collapse;
     323              : 
     324              :   /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
     325              :      we have either the option to expensively remember at runtime how we've
     326              :      distributed work from first loop and reuse that in following loops with
     327              :      the same number of iterations and schedule, or just force static schedule.
     328              :      OpenMP API calls etc. aren't allowed in order(concurrent) bodies so
     329              :      users can't observe it easily anyway.  */
     330       129291 :   if (order_reproducible)
     331         7423 :     fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
     332       129291 :   if (fd->collapse > 1 || fd->tiling)
     333        34264 :     fd->loops = loops;
     334              :   else
     335        95027 :     fd->loops = &fd->loop;
     336              : 
     337       129291 :   if (fd->ordered && fd->collapse == 1 && loops != NULL)
     338              :     {
     339          188 :       fd->loops = loops;
     340          188 :       iterv = NULL_TREE;
     341          188 :       countv = NULL_TREE;
     342          188 :       collapse_iter = &iterv;
     343          188 :       collapse_count = &countv;
     344              :     }
     345              : 
     346              :   /* FIXME: for now map schedule(auto) to schedule(static).
     347              :      There should be analysis to determine whether all iterations
     348              :      are approximately the same amount of work (then schedule(static)
     349              :      is best) or if it varies (then schedule(dynamic,N) is better).  */
     350       129291 :   if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
     351              :     {
     352         5747 :       fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
     353         5747 :       gcc_assert (fd->chunk_size == NULL);
     354              :     }
     355       129291 :   gcc_assert ((fd->collapse == 1 && !fd->tiling) || collapse_iter != NULL);
     356       129291 :   if (taskloop)
     357         9547 :     fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
     358       129291 :   if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
     359        16548 :     gcc_assert (fd->chunk_size == NULL);
     360       112743 :   else if (fd->chunk_size == NULL)
     361              :     {
     362              :       /* We only need to compute a default chunk size for ordered
     363              :          static loops and dynamic loops.  */
     364        89612 :       if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
     365        89030 :           || fd->have_ordered)
     366         1303 :         fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
     367         1303 :                          ? integer_zero_node : integer_one_node;
     368              :     }
     369              : 
     370       129291 :   int cnt = fd->ordered ? fd->ordered : fd->collapse;
     371       129291 :   int single_nonrect = -1;
     372       129291 :   tree single_nonrect_count = NULL_TREE;
     373       129291 :   enum tree_code single_nonrect_cond_code = ERROR_MARK;
     374       193501 :   for (i = 1; i < cnt; i++)
     375              :     {
     376        64338 :       tree n1 = gimple_omp_for_initial (for_stmt, i);
     377        64338 :       tree n2 = gimple_omp_for_final (for_stmt, i);
     378        64338 :       if (TREE_CODE (n1) == TREE_VEC)
     379              :         {
     380         1786 :           if (fd->non_rect)
     381              :             {
     382              :               single_nonrect = -1;
     383              :               break;
     384              :             }
     385         2152 :           for (int j = i - 1; j >= 0; j--)
     386         2152 :             if (TREE_VEC_ELT (n1, 0) == gimple_omp_for_index (for_stmt, j))
     387              :               {
     388              :                 single_nonrect = j;
     389              :                 break;
     390              :               }
     391         1664 :           fd->non_rect = true;
     392              :         }
     393        62552 :       else if (TREE_CODE (n2) == TREE_VEC)
     394              :         {
     395          531 :           if (fd->non_rect)
     396              :             {
     397              :               single_nonrect = -1;
     398              :               break;
     399              :             }
     400          681 :           for (int j = i - 1; j >= 0; j--)
     401          681 :             if (TREE_VEC_ELT (n2, 0) == gimple_omp_for_index (for_stmt, j))
     402              :               {
     403              :                 single_nonrect = j;
     404              :                 break;
     405              :               }
     406          525 :           fd->non_rect = true;
     407              :         }
     408              :     }
     409       323004 :   for (i = 0; i < cnt; i++)
     410              :     {
     411       193713 :       if (i == 0
     412       129291 :           && fd->collapse == 1
     413        95199 :           && !fd->tiling
     414        95027 :           && (fd->ordered == 0 || loops == NULL))
     415        94839 :         loop = &fd->loop;
     416        98686 :       else if (loops != NULL)
     417        32768 :         loop = loops + i;
     418              :       else
     419              :         loop = &dummy_loop;
     420              : 
     421       193713 :       loop->v = gimple_omp_for_index (for_stmt, i);
     422       193713 :       gcc_assert (SSA_VAR_P (loop->v));
     423       193713 :       gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
     424              :                   || TREE_CODE (TREE_TYPE (loop->v)) == BITINT_TYPE
     425              :                   || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
     426       193713 :       var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
     427       193713 :       loop->n1 = gimple_omp_for_initial (for_stmt, i);
     428       193713 :       loop->m1 = NULL_TREE;
     429       193713 :       loop->m2 = NULL_TREE;
     430       193713 :       loop->outer = 0;
     431       193713 :       loop->non_rect_referenced = false;
     432       193713 :       if (TREE_CODE (loop->n1) == TREE_VEC)
     433              :         {
     434         2313 :           for (int j = i - 1; j >= 0; j--)
     435         2313 :             if (TREE_VEC_ELT (loop->n1, 0) == gimple_omp_for_index (for_stmt, j))
     436              :               {
     437         1786 :                 loop->outer = i - j;
     438         1786 :                 if (loops != NULL)
     439          639 :                   loops[j].non_rect_referenced = true;
     440         1786 :                 if (fd->first_nonrect == -1 || fd->first_nonrect > j)
     441         1664 :                   fd->first_nonrect = j;
     442              :                 break;
     443              :               }
     444         1786 :           gcc_assert (loop->outer);
     445         1786 :           loop->m1 = TREE_VEC_ELT (loop->n1, 1);
     446         1786 :           loop->n1 = TREE_VEC_ELT (loop->n1, 2);
     447         1786 :           fd->non_rect = true;
     448         1786 :           fd->last_nonrect = i;
     449              :         }
     450              : 
     451       193713 :       loop->cond_code = gimple_omp_for_cond (for_stmt, i);
     452       193713 :       loop->n2 = gimple_omp_for_final (for_stmt, i);
     453       193713 :       gcc_assert (loop->cond_code != NE_EXPR
     454              :                   || (gimple_omp_for_kind (for_stmt)
     455              :                       != GF_OMP_FOR_KIND_OACC_LOOP));
     456       193713 :       if (TREE_CODE (loop->n2) == TREE_VEC)
     457              :         {
     458         1273 :           if (loop->outer)
     459          742 :             gcc_assert (TREE_VEC_ELT (loop->n2, 0)
     460              :                         == gimple_omp_for_index (for_stmt, i - loop->outer));
     461              :           else
     462          690 :             for (int j = i - 1; j >= 0; j--)
     463          690 :               if (TREE_VEC_ELT (loop->n2, 0) == gimple_omp_for_index (for_stmt, j))
     464              :                 {
     465          531 :                   loop->outer = i - j;
     466          531 :                   if (loops != NULL)
     467          241 :                     loops[j].non_rect_referenced = true;
     468          531 :                   if (fd->first_nonrect == -1 || fd->first_nonrect > j)
     469          525 :                     fd->first_nonrect = j;
     470              :                   break;
     471              :                 }
     472         1273 :           gcc_assert (loop->outer);
     473         1273 :           loop->m2 = TREE_VEC_ELT (loop->n2, 1);
     474         1273 :           loop->n2 = TREE_VEC_ELT (loop->n2, 2);
     475         1273 :           fd->non_rect = true;
     476         1273 :           fd->last_nonrect = i;
     477              :         }
     478              : 
     479       193713 :       t = gimple_omp_for_incr (for_stmt, i);
     480       193713 :       gcc_assert (TREE_OPERAND (t, 0) == var);
     481       193713 :       loop->step = omp_get_for_step_from_incr (loc, t);
     482              : 
     483       193713 :       omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2, loop->v,
     484              :                                 loop->step);
     485              : 
     486       193713 :       if (simd
     487       153842 :           || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
     488       114457 :               && !fd->have_ordered))
     489              :         {
     490       152607 :           if (fd->collapse == 1 && !fd->tiling)
     491        77262 :             iter_type = TREE_TYPE (loop->v);
     492        75345 :           else if (i == 0
     493        75345 :                    || TYPE_PRECISION (iter_type)
     494        48590 :                       < TYPE_PRECISION (TREE_TYPE (loop->v)))
     495              :             {
     496        37632 :               if (TREE_CODE (iter_type) == BITINT_TYPE
     497        37632 :                   || TREE_CODE (TREE_TYPE (loop->v)) == BITINT_TYPE)
     498            2 :                 iter_type
     499            2 :                   = build_bitint_type (TYPE_PRECISION (TREE_TYPE (loop->v)),
     500              :                                        1);
     501              :               else
     502        37630 :                 iter_type
     503              :                   = build_nonstandard_integer_type
     504        37630 :                         (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
     505              :             }
     506              :         }
     507        41106 :       else if (iter_type != long_long_unsigned_type_node)
     508              :         {
     509        37646 :           if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
     510              :             iter_type = long_long_unsigned_type_node;
     511        35684 :           else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
     512        35684 :                    && TYPE_PRECISION (TREE_TYPE (loop->v))
     513         6285 :                       >= TYPE_PRECISION (iter_type))
     514              :             {
     515         2319 :               tree n;
     516              : 
     517         2319 :               if (loop->cond_code == LT_EXPR)
     518          451 :                 n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
     519              :                                      loop->n2, loop->step);
     520              :               else
     521         1868 :                 n = loop->n1;
     522         2319 :               if (loop->m1
     523         2319 :                   || loop->m2
     524         2319 :                   || TREE_CODE (n) != INTEGER_CST
     525         4284 :                   || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
     526         2242 :                 iter_type = long_long_unsigned_type_node;
     527              :             }
     528        33365 :           else if (TYPE_PRECISION (TREE_TYPE (loop->v))
     529        33365 :                    > TYPE_PRECISION (iter_type))
     530              :             {
     531            0 :               tree n1, n2;
     532              : 
     533            0 :               if (loop->cond_code == LT_EXPR)
     534              :                 {
     535            0 :                   n1 = loop->n1;
     536            0 :                   n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
     537              :                                         loop->n2, loop->step);
     538              :                 }
     539              :               else
     540              :                 {
     541            0 :                   n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
     542              :                                         loop->n2, loop->step);
     543            0 :                   n2 = loop->n1;
     544              :                 }
     545            0 :               if (loop->m1
     546            0 :                   || loop->m2
     547            0 :                   || TREE_CODE (n1) != INTEGER_CST
     548            0 :                   || TREE_CODE (n2) != INTEGER_CST
     549            0 :                   || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
     550            0 :                   || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
     551            0 :                 iter_type = long_long_unsigned_type_node;
     552              :             }
     553              :         }
     554              : 
     555       193713 :       if (i >= fd->collapse)
     556         1802 :         continue;
     557              : 
     558       191911 :       if (collapse_count && *collapse_count == NULL)
     559              :         {
     560        31943 :           if (count && integer_zerop (count))
     561         2244 :             continue;
     562        29699 :           tree n1first = NULL_TREE, n2first = NULL_TREE;
     563        29699 :           tree n1last = NULL_TREE, n2last = NULL_TREE;
     564        29699 :           tree ostep = NULL_TREE;
     565        29699 :           if (loop->m1 || loop->m2)
     566              :             {
     567          911 :               if (count == NULL_TREE)
     568          645 :                 continue;
     569          266 :               if (single_nonrect == -1
     570          247 :                   || (loop->m1 && TREE_CODE (loop->m1) != INTEGER_CST)
     571          206 :                   || (loop->m2 && TREE_CODE (loop->m2) != INTEGER_CST)
     572          190 :                   || TREE_CODE (loop->n1) != INTEGER_CST
     573          186 :                   || TREE_CODE (loop->n2) != INTEGER_CST
     574          182 :                   || TREE_CODE (loop->step) != INTEGER_CST)
     575              :                 {
     576           84 :                   count = NULL_TREE;
     577           84 :                   continue;
     578              :                 }
     579          182 :               tree var = gimple_omp_for_initial (for_stmt, single_nonrect);
     580          182 :               tree itype = TREE_TYPE (var);
     581          182 :               tree first = gimple_omp_for_initial (for_stmt, single_nonrect);
     582          182 :               t = gimple_omp_for_incr (for_stmt, single_nonrect);
     583          182 :               ostep = omp_get_for_step_from_incr (loc, t);
     584          182 :               t = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
     585              :                                single_nonrect_count,
     586              :                                build_one_cst (long_long_unsigned_type_node));
     587          182 :               t = fold_convert (itype, t);
     588          182 :               first = fold_convert (itype, first);
     589          182 :               ostep = fold_convert (itype, ostep);
     590          182 :               tree last = fold_binary (PLUS_EXPR, itype, first,
     591              :                                        fold_binary (MULT_EXPR, itype, t,
     592              :                                                     ostep));
     593          182 :               if (TREE_CODE (first) != INTEGER_CST
     594          182 :                   || TREE_CODE (last) != INTEGER_CST)
     595              :                 {
     596            0 :                   count = NULL_TREE;
     597            0 :                   continue;
     598              :                 }
     599          182 :               if (loop->m1)
     600              :                 {
     601          115 :                   tree m1 = fold_convert (itype, loop->m1);
     602          115 :                   tree n1 = fold_convert (itype, loop->n1);
     603          115 :                   n1first = fold_binary (PLUS_EXPR, itype,
     604              :                                          fold_binary (MULT_EXPR, itype,
     605              :                                                       first, m1), n1);
     606          115 :                   n1last = fold_binary (PLUS_EXPR, itype,
     607              :                                         fold_binary (MULT_EXPR, itype,
     608              :                                                      last, m1), n1);
     609              :                 }
     610              :               else
     611           67 :                 n1first = n1last = loop->n1;
     612          182 :               if (loop->m2)
     613              :                 {
     614          136 :                   tree n2 = fold_convert (itype, loop->n2);
     615          136 :                   tree m2 = fold_convert (itype, loop->m2);
     616          136 :                   n2first = fold_binary (PLUS_EXPR, itype,
     617              :                                          fold_binary (MULT_EXPR, itype,
     618              :                                                       first, m2), n2);
     619          136 :                   n2last = fold_binary (PLUS_EXPR, itype,
     620              :                                         fold_binary (MULT_EXPR, itype,
     621              :                                                      last, m2), n2);
     622              :                 }
     623              :               else
     624           46 :                 n2first = n2last = loop->n2;
     625          182 :               n1first = fold_convert (TREE_TYPE (loop->v), n1first);
     626          182 :               n2first = fold_convert (TREE_TYPE (loop->v), n2first);
     627          182 :               n1last = fold_convert (TREE_TYPE (loop->v), n1last);
     628          182 :               n2last = fold_convert (TREE_TYPE (loop->v), n2last);
     629          182 :               t = fold_binary (loop->cond_code, boolean_type_node,
     630              :                                n1first, n2first);
     631          182 :               tree t2 = fold_binary (loop->cond_code, boolean_type_node,
     632              :                                      n1last, n2last);
     633          182 :               if (t && t2 && integer_nonzerop (t) && integer_nonzerop (t2))
     634              :                 /* All outer loop iterators have at least one inner loop
     635              :                    iteration.  Try to compute the count at compile time.  */
     636              :                 t = NULL_TREE;
     637          103 :               else if (t && t2 && integer_zerop (t) && integer_zerop (t2))
     638              :                 /* No iterations of the inner loop.  count will be set to
     639              :                    zero cst below.  */;
     640           95 :               else if (TYPE_UNSIGNED (itype)
     641           95 :                        || t == NULL_TREE
     642           95 :                        || t2 == NULL_TREE
     643           95 :                        || TREE_CODE (t) != INTEGER_CST
     644          190 :                        || TREE_CODE (t2) != INTEGER_CST)
     645              :                 {
     646              :                   /* Punt (for now).  */
     647            0 :                   count = NULL_TREE;
     648            0 :                   continue;
     649              :                 }
     650              :               else
     651              :                 {
     652              :                   /* Some iterations of the outer loop have zero iterations
     653              :                      of the inner loop, while others have at least one.
     654              :                      In this case, we need to adjust one of those outer
     655              :                      loop bounds.  If ADJ_FIRST, we need to adjust outer n1
     656              :                      (first), otherwise outer n2 (last).  */
     657           95 :                   bool adj_first = integer_zerop (t);
     658           95 :                   tree n1 = fold_convert (itype, loop->n1);
     659           95 :                   tree n2 = fold_convert (itype, loop->n2);
     660           95 :                   tree m1 = loop->m1 ? fold_convert (itype, loop->m1)
     661           25 :                                      : build_zero_cst (itype);
     662           95 :                   tree m2 = loop->m2 ? fold_convert (itype, loop->m2)
     663           11 :                                      : build_zero_cst (itype);
     664           95 :                   t = fold_binary (MINUS_EXPR, itype, n1, n2);
     665           95 :                   t2 = fold_binary (MINUS_EXPR, itype, m2, m1);
     666           95 :                   t = fold_binary (TRUNC_DIV_EXPR, itype, t, t2);
     667           95 :                   t2 = fold_binary (MINUS_EXPR, itype, t, first);
     668           95 :                   t2 = fold_binary (TRUNC_MOD_EXPR, itype, t2, ostep);
     669           95 :                   t = fold_binary (MINUS_EXPR, itype, t, t2);
     670           95 :                   tree n1cur
     671           95 :                     = fold_binary (PLUS_EXPR, itype, n1,
     672              :                                    fold_binary (MULT_EXPR, itype, m1, t));
     673           95 :                   tree n2cur
     674           95 :                     = fold_binary (PLUS_EXPR, itype, n2,
     675              :                                    fold_binary (MULT_EXPR, itype, m2, t));
     676           95 :                   t2 = fold_binary (loop->cond_code, boolean_type_node,
     677              :                                     n1cur, n2cur);
     678           95 :                   tree t3 = fold_binary (MULT_EXPR, itype, m1, ostep);
     679           95 :                   tree t4 = fold_binary (MULT_EXPR, itype, m2, ostep);
     680           95 :                   tree diff;
     681           95 :                   if (adj_first)
     682              :                     {
     683           67 :                       tree new_first;
     684           67 :                       if (integer_nonzerop (t2))
     685              :                         {
     686            6 :                           new_first = t;
     687            6 :                           n1first = n1cur;
     688            6 :                           n2first = n2cur;
     689            6 :                           if (flag_checking)
     690              :                             {
     691            6 :                               t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
     692            6 :                               t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
     693            6 :                               t3 = fold_binary (loop->cond_code,
     694              :                                                 boolean_type_node, t3, t4);
     695            6 :                               gcc_assert (integer_zerop (t3));
     696              :                             }
     697              :                         }
     698              :                       else
     699              :                         {
     700           61 :                           t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
     701           61 :                           t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
     702           61 :                           new_first = fold_binary (PLUS_EXPR, itype, t, ostep);
     703           61 :                           n1first = t3;
     704           61 :                           n2first = t4;
     705           61 :                           if (flag_checking)
     706              :                             {
     707           61 :                               t3 = fold_binary (loop->cond_code,
     708              :                                                 boolean_type_node, t3, t4);
     709           61 :                               gcc_assert (integer_nonzerop (t3));
     710              :                             }
     711              :                         }
     712           67 :                       diff = fold_binary (MINUS_EXPR, itype, new_first, first);
     713           67 :                       first = new_first;
     714           67 :                       fd->adjn1 = first;
     715              :                     }
     716              :                   else
     717              :                     {
     718           28 :                       tree new_last;
     719           28 :                       if (integer_zerop (t2))
     720              :                         {
     721           11 :                           t3 = fold_binary (MINUS_EXPR, itype, n1cur, t3);
     722           11 :                           t4 = fold_binary (MINUS_EXPR, itype, n2cur, t4);
     723           11 :                           new_last = fold_binary (MINUS_EXPR, itype, t, ostep);
     724           11 :                           n1last = t3;
     725           11 :                           n2last = t4;
     726           11 :                           if (flag_checking)
     727              :                             {
     728           11 :                               t3 = fold_binary (loop->cond_code,
     729              :                                                 boolean_type_node, t3, t4);
     730           11 :                               gcc_assert (integer_nonzerop (t3));
     731              :                             }
     732              :                         }
     733              :                       else
     734              :                         {
     735           17 :                           new_last = t;
     736           17 :                           n1last = n1cur;
     737           17 :                           n2last = n2cur;
     738           17 :                           if (flag_checking)
     739              :                             {
     740           17 :                               t3 = fold_binary (PLUS_EXPR, itype, n1cur, t3);
     741           17 :                               t4 = fold_binary (PLUS_EXPR, itype, n2cur, t4);
     742           17 :                               t3 = fold_binary (loop->cond_code,
     743              :                                                 boolean_type_node, t3, t4);
     744           17 :                               gcc_assert (integer_zerop (t3));
     745              :                             }
     746              :                         }
     747           28 :                       diff = fold_binary (MINUS_EXPR, itype, last, new_last);
     748              :                     }
     749           95 :                   if (TYPE_UNSIGNED (itype)
     750           95 :                       && single_nonrect_cond_code == GT_EXPR)
     751            0 :                     diff = fold_binary (TRUNC_DIV_EXPR, itype,
     752              :                                         fold_unary (NEGATE_EXPR, itype, diff),
     753              :                                         fold_unary (NEGATE_EXPR, itype,
     754              :                                                     ostep));
     755              :                   else
     756           95 :                     diff = fold_binary (TRUNC_DIV_EXPR, itype, diff, ostep);
     757           95 :                   diff = fold_convert (long_long_unsigned_type_node, diff);
     758           95 :                   single_nonrect_count
     759           95 :                     = fold_binary (MINUS_EXPR, long_long_unsigned_type_node,
     760              :                                    single_nonrect_count, diff);
     761           95 :                   t = NULL_TREE;
     762              :                 }
     763              :             }
     764              :           else
     765        28788 :             t = fold_binary (loop->cond_code, boolean_type_node,
     766              :                              fold_convert (TREE_TYPE (loop->v), loop->n1),
     767              :                              fold_convert (TREE_TYPE (loop->v), loop->n2));
     768        28891 :           if (t && integer_zerop (t))
     769         2252 :             count = build_zero_cst (long_long_unsigned_type_node);
     770        26718 :           else if ((i == 0 || count != NULL_TREE)
     771        17002 :                    && (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
     772         1202 :                        || TREE_CODE (TREE_TYPE (loop->v)) == BITINT_TYPE)
     773        15801 :                    && TREE_CONSTANT (loop->n1)
     774        11797 :                    && TREE_CONSTANT (loop->n2)
     775        37508 :                    && TREE_CODE (loop->step) == INTEGER_CST)
     776              :             {
     777        10768 :               tree itype = TREE_TYPE (loop->v);
     778              : 
     779        10768 :               if (POINTER_TYPE_P (itype))
     780            0 :                 itype = signed_type_for (itype);
     781        13136 :               t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
     782        10768 :               t = fold_build2 (PLUS_EXPR, itype,
     783              :                                fold_convert (itype, loop->step), t);
     784        10768 :               tree n1 = loop->n1;
     785        10768 :               tree n2 = loop->n2;
     786        10768 :               if (loop->m1 || loop->m2)
     787              :                 {
     788          174 :                   gcc_assert (single_nonrect != -1);
     789              :                   n1 = n1first;
     790              :                   n2 = n2first;
     791              :                 }
     792        10768 :               t = fold_build2 (PLUS_EXPR, itype, t, fold_convert (itype, n2));
     793        10768 :               t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
     794        10768 :               tree step = fold_convert_loc (loc, itype, loop->step);
     795        10768 :               if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
     796         2254 :                 t = fold_build2 (TRUNC_DIV_EXPR, itype,
     797              :                                  fold_build1 (NEGATE_EXPR, itype, t),
     798              :                                  fold_build1 (NEGATE_EXPR, itype, step));
     799              :               else
     800         8514 :                 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
     801        10768 :               tree llutype = long_long_unsigned_type_node;
     802        10768 :               t = fold_convert (llutype, t);
     803        10768 :               if (loop->m1 || loop->m2)
     804              :                 {
     805              :                   /* t is number of iterations of inner loop at either first
     806              :                      or last value of the outer iterator (the one with fewer
     807              :                      iterations).
     808              :                      Compute t2 = ((m2 - m1) * ostep) / step
     809              :                      and niters = outer_count * t
     810              :                                   + t2 * ((outer_count - 1) * outer_count / 2)
     811              :                    */
     812          174 :                   tree m1 = loop->m1 ? loop->m1 : integer_zero_node;
     813          174 :                   tree m2 = loop->m2 ? loop->m2 : integer_zero_node;
     814          174 :                   m1 = fold_convert (itype, m1);
     815          174 :                   m2 = fold_convert (itype, m2);
     816          174 :                   tree t2 = fold_build2 (MINUS_EXPR, itype, m2, m1);
     817          174 :                   t2 = fold_build2 (MULT_EXPR, itype, t2, ostep);
     818          174 :                   if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
     819            0 :                     t2 = fold_build2 (TRUNC_DIV_EXPR, itype,
     820              :                                       fold_build1 (NEGATE_EXPR, itype, t2),
     821              :                                       fold_build1 (NEGATE_EXPR, itype, step));
     822              :                   else
     823          174 :                     t2 = fold_build2 (TRUNC_DIV_EXPR, itype, t2, step);
     824          174 :                   t2 = fold_convert (llutype, t2);
     825          174 :                   fd->first_inner_iterations = t;
     826          174 :                   fd->factor = t2;
     827          174 :                   t = fold_build2 (MULT_EXPR, llutype, t,
     828              :                                    single_nonrect_count);
     829          174 :                   tree t3 = fold_build2 (MINUS_EXPR, llutype,
     830              :                                          single_nonrect_count,
     831              :                                          build_one_cst (llutype));
     832          174 :                   t3 = fold_build2 (MULT_EXPR, llutype, t3,
     833              :                                     single_nonrect_count);
     834          174 :                   t3 = fold_build2 (TRUNC_DIV_EXPR, llutype, t3,
     835              :                                     build_int_cst (llutype, 2));
     836          174 :                   t2 = fold_build2 (MULT_EXPR, llutype, t2, t3);
     837          174 :                   t = fold_build2 (PLUS_EXPR, llutype, t, t2);
     838              :                 }
     839        10768 :               if (i == single_nonrect)
     840              :                 {
     841          247 :                   if (integer_zerop (t) || TREE_CODE (t) != INTEGER_CST)
     842              :                     count = t;
     843              :                   else
     844              :                     {
     845          247 :                       single_nonrect_count = t;
     846          247 :                       single_nonrect_cond_code = loop->cond_code;
     847          247 :                       if (count == NULL_TREE)
     848          246 :                         count = build_one_cst (llutype);
     849              :                     }
     850              :                 }
     851        10521 :               else if (count != NULL_TREE)
     852         4207 :                 count = fold_build2 (MULT_EXPR, llutype, count, t);
     853              :               else
     854              :                 count = t;
     855        10768 :               if (TREE_CODE (count) != INTEGER_CST)
     856            0 :                 count = NULL_TREE;
     857              :             }
     858        15950 :           else if (count && !integer_zerop (count))
     859              :             count = NULL_TREE;
     860              :         }
     861              :     }
     862              : 
     863       129291 :   if (count
     864       129291 :       && !simd
     865         4050 :       && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
     866         3297 :           || fd->have_ordered))
     867              :     {
     868          853 :       if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
     869            0 :         iter_type = long_long_unsigned_type_node;
     870              :       else
     871          853 :         iter_type = long_integer_type_node;
     872              :     }
     873       128438 :   else if (collapse_iter && *collapse_iter != NULL)
     874        22907 :     iter_type = TREE_TYPE (*collapse_iter);
     875       129291 :   fd->iter_type = iter_type;
     876       129291 :   if (collapse_iter && *collapse_iter == NULL)
     877        11549 :     *collapse_iter = create_tmp_var (iter_type, ".iter");
     878       129291 :   if (collapse_count && *collapse_count == NULL)
     879              :     {
     880        11549 :       if (count)
     881              :         {
     882         5231 :           *collapse_count = fold_convert_loc (loc, iter_type, count);
     883         5231 :           if (fd->first_inner_iterations && fd->factor)
     884              :             {
     885          174 :               t = make_tree_vec (4);
     886          174 :               TREE_VEC_ELT (t, 0) = *collapse_count;
     887          174 :               TREE_VEC_ELT (t, 1) = fd->first_inner_iterations;
     888          174 :               TREE_VEC_ELT (t, 2) = fd->factor;
     889          174 :               TREE_VEC_ELT (t, 3) = fd->adjn1;
     890          174 :               *collapse_count = t;
     891              :             }
     892              :         }
     893              :       else
     894         6318 :         *collapse_count = create_tmp_var (iter_type, ".count");
     895              :     }
     896              : 
     897       129291 :   if (fd->collapse > 1 || fd->tiling || (fd->ordered && loops))
     898              :     {
     899        34452 :       fd->loop.v = *collapse_iter;
     900        34452 :       fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
     901        34452 :       fd->loop.n2 = *collapse_count;
     902        34452 :       if (TREE_CODE (fd->loop.n2) == TREE_VEC)
     903              :         {
     904          377 :           gcc_assert (fd->non_rect);
     905          377 :           fd->first_inner_iterations = TREE_VEC_ELT (fd->loop.n2, 1);
     906          377 :           fd->factor = TREE_VEC_ELT (fd->loop.n2, 2);
     907          377 :           fd->adjn1 = TREE_VEC_ELT (fd->loop.n2, 3);
     908          377 :           fd->loop.n2 = TREE_VEC_ELT (fd->loop.n2, 0);
     909              :         }
     910        34452 :       fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
     911        34452 :       fd->loop.m1 = NULL_TREE;
     912        34452 :       fd->loop.m2 = NULL_TREE;
     913        34452 :       fd->loop.outer = 0;
     914        34452 :       fd->loop.cond_code = LT_EXPR;
     915              :     }
     916        94623 :   else if (loops)
     917        36074 :     loops[0] = fd->loop;
     918       129291 : }
     919              : 
     920              : /* Build a call to GOMP_barrier.  */
     921              : 
     922              : gimple *
     923         4701 : omp_build_barrier (tree lhs, int kind)
     924              : {
     925         9368 :   tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
     926              :                                            : BUILT_IN_GOMP_BARRIER);
     927         4701 :   gcall *g = gimple_build_call (fndecl, 1,
     928         4701 :                                 build_int_cst (integer_type_node, kind));
     929         4701 :   if (lhs)
     930           34 :     gimple_call_set_lhs (g, lhs);
     931         4701 :   return g;
     932              : }
     933              : 
     934              : /* Find OMP_FOR resp. OMP_SIMD with non-NULL OMP_FOR_INIT.  Also, fill in pdata
     935              :    array, pdata[0] non-NULL if there is anything non-trivial in between,
     936              :    pdata[1] is address of OMP_PARALLEL in between if any, pdata[2] is address
     937              :    of OMP_FOR in between if any and pdata[3] is address of the inner
     938              :    OMP_FOR/OMP_SIMD.  */
     939              : 
     940              : tree
     941       110126 : find_combined_omp_for (tree *tp, int *walk_subtrees, void *data)
     942              : {
     943       110126 :   tree **pdata = (tree **) data;
     944       110126 :   *walk_subtrees = 0;
     945       110126 :   switch (TREE_CODE (*tp))
     946              :     {
     947        11876 :     case OMP_FOR:
     948        11876 :       if (OMP_FOR_INIT (*tp) != NULL_TREE)
     949              :         {
     950         6057 :           pdata[3] = tp;
     951         6057 :           return *tp;
     952              :         }
     953         5819 :       pdata[2] = tp;
     954         5819 :       *walk_subtrees = 1;
     955         5819 :       break;
     956        15322 :     case OMP_SIMD:
     957        15322 :       if (OMP_FOR_INIT (*tp) != NULL_TREE)
     958              :         {
     959        15322 :           pdata[3] = tp;
     960        15322 :           return *tp;
     961              :         }
     962              :       break;
     963        46745 :     case BIND_EXPR:
     964        46745 :       if (BIND_EXPR_VARS (*tp)
     965        46745 :           || (BIND_EXPR_BLOCK (*tp)
     966        41141 :               && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
     967         5149 :         pdata[0] = tp;
     968        46745 :       *walk_subtrees = 1;
     969        46745 :       break;
     970         8573 :     case STATEMENT_LIST:
     971         8573 :       if (!tsi_one_before_end_p (tsi_start (*tp)))
     972          241 :         pdata[0] = tp;
     973         8573 :       *walk_subtrees = 1;
     974         8573 :       break;
     975          216 :     case TRY_FINALLY_EXPR:
     976          216 :     case CLEANUP_POINT_EXPR:
     977          216 :       pdata[0] = tp;
     978          216 :       *walk_subtrees = 1;
     979          216 :       break;
     980        11904 :     case OMP_PARALLEL:
     981        11904 :       pdata[1] = tp;
     982        11904 :       *walk_subtrees = 1;
     983        11904 :       break;
     984              :     default:
     985              :       break;
     986              :     }
     987              :   return NULL_TREE;
     988              : }
     989              : 
     990              : /* Return maximum possible vectorization factor for the target, or for
     991              :    the OpenMP offload target if one exists.  */
     992              : 
     993              : poly_uint64
     994        33481 : omp_max_vf (bool offload)
     995              : {
     996        33481 :   if (!optimize
     997        32143 :       || optimize_debug
     998        32143 :       || !flag_tree_loop_optimize
     999        32142 :       || (!flag_tree_loop_vectorize
    1000          585 :           && OPTION_SET_P (flag_tree_loop_vectorize)))
    1001         1343 :     return 1;
    1002              : 
    1003        32138 :   if (ENABLE_OFFLOADING && offload)
    1004              :     {
    1005              :       for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
    1006              :         {
    1007              :           if (startswith (c, "amdgcn"))
    1008              :             return ordered_max (poly_uint64 (64), omp_max_vf (false));
    1009              :           else if ((c = strchr (c, ':')))
    1010              :             c++;
    1011              :         }
    1012              :       /* Otherwise, fall through to host VF.  */
    1013              :     }
    1014              : 
    1015        32138 :   auto_vector_modes modes;
    1016        32138 :   targetm.vectorize.autovectorize_vector_modes (&modes, true);
    1017        32138 :   if (!modes.is_empty ())
    1018              :     {
    1019              :       poly_uint64 vf = 0;
    1020       134018 :       for (unsigned int i = 0; i < modes.length (); ++i)
    1021              :         /* The returned modes use the smallest element size (and thus
    1022              :            the largest nunits) for the vectorization approach that they
    1023              :            represent.  */
    1024       203768 :         vf = ordered_max (vf, GET_MODE_NUNITS (modes[i]));
    1025        32134 :       return vf;
    1026              :     }
    1027              : 
    1028            4 :   machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
    1029            4 :   if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
    1030            0 :     return GET_MODE_NUNITS (vqimode);
    1031              : 
    1032            4 :   return 1;
    1033        32138 : }
    1034              : 
    1035              : /* Return maximum SIMT width if offloading may target SIMT hardware.  */
    1036              : 
    1037              : int
    1038         3641 : omp_max_simt_vf (void)
    1039              : {
    1040         3641 :   if (!optimize)
    1041              :     return 0;
    1042              :   if (ENABLE_OFFLOADING)
    1043              :     for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
    1044              :       {
    1045              :         if (startswith (c, "nvptx"))
    1046              :           return 32;
    1047              :         else if ((c = strchr (c, ':')))
    1048              :           c++;
    1049              :       }
    1050              :   return 0;
    1051              : }
    1052              : 
    1053              : /* Return true if PROP is possibly present in one of the offloading target's
    1054              :    OpenMP contexts.  The format of PROPS string is always offloading target's
    1055              :    name terminated by '\0', followed by properties for that offloading
    1056              :    target separated by '\0' and terminated by another '\0'.  The strings
    1057              :    are created from omp-device-properties installed files of all configured
    1058              :    offloading targets.  */
    1059              : 
    1060              : static bool
    1061            0 : omp_offload_device_kind_arch_isa (const char *props, const char *prop)
    1062              : {
    1063            0 :   const char *names = getenv ("OFFLOAD_TARGET_NAMES");
    1064            0 :   if (names == NULL || *names == '\0')
    1065              :     return false;
    1066            0 :   while (*props != '\0')
    1067              :     {
    1068            0 :       size_t name_len = strlen (props);
    1069            0 :       bool matches = false;
    1070            0 :       for (const char *c = names; c; )
    1071              :         {
    1072            0 :           if (strncmp (props, c, name_len) == 0
    1073            0 :               && (c[name_len] == '\0'
    1074              :                   || c[name_len] == ':'
    1075              :                   || c[name_len] == '='))
    1076              :             {
    1077              :               matches = true;
    1078              :               break;
    1079              :             }
    1080            0 :           else if ((c = strchr (c, ':')))
    1081            0 :             c++;
    1082              :         }
    1083            0 :       props = props + name_len + 1;
    1084            0 :       while (*props != '\0')
    1085              :         {
    1086            0 :           if (matches && strcmp (props, prop) == 0)
    1087              :             return true;
    1088            0 :           props = strchr (props, '\0') + 1;
    1089              :         }
    1090            0 :       props++;
    1091              :     }
    1092              :   return false;
    1093              : }
    1094              : 
    1095              : /* Return true if the current code location is or might be offloaded.
    1096              :    Return true in declare target functions, or when nested in a target
    1097              :    region or when unsure, return false otherwise.  */
    1098              : 
    1099              : static bool
    1100            0 : omp_maybe_offloaded (tree construct_context)
    1101              : {
    1102              :   /* No offload targets available?  */
    1103            0 :   if (!ENABLE_OFFLOADING)
    1104            0 :     return false;
    1105              :   const char *names = getenv ("OFFLOAD_TARGET_NAMES");
    1106              :   if (names == NULL || *names == '\0')
    1107              :     return false;
    1108              : 
    1109              :   /* Parsing is too early to tell.  */
    1110              :   if (symtab->state == PARSING)
    1111              :     /* Maybe.  */
    1112              :     return true;
    1113              : 
    1114              :   /* Late resolution of offloaded code happens in the offload compiler,
    1115              :      where it's treated as native code instead.  So return false here.  */
    1116              :   if (cfun && cfun->after_inlining)
    1117              :     return false;
    1118              : 
    1119              :   /* Check if the function is marked for offloading (either explicitly
    1120              :      or via omp_discover_implicit_declare_target).  */
    1121              :   if (current_function_decl
    1122              :       && lookup_attribute ("omp declare target",
    1123              :                            DECL_ATTRIBUTES (current_function_decl)))
    1124              :     return true;
    1125              : 
    1126              :   /* Check for nesting inside a target directive.  */
    1127              :   for (tree ts = construct_context; ts; ts = TREE_CHAIN (ts))
    1128              :     if (OMP_TS_CODE (ts) == OMP_TRAIT_CONSTRUCT_TARGET)
    1129              :       return true;
    1130              : 
    1131              :   return false;
    1132              : }
    1133              : 
    1134              : /* Lookup tables for context selectors.  */
    1135              : const char *omp_tss_map[] =
    1136              :   {
    1137              :    "construct",
    1138              :    "device",
    1139              :    "target_device",
    1140              :    "implementation",
    1141              :    "user",
    1142              :    NULL
    1143              : };
    1144              : 
    1145              : /* Arrays of property candidates must be null-terminated.  */
    1146              : static const char *const kind_properties[] =
    1147              :   { "host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
    1148              : static const char *const vendor_properties[] =
    1149              :   { "amd", "arm", "bsc", "cray", "fujitsu", "gnu", "hpe", "ibm", "intel",
    1150              :     "llvm", "nec", "nvidia", "pgi", "ti", "unknown", NULL };
    1151              : static const char *const extension_properties[] =
    1152              :   { NULL };
    1153              : static const char *const atomic_default_mem_order_properties[] =
    1154              :   { "seq_cst", "relaxed", "acq_rel", "acquire", "release", NULL };
    1155              : 
    1156              : struct omp_ts_info omp_ts_map[] =
    1157              :   {
    1158              :    { "kind",
    1159              :      (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
    1160              :      OMP_TRAIT_PROPERTY_NAME_LIST, false,
    1161              :      kind_properties
    1162              :    },
    1163              :    { "isa",
    1164              :      (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
    1165              :      OMP_TRAIT_PROPERTY_NAME_LIST, false,
    1166              :      NULL
    1167              :    },
    1168              :    { "arch",
    1169              :      (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
    1170              :      OMP_TRAIT_PROPERTY_NAME_LIST, false,
    1171              :      NULL
    1172              :    },
    1173              :    { "device_num",
    1174              :      (1 << OMP_TRAIT_SET_TARGET_DEVICE),
    1175              :      OMP_TRAIT_PROPERTY_DEV_NUM_EXPR, false,
    1176              :      NULL
    1177              :    },
    1178              :    { "vendor",
    1179              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1180              :      OMP_TRAIT_PROPERTY_NAME_LIST, true,
    1181              :      vendor_properties,
    1182              :    },
    1183              :    { "extension",
    1184              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1185              :      OMP_TRAIT_PROPERTY_NAME_LIST, true,
    1186              :      extension_properties,
    1187              :    },
    1188              :    { "atomic_default_mem_order",
    1189              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1190              :      OMP_TRAIT_PROPERTY_ID, true,
    1191              :      atomic_default_mem_order_properties,
    1192              :    },
    1193              :    { "requires",
    1194              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1195              :      OMP_TRAIT_PROPERTY_CLAUSE_LIST, true,
    1196              :      NULL
    1197              :    },
    1198              :    { "unified_address",
    1199              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1200              :      OMP_TRAIT_PROPERTY_NONE, true,
    1201              :      NULL
    1202              :    },
    1203              :    { "unified_shared_memory",
    1204              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1205              :      OMP_TRAIT_PROPERTY_NONE, true,
    1206              :      NULL
    1207              :    },
    1208              :    { "self_maps",
    1209              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1210              :      OMP_TRAIT_PROPERTY_NONE, true,
    1211              :      NULL
    1212              :    },
    1213              :    { "dynamic_allocators",
    1214              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1215              :      OMP_TRAIT_PROPERTY_NONE, true,
    1216              :      NULL
    1217              :    },
    1218              :    { "reverse_offload",
    1219              :      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
    1220              :      OMP_TRAIT_PROPERTY_NONE, true,
    1221              :      NULL
    1222              :    },
    1223              :    { "condition",
    1224              :      (1 << OMP_TRAIT_SET_USER),
    1225              :      OMP_TRAIT_PROPERTY_BOOL_EXPR, true,
    1226              :      NULL
    1227              :    },
    1228              :    { "target",
    1229              :      (1 << OMP_TRAIT_SET_CONSTRUCT),
    1230              :      OMP_TRAIT_PROPERTY_NONE, false,
    1231              :      NULL
    1232              :    },
    1233              :    { "teams",
    1234              :      (1 << OMP_TRAIT_SET_CONSTRUCT),
    1235              :      OMP_TRAIT_PROPERTY_NONE, false,
    1236              :      NULL
    1237              :    },
    1238              :    { "parallel",
    1239              :      (1 << OMP_TRAIT_SET_CONSTRUCT),
    1240              :      OMP_TRAIT_PROPERTY_NONE, false,
    1241              :      NULL
    1242              :    },
    1243              :    { "for",
    1244              :      (1 << OMP_TRAIT_SET_CONSTRUCT),
    1245              :      OMP_TRAIT_PROPERTY_NONE, false,
    1246              :      NULL
    1247              :    },
    1248              :    { "simd",
    1249              :      (1 << OMP_TRAIT_SET_CONSTRUCT),
    1250              :      OMP_TRAIT_PROPERTY_CLAUSE_LIST,  false,
    1251              :      NULL
    1252              :    },
    1253              :    { "dispatch",
    1254              :      (1 << OMP_TRAIT_SET_CONSTRUCT),
    1255              :      OMP_TRAIT_PROPERTY_NONE,  false,
    1256              :      NULL
    1257              :    },
    1258              :    { NULL, 0, OMP_TRAIT_PROPERTY_NONE, false, NULL }  /* OMP_TRAIT_LAST */
    1259              :   };
    1260              : 
    1261              : /* Return a name from PROP, a property in selectors accepting
    1262              :    name lists.  */
    1263              : 
    1264              : const char *
    1265        13748 : omp_context_name_list_prop (tree prop)
    1266              : {
    1267        13748 :   gcc_assert (OMP_TP_NAME (prop) == OMP_TP_NAMELIST_NODE);
    1268        13748 :   tree val = OMP_TP_VALUE (prop);
    1269        13748 :   switch (TREE_CODE (val))
    1270              :     {
    1271         8351 :     case IDENTIFIER_NODE:
    1272         8351 :       return IDENTIFIER_POINTER (val);
    1273         5397 :     case STRING_CST:
    1274              : #ifdef ACCEL_COMPILER
    1275              :       return TREE_STRING_POINTER (val);
    1276              : #else
    1277         5397 :       {
    1278         5397 :         const char *ret = TREE_STRING_POINTER (val);
    1279        10794 :         if ((size_t) TREE_STRING_LENGTH (val)
    1280        10318 :             == strlen (ret) + (lang_GNU_Fortran () ? 0 : 1))
    1281              :           return ret;
    1282              :         return NULL;
    1283              :       }
    1284              : #endif
    1285              :     default:
    1286              :       return NULL;
    1287              :     }
    1288              : }
    1289              : 
    1290              : 
    1291              : /* Helper function called via walk_tree, to determine if *TP is a
    1292              :    PARM_DECL.  */
    1293              : static tree
    1294         1437 : expr_uses_parm_decl (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
    1295              :                      void *data ATTRIBUTE_UNUSED)
    1296              : {
    1297         1437 :   if (TREE_CODE (*tp) == PARM_DECL)
    1298           26 :     return *tp;
    1299              :   return NULL_TREE;
    1300              : }
    1301              : 
    1302              : /* Diagnose errors in an OpenMP context selector, return CTX if
    1303              :    it is correct or error_mark_node otherwise.  */
    1304              : 
    1305              : tree
    1306         3686 : omp_check_context_selector (location_t loc, tree ctx,
    1307              :                             enum omp_ctx_directive directive)
    1308              : {
    1309         3686 :   bool tss_seen[OMP_TRAIT_SET_LAST], ts_seen[OMP_TRAIT_LAST];
    1310              : 
    1311         3686 :   memset (tss_seen, 0, sizeof (tss_seen));
    1312         7844 :   for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
    1313              :     {
    1314         4288 :       enum omp_tss_code tss_code = OMP_TSS_CODE (tss);
    1315         4288 :       bool saw_any_prop = false;
    1316         4288 :       bool saw_other_prop = false;
    1317              : 
    1318              :       /* Each trait-set-selector-name can only be specified once.  */
    1319         4288 :       if (tss_seen[tss_code])
    1320              :         {
    1321           60 :           error_at (loc, "selector set %qs specified more than once",
    1322           30 :                     OMP_TSS_NAME (tss));
    1323           30 :           return error_mark_node;
    1324              :         }
    1325              :       else
    1326         4258 :         tss_seen[tss_code] = true;
    1327              : 
    1328         4258 :       memset (ts_seen, 0, sizeof (ts_seen));
    1329         9307 :       for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
    1330              :         {
    1331         5129 :           enum omp_ts_code ts_code = OMP_TS_CODE (ts);
    1332              : 
    1333              :           /* Ignore unknown traits.  */
    1334         5129 :           if (ts_code == OMP_TRAIT_INVALID)
    1335           73 :             continue;
    1336              : 
    1337              :           /* Each trait-selector-name can only be specified once.  */
    1338         5056 :           if (ts_seen[ts_code])
    1339              :             {
    1340           15 :               error_at (loc,
    1341              :                         "selector %qs specified more than once in set %qs",
    1342           15 :                         OMP_TS_NAME (ts),
    1343           15 :                         OMP_TSS_NAME (tss));
    1344           15 :               return error_mark_node;
    1345              :             }
    1346              :           else
    1347         5041 :             ts_seen[ts_code] = true;
    1348              : 
    1349              :           /* If trait-property "any" is specified in the "kind"
    1350              :              trait-selector of the "device" selector set or the
    1351              :              "target_device" selector sets, no other trait-property
    1352              :              may be specified in the same selector set.  */
    1353         5041 :           if (ts_code == OMP_TRAIT_DEVICE_KIND)
    1354         1306 :             for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
    1355              :               {
    1356          478 :                 const char *prop = omp_context_name_list_prop (p);
    1357          478 :                 if (!prop)
    1358            4 :                   continue;
    1359          474 :                 else if (strcmp (prop, "any") == 0)
    1360              :                   saw_any_prop = true;
    1361              :                 else
    1362          399 :                   saw_other_prop = true;
    1363              :               }
    1364              :           /* It seems slightly suspicious that the spec's language covers
    1365              :              the device_num selector too, but
    1366              :                target_device={device_num(whatever),kind(any)}
    1367              :              is probably not terribly useful anyway.  */
    1368         4627 :           else if (ts_code == OMP_TRAIT_DEVICE_ARCH
    1369              :                    || ts_code == OMP_TRAIT_DEVICE_ISA
    1370         4627 :                    || ts_code == OMP_TRAIT_DEVICE_NUM)
    1371         1052 :             saw_other_prop = true;
    1372              : 
    1373              :           /* Each trait-property can only be specified once in a trait-selector
    1374              :              other than the construct selector set.  FIXME: only handles
    1375              :              name-list properties, not clause-list properties, since the
    1376              :              "requires" selector is not implemented yet (PR 113067).  */
    1377         5041 :           if (tss_code != OMP_TRAIT_SET_CONSTRUCT)
    1378         8292 :             for (tree p1 = OMP_TS_PROPERTIES (ts); p1; p1 = TREE_CHAIN (p1))
    1379              :               {
    1380         3199 :                 if (OMP_TP_NAME (p1) != OMP_TP_NAMELIST_NODE)
    1381              :                   break;
    1382         2268 :                 const char *n1 = omp_context_name_list_prop (p1);
    1383         2268 :                 if (!n1)
    1384            8 :                   continue;
    1385         2618 :                 for (tree p2 = TREE_CHAIN (p1); p2; p2 = TREE_CHAIN (p2))
    1386              :                   {
    1387          388 :                     const char *n2 = omp_context_name_list_prop (p2);
    1388          388 :                     if (!n2)
    1389            0 :                       continue;
    1390          388 :                     if (!strcmp (n1, n2))
    1391              :                       {
    1392           30 :                         error_at (loc,
    1393              :                                   "trait-property %qs specified more "
    1394              :                                   "than once in %qs selector",
    1395           30 :                                   n1, OMP_TS_NAME (ts));
    1396           30 :                         return error_mark_node;
    1397              :                       }
    1398              :                   }
    1399              :               }
    1400              : 
    1401              :           /* This restriction is documented in the spec in the section
    1402              :              for the metadirective "when" clause (7.4.1 in the 5.2 spec).  */
    1403         5011 :           if (directive == OMP_CTX_METADIRECTIVE
    1404         5011 :               && ts_code == OMP_TRAIT_CONSTRUCT_SIMD
    1405         5015 :               && OMP_TS_PROPERTIES (ts))
    1406              :             {
    1407            0 :               error_at (loc,
    1408              :                         "properties must not be specified for the %<simd%> "
    1409              :                         "selector in a %<metadirective%> context-selector");
    1410            0 :               return error_mark_node;
    1411              :             }
    1412              : 
    1413              :           /* "simd" is not allowed at all in "begin declare variant"
    1414              :              selectors.  */
    1415         5011 :           if (directive == OMP_CTX_BEGIN_DECLARE_VARIANT
    1416         5011 :               && ts_code == OMP_TRAIT_CONSTRUCT_SIMD)
    1417              :             {
    1418            4 :               error_at (loc,
    1419              :                         "the %<simd%> selector is not permitted in a "
    1420              :                         "%<begin declare variant%> context selector");
    1421            4 :               return error_mark_node;
    1422              :             }
    1423              : 
    1424              :           /* Reject expressions that reference parameter variables in
    1425              :              "declare variant", as this is not yet implemented.  FIXME;
    1426              :              see PR middle-end/113904.  */
    1427         5007 :           if (directive != OMP_CTX_METADIRECTIVE
    1428         4135 :               && (ts_code == OMP_TRAIT_DEVICE_NUM
    1429         4135 :                   || ts_code == OMP_TRAIT_USER_CONDITION))
    1430              :             {
    1431          552 :               tree exp = OMP_TS_PROPERTIES (ts);
    1432          552 :               if (walk_tree (&exp, expr_uses_parm_decl, NULL, NULL))
    1433              :                 {
    1434           26 :                   sorry_at (loc,
    1435              :                             "reference to function parameter in "
    1436              :                             "%<declare variant%> dynamic selector expression");
    1437           26 :                   return error_mark_node;
    1438              :                 }
    1439              :             }
    1440              : 
    1441              :           /* Check for unknown properties.  */
    1442         4981 :           if (omp_ts_map[ts_code].valid_properties == NULL)
    1443         3799 :             continue;
    1444         3630 :           for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
    1445         4959 :             for (unsigned j = 0; ; j++)
    1446              :               {
    1447         6230 :                 const char *candidate
    1448         6230 :                   = omp_ts_map[ts_code].valid_properties[j];
    1449         6230 :                 if (candidate == NULL)
    1450              :                   {
    1451              :                     /* We've reached the end of the candidate array.  */
    1452           83 :                     if (ts_code == OMP_TRAIT_IMPLEMENTATION_ADMO)
    1453              :                       /* FIXME: not sure why this is an error vs warnings
    1454              :                          for the others, + incorrect/unknown wording?  */
    1455              :                       {
    1456            5 :                         error_at (loc,
    1457              :                                   "incorrect property %qs of %qs selector",
    1458            5 :                                   IDENTIFIER_POINTER (OMP_TP_NAME (p)),
    1459              :                                   "atomic_default_mem_order");
    1460            5 :                         return error_mark_node;
    1461              :                       }
    1462           78 :                     if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE
    1463           78 :                         && (TREE_CODE (OMP_TP_VALUE (p)) == STRING_CST))
    1464           46 :                       warning_at (loc, OPT_Wopenmp,
    1465              :                                   "unknown property %qE of %qs selector",
    1466           23 :                                   OMP_TP_VALUE (p),
    1467           23 :                                   OMP_TS_NAME (ts));
    1468           55 :                     else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
    1469          110 :                       warning_at (loc, OPT_Wopenmp,
    1470              :                                   "unknown property %qs of %qs selector",
    1471              :                                   omp_context_name_list_prop (p),
    1472           55 :                                   OMP_TS_NAME (ts));
    1473            0 :                     else if (OMP_TP_NAME (p))
    1474            0 :                       warning_at (loc, OPT_Wopenmp,
    1475              :                                   "unknown property %qs of %qs selector",
    1476            0 :                                   IDENTIFIER_POINTER (OMP_TP_NAME (p)),
    1477            0 :                                   OMP_TS_NAME (ts));
    1478              :                     break;
    1479              :                   }
    1480         6147 :                 else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
    1481              :                   /* Property-list traits.  */
    1482              :                   {
    1483         5899 :                     const char *str = omp_context_name_list_prop (p);
    1484         5899 :                     if (str && !strcmp (str, candidate))
    1485              :                       break;
    1486              :                   }
    1487          248 :                 else if (!strcmp (IDENTIFIER_POINTER (OMP_TP_NAME (p)),
    1488              :                                   candidate))
    1489              :                   /* Identifier traits.  */
    1490              :                   break;
    1491         4959 :               }
    1492              :         }
    1493              : 
    1494         4178 :       if (saw_any_prop && saw_other_prop)
    1495              :         {
    1496           20 :           error_at (loc,
    1497              :                     "no other trait-property may be specified "
    1498              :                     "in the same selector set with %<kind(\"any\")%>");
    1499           20 :           return error_mark_node;
    1500              :         }
    1501              :     }
    1502              :   return ctx;
    1503              : }
    1504              : 
    1505              : /* Produce a mangled version of BASE_ID for the name of the variant
    1506              :    function with context selector CTX.  SEP is a separator string.
    1507              :    The return value is an IDENTIFIER_NODE.
    1508              : 
    1509              :    Per the OpenMP spec, "the symbol names of two definitions of a function are
    1510              :    considered to be equal if and only if their effective context selectors are
    1511              :    equivalent".  However, if we did have two such definitions, we'd get an ODR
    1512              :    violation.  We already take steps in the front ends to make variant
    1513              :    functions internal to the compilation unit, since there is no (portable) way
    1514              :    to reference them directly by name or declare them as extern in another
    1515              :    compilation unit.  So, we can diagnose the would-be ODR violations by
    1516              :    checking that there is not already a variant for the same function with an
    1517              :    equivalent context selector, and otherwise just use a simple counter to name
    1518              :    the variant functions instead of any complicated scheme to encode the
    1519              :    context selector in the name.
    1520              : 
    1521              :    C++ and Fortran modules are an exception to this, as variants in a module
    1522              :    interface unit are visible to implementation TUs for that module.  This
    1523              :    is handled in the C++ front end by adding an additional prefix to SEP for
    1524              :    variants in a module interface to prevent collisions with names in the
    1525              :    other TUs.  The Fortran and C++ front ends add the module name to the
    1526              :    output of this function using their normal mechanisms for symbols with
    1527              :    module linkage.  */
    1528              : tree
    1529          308 : omp_mangle_variant_name (tree base_id, tree ctx ATTRIBUTE_UNUSED,
    1530              :                          const char *sep)
    1531              : {
    1532          308 :   const char *base_name = IDENTIFIER_POINTER (base_id);
    1533              : 
    1534              :   /* Now do the actual mangling.  */
    1535          308 :   static int variant_counter;
    1536              :   /* The numeric suffix and terminating byte ought to need way less than
    1537              :      32 bytes extra, that's just a magic number.  */
    1538          308 :   size_t buflen = (strlen (base_name) + strlen (sep) + strlen ("ompvariant")
    1539              :                    + 32);
    1540          308 :   char *buffer = (char *) alloca (buflen);
    1541          308 :   buflen = snprintf (buffer, buflen, "%s%sompvariant%d", base_name, sep,
    1542              :                      ++variant_counter);
    1543          308 :   return get_identifier_with_length (buffer, buflen);
    1544              : }
    1545              : 
    1546              : /* Forward declaration.  */
    1547              : static int omp_context_selector_compare (tree ctx1, tree ctx2);
    1548              : 
    1549              : /* Diagnose an error if there is already a variant with CTX registered
    1550              :    for BASE_DECL.  Returns true if OK, false otherwise.  */
    1551              : bool
    1552          233 : omp_check_for_duplicate_variant (location_t loc, tree base_decl, tree ctx)
    1553              : {
    1554          262 :   for (tree attr = DECL_ATTRIBUTES (base_decl); attr; attr = TREE_CHAIN (attr))
    1555              :     {
    1556           33 :       attr = lookup_attribute ("omp declare variant base", attr);
    1557           33 :       if (attr == NULL_TREE)
    1558              :         break;
    1559              : 
    1560           33 :       tree selector = TREE_VALUE (TREE_VALUE (attr));
    1561           33 :       if (omp_context_selector_compare (ctx, selector) == 0)
    1562              :         {
    1563            4 :           error_at (loc,
    1564              :                     "multiple definitions of variants with the same "
    1565              :                     "context selector violate the one-definition rule");
    1566            4 :           inform (DECL_SOURCE_LOCATION (TREE_PURPOSE (TREE_VALUE (attr))),
    1567              :                   "previous variant declaration here");
    1568            4 :           return false;
    1569              :         }
    1570              :     }
    1571              :   return true;
    1572              : }
    1573              : 
    1574              : /* Forward declarations.  */
    1575              : static int omp_context_selector_set_compare (enum omp_tss_code, tree, tree);
    1576              : static int omp_construct_simd_compare (tree, tree, bool);
    1577              : 
    1578              : /* Register VARIANT as variant of some base function marked with
    1579              :    #pragma omp declare variant.  CONSTRUCT is corresponding list of
    1580              :    trait-selectors for the construct selector set.  This is stashed as the
    1581              :    value of the "omp declare variant variant" attribute on VARIANT.  */
    1582              : void
    1583         2642 : omp_mark_declare_variant (location_t loc, tree variant, tree construct)
    1584              : {
    1585              :   /* Ignore this variant if it contains unknown construct selectors.
    1586              :      It will never match, and the front ends have already issued a warning
    1587              :      about it.  */
    1588         4246 :   for (tree c = construct; c; c = TREE_CHAIN (c))
    1589         1660 :     if (OMP_TS_CODE (c) == OMP_TRAIT_INVALID)
    1590              :       return;
    1591              : 
    1592         2586 :   tree attr = lookup_attribute ("omp declare variant variant",
    1593         2586 :                                 DECL_ATTRIBUTES (variant));
    1594         2586 :   if (attr == NULL_TREE)
    1595              :     {
    1596         1882 :       attr = tree_cons (get_identifier ("omp declare variant variant"),
    1597              :                         unshare_expr (construct),
    1598         1882 :                         DECL_ATTRIBUTES (variant));
    1599         1882 :       DECL_ATTRIBUTES (variant) = attr;
    1600         1882 :       return;
    1601              :     }
    1602          704 :   if ((TREE_VALUE (attr) != NULL_TREE) != (construct != NULL_TREE)
    1603          704 :       || (construct != NULL_TREE
    1604          154 :           && omp_context_selector_set_compare (OMP_TRAIT_SET_CONSTRUCT,
    1605          154 :                                                TREE_VALUE (attr),
    1606              :                                                construct)))
    1607           53 :     error_at (loc, "%qD used as a variant with incompatible %<construct%> "
    1608              :                    "selector sets", variant);
    1609              : }
    1610              : 
    1611              : 
    1612              : /* Constructors for context selectors.  */
    1613              : 
    1614              : tree
    1615         4363 : make_trait_set_selector (enum omp_tss_code code, tree selectors, tree chain)
    1616              : {
    1617         4363 :   return tree_cons (build_int_cst (integer_type_node, code),
    1618         4363 :                     selectors, chain);
    1619              : }
    1620              : 
    1621              : tree
    1622         7701 : make_trait_selector (enum omp_ts_code code, tree score, tree properties,
    1623              :                      tree chain)
    1624              : {
    1625         7701 :   if (score == NULL_TREE)
    1626         7260 :     return tree_cons (build_int_cst (integer_type_node, code),
    1627              :                       properties, chain);
    1628              :   else
    1629          441 :     return tree_cons (build_int_cst (integer_type_node, code),
    1630              :                       tree_cons (OMP_TS_SCORE_NODE, score, properties),
    1631              :                       chain);
    1632              : }
    1633              : 
    1634              : tree
    1635         3318 : make_trait_property (tree name, tree value, tree chain)
    1636              : {
    1637         3318 :   return tree_cons (name, value, chain);
    1638              : }
    1639              : 
    1640              : /* Constructor for metadirective variants.  */
    1641              : tree
    1642          904 : make_omp_metadirective_variant (tree selector, tree directive, tree body)
    1643              : {
    1644          904 :   return build_tree_list (selector, build_tree_list (directive, body));
    1645              : }
    1646              : 
    1647              : /* If the construct selector traits SELECTOR_TRAITS match the corresponding
    1648              :    OpenMP context traits CONTEXT_TRAITS, return true and set *SCORE to the
    1649              :    corresponding score if it is non-null.  */
    1650              : static bool
    1651         4699 : omp_construct_traits_match (tree selector_traits, tree context_traits,
    1652              :                             score_wide_int *score)
    1653              : {
    1654         4699 :   int slength = list_length (selector_traits);
    1655         4699 :   int clength = list_length (context_traits);
    1656              : 
    1657              :   /* Trivial failure: the selector has more traits than the OpenMP context.  */
    1658         4699 :   if (slength > clength)
    1659              :     return false;
    1660              : 
    1661              :   /* There's only one trait in the selector and it doesn't have any properties
    1662              :      to match.  */
    1663         8072 :   if (slength == 1 && !OMP_TS_PROPERTIES (selector_traits))
    1664              :     {
    1665         3786 :       int p = 0, i = 1;
    1666         3786 :       enum omp_ts_code code = OMP_TS_CODE (selector_traits);
    1667         7868 :       for (tree t = context_traits; t; t = TREE_CHAIN (t), i++)
    1668         4082 :         if (OMP_TS_CODE (t) == code)
    1669         3819 :           p = i;
    1670         3786 :       if (p != 0)
    1671              :         {
    1672         3759 :           if (score)
    1673         1317 :             *score = wi::shifted_mask <score_wide_int> (p - 1, 1, false);
    1674         3759 :           return true;
    1675              :         }
    1676              :       else
    1677              :         return false;
    1678              :     }
    1679              : 
    1680              :   /* Now handle the more general cases.
    1681              :      Both lists of traits are ordered from outside in, corresponding to
    1682              :      the c1, ..., cN numbering for the OpenMP context specified in
    1683              :      in section 7.1 of the OpenMP 5.2 spec.  Section 7.3 of the spec says
    1684              :      "if the traits that correspond to the construct selector set appear
    1685              :      multiple times in the OpenMP context, the highest valued subset of
    1686              :      context traits that contains all trait selectors in the same order
    1687              :      are used".  This means that we want to start the search for a match
    1688              :      from the end of the list, rather than the beginning.  To facilitate
    1689              :      that, transfer the lists to temporary arrays to allow random access
    1690              :      to the elements (their order remains outside in).  */
    1691          492 :   int i, j;
    1692          492 :   tree s, c;
    1693              : 
    1694          492 :   tree *sarray = (tree *) alloca (slength * sizeof (tree));
    1695         1574 :   for (s = selector_traits, i = 0; s; s = TREE_CHAIN (s), i++)
    1696         1082 :     sarray[i] = s;
    1697              : 
    1698          492 :   tree *carray = (tree *) alloca (clength * sizeof (tree));
    1699         1785 :   for (c = context_traits, j = 0; c; c = TREE_CHAIN (c), j++)
    1700         1293 :     carray[j] = c;
    1701              : 
    1702              :   /* The variable "i" indexes the selector, "j" indexes the OpenMP context.
    1703              :      Find the "j" corresponding to each sarray[i].  Note that the spec uses
    1704              :      "p" as the 1-based position, but "j" is zero-based, e.g. equal to
    1705              :      p - 1.  */
    1706          492 :   score_wide_int result = 0;
    1707          492 :   j = clength - 1;
    1708         1452 :   for (i = slength - 1; i >= 0; i--)
    1709              :     {
    1710         1029 :       enum omp_ts_code code = OMP_TS_CODE (sarray[i]);
    1711         1029 :       tree props = OMP_TS_PROPERTIES (sarray[i]);
    1712         1287 :       for (; j >= 0; j--)
    1713              :         {
    1714         1218 :           if (OMP_TS_CODE (carray[j]) != code)
    1715          218 :             continue;
    1716         1040 :           if (code == OMP_TRAIT_CONSTRUCT_SIMD
    1717         1000 :               && props
    1718         1040 :               && omp_construct_simd_compare (props,
    1719           40 :                                              OMP_TS_PROPERTIES (carray[j]),
    1720              :                                              true) > 0)
    1721           40 :             continue;
    1722              :           break;
    1723              :         }
    1724              :       /* If j >= 0, we have a match for this trait at position j.  */
    1725          960 :       if (j < 0)
    1726              :         return false;
    1727          960 :       result += wi::shifted_mask <score_wide_int> (j, 1, false);
    1728          960 :       j--;
    1729              :     }
    1730          423 :   if (score)
    1731          141 :     *score = result;
    1732              :   return true;
    1733              : }
    1734              : 
    1735              : /* Return 1 if context selector CTX matches the current OpenMP context, 0
    1736              :    if it does not and -1 if it is unknown and need to be determined later.
    1737              :    Some properties can be checked right away during parsing, others need
    1738              :    to wait until the whole TU is parsed, others need to wait until
    1739              :    IPA, others until vectorization.
    1740              : 
    1741              :    CONSTRUCT_CONTEXT is a list of construct traits from the OpenMP context,
    1742              :    which must be collected by omp_get_construct_context during
    1743              :    gimplification.  It is ignored (and may be null) if this function is
    1744              :    called during parsing.  Otherwise COMPLETE_P should indicate whether
    1745              :    CONSTRUCT_CONTEXT is known to be complete and not missing constructs
    1746              :    filled in later during compilation.
    1747              : 
    1748              :    If DECLARE_VARIANT_ELISION_P is true, the function implements the test
    1749              :    for elision of preprocessed code in "begin declare variant" constructs,
    1750              :    and returns 0 only for failure to match traits in the device and
    1751              :    implementation sets.
    1752              : 
    1753              :    Dynamic properties (which are evaluated at run-time) should always
    1754              :    return 1.  */
    1755              : 
    1756              : int
    1757        10745 : omp_context_selector_matches (tree ctx,
    1758              :                               tree construct_context,
    1759              :                               bool complete_p,
    1760              :                               bool declare_variant_elision_p)
    1761              : {
    1762        10745 :   int ret = 1;
    1763        10745 :   bool maybe_offloaded = omp_maybe_offloaded (construct_context);
    1764              : 
    1765        20542 :   for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
    1766              :     {
    1767        11536 :       enum omp_tss_code set = OMP_TSS_CODE (tss);
    1768        11536 :       tree selectors = OMP_TSS_TRAIT_SELECTORS (tss);
    1769              : 
    1770              :       /* Immediately reject the match if there are any ignored
    1771              :          selectors present.  */
    1772        11536 :       if (!declare_variant_elision_p
    1773        11536 :           || set == OMP_TRAIT_SET_DEVICE
    1774          369 :           || set == OMP_TRAIT_SET_IMPLEMENTATION)
    1775        24776 :         for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
    1776        13387 :           if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
    1777              :             return 0;
    1778              : 
    1779        11468 :       if (set == OMP_TRAIT_SET_CONSTRUCT)
    1780              :         {
    1781              :           /* We cannot resolve the construct selector during parsing because
    1782              :              the OpenMP context (and CONSTRUCT_CONTEXT) isn't available
    1783              :              until gimplification.  */
    1784         4794 :           if (symtab->state == PARSING)
    1785              :             {
    1786         1557 :               ret = -1;
    1787         1557 :               continue;
    1788              :             }
    1789              : 
    1790         3237 :           gcc_assert (selectors);
    1791              : 
    1792              :           /* During gimplification, CONSTRUCT_CONTEXT is partial, and doesn't
    1793              :              include a construct for "declare simd" that may be added
    1794              :              when there is not an enclosing "target" construct.  We might
    1795              :              be able to find a positive match against the partial context
    1796              :              (although we cannot yet score it accurately), but if we can't,
    1797              :              treat it as unknown instead of no match.  */
    1798         3237 :           if (!omp_construct_traits_match (selectors, construct_context, NULL))
    1799              :             {
    1800              :               /* If we've got a complete context, it's definitely a failed
    1801              :                  match.  */
    1802          513 :               if (complete_p)
    1803              :                 return 0;
    1804              : 
    1805              :               /* If the selector doesn't include simd, then we don't have
    1806              :                  to worry about whether "declare simd" would cause it to
    1807              :                  match; so this is also a definite failure.  */
    1808            8 :               bool have_simd = false;
    1809            8 :               for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
    1810            8 :                 if (OMP_TS_CODE (ts) == OMP_TRAIT_CONSTRUCT_SIMD)
    1811              :                   {
    1812              :                     have_simd = true;
    1813              :                     break;
    1814              :                   }
    1815            8 :               if (!have_simd)
    1816              :                 return 0;
    1817              :               else
    1818              :                 ret = -1;
    1819              :             }
    1820         2732 :           continue;
    1821         2732 :         }
    1822         6674 :       else if (set == OMP_TRAIT_SET_TARGET_DEVICE)
    1823              :         /* The target_device set is dynamic, so treat it as always
    1824              :            resolvable.  However, the current implementation doesn't
    1825              :            support it in a target region, so diagnose that as an error.
    1826              :            FIXME: maybe make this a warning and return 0 instead?  */
    1827              :         {
    1828          489 :           for (tree ts = construct_context; ts; ts = TREE_CHAIN (ts))
    1829            0 :             if (OMP_TS_CODE (ts) == OMP_TRAIT_CONSTRUCT_TARGET)
    1830            0 :               sorry ("%<target_device%> selector set inside of %<target%> "
    1831              :                      "directive");
    1832          489 :           continue;
    1833          489 :         }
    1834              : 
    1835        11499 :       for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
    1836              :         {
    1837         6480 :           enum omp_ts_code sel = OMP_TS_CODE (ts);
    1838         6480 :           switch (sel)
    1839              :             {
    1840         1591 :             case OMP_TRAIT_IMPLEMENTATION_VENDOR:
    1841         1591 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1842         4618 :               for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
    1843              :                 {
    1844         1606 :                   const char *prop = omp_context_name_list_prop (p);
    1845         1606 :                   if (prop == NULL)
    1846              :                     return 0;
    1847         1602 :                   if (!strcmp (prop, "gnu"))
    1848         1436 :                     continue;
    1849              :                   return 0;
    1850              :                 }
    1851              :               break;
    1852           30 :             case OMP_TRAIT_IMPLEMENTATION_EXTENSION:
    1853           30 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1854              :               /* We don't support any extensions right now.  */
    1855              :               return 0;
    1856          163 :               break;
    1857          163 :             case OMP_TRAIT_IMPLEMENTATION_ADMO:
    1858          163 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1859          163 :               if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    1860              :                 break;
    1861              : 
    1862          163 :               {
    1863          163 :                 enum omp_memory_order omo
    1864              :                   = ((enum omp_memory_order)
    1865          163 :                      (omp_requires_mask
    1866              :                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER));
    1867          163 :                 if (omo == OMP_MEMORY_ORDER_UNSPECIFIED)
    1868              :                   {
    1869              :                     /* We don't know yet, until end of TU.  */
    1870           72 :                     if (symtab->state == PARSING)
    1871              :                       {
    1872              :                         ret = -1;
    1873              :                         break;
    1874              :                       }
    1875              :                     else
    1876              :                       omo = OMP_MEMORY_ORDER_RELAXED;
    1877              :                   }
    1878           91 :                 tree p = OMP_TS_PROPERTIES (ts);
    1879           91 :                 const char *prop = IDENTIFIER_POINTER (OMP_TP_NAME (p));
    1880           91 :                 if (!strcmp (prop, "relaxed")
    1881            5 :                     && omo != OMP_MEMORY_ORDER_RELAXED)
    1882              :                   return 0;
    1883           86 :                 else if (!strcmp (prop, "seq_cst")
    1884           86 :                          && omo != OMP_MEMORY_ORDER_SEQ_CST)
    1885              :                   return 0;
    1886           86 :                 else if (!strcmp (prop, "acq_rel")
    1887            0 :                          && omo != OMP_MEMORY_ORDER_ACQ_REL)
    1888              :                   return 0;
    1889           86 :                 else if (!strcmp (prop, "acquire")
    1890            0 :                          && omo != OMP_MEMORY_ORDER_ACQUIRE)
    1891              :                   return 0;
    1892           86 :                 else if (!strcmp (prop, "release")
    1893            0 :                          && omo != OMP_MEMORY_ORDER_RELEASE)
    1894              :                   return 0;
    1895              :               }
    1896              :               break;
    1897          734 :             case OMP_TRAIT_DEVICE_ARCH:
    1898          734 :               gcc_assert (set == OMP_TRAIT_SET_DEVICE);
    1899         1655 :               for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
    1900              :                 {
    1901          739 :                   const char *arch = omp_context_name_list_prop (p);
    1902          739 :                   if (arch == NULL)
    1903              :                     return 0;
    1904          739 :                   int r = 0;
    1905          739 :                   if (targetm.omp.device_kind_arch_isa != NULL)
    1906          739 :                     r = targetm.omp.device_kind_arch_isa (omp_device_arch,
    1907              :                                                           arch);
    1908          739 :                   if (r == 0 || (r == -1 && symtab->state != PARSING))
    1909              :                     {
    1910              :                       /* If we are or might be in a target region or
    1911              :                          declare target function, need to take into account
    1912              :                          also offloading values.
    1913              :                          Note that maybe_offloaded is always false in late
    1914              :                          resolution; that's handled as native code (the
    1915              :                          above case) in the offload compiler instead.  */
    1916          552 :                       if (!maybe_offloaded)
    1917          552 :                         return 0;
    1918              :                       if (ENABLE_OFFLOADING)
    1919              :                         {
    1920              :                           const char *arches = omp_offload_device_arch;
    1921              :                           if (omp_offload_device_kind_arch_isa (arches, arch))
    1922              :                             {
    1923              :                               ret = -1;
    1924              :                               continue;
    1925              :                             }
    1926              :                         }
    1927              :                       return 0;
    1928              :                     }
    1929              :                   else if (r == -1)
    1930              :                     ret = -1;
    1931              :                   /* If arch matches on the host, it still might not match
    1932              :                      in the offloading region.  */
    1933              :                   else if (maybe_offloaded)
    1934              :                     ret = -1;
    1935              :                 }
    1936              :               break;
    1937           20 :             case OMP_TRAIT_IMPLEMENTATION_UNIFIED_ADDRESS:
    1938           20 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1939           20 :               if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    1940              :                 break;
    1941              : 
    1942           20 :               if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
    1943              :                 {
    1944           20 :                   if (symtab->state == PARSING)
    1945              :                     ret = -1;
    1946              :                   else
    1947              :                     return 0;
    1948              :                 }
    1949              :               break;
    1950           15 :             case OMP_TRAIT_IMPLEMENTATION_UNIFIED_SHARED_MEMORY:
    1951           15 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1952           15 :               if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    1953              :                 break;
    1954              : 
    1955           15 :               if ((omp_requires_mask
    1956              :                    & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
    1957              :                 {
    1958           15 :                   if (symtab->state == PARSING)
    1959              :                     ret = -1;
    1960              :                   else
    1961              :                     return 0;
    1962              :                 }
    1963              :               break;
    1964            5 :             case OMP_TRAIT_IMPLEMENTATION_SELF_MAPS:
    1965            5 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1966            5 :               if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    1967              :                 break;
    1968              : 
    1969            5 :               if ((omp_requires_mask & OMP_REQUIRES_SELF_MAPS) == 0)
    1970              :                 {
    1971            5 :                   if (symtab->state == PARSING)
    1972              :                     ret = -1;
    1973              :                   else
    1974              :                     return 0;
    1975              :                 }
    1976              :               break;
    1977           10 :             case OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS:
    1978           10 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1979           10 :               if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    1980              :                 break;
    1981              : 
    1982           10 :               if ((omp_requires_mask
    1983              :                    & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
    1984              :                 {
    1985           10 :                   if (symtab->state == PARSING)
    1986              :                     ret = -1;
    1987              :                   else
    1988              :                     return 0;
    1989              :                 }
    1990              :               break;
    1991           10 :             case OMP_TRAIT_IMPLEMENTATION_REVERSE_OFFLOAD:
    1992           10 :               gcc_assert (set == OMP_TRAIT_SET_IMPLEMENTATION);
    1993           10 :               if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    1994              :                 break;
    1995              : 
    1996           10 :               if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
    1997              :                 {
    1998           10 :                   if (symtab->state == PARSING)
    1999              :                     ret = -1;
    2000              :                   else
    2001              :                     return 0;
    2002              :                 }
    2003              :               break;
    2004          714 :             case OMP_TRAIT_DEVICE_KIND:
    2005          714 :               gcc_assert (set == OMP_TRAIT_SET_DEVICE);
    2006         2084 :               for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
    2007              :                 {
    2008          738 :                   const char *prop = omp_context_name_list_prop (p);
    2009          738 :                   if (prop == NULL)
    2010              :                     return 0;
    2011          734 :                   if (!strcmp (prop, "any"))
    2012           42 :                     continue;
    2013          692 :                   if (!strcmp (prop, "host"))
    2014              :                     {
    2015              : #ifdef ACCEL_COMPILER
    2016              :                       return 0;
    2017              : #else
    2018          345 :                       if (maybe_offloaded)
    2019              :                         ret = -1;
    2020          345 :                       continue;
    2021              : #endif
    2022              :                     }
    2023          347 :                   if (!strcmp (prop, "nohost"))
    2024              :                     {
    2025              : #ifndef ACCEL_COMPILER
    2026              :                       if (maybe_offloaded)
    2027              :                         ret = -1;
    2028              :                       else
    2029              :                         return 0;
    2030              : #endif
    2031              :                       continue;
    2032              :                     }
    2033              : 
    2034          319 :                   int r = 0;
    2035          319 :                   if (targetm.omp.device_kind_arch_isa != NULL)
    2036          319 :                     r = targetm.omp.device_kind_arch_isa (omp_device_kind,
    2037              :                                                           prop);
    2038              :                   else
    2039              : #ifndef ACCEL_COMPILER
    2040            0 :                     r = strcmp (prop, "cpu") == 0;
    2041              : #else
    2042              :                     gcc_unreachable ();
    2043              : #endif
    2044          319 :                     if (r == 0 || (r == -1 && symtab->state != PARSING))
    2045              :                     {
    2046              :                       /* If we are or might be in a target region or
    2047              :                          declare target function, need to take into account
    2048              :                          also offloading values.
    2049              :                          Note that maybe_offloaded is always false in late
    2050              :                          resolution; that's handled as native code (the
    2051              :                          above case) in the offload compiler instead.  */
    2052              :                       if (!maybe_offloaded)
    2053              :                         return 0;
    2054              :                       if (ENABLE_OFFLOADING)
    2055              :                         {
    2056              :                           const char *kinds = omp_offload_device_kind;
    2057              :                           if (omp_offload_device_kind_arch_isa (kinds, prop))
    2058              :                             {
    2059              :                               ret = -1;
    2060              :                               continue;
    2061              :                             }
    2062              :                         }
    2063              :                       return 0;
    2064              :                     }
    2065              :                   else if (r == -1)
    2066              :                     ret = -1;
    2067              :                   /* If kind matches on the host, it still might not match
    2068              :                      in the offloading region.  */
    2069              :                   else if (maybe_offloaded)
    2070              :                     ret = -1;
    2071              :                 }
    2072              :               break;
    2073          543 :             case OMP_TRAIT_DEVICE_ISA:
    2074          543 :               gcc_assert (set == OMP_TRAIT_SET_DEVICE);
    2075         1732 :               for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
    2076              :                 {
    2077          801 :                   const char *isa = omp_context_name_list_prop (p);
    2078          801 :                   if (isa == NULL)
    2079              :                     return 0;
    2080          801 :                   int r = 0;
    2081          801 :                   if (targetm.omp.device_kind_arch_isa != NULL)
    2082          801 :                     r = targetm.omp.device_kind_arch_isa (omp_device_isa,
    2083              :                                                           isa);
    2084          801 :                   if (r == 0 || (r == -1 && symtab->state != PARSING))
    2085              :                     {
    2086              :                       /* If isa is valid on the target, but not in the
    2087              :                          current function and current function has
    2088              :                          #pragma omp declare simd on it, some simd clones
    2089              :                          might have the isa added later on.  */
    2090          139 :                       if (r == -1
    2091          139 :                           && targetm.simd_clone.compute_vecsize_and_simdlen
    2092          139 :                           && (cfun == NULL || !cfun->after_inlining))
    2093              :                         {
    2094           55 :                           tree attrs
    2095           55 :                             = DECL_ATTRIBUTES (current_function_decl);
    2096           55 :                           if (lookup_attribute ("omp declare simd", attrs))
    2097              :                             {
    2098           34 :                               ret = -1;
    2099           34 :                               continue;
    2100              :                             }
    2101              :                         }
    2102              :                       /* If we are or might be in a target region or
    2103              :                          declare target function, need to take into account
    2104              :                          also offloading values.
    2105              :                          Note that maybe_offloaded is always false in late
    2106              :                          resolution; that's handled as native code (the
    2107              :                          above case) in the offload compiler instead.  */
    2108          155 :                       if (!maybe_offloaded)
    2109          155 :                         return 0;
    2110              :                       if (ENABLE_OFFLOADING)
    2111              :                         {
    2112              :                           const char *isas = omp_offload_device_isa;
    2113              :                           if (omp_offload_device_kind_arch_isa (isas, isa))
    2114              :                             {
    2115              :                               ret = -1;
    2116              :                               continue;
    2117              :                             }
    2118              :                         }
    2119              :                       return 0;
    2120              :                     }
    2121              :                   else if (r == -1)
    2122              :                     ret = -1;
    2123              :                   /* If isa matches on the host, it still might not match
    2124              :                      in the offloading region.  */
    2125              :                   else if (maybe_offloaded)
    2126              :                     ret = -1;
    2127              :                 }
    2128              :               break;
    2129         2645 :             case OMP_TRAIT_USER_CONDITION:
    2130         2645 :               gcc_assert (set == OMP_TRAIT_SET_USER);
    2131              :               /* The spec does not include the "user" set in the things that
    2132              :                  can trigger code elision in "begin declare variant".  */
    2133         2645 :               if (declare_variant_elision_p)
    2134              :                 {
    2135              :                   ret = -1;
    2136              :                   break;
    2137              :                 }
    2138         5266 :               for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
    2139         2633 :                 if (OMP_TP_NAME (p) == NULL_TREE)
    2140              :                   {
    2141              :                     /* If the expression is not a constant, the selector
    2142              :                        is dynamic.  */
    2143         2633 :                     if (!tree_fits_shwi_p (OMP_TP_VALUE (p)))
    2144              :                       break;
    2145              : 
    2146         1001 :                     if (integer_zerop (OMP_TP_VALUE (p)))
    2147              :                       return 0;
    2148          829 :                     if (integer_nonzerop (OMP_TP_VALUE (p)))
    2149              :                       break;
    2150              :                     ret = -1;
    2151              :                   }
    2152              :               break;
    2153              :             case OMP_TRAIT_INVALID:
    2154              :               /* This is only for the declare_variant_elision_p case.  */
    2155         5314 :               ret = -1;
    2156              :               break;
    2157              :             default:
    2158              :               break;
    2159              :             }
    2160              :         }
    2161              :     }
    2162              :   return ret;
    2163              : }
    2164              : 
    2165              : /* Helper function for resolve_omp_target_device_matches, also used
    2166              :    directly when we know in advance that the device is the host to avoid
    2167              :    the overhead of late resolution.  SEL is the selector code and
    2168              :    PROPERTIES are the properties to match.  The return value is a
    2169              :    boolean.  */
    2170              : static bool
    2171          153 : omp_target_device_matches_on_host (enum omp_ts_code selector,
    2172              :                                    tree properties)
    2173              : {
    2174          153 :   bool result = 1;
    2175              : 
    2176          153 :   if (dump_file)
    2177            0 :     fprintf (dump_file, "omp_target_device_matches_on_host:\n");
    2178              : 
    2179          153 :   switch (selector)
    2180              :     {
    2181              :     case OMP_TRAIT_DEVICE_KIND:
    2182          216 :       for (tree p = properties; p && result; p = TREE_CHAIN (p))
    2183              :         {
    2184          108 :           const char *prop = omp_context_name_list_prop (p);
    2185              : 
    2186          108 :           if (prop == NULL)
    2187              :             result = 0;
    2188          108 :           else if (!strcmp (prop, "any"))
    2189              :             ;
    2190          108 :           else if (!strcmp (prop, "host"))
    2191              :             {
    2192              : #ifdef ACCEL_COMPILER
    2193              :               result = 0;
    2194              : #else
    2195              :               ;
    2196              : #endif
    2197              :             }
    2198           52 :           else if (!strcmp (prop, "nohost"))
    2199              :             {
    2200              : #ifdef ACCEL_COMPILER
    2201              :               ;
    2202              : #else
    2203              :               result = 0;
    2204              : #endif
    2205              :             }
    2206           44 :           else if (targetm.omp.device_kind_arch_isa != NULL)
    2207           44 :             result = targetm.omp.device_kind_arch_isa (omp_device_kind, prop);
    2208              :           else
    2209              : #ifndef ACCEL_COMPILER
    2210            0 :             result = strcmp (prop, "cpu") == 0;
    2211              : #else
    2212              :             gcc_unreachable ();
    2213              : #endif
    2214          108 :           if (dump_file)
    2215            0 :             fprintf (dump_file, "Matching device kind %s = %s\n",
    2216              :                      prop, (result ? "true" : "false"));
    2217              :         }
    2218              :       break;
    2219           29 :     case OMP_TRAIT_DEVICE_ARCH:
    2220           29 :       if (targetm.omp.device_kind_arch_isa != NULL)
    2221           58 :         for (tree p = properties; p && result; p = TREE_CHAIN (p))
    2222              :           {
    2223           29 :             const char *prop = omp_context_name_list_prop (p);
    2224           29 :             if (prop == NULL)
    2225              :               result = 0;
    2226              :             else
    2227           29 :               result = targetm.omp.device_kind_arch_isa (omp_device_arch,
    2228              :                                                          prop);
    2229           29 :             if (dump_file)
    2230            0 :               fprintf (dump_file, "Matching device arch %s = %s\n",
    2231              :                        prop, (result ? "true" : "false"));
    2232              :           }
    2233              :       else
    2234              :         {
    2235            0 :           result = 0;
    2236            0 :           if (dump_file)
    2237            0 :             fprintf (dump_file, "Cannot match device arch on target\n");
    2238              :         }
    2239              :       break;
    2240           16 :     case OMP_TRAIT_DEVICE_ISA:
    2241           16 :       if (targetm.omp.device_kind_arch_isa != NULL)
    2242           32 :         for (tree p = properties; p && result; p = TREE_CHAIN (p))
    2243              :           {
    2244           16 :             const char *prop = omp_context_name_list_prop (p);
    2245           16 :             if (prop == NULL)
    2246              :               result = 0;
    2247              :             else
    2248           16 :               result = targetm.omp.device_kind_arch_isa (omp_device_isa,
    2249              :                                                          prop);
    2250           16 :             if (dump_file)
    2251            0 :               fprintf (dump_file, "Matching device isa %s = %s\n",
    2252              :                        prop, (result ? "true" : "false"));
    2253              :           }
    2254              :       else
    2255              :         {
    2256            0 :           result = 0;
    2257            0 :           if (dump_file)
    2258            0 :             fprintf (dump_file, "Cannot match device isa on target\n");
    2259              :         }
    2260              :       break;
    2261            0 :     default:
    2262            0 :       gcc_unreachable ();
    2263              :     }
    2264          153 :   return result;
    2265              : }
    2266              : 
    2267              : /* Called for late resolution of the OMP_TARGET_DEVICE_MATCHES tree node to
    2268              :    a constant in omp-offload.cc.  This is used in code that is wrapped in a
    2269              :    #pragma omp target construct to execute on the specified device, and
    2270              :    can be reduced to a compile-time constant in the offload compiler.
    2271              :    NODE is an OMP_TARGET_DEVICE_MATCHES tree node and the result is an
    2272              :    INTEGER_CST.  */
    2273              : tree
    2274            0 : resolve_omp_target_device_matches (tree node)
    2275              : {
    2276            0 :   tree sel = OMP_TARGET_DEVICE_MATCHES_SELECTOR (node);
    2277            0 :   enum omp_ts_code selector = (enum omp_ts_code) tree_to_shwi (sel);
    2278            0 :   tree properties = OMP_TARGET_DEVICE_MATCHES_PROPERTIES (node);
    2279            0 :   if (omp_target_device_matches_on_host (selector, properties))
    2280            0 :     return integer_one_node;
    2281              :   else
    2282            0 :     return integer_zero_node;
    2283              : }
    2284              : 
    2285              : /* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
    2286              :    in omp_context_selector_set_compare.  If MATCH_P is true, additionally
    2287              :    apply the special matching rules for the "simdlen" and "aligned" clauses
    2288              :    used to determine whether the selector CLAUSES1 is part of matches
    2289              :    the OpenMP context containing CLAUSES2.  */
    2290              : 
    2291              : static int
    2292           58 : omp_construct_simd_compare (tree clauses1, tree clauses2, bool match_p)
    2293              : {
    2294           58 :   if (clauses1 == NULL_TREE)
    2295            0 :     return clauses2 == NULL_TREE ? 0 : -1;
    2296           58 :   if (clauses2 == NULL_TREE)
    2297              :     return 1;
    2298              : 
    2299          102 :   int r = 0;
    2300           68 :   struct declare_variant_simd_data {
    2301              :     bool inbranch, notinbranch;
    2302              :     tree simdlen;
    2303              :     auto_vec<tree,16> data_sharing;
    2304              :     auto_vec<tree,16> aligned;
    2305           68 :     declare_variant_simd_data ()
    2306           68 :       : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
    2307          238 :   } data[2];
    2308              :   unsigned int i;
    2309              :   tree e0, e1;
    2310          102 :   for (i = 0; i < 2; i++)
    2311          332 :     for (tree c = i ? clauses2 : clauses1; c; c = OMP_CLAUSE_CHAIN (c))
    2312              :       {
    2313          196 :         vec<tree> *v;
    2314          196 :         switch (OMP_CLAUSE_CODE (c))
    2315              :           {
    2316           12 :           case OMP_CLAUSE_INBRANCH:
    2317           12 :             data[i].inbranch = true;
    2318           12 :             continue;
    2319           40 :           case OMP_CLAUSE_NOTINBRANCH:
    2320           40 :             data[i].notinbranch = true;
    2321           40 :             continue;
    2322           68 :           case OMP_CLAUSE_SIMDLEN:
    2323           68 :             data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
    2324           68 :             continue;
    2325           52 :           case OMP_CLAUSE_UNIFORM:
    2326           52 :           case OMP_CLAUSE_LINEAR:
    2327           52 :             v = &data[i].data_sharing;
    2328           52 :             break;
    2329           24 :           case OMP_CLAUSE_ALIGNED:
    2330           24 :             v = &data[i].aligned;
    2331           24 :             break;
    2332            0 :           default:
    2333            0 :             gcc_unreachable ();
    2334              :           }
    2335           76 :         unsigned HOST_WIDE_INT argno = tree_to_uhwi (OMP_CLAUSE_DECL (c));
    2336           76 :         if (argno >= v->length ())
    2337           76 :           v->safe_grow_cleared (argno + 1, true);
    2338           76 :         (*v)[argno] = c;
    2339              :       }
    2340              :   /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
    2341              :      CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
    2342              :      doesn't.  Thus, r == 3 implies return value 2, r == 1 implies
    2343              :      -1, r == 2 implies 1 and r == 0 implies 0.  */
    2344           34 :   if (data[0].inbranch != data[1].inbranch)
    2345            0 :     r |= data[0].inbranch ? 2 : 1;
    2346           34 :   if (data[0].notinbranch != data[1].notinbranch)
    2347           16 :     r |= data[0].notinbranch ? 2 : 1;
    2348           34 :   e0 = data[0].simdlen;
    2349           34 :   e1 = data[1].simdlen;
    2350           34 :   if (!simple_cst_equal (e0, e1))
    2351              :     {
    2352            8 :       if (e0 && e1)
    2353              :         {
    2354            8 :           if (match_p && tree_fits_uhwi_p (e0) && tree_fits_uhwi_p (e1))
    2355              :             {
    2356              :               /* The two simdlen clauses match if m is a multiple of n.  */
    2357            8 :               unsigned HOST_WIDE_INT n = tree_to_uhwi (e0);
    2358            8 :               unsigned HOST_WIDE_INT m = tree_to_uhwi (e1);
    2359            8 :               if (m % n != 0)
    2360              :                 return 2;
    2361              :             }
    2362              :           else
    2363              :             return 2;
    2364              :         }
    2365            0 :       r |= data[0].simdlen ? 2 : 1;
    2366              :     }
    2367           78 :   if (data[0].data_sharing.length () < data[1].data_sharing.length ()
    2368           52 :       || data[0].aligned.length () < data[1].aligned.length ())
    2369            0 :     r |= 1;
    2370              :   tree c1, c2;
    2371           90 :   FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
    2372              :     {
    2373           72 :       c2 = (i < data[1].data_sharing.length ()
    2374          120 :             ? data[1].data_sharing[i] : NULL_TREE);
    2375           72 :       if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
    2376              :         {
    2377            8 :           r |= c1 != NULL_TREE ? 2 : 1;
    2378            8 :           continue;
    2379              :         }
    2380           64 :       if (c1 == NULL_TREE)
    2381           46 :         continue;
    2382           18 :       if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
    2383              :         return 2;
    2384           13 :       if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
    2385            7 :         continue;
    2386            6 :       if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
    2387            6 :           != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
    2388              :         return 2;
    2389            6 :       if (OMP_CLAUSE_LINEAR_KIND (c1) != OMP_CLAUSE_LINEAR_KIND (c2))
    2390              :         return 2;
    2391            6 :       if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
    2392            6 :                              OMP_CLAUSE_LINEAR_STEP (c2)))
    2393              :         return 2;
    2394              :     }
    2395           55 :   FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
    2396              :     {
    2397           60 :       c2 = i < data[1].aligned.length () ? data[1].aligned[i] : NULL_TREE;
    2398           42 :       if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
    2399              :         {
    2400            8 :           r |= c1 != NULL_TREE ? 2 : 1;
    2401            8 :           continue;
    2402              :         }
    2403           34 :       if (c1 == NULL_TREE)
    2404           28 :         continue;
    2405            6 :       e0 = OMP_CLAUSE_ALIGNED_ALIGNMENT (c1);
    2406            6 :       e1 = OMP_CLAUSE_ALIGNED_ALIGNMENT (c2);
    2407            6 :       if (!simple_cst_equal (e0, e1))
    2408              :         {
    2409            5 :           if (e0 && e1
    2410            1 :               && match_p && tree_fits_uhwi_p (e0) && tree_fits_uhwi_p (e1))
    2411              :             {
    2412              :               /* The two aligned clauses match if n is a multiple of m.  */
    2413            0 :               unsigned HOST_WIDE_INT n = tree_to_uhwi (e0);
    2414            0 :               unsigned HOST_WIDE_INT m = tree_to_uhwi (e1);
    2415            0 :               if (n % m != 0)
    2416              :                 return 2;
    2417              :             }
    2418              :           else
    2419              :             return 2;
    2420              :         }
    2421              :     }
    2422           13 :   switch (r)
    2423              :     {
    2424              :     case 0: return 0;
    2425            0 :     case 1: return -1;
    2426            8 :     case 2: return 1;
    2427              :     case 3: return 2;
    2428            0 :     default: gcc_unreachable ();
    2429              :     }
    2430          102 : }
    2431              : 
    2432              : /* Compare properties of selectors SEL from SET other than construct.
    2433              :    CTX1 and CTX2 are the lists of properties to compare.
    2434              :    Return 0/-1/1/2 as in omp_context_selector_set_compare.
    2435              :    Unlike set names or selector names, properties can have duplicates.  */
    2436              : 
    2437              : static int
    2438          171 : omp_context_selector_props_compare (enum omp_tss_code set,
    2439              :                                     enum omp_ts_code sel,
    2440              :                                     tree ctx1, tree ctx2)
    2441              : {
    2442          171 :   int ret = 0;
    2443          374 :   for (int pass = 0; pass < 2; pass++)
    2444          758 :     for (tree p1 = pass ? ctx2 : ctx1; p1; p1 = TREE_CHAIN (p1))
    2445              :       {
    2446          285 :         tree p2;
    2447          640 :         for (p2 = pass ? ctx1 : ctx2; p2; p2 = TREE_CHAIN (p2))
    2448          345 :           if (OMP_TP_NAME (p1) == OMP_TP_NAME (p2))
    2449              :             {
    2450          345 :               if (OMP_TP_NAME (p1) == NULL_TREE)
    2451              :                 {
    2452          173 :                   if (set == OMP_TRAIT_SET_USER
    2453          173 :                       && sel == OMP_TRAIT_USER_CONDITION)
    2454              :                     {
    2455              :                       /* Recognize constants that have equal truth values,
    2456              :                          otherwise assume all expressions are unique.  */
    2457          122 :                       tree v1 = OMP_TP_VALUE (p1);
    2458          122 :                       tree v2 = OMP_TP_VALUE (p2);
    2459          122 :                       if (TREE_CODE (v1) != INTEGER_CST
    2460          106 :                           || TREE_CODE (v2) != INTEGER_CST
    2461          228 :                           || integer_zerop (v1) != integer_zerop (v2))
    2462           16 :                         return 2;
    2463              :                       break;
    2464              :                     }
    2465           51 :                   if (set == OMP_TRAIT_SET_TARGET_DEVICE
    2466           51 :                       && sel == OMP_TRAIT_DEVICE_NUM)
    2467              :                     {
    2468              :                       /* Recognize constants that have equal values,
    2469              :                          otherwise assume all expressions are unique.  */
    2470           51 :                       tree v1 = OMP_TP_VALUE (p1);
    2471           51 :                       tree v2 = OMP_TP_VALUE (p2);
    2472           51 :                       if (TREE_CODE (v1) != INTEGER_CST
    2473            0 :                           || TREE_CODE (v2) != INTEGER_CST
    2474           51 :                           || tree_int_cst_compare (v1, v2) != 0)
    2475           51 :                         return 2;
    2476              :                       break;
    2477              :                     }
    2478            0 :                   if (simple_cst_equal (OMP_TP_VALUE (p1), OMP_TP_VALUE (p2)))
    2479              :                     break;
    2480              :                 }
    2481          172 :               else if (OMP_TP_NAME (p1) == OMP_TP_NAMELIST_NODE)
    2482              :                 {
    2483              :                   /* Handle string constant vs identifier comparison for
    2484              :                      name-list properties.  */
    2485          172 :                   const char *n1 = omp_context_name_list_prop (p1);
    2486          172 :                   const char *n2 = omp_context_name_list_prop (p2);
    2487          172 :                   if (n1 && n2 && !strcmp (n1, n2))
    2488              :                     break;
    2489              :                 }
    2490              :               else
    2491              :                 break;
    2492              :             }
    2493          208 :         if (p2 == NULL_TREE)
    2494              :           {
    2495           10 :             int r = pass ? -1 : 1;
    2496           10 :             if (ret && ret != r)
    2497              :               return 2;
    2498           10 :             else if (pass)
    2499              :               return r;
    2500              :             else
    2501              :               {
    2502              :                 ret = r;
    2503              :                 break;
    2504              :               }
    2505              :           }
    2506              :       }
    2507              :   return ret;
    2508              : }
    2509              : 
    2510              : /* Compare single context selector sets CTX1 and CTX2 with SET name.
    2511              :    CTX1 and CTX2 are lists of trait-selectors.
    2512              :    Return 0 if CTX1 is equal to CTX2,
    2513              :    -1 if CTX1 is a strict subset of CTX2,
    2514              :    1 if CTX2 is a strict subset of CTX1, or
    2515              :    2 if neither context is a subset of another one.  */
    2516              : 
    2517              : static int
    2518         2665 : omp_context_selector_set_compare (enum omp_tss_code set, tree ctx1, tree ctx2)
    2519              : {
    2520              : 
    2521              :   /* If either list includes an ignored selector trait, neither can
    2522              :      be a subset of the other.  */
    2523         5585 :   for (tree ts = ctx1; ts; ts = TREE_CHAIN (ts))
    2524         2920 :     if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
    2525              :       return 2;
    2526         5612 :   for (tree ts = ctx2; ts; ts = TREE_CHAIN (ts))
    2527         2947 :     if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
    2528              :       return 2;
    2529              : 
    2530         2665 :   bool swapped = false;
    2531         2665 :   int ret = 0;
    2532         2665 :   int len1 = list_length (ctx1);
    2533         2665 :   int len2 = list_length (ctx2);
    2534         2665 :   int cnt = 0;
    2535         2665 :   if (len1 < len2)
    2536              :     {
    2537           76 :       swapped = true;
    2538           76 :       std::swap (ctx1, ctx2);
    2539           76 :       std::swap (len1, len2);
    2540              :     }
    2541              : 
    2542         2665 :   if (set == OMP_TRAIT_SET_CONSTRUCT)
    2543              :     {
    2544              :       tree ts1;
    2545              :       tree ts2 = ctx2;
    2546              :       /* Handle construct set specially.  In this case the order
    2547              :          of the selector matters too.  */
    2548          420 :       for (ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
    2549          411 :         if (OMP_TS_CODE (ts1) == OMP_TS_CODE (ts2))
    2550              :           {
    2551          328 :             int r = 0;
    2552          328 :             if (OMP_TS_CODE (ts1) == OMP_TRAIT_CONSTRUCT_SIMD)
    2553           18 :               r = omp_construct_simd_compare (OMP_TS_PROPERTIES (ts1),
    2554           18 :                                               OMP_TS_PROPERTIES (ts2),
    2555              :                                               false);
    2556          328 :             if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
    2557           13 :               return 2;
    2558          315 :             if (ret == 0)
    2559          234 :               ret = r;
    2560          315 :             ts2 = TREE_CHAIN (ts2);
    2561          315 :             if (ts2 == NULL_TREE)
    2562              :               {
    2563          233 :                 ts1 = TREE_CHAIN (ts1);
    2564          233 :                 break;
    2565              :               }
    2566              :           }
    2567           83 :         else if (ret < 0)
    2568              :           return 2;
    2569              :         else
    2570              :           ret = 1;
    2571          242 :       if (ts2 != NULL_TREE)
    2572              :         return 2;
    2573          233 :       if (ts1 != NULL_TREE)
    2574              :         {
    2575           36 :           if (ret < 0)
    2576              :             return 2;
    2577              :           ret = 1;
    2578              :         }
    2579          197 :       if (ret == 0)
    2580              :         return 0;
    2581           89 :       return swapped ? -ret : ret;
    2582              :     }
    2583         2613 :   for (tree ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
    2584              :     {
    2585         2430 :       enum omp_ts_code sel = OMP_TS_CODE (ts1);
    2586         2430 :       tree ts2;
    2587         2547 :       for (ts2 = ctx2; ts2; ts2 = TREE_CHAIN (ts2))
    2588         2440 :         if (sel == OMP_TS_CODE (ts2))
    2589              :           {
    2590         2323 :             tree score1 = OMP_TS_SCORE (ts1);
    2591         2323 :             tree score2 = OMP_TS_SCORE (ts2);
    2592         2144 :             if ((score1 && score2 && !simple_cst_equal (score1, score2))
    2593          179 :                 || (score1 && !score2)
    2594         2495 :                 || (!score1 && score2))
    2595         2160 :               return 2;
    2596              : 
    2597          326 :             int r = omp_context_selector_props_compare (set, OMP_TS_CODE (ts1),
    2598          163 :                                                         OMP_TS_PROPERTIES (ts1),
    2599          163 :                                                         OMP_TS_PROPERTIES (ts2));
    2600          163 :             if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
    2601              :               return 2;
    2602           96 :             if (ret == 0)
    2603           91 :               ret = r;
    2604           96 :             cnt++;
    2605           96 :             break;
    2606              :           }
    2607          203 :       if (ts2 == NULL_TREE)
    2608              :         {
    2609          107 :           if (ret == -1)
    2610              :             return 2;
    2611              :           ret = 1;
    2612              :         }
    2613              :     }
    2614          183 :   if (cnt < len2)
    2615              :     return 2;
    2616           91 :   if (ret == 0)
    2617              :     return 0;
    2618           20 :   return swapped ? -ret : ret;
    2619              : }
    2620              : 
    2621              : /* Compare whole context selector specification CTX1 and CTX2.
    2622              :    Return 0 if CTX1 is equal to CTX2,
    2623              :    -1 if CTX1 is a strict subset of CTX2,
    2624              :    1 if CTX2 is a strict subset of CTX1, or
    2625              :    2 if neither context is a subset of another one.  */
    2626              : 
    2627              : static int
    2628         3726 : omp_context_selector_compare (tree ctx1, tree ctx2)
    2629              : {
    2630         3726 :   bool swapped = false;
    2631         3726 :   int ret = 0;
    2632         3726 :   int len1 = list_length (ctx1);
    2633         3726 :   int len2 = list_length (ctx2);
    2634         3726 :   int cnt = 0;
    2635         3726 :   if (len1 < len2)
    2636              :     {
    2637           89 :       swapped = true;
    2638           89 :       std::swap (ctx1, ctx2);
    2639           89 :       std::swap (len1, len2);
    2640              :     }
    2641         5362 :   for (tree tss1 = ctx1; tss1; tss1 = TREE_CHAIN (tss1))
    2642              :     {
    2643         3971 :       enum omp_tss_code set = OMP_TSS_CODE (tss1);
    2644         3971 :       tree tss2;
    2645         5457 :       for (tss2 = ctx2; tss2; tss2 = TREE_CHAIN (tss2))
    2646         3997 :         if (set == OMP_TSS_CODE (tss2))
    2647              :           {
    2648         2511 :             int r
    2649              :               = omp_context_selector_set_compare
    2650         5022 :                   (set, OMP_TSS_TRAIT_SELECTORS (tss1),
    2651         2511 :                    OMP_TSS_TRAIT_SELECTORS (tss2));
    2652         2511 :             if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
    2653              :               return 2;
    2654          191 :             if (ret == 0)
    2655          138 :               ret = r;
    2656          191 :             cnt++;
    2657          191 :             break;
    2658              :           }
    2659         1651 :       if (tss2 == NULL_TREE)
    2660              :         {
    2661         1460 :           if (ret == -1)
    2662              :             return 2;
    2663              :           ret = 1;
    2664              :         }
    2665              :     }
    2666         1391 :   if (cnt < len2)
    2667              :     return 2;
    2668          155 :   if (ret == 0)
    2669              :     return 0;
    2670          147 :   return swapped ? -ret : ret;
    2671              : }
    2672              : 
    2673              : /* From context selector CTX, return trait-selector with name SEL in
    2674              :    trait-selector-set with name SET if any, or NULL_TREE if not found.  */
    2675              : tree
    2676         7750 : omp_get_context_selector (tree ctx, enum omp_tss_code set,
    2677              :                           enum omp_ts_code sel)
    2678              : {
    2679        14133 :   for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
    2680         8766 :     if (OMP_TSS_CODE (tss) == set)
    2681         6066 :       for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
    2682         4559 :         if (OMP_TS_CODE (ts) == sel)
    2683              :           return ts;
    2684              :   return NULL_TREE;
    2685              : }
    2686              : 
    2687              : /* Similar, but returns the whole trait-selector list for SET in CTX.  */
    2688              : tree
    2689         5985 : omp_get_context_selector_list (tree ctx, enum omp_tss_code set)
    2690              : {
    2691        10759 :   for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
    2692         6448 :     if (OMP_TSS_CODE (tss) == set)
    2693         1674 :       return OMP_TSS_TRAIT_SELECTORS (tss);
    2694              :   return NULL_TREE;
    2695              : }
    2696              : 
    2697              : /* Map string S onto a trait selector set code.  */
    2698              : enum omp_tss_code
    2699         4539 : omp_lookup_tss_code (const char * s)
    2700              : {
    2701        11854 :   for (int i = 0; i < OMP_TRAIT_SET_LAST; i++)
    2702        11827 :     if (strcmp (s, omp_tss_map[i]) == 0)
    2703              :       return (enum omp_tss_code) i;
    2704              :   return OMP_TRAIT_SET_INVALID;
    2705              : }
    2706              : 
    2707              : /* Map string S onto a trait selector code for set SET.  */
    2708              : enum omp_ts_code
    2709         5288 : omp_lookup_ts_code (enum omp_tss_code set, const char *s)
    2710              : {
    2711         5288 :   unsigned int mask = 1 << set;
    2712        55855 :   for (int i = 0; i < OMP_TRAIT_LAST; i++)
    2713        55766 :     if ((mask & omp_ts_map[i].tss_mask) != 0
    2714        13126 :         && strcmp (s, omp_ts_map[i].name) == 0)
    2715              :       return (enum omp_ts_code) i;
    2716              :   return OMP_TRAIT_INVALID;
    2717              : }
    2718              : 
    2719              : 
    2720              : /* Return true if the selector CTX is dynamic.  */
    2721              : static bool
    2722         3631 : omp_selector_is_dynamic (tree ctx)
    2723              : {
    2724         3631 :   tree user_sel = omp_get_context_selector (ctx, OMP_TRAIT_SET_USER,
    2725              :                                             OMP_TRAIT_USER_CONDITION);
    2726         3631 :   if (user_sel)
    2727              :     {
    2728         1455 :       tree expr = OMP_TP_VALUE (OMP_TS_PROPERTIES (user_sel));
    2729              : 
    2730              :       /* The user condition is not dynamic if it is constant.  */
    2731         1455 :       if (!tree_fits_shwi_p (expr))
    2732              :         return true;
    2733              :     }
    2734              : 
    2735         2470 :   tree target_device_ss
    2736         2470 :     = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_TARGET_DEVICE);
    2737         2470 :   if (target_device_ss)
    2738              :     return true;
    2739              : 
    2740              :   return false;
    2741              : }
    2742              : 
    2743              : /* Helper function for omp_dynamic_cond: return a boolean tree expression
    2744              :    that tests whether *DEVICE_NUM is a "conforming device number other
    2745              :    than omp_invalid_device".  This may modify *DEVICE_NUM (i.e, to be
    2746              :    a save_expr).  *IS_HOST is set to true if the device can be statically
    2747              :    determined to be the host.  */
    2748              : 
    2749              : static tree
    2750          103 : omp_device_num_check (tree *device_num, bool *is_host)
    2751              : {
    2752              :   /* C++ may wrap the device_num expr in a CLEANUP_POINT_EXPR; we want
    2753              :      to look inside of it for the special cases.  */
    2754          103 :   tree t = *device_num;
    2755          103 :   if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
    2756           15 :     t = TREE_OPERAND (t, 0);
    2757              : 
    2758              :   /* First check for some constant values we can treat specially.  */
    2759          103 :   if (tree_fits_shwi_p (t))
    2760              :     {
    2761           32 :       HOST_WIDE_INT num = tree_to_shwi (t);
    2762           32 :       if (num < -1)
    2763            4 :         return integer_zero_node;
    2764              :       /* Initial device?  */
    2765           28 :       if (num == -1)
    2766              :         {
    2767           20 :           *is_host = true;
    2768           20 :           return integer_one_node;
    2769              :         }
    2770              :       /* There is always at least one device (the host + offload devices).  */
    2771            8 :       if (num == 0)
    2772            4 :         return integer_one_node;
    2773              :       /* If there is no offloading, there is exactly one device.  */
    2774            4 :       if (!ENABLE_OFFLOADING && num > 0)
    2775            4 :         return integer_zero_node;
    2776              :     }
    2777              : 
    2778              :   /* Also test for direct calls to OpenMP routines that return valid
    2779              :      device numbers.  */
    2780           71 :   if (TREE_CODE (t) == CALL_EXPR)
    2781              :     {
    2782           20 :       tree fndecl = get_callee_fndecl (t);
    2783           20 :       if (fndecl && omp_runtime_api_call (fndecl))
    2784              :         {
    2785           20 :           const char *fnname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
    2786           20 :           if (strcmp (fnname, "omp_get_default_device") == 0
    2787           12 :               || strcmp (fnname, "omp_get_device_num") == 0)
    2788           12 :             return integer_one_node;
    2789            8 :           if (strcmp (fnname, "omp_get_num_devices") == 0
    2790            4 :               || strcmp (fnname, "omp_get_initial_device") == 0)
    2791              :             {
    2792            8 :               *is_host = true;
    2793            8 :               return integer_one_node;
    2794              :             }
    2795              :         }
    2796              :     }
    2797              : 
    2798              :   /* Otherwise, test that -1 <= *device_num <= omp_get_num_devices ().  */
    2799           51 :   *device_num = save_expr (*device_num);
    2800           51 :   tree lotest = build2 (GE_EXPR, integer_type_node, *device_num,
    2801              :                         integer_minus_one_node);
    2802           51 :   tree fndecl = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_DEVICES);
    2803           51 :   tree hitest = build2 (LE_EXPR, integer_type_node, *device_num,
    2804              :                         build_call_expr (fndecl, 0));
    2805           51 :   return build2 (TRUTH_ANDIF_EXPR, integer_type_node, lotest, hitest);
    2806              : }
    2807              : 
    2808              : /* Return a tree expression representing the dynamic part of the context
    2809              :    selector CTX.  SUPERCONTEXT is the surrounding BLOCK, in case we need
    2810              :    to introduce a new BLOCK in the result.  */
    2811              : tree
    2812          513 : omp_dynamic_cond (tree ctx, tree supercontext)
    2813              : {
    2814          513 :   tree user_cond = NULL_TREE, target_device_cond = NULL_TREE;
    2815              : 
    2816              :   /* Build the "user" part of the dynamic selector.  This is a test
    2817              :      predicate taken directly for the "condition" trait in this set.  */
    2818          513 :   tree user_sel = omp_get_context_selector (ctx, OMP_TRAIT_SET_USER,
    2819              :                                             OMP_TRAIT_USER_CONDITION);
    2820          513 :   if (user_sel)
    2821              :     {
    2822          163 :       tree expr = OMP_TP_VALUE (OMP_TS_PROPERTIES (user_sel));
    2823              : 
    2824              :       /* The user condition is not dynamic if it is constant.  */
    2825          163 :       if (!tree_fits_shwi_p (expr))
    2826          161 :         user_cond = unshare_expr (expr);
    2827              :     }
    2828              : 
    2829              :   /* Build the "target_device" part of the dynamic selector.  In the
    2830              :      most general case this requires building a bit of code that runs
    2831              :      on the specified device_num using the same mechanism as
    2832              :      "#pragma omp target" that uses the OMP_TARGET_DEVICE_MATCHES magic
    2833              :      cookie to represent the kind/arch/isa tests which are and'ed together.
    2834              :      These cookies can be resolved into a constant truth value by the
    2835              :      offload compiler; see resolve_omp_target_device_matches, above.
    2836              : 
    2837              :      In some cases, we can (in)validate the device number in advance.
    2838              :      If it is not valid, the whole selector fails to match.  If it is
    2839              :      valid and refers to the host (e.g., constant -1), then we can
    2840              :      resolve the match to a constant truth value now instead of having
    2841              :      to create a OMP_TARGET_DEVICE_MATCHES.  */
    2842              : 
    2843          513 :   tree target_device_ss
    2844          513 :     = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_TARGET_DEVICE);
    2845          513 :   if (target_device_ss)
    2846              :     {
    2847          138 :       tree device_num = NULL_TREE;
    2848          138 :       tree kind = NULL_TREE;
    2849          138 :       tree arch = NULL_TREE;
    2850          138 :       tree isa = NULL_TREE;
    2851          138 :       tree device_ok = NULL_TREE;
    2852          138 :       bool is_host = !ENABLE_OFFLOADING;
    2853              : 
    2854          138 :       tree device_num_sel
    2855          138 :         = omp_get_context_selector (ctx, OMP_TRAIT_SET_TARGET_DEVICE,
    2856              :                                     OMP_TRAIT_DEVICE_NUM);
    2857          138 :       if (device_num_sel)
    2858              :         {
    2859          103 :           device_num = OMP_TP_VALUE (OMP_TS_PROPERTIES (device_num_sel));
    2860          103 :           device_ok = omp_device_num_check (&device_num, &is_host);
    2861              :           /* If an invalid constant device number was specified, the
    2862              :              whole selector fails to match, and there's no point in
    2863              :              continuing to generate code that would never be executed.  */
    2864          103 :           if (device_ok == integer_zero_node)
    2865              :             {
    2866            8 :               target_device_cond = integer_zero_node;
    2867           51 :               goto wrapup;
    2868              :             }
    2869              :         }
    2870              : 
    2871          130 :       tree kind_sel
    2872          130 :         = omp_get_context_selector (ctx, OMP_TRAIT_SET_TARGET_DEVICE,
    2873              :                                     OMP_TRAIT_DEVICE_KIND);
    2874              :       /* "any" is equivalent to omitting this trait selector.  */
    2875          130 :       if (kind_sel
    2876          240 :           && strcmp (omp_context_name_list_prop (OMP_TS_PROPERTIES (kind_sel)),
    2877              :                      "any"))
    2878              :         {
    2879          108 :           tree props = OMP_TS_PROPERTIES (kind_sel);
    2880          108 :           if (!is_host)
    2881            0 :             kind = build2 (OMP_TARGET_DEVICE_MATCHES, integer_type_node,
    2882              :                            build_int_cst (integer_type_node,
    2883              :                                           (int) OMP_TRAIT_DEVICE_KIND),
    2884              :                            props);
    2885          108 :           else if (!omp_target_device_matches_on_host (OMP_TRAIT_DEVICE_KIND,
    2886              :                                                        props))
    2887              :             {
    2888              :               /* The whole selector fails to match.  */
    2889           43 :               target_device_cond = integer_zero_node;
    2890           43 :               goto wrapup;
    2891              :             }
    2892              :           /* else it is statically resolved to true and is a no-op.  */
    2893              :         }
    2894           87 :       tree arch_sel
    2895           87 :         = omp_get_context_selector (ctx, OMP_TRAIT_SET_TARGET_DEVICE,
    2896              :                                     OMP_TRAIT_DEVICE_ARCH);
    2897           87 :       if (arch_sel)
    2898              :         {
    2899           29 :           tree props = OMP_TS_PROPERTIES (arch_sel);
    2900           29 :           if (!is_host)
    2901            0 :             arch = build2 (OMP_TARGET_DEVICE_MATCHES, integer_type_node,
    2902              :                            build_int_cst (integer_type_node,
    2903              :                                           (int) OMP_TRAIT_DEVICE_ARCH),
    2904              :                            props);
    2905           29 :           else if (!omp_target_device_matches_on_host (OMP_TRAIT_DEVICE_ARCH,
    2906              :                                                        props))
    2907              :             {
    2908              :               /* The whole selector fails to match.  */
    2909            0 :               target_device_cond = integer_zero_node;
    2910            0 :               goto wrapup;
    2911              :             }
    2912              :           /* else it is statically resolved to true and is a no-op.  */
    2913              :         }
    2914              : 
    2915           87 :       tree isa_sel
    2916           87 :         = omp_get_context_selector (ctx, OMP_TRAIT_SET_TARGET_DEVICE,
    2917              :                                     OMP_TRAIT_DEVICE_ISA);
    2918           87 :       if (isa_sel)
    2919              :         {
    2920           16 :           tree props = OMP_TS_PROPERTIES (isa_sel);
    2921           16 :           if (!is_host)
    2922            0 :             isa = build2 (OMP_TARGET_DEVICE_MATCHES, integer_type_node,
    2923              :                           build_int_cst (integer_type_node,
    2924              :                                          (int) OMP_TRAIT_DEVICE_ISA),
    2925              :                           props);
    2926           16 :           else if (!omp_target_device_matches_on_host (OMP_TRAIT_DEVICE_ISA,
    2927              :                                                        props))
    2928              :             {
    2929              :               /* The whole selector fails to match.  */
    2930            0 :               target_device_cond = integer_zero_node;
    2931            0 :               goto wrapup;
    2932              :             }
    2933              :           /* else it is statically resolved to true and is a no-op.  */
    2934              :         }
    2935              : 
    2936              :       /* AND the three possible tests together.  */
    2937           87 :       tree test_expr = kind ? kind : NULL_TREE;
    2938           87 :       if (arch && test_expr)
    2939            0 :         test_expr = build2 (TRUTH_ANDIF_EXPR, integer_type_node,
    2940              :                             arch, test_expr);
    2941           87 :       else if (arch)
    2942            0 :         test_expr = arch;
    2943           87 :       if (isa && test_expr)
    2944            0 :         test_expr = build2 (TRUTH_ANDIF_EXPR, integer_type_node,
    2945              :                             isa, test_expr);
    2946           87 :       else if (isa)
    2947              :         test_expr = isa;
    2948              : 
    2949           87 :       if (!test_expr)
    2950              :         /* This could happen if the selector includes only kind="any",
    2951              :            or is_host is true and it could be statically determined to
    2952              :            be true.  The selector always matches, but we still have to
    2953              :            evaluate the device_num expression.  */
    2954              :         {
    2955           87 :           if (device_num)
    2956           67 :             target_device_cond = build2 (COMPOUND_EXPR, integer_type_node,
    2957              :                                          device_num, integer_one_node);
    2958              :           else
    2959           20 :             target_device_cond = integer_one_node;
    2960              :         }
    2961              :       else
    2962              :         {
    2963              :           /* Arrange to evaluate test_expr in the offload compiler for
    2964              :              device device_num.  */
    2965            0 :           tree stmt = make_node (OMP_TARGET);
    2966            0 :           TREE_TYPE (stmt) = void_type_node;
    2967            0 :           tree result_var = create_tmp_var (integer_type_node, "td_match");
    2968            0 :           tree map = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP);
    2969            0 :           OMP_CLAUSE_DECL (map) = result_var;
    2970            0 :           OMP_CLAUSE_SET_MAP_KIND (map, GOMP_MAP_FROM);
    2971            0 :           OMP_TARGET_CLAUSES (stmt) = map;
    2972            0 :           if (device_num)
    2973              :             {
    2974            0 :               tree clause = build_omp_clause (UNKNOWN_LOCATION,
    2975              :                                               OMP_CLAUSE_DEVICE);
    2976            0 :               OMP_CLAUSE_CHAIN (clause) = NULL_TREE;
    2977            0 :               OMP_CLAUSE_DEVICE_ID (clause) = device_num;
    2978            0 :               OMP_CLAUSE_DEVICE_ANCESTOR (clause) = false;
    2979            0 :               OMP_CLAUSE_CHAIN (map) = clause;
    2980              :             }
    2981              : 
    2982            0 :           tree block = make_node (BLOCK);
    2983            0 :           BLOCK_SUPERCONTEXT (block) = supercontext;
    2984              : 
    2985            0 :           tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
    2986              :                               build2 (MODIFY_EXPR, integer_type_node,
    2987              :                                       result_var, test_expr),
    2988              :                               block);
    2989            0 :           TREE_SIDE_EFFECTS (bind) = 1;
    2990            0 :           OMP_TARGET_BODY (stmt) = bind;
    2991            0 :           target_device_cond = build2 (COMPOUND_EXPR, integer_type_node,
    2992              :                                        stmt, result_var);
    2993              : 
    2994              :           /* If necessary, "and" target_device_cond with the test to
    2995              :              make sure the device number is valid.  */
    2996            0 :           if (device_ok && device_ok != integer_one_node)
    2997            0 :             target_device_cond = build2 (TRUTH_ANDIF_EXPR, integer_type_node,
    2998              :                                          device_ok, target_device_cond);
    2999              : 
    3000              :           /* Set the bit to trigger resolution of OMP_TARGET_DEVICE_MATCHES
    3001              :              in the ompdevlow pass.  */
    3002            0 :           if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    3003            0 :             cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
    3004              :         }
    3005              :     }
    3006              : 
    3007          375 :  wrapup:
    3008          513 :   if (user_cond && target_device_cond)
    3009           12 :     return build2 (TRUTH_ANDIF_EXPR, integer_type_node,
    3010           12 :                    user_cond, target_device_cond);
    3011          501 :   else if (user_cond)
    3012          149 :     return user_cond;
    3013              :   else if (target_device_cond)
    3014              :     return target_device_cond;
    3015              :   else
    3016              :     return NULL_TREE;
    3017              : }
    3018              : 
    3019              : 
    3020              : /* Given an omp_variant VARIANT, compute VARIANT->score and
    3021              :    VARIANT->scorable.
    3022              :    CONSTRUCT_CONTEXT is the OpenMP construct context; if this is null or
    3023              :    COMPLETE_P is false (e.g., during parsing or gimplification) then it
    3024              :    may not be possible to compute the score accurately and the scorable
    3025              :    flag is set to false.
    3026              : 
    3027              :    Cited text in the comments is from section 7.2 of the OpenMP 5.2
    3028              :    specification.  */
    3029              : 
    3030              : static void
    3031         3631 : omp_context_compute_score (struct omp_variant *variant,
    3032              :                            tree construct_context, bool complete_p)
    3033              : {
    3034         3631 :   int l = list_length (construct_context);
    3035         3631 :   tree ctx = variant->selector;
    3036         3631 :   variant->scorable = true;
    3037              : 
    3038              :   /* "the final score is the sum of the values of all specified selectors
    3039              :      plus 1".  */
    3040         3631 :   variant->score = 1;
    3041         7709 :   for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
    3042              :     {
    3043         4078 :       if (OMP_TSS_CODE (tss) == OMP_TRAIT_SET_CONSTRUCT)
    3044              :         {
    3045              :           /* "Each trait selector for which the corresponding trait appears
    3046              :              in the context trait set in the OpenMP context..."  */
    3047         1462 :           score_wide_int tss_score = 0;
    3048         1462 :           omp_construct_traits_match (OMP_TSS_TRAIT_SELECTORS (tss),
    3049              :                                       construct_context, &tss_score);
    3050         1462 :           variant->score += tss_score;
    3051         1462 :           if (!complete_p)
    3052            4 :             variant->scorable = false;
    3053              :         }
    3054         2616 :       else if (OMP_TSS_CODE (tss) == OMP_TRAIT_SET_DEVICE
    3055         2616 :                || OMP_TSS_CODE (tss) == OMP_TRAIT_SET_TARGET_DEVICE)
    3056              :         {
    3057              :           /* "The kind, arch, and isa selectors, if specified, are given
    3058              :              the values 2**l, 2**(l+1), and 2**(l+2), respectively..."
    3059              :              FIXME: the spec isn't clear what should happen if there are
    3060              :              both "device" and "target_device" selector sets specified.
    3061              :              This implementation adds up the bits rather than ORs them.  */
    3062         1460 :           for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
    3063          858 :                ts = TREE_CHAIN (ts))
    3064              :             {
    3065          858 :               enum omp_ts_code code = OMP_TS_CODE (ts);
    3066          858 :               if (code == OMP_TRAIT_DEVICE_KIND)
    3067          461 :                 variant->score
    3068          461 :                   += wi::shifted_mask <score_wide_int> (l, 1, false);
    3069          397 :               else if (code == OMP_TRAIT_DEVICE_ARCH)
    3070          119 :                 variant->score
    3071          119 :                   += wi::shifted_mask <score_wide_int> (l + 1, 1, false);
    3072          278 :               else if (code == OMP_TRAIT_DEVICE_ISA)
    3073          151 :                 variant->score
    3074          151 :                   += wi::shifted_mask <score_wide_int> (l + 2, 1, false);
    3075              :             }
    3076          602 :           if (!complete_p)
    3077          195 :             variant->scorable = false;
    3078              :         }
    3079              :       else
    3080              :         {
    3081              :           /* "Trait selectors for which a trait-score is specified..."
    3082              :              Note that there are no implementation-defined selectors, and
    3083              :              "other selectors are given a value of zero".  */
    3084         4028 :           for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
    3085         2014 :                ts = TREE_CHAIN (ts))
    3086              :             {
    3087         2014 :               tree s = OMP_TS_SCORE (ts);
    3088         1436 :               if (s && TREE_CODE (s) == INTEGER_CST)
    3089         1436 :                 variant->score
    3090         2872 :                   += score_wide_int::from (wi::to_wide (s),
    3091         2872 :                                            TYPE_SIGN (TREE_TYPE (s)));
    3092              :             }
    3093              :         }
    3094              :     }
    3095         3631 : }
    3096              : 
    3097              : /* CONSTRUCT_CONTEXT contains "the directive names, each being a trait,
    3098              :    of all enclosing constructs at that point in the program up to a target
    3099              :    construct", per section 7.1 of the 5.2 specification.  The traits are
    3100              :    collected during gimplification and are listed outermost first.
    3101              : 
    3102              :    This function attempts to apply the "if the point in the program is not
    3103              :    enclosed by a target construct, the following rules are applied in order"
    3104              :    requirements that follow in the same paragraph.  This may not be possible,
    3105              :    depending on the compilation phase; in particular, "declare simd" clones
    3106              :    are not known until late resolution.
    3107              : 
    3108              :    The augmented context is returned, and *COMPLETEP is set to true if
    3109              :    the context is known to be complete, false otherwise.  */
    3110              : static tree
    3111         5370 : omp_complete_construct_context (tree construct_context, bool *completep)
    3112              : {
    3113              :   /* The point in the program is enclosed by a target construct.  */
    3114         5370 :   if (construct_context
    3115         8566 :       && OMP_TS_CODE (construct_context) == OMP_TRAIT_CONSTRUCT_TARGET)
    3116          242 :     *completep = true;
    3117              : 
    3118              :   /* At parse time we have none of the information we need to collect
    3119              :      the missing pieces.  */
    3120         5128 :   else if (symtab->state == PARSING)
    3121          640 :     *completep = false;
    3122              : 
    3123              :   else
    3124              :     {
    3125         4488 :       tree attributes = DECL_ATTRIBUTES (current_function_decl);
    3126              : 
    3127              :       /* Add simd trait when in a simd clone.  This information is only
    3128              :          available during late resolution in the omp_device_lower pass,
    3129              :          however we can also rule out cases where we know earlier that
    3130              :          cfun is not a candidate for cloning.  */
    3131         4488 :       if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    3132              :         {
    3133          304 :           cgraph_node *node = cgraph_node::get (cfun->decl);
    3134          304 :           if (node->simdclone)
    3135          288 :             construct_context = make_trait_selector (OMP_TRAIT_CONSTRUCT_SIMD,
    3136              :                                                      NULL_TREE, NULL_TREE,
    3137              :                                                      construct_context);
    3138          304 :           *completep = true;
    3139          304 :         }
    3140         4184 :       else if (lookup_attribute ("omp declare simd", attributes))
    3141           42 :         *completep = false;
    3142              :       else
    3143         4142 :         *completep = true;
    3144              : 
    3145              :       /* Add construct selector set within a "declare variant" function.  */
    3146         4488 :       tree variant_attr
    3147         4488 :         = lookup_attribute ("omp declare variant variant", attributes);
    3148         4488 :       if (variant_attr)
    3149              :         {
    3150           28 :           tree temp = NULL_TREE;
    3151           48 :           for (tree t = TREE_VALUE (variant_attr); t; t = TREE_CHAIN (t))
    3152           20 :             temp = chainon (temp, copy_node (t));
    3153           28 :           construct_context = chainon (temp, construct_context);
    3154              :         }
    3155              : 
    3156              :       /* Add target trait when in a target variant.  */
    3157         4488 :       if (lookup_attribute ("omp declare target", attributes))
    3158           74 :         construct_context = make_trait_selector (OMP_TRAIT_CONSTRUCT_TARGET,
    3159              :                                                  NULL_TREE, NULL_TREE,
    3160              :                                                  construct_context);
    3161              :     }
    3162         5370 :   return construct_context;
    3163              : }
    3164              : 
    3165              : /* Comparison function for sorting routines, to sort OpenMP metadirective
    3166              :    variants by decreasing score.  */
    3167              : 
    3168              : static int
    3169        11991 : sort_variant (const void * a, const void *b, void *)
    3170              : {
    3171        11991 :   score_wide_int score1
    3172              :     = ((const struct omp_variant *) a)->score;
    3173        11991 :   score_wide_int score2
    3174              :     = ((const struct omp_variant *) b)->score;
    3175              : 
    3176        11991 :   if (score1 > score2)
    3177              :     return -1;
    3178         5240 :   else if (score1 < score2)
    3179              :     return 1;
    3180              :   else
    3181          279 :     return 0;
    3182              : }
    3183              : 
    3184              : /* Return a vector of dynamic replacement candidates for the directive
    3185              :    candidates in ALL_VARIANTS.  Return an empty vector if the candidates
    3186              :    cannot be resolved.  */
    3187              : 
    3188              : vec<struct omp_variant>
    3189         2837 : omp_get_dynamic_candidates (vec <struct omp_variant> &all_variants,
    3190              :                             tree construct_context)
    3191              : {
    3192         2837 :   auto_vec <struct omp_variant> variants;
    3193         2837 :   struct omp_variant default_variant;
    3194         2837 :   bool default_found = false;
    3195         2837 :   bool complete_p;
    3196              : 
    3197         2837 :   construct_context
    3198         2837 :     = omp_complete_construct_context (construct_context, &complete_p);
    3199              : 
    3200         2837 :   if (dump_file)
    3201              :     {
    3202           78 :       fprintf (dump_file, "\nIn omp_get_dynamic_candidates:\n");
    3203           78 :       if (symtab->state == PARSING)
    3204           78 :         fprintf (dump_file, "invoked during parsing\n");
    3205            0 :       else if (cfun && (cfun->curr_properties & PROP_gimple_any) == 0)
    3206            0 :         fprintf (dump_file, "invoked during gimplification\n");
    3207            0 :       else if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
    3208            0 :         fprintf (dump_file, "invoked during late resolution\n");
    3209              :       else
    3210            0 :         fprintf (dump_file, "confused about invocation context?!?\n");
    3211          156 :       fprintf (dump_file, "construct_context has %d traits (%s)\n",
    3212            0 :                (construct_context ? list_length (construct_context) : 0),
    3213              :                (complete_p ? "complete" : "incomplete"));
    3214              :     }
    3215              : 
    3216         9315 :   for (unsigned int i = 0; i < all_variants.length (); i++)
    3217              :     {
    3218         6556 :       struct omp_variant variant = all_variants[i];
    3219              : 
    3220         6556 :       if (variant.selector == NULL_TREE)
    3221              :         {
    3222         2759 :           gcc_assert (!default_found);
    3223         2759 :           default_found = true;
    3224         2759 :           default_variant = variant;
    3225         2759 :           default_variant.score = 0;
    3226         2759 :           default_variant.scorable = true;
    3227         2759 :           default_variant.matchable = true;
    3228         2759 :           default_variant.dynamic_selector = false;
    3229         2759 :           if (dump_file)
    3230           54 :             fprintf (dump_file,
    3231              :                      "Considering default selector as candidate\n");
    3232         2759 :           continue;
    3233              :         }
    3234              : 
    3235         3797 :       variant.matchable = true;
    3236         3797 :       variant.scorable = true;
    3237              : 
    3238         3797 :       if (dump_file)
    3239              :         {
    3240           78 :           fprintf (dump_file, "Considering selector ");
    3241           78 :           print_omp_context_selector (dump_file, variant.selector, TDF_NONE);
    3242           78 :           fprintf (dump_file, " as candidate - ");
    3243              :         }
    3244              : 
    3245         3797 :      switch (omp_context_selector_matches (variant.selector,
    3246              :                                            construct_context, complete_p))
    3247              :         {
    3248           99 :         case -1:
    3249           99 :           if (dump_file)
    3250           24 :             fprintf (dump_file, "unmatchable\n");
    3251              :           /* At parse time, just give up if we can't determine whether
    3252              :              things match.  */
    3253           99 :           if (symtab->state == PARSING)
    3254              :             {
    3255           78 :               variants.truncate (0);
    3256           78 :               return variants.copy ();
    3257              :             }
    3258              :           /* Otherwise we must be invoked from the gimplifier.  */
    3259           21 :           gcc_assert (cfun && (cfun->curr_properties & PROP_gimple_any) == 0);
    3260           21 :           variant.matchable = false;
    3261              :           /* FALLTHRU */
    3262         3631 :         case 1:
    3263         3631 :           omp_context_compute_score (&variant, construct_context, complete_p);
    3264         3631 :           variant.dynamic_selector
    3265         3631 :             = omp_selector_is_dynamic (variant.selector);
    3266         3631 :           variants.safe_push (variant);
    3267         3631 :           if (dump_file && variant.matchable)
    3268              :             {
    3269           54 :               if (variant.dynamic_selector)
    3270           48 :                 fprintf (dump_file, "matched, dynamic");
    3271              :               else
    3272            6 :                 fprintf (dump_file, "matched, non-dynamic");
    3273              :             }
    3274              :           break;
    3275           88 :         case 0:
    3276           88 :           if (dump_file)
    3277            0 :             fprintf (dump_file, "no match");
    3278              :           break;
    3279              :         }
    3280              : 
    3281         3719 :       if (dump_file)
    3282           54 :         fprintf (dump_file, "\n");
    3283              :     }
    3284              : 
    3285              :   /* There must be one default variant.  */
    3286         2759 :   gcc_assert (default_found);
    3287              : 
    3288              :   /* If there are no matching selectors, return the default.  */
    3289         2759 :   if (variants.length () == 0)
    3290              :     {
    3291          685 :       variants.safe_push (default_variant);
    3292          685 :       return variants.copy ();
    3293              :     }
    3294              : 
    3295              :   /* If there is only one matching selector, use it.  */
    3296         2074 :   if (variants.length () == 1)
    3297              :     {
    3298         1460 :       if (variants[0].matchable)
    3299              :         {
    3300         1460 :           if (variants[0].dynamic_selector)
    3301          198 :             variants.safe_push (default_variant);
    3302         1460 :           return variants.copy ();
    3303              :         }
    3304              :       else
    3305              :         {
    3306              :           /* We don't know whether the one non-default selector will
    3307              :              actually match.  */
    3308            0 :           variants.truncate (0);
    3309            0 :           return variants.copy ();
    3310              :         }
    3311              :     }
    3312              : 
    3313              :   /* A context selector that is a strict subset of another context selector
    3314              :      has a score of zero.  This only applies if the selector that is a
    3315              :      superset definitely matches, though.  */
    3316         2785 :   for (unsigned int i = 0; i < variants.length (); i++)
    3317         5811 :     for (unsigned int j = i + 1; j < variants.length (); j++)
    3318              :       {
    3319         7386 :         int r = omp_context_selector_compare (variants[i].selector,
    3320         3693 :                                               variants[j].selector);
    3321         3746 :         if (r == -1 && variants[j].matchable)
    3322              :           {
    3323              :             /* variant i is a strict subset of variant j.  */
    3324           53 :             variants[i].score = 0;
    3325           53 :             variants[i].scorable = true;
    3326           53 :             break;
    3327              :           }
    3328         3734 :         else if (r == 1 && variants[i].matchable)
    3329              :           /* variant j is a strict subset of variant i.  */
    3330              :           {
    3331           94 :             variants[j].score = 0;
    3332           94 :             variants[j].scorable = true;
    3333              :           }
    3334              :       }
    3335              : 
    3336              :   /* Sort the variants by decreasing score, preserving the original order
    3337              :      in case of a tie.  */
    3338          614 :   variants.stablesort (sort_variant, NULL);
    3339              : 
    3340              :   /* Add the default as a final choice.  */
    3341          614 :   variants.safe_push (default_variant);
    3342              : 
    3343          614 :   if (dump_file)
    3344              :     {
    3345            0 :       fprintf (dump_file, "Sorted variants are:\n");
    3346            0 :       for (unsigned i = 0; i < variants.length (); i++)
    3347              :         {
    3348            0 :           HOST_WIDE_INT score = variants[i].score.to_shwi ();
    3349            0 :           fprintf (dump_file, "score %d matchable %d scorable %d ",
    3350            0 :                    (int)score, (int)(variants[i].matchable),
    3351            0 :                    (int)(variants[i].scorable));
    3352            0 :           if (variants[i].selector)
    3353              :             {
    3354            0 :               fprintf (dump_file, "selector ");
    3355            0 :               print_omp_context_selector (dump_file, variants[i].selector,
    3356              :                                           TDF_NONE);
    3357            0 :               fprintf (dump_file, "\n");
    3358              :             }
    3359              :           else
    3360            0 :             fprintf (dump_file, "default selector\n");
    3361              :         }
    3362              :     }
    3363              : 
    3364              :   /* Build the dynamic candidate list.  */
    3365         1711 :   for (unsigned i = 0; i < variants.length (); i++)
    3366              :     {
    3367              :       /* If we encounter a candidate that wasn't definitely matched,
    3368              :          give up now.  */
    3369         1711 :       if (!variants[i].matchable)
    3370              :         {
    3371            4 :           variants.truncate (0);
    3372            4 :           break;
    3373              :         }
    3374              : 
    3375              :       /* In general, we can't proceed if we can't accurately score any
    3376              :          of the selectors, since the sorting may be incorrect.  But, since
    3377              :          the actual score will never be lower than the guessed value, we
    3378              :          can use the first variant if it is not scorable but either the next
    3379              :          one is a subset of the first, is scorable, or we can make a
    3380              :          direct comparison of the high-order isa/arch/kind bits.  */
    3381         1707 :       if (!variants[i].scorable)
    3382              :         {
    3383           28 :           bool ok = true;
    3384           28 :           if (i != 0)
    3385              :             ok = false;
    3386           20 :           else if (variants[i+1].scorable)
    3387              :             /* ok */
    3388              :             ;
    3389           20 :           else if (variants[i+1].score > 0)
    3390              :             {
    3391              :               /* To keep comparisons simple, reject selectors that contain
    3392              :                  sets other than device, target_device, or construct.  */
    3393           20 :               for (tree tss = variants[i].selector;
    3394           40 :                    tss && ok; tss = TREE_CHAIN (tss))
    3395              :                 {
    3396           20 :                   enum omp_tss_code code = OMP_TSS_CODE (tss);
    3397           20 :                   if (code != OMP_TRAIT_SET_DEVICE
    3398              :                       && code != OMP_TRAIT_SET_TARGET_DEVICE
    3399           20 :                       && code != OMP_TRAIT_SET_CONSTRUCT)
    3400           12 :                     ok = false;
    3401              :                 }
    3402           20 :               for (tree tss = variants[i+1].selector;
    3403           28 :                    tss && ok; tss = TREE_CHAIN (tss))
    3404              :                 {
    3405            8 :                   enum omp_tss_code code = OMP_TSS_CODE (tss);
    3406            8 :                   if (code != OMP_TRAIT_SET_DEVICE
    3407              :                       && code != OMP_TRAIT_SET_TARGET_DEVICE
    3408            8 :                       && code != OMP_TRAIT_SET_CONSTRUCT)
    3409            0 :                     ok = false;
    3410              :                 }
    3411              :               /* Ignore the construct bits of the score.  If the isa/arch/kind
    3412              :                  bits are strictly ordered, we're good to go.  Since
    3413              :                  "the final score is the sum of the values of all specified
    3414              :                  selectors plus 1", subtract that 1 from both scores before
    3415              :                  getting rid of the low bits.  */
    3416           20 :               if (ok)
    3417              :                 {
    3418            8 :                   size_t l = list_length (construct_context);
    3419            8 :                   gcc_assert (variants[i].score > 0
    3420              :                               && variants[i+1].score > 0);
    3421            8 :                   if ((variants[i].score - 1) >> l
    3422           16 :                       <= (variants[i+1].score - 1) >> l)
    3423            0 :                     ok = false;
    3424              :                 }
    3425              :             }
    3426              : 
    3427            8 :           if (!ok)
    3428              :             {
    3429           20 :               variants.truncate (0);
    3430           20 :               break;
    3431              :             }
    3432              :         }
    3433              : 
    3434         1687 :       if (dump_file)
    3435              :         {
    3436            0 :           fprintf (dump_file, "Adding directive variant with ");
    3437              : 
    3438            0 :           if (variants[i].selector)
    3439              :             {
    3440            0 :               fprintf (dump_file, "selector ");
    3441            0 :               print_omp_context_selector (dump_file, variants[i].selector,
    3442              :                                           TDF_NONE);
    3443              :             }
    3444              :           else
    3445            0 :             fprintf (dump_file, "default selector");
    3446              : 
    3447            0 :           fprintf (dump_file, " as candidate.\n");
    3448              :         }
    3449              : 
    3450              :       /* The last of the candidates is ended by a static selector.  */
    3451         1687 :       if (!variants[i].dynamic_selector)
    3452              :         {
    3453          590 :           variants.truncate (i + 1);
    3454          590 :           break;
    3455              :         }
    3456              :     }
    3457              : 
    3458          614 :   return variants.copy ();
    3459         2837 : }
    3460              : 
    3461              : /* Two attempts are made to resolve calls to "declare variant" functions:
    3462              :    early resolution in the gimplifier, and late resolution in the
    3463              :    omp_device_lower pass.  If early resolution is not possible, the
    3464              :    original function call is gimplified into the same form as metadirective
    3465              :    and goes through the same late resolution code as metadirective.  */
    3466              : 
    3467              : /* Collect "declare variant" candidates for BASE.  CONSTRUCT_CONTEXT
    3468              :    is the un-augmented context, or NULL_TREE if that information is not
    3469              :    available yet.  */
    3470              : vec<struct omp_variant>
    3471         2039 : omp_declare_variant_candidates (tree base, tree construct_context)
    3472              : {
    3473         2039 :   auto_vec <struct omp_variant> candidates;
    3474         2039 :   bool complete_p;
    3475         2039 :   tree augmented_context
    3476         2039 :     = omp_complete_construct_context (construct_context, &complete_p);
    3477              : 
    3478              :   /* The variants are stored on (possible multiple) "omp declare variant base"
    3479              :      attributes on the base function.  */
    3480         4320 :   for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
    3481              :     {
    3482         2342 :       attr = lookup_attribute ("omp declare variant base", attr);
    3483         2342 :       if (attr == NULL_TREE)
    3484              :         break;
    3485              : 
    3486         2281 :       tree fndecl = TREE_PURPOSE (TREE_VALUE (attr));
    3487         2281 :       tree selector = TREE_VALUE (TREE_VALUE (attr));
    3488              : 
    3489         2281 :       if (TREE_CODE (fndecl) != FUNCTION_DECL)
    3490          467 :         continue;
    3491              : 
    3492              :       /* Ignore this variant if its selector is known not to match.  */
    3493         2281 :       if (!omp_context_selector_matches (selector, augmented_context,
    3494              :                                          complete_p))
    3495          467 :           continue;
    3496              : 
    3497         1814 :       struct omp_variant candidate;
    3498         1814 :       candidate.selector = selector;
    3499         1814 :       candidate.dynamic_selector = false;
    3500         1814 :       candidate.alternative = fndecl;
    3501         1814 :       candidate.body = NULL_TREE;
    3502         1814 :       candidates.safe_push (candidate);
    3503              :     }
    3504              : 
    3505              :   /* Add a default that is the base function.  */
    3506         2039 :   struct omp_variant v;
    3507         2039 :   v.selector = NULL_TREE;
    3508         2039 :   v.dynamic_selector = false;
    3509         2039 :   v.alternative = base;
    3510         2039 :   v.body = NULL_TREE;
    3511         2039 :   candidates.safe_push (v);
    3512         2039 :   return candidates.copy ();
    3513         2039 : }
    3514              : 
    3515              : /* Collect metadirective candidates for METADIRECTIVE.  CONSTRUCT_CONTEXT
    3516              :    is the un-augmented context, or NULL_TREE if that information is not
    3517              :    available yet.  */
    3518              : vec<struct omp_variant>
    3519          494 : omp_metadirective_candidates (tree metadirective, tree construct_context)
    3520              : {
    3521          494 :   auto_vec <struct omp_variant> candidates;
    3522          494 :   tree variant = OMP_METADIRECTIVE_VARIANTS (metadirective);
    3523          494 :   bool complete_p;
    3524          494 :   tree augmented_context
    3525          494 :     = omp_complete_construct_context (construct_context, &complete_p);
    3526              : 
    3527          494 :   gcc_assert (variant);
    3528         1578 :   for (; variant; variant = TREE_CHAIN (variant))
    3529              :     {
    3530         1084 :       tree selector = OMP_METADIRECTIVE_VARIANT_SELECTOR (variant);
    3531              : 
    3532              :       /* Ignore this variant if its selector is known not to match.  */
    3533         1084 :       if (!omp_context_selector_matches (selector, augmented_context,
    3534              :                                          complete_p))
    3535           59 :         continue;
    3536              : 
    3537         1025 :       struct omp_variant candidate;
    3538         1025 :       candidate.selector = selector;
    3539         1025 :       candidate.dynamic_selector = false;
    3540         1025 :       candidate.alternative = OMP_METADIRECTIVE_VARIANT_DIRECTIVE (variant);
    3541         1025 :       candidate.body = OMP_METADIRECTIVE_VARIANT_BODY (variant);
    3542         1025 :       candidates.safe_push (candidate);
    3543              :     }
    3544          494 :   return candidates.copy ();
    3545          494 : }
    3546              : 
    3547              : /* Return a vector of dynamic replacement candidates for the metadirective
    3548              :    statement in METADIRECTIVE.  Return an empty vector if the metadirective
    3549              :    cannot be resolved.  This function is intended to be called from the
    3550              :    front ends, prior to gimplification.  */
    3551              : 
    3552              : vec<struct omp_variant>
    3553          320 : omp_early_resolve_metadirective (tree metadirective)
    3554              : {
    3555          320 :   vec <struct omp_variant> candidates
    3556          320 :     = omp_metadirective_candidates (metadirective, NULL_TREE);
    3557          320 :   return omp_get_dynamic_candidates (candidates, NULL_TREE);
    3558              : }
    3559              : 
    3560              : /* Return a vector of dynamic replacement candidates for the variant construct
    3561              :    with SELECTORS and CONSTRUCT_CONTEXT.  This version is called during late
    3562              :    resolution in the ompdevlow pass.  */
    3563              : 
    3564              : vec<struct omp_variant>
    3565          304 : omp_resolve_variant_construct (tree construct_context, tree selectors)
    3566              : {
    3567          304 :   auto_vec <struct omp_variant> variants;
    3568              : 
    3569         2108 :   for (int i = 0; i < TREE_VEC_LENGTH (selectors); i++)
    3570              :     {
    3571         1804 :       struct omp_variant variant;
    3572              : 
    3573         1804 :       variant.selector = TREE_VEC_ELT (selectors, i);
    3574         1804 :       variant.dynamic_selector = false;
    3575         1804 :       variant.alternative = build_int_cst (integer_type_node, i + 1);
    3576         1804 :       variant.body = NULL_TREE;
    3577              : 
    3578         1804 :       variants.safe_push (variant);
    3579              :     }
    3580              : 
    3581          304 :   return omp_get_dynamic_candidates (variants, construct_context);
    3582          304 : }
    3583              : 
    3584              : /* Encode an oacc launch argument.  This matches the GOMP_LAUNCH_PACK
    3585              :    macro on gomp-constants.h.  We do not check for overflow.  */
    3586              : 
    3587              : tree
    3588        11070 : oacc_launch_pack (unsigned code, tree device, unsigned op)
    3589              : {
    3590        11070 :   tree res;
    3591              : 
    3592        11070 :   res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
    3593        11070 :   if (device)
    3594              :     {
    3595            0 :       device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
    3596              :                             device, build_int_cst (unsigned_type_node,
    3597              :                                                    GOMP_LAUNCH_DEVICE_SHIFT));
    3598            0 :       res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
    3599              :     }
    3600        11070 :   return res;
    3601              : }
    3602              : 
    3603              : /* Openacc compute grid dimension clauses are converted to an attribute
    3604              :    attached to the function.  This permits the target-side code to (a) massage
    3605              :    the dimensions, (b) emit that data and (c) optimize.  Non-constant
    3606              :    dimensions are pushed onto ARGS.
    3607              : 
    3608              :    The attribute value is a TREE_LIST.  A set of dimensions is
    3609              :    represented as a list of INTEGER_CST.  Those that are runtime
    3610              :    exprs are represented as an INTEGER_CST of zero.
    3611              : 
    3612              :    TODO: Normally the attribute will just contain a single such list.  If
    3613              :    however it contains a list of lists, this will represent the use of
    3614              :    device_type.  Each member of the outer list is an assoc list of
    3615              :    dimensions, keyed by the device type.  The first entry will be the
    3616              :    default.  Well, that's the plan.  */
    3617              : 
    3618              : /* Replace any existing oacc fn attribute in ATTRIBS with updated
    3619              :    dimensions.  */
    3620              : 
    3621              : tree
    3622        20654 : oacc_replace_fn_attrib_attr (tree attribs, tree dims)
    3623              : {
    3624        20654 :   tree ident = get_identifier (OACC_FN_ATTRIB);
    3625              : 
    3626              :   /* If we happen to be present as the first attrib, drop it.  */
    3627        40239 :   if (attribs && TREE_PURPOSE (attribs) == ident)
    3628         9583 :     attribs = TREE_CHAIN (attribs);
    3629        20654 :   return tree_cons (ident, dims, attribs);
    3630              : }
    3631              : 
    3632              : /* Replace any existing oacc fn attribute on FN with updated
    3633              :    dimensions.  */
    3634              : 
    3635              : void
    3636        20299 : oacc_replace_fn_attrib (tree fn, tree dims)
    3637              : {
    3638        20299 :   DECL_ATTRIBUTES (fn)
    3639        20299 :     = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn), dims);
    3640        20299 : }
    3641              : 
    3642              : /* Scan CLAUSES for launch dimensions and attach them to the oacc
    3643              :    function attribute.  Push any that are non-constant onto the ARGS
    3644              :    list, along with an appropriate GOMP_LAUNCH_DIM tag.  */
    3645              : 
    3646              : void
    3647         9904 : oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
    3648              : {
    3649              :   /* Must match GOMP_DIM ordering.  */
    3650         9904 :   static const omp_clause_code ids[]
    3651              :     = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
    3652              :         OMP_CLAUSE_VECTOR_LENGTH };
    3653         9904 :   unsigned ix;
    3654         9904 :   tree dims[GOMP_DIM_MAX];
    3655              : 
    3656         9904 :   tree attr = NULL_TREE;
    3657         9904 :   unsigned non_const = 0;
    3658              : 
    3659        39616 :   for (ix = GOMP_DIM_MAX; ix--;)
    3660              :     {
    3661        29712 :       tree clause = omp_find_clause (clauses, ids[ix]);
    3662        29712 :       tree dim = NULL_TREE;
    3663              : 
    3664        29712 :       if (clause)
    3665         3275 :         dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
    3666        29712 :       dims[ix] = dim;
    3667        29712 :       if (dim && TREE_CODE (dim) != INTEGER_CST)
    3668              :         {
    3669          157 :           dim = integer_zero_node;
    3670          157 :           non_const |= GOMP_DIM_MASK (ix);
    3671              :         }
    3672        29712 :       attr = tree_cons (NULL_TREE, dim, attr);
    3673              :     }
    3674              : 
    3675         9904 :   oacc_replace_fn_attrib (fn, attr);
    3676              : 
    3677         9904 :   if (non_const)
    3678              :     {
    3679              :       /* Push a dynamic argument set.  */
    3680          101 :       args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
    3681              :                                          NULL_TREE, non_const));
    3682          404 :       for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
    3683          303 :         if (non_const & GOMP_DIM_MASK (ix))
    3684          157 :           args->safe_push (dims[ix]);
    3685              :     }
    3686         9904 : }
    3687              : 
    3688              : /* Verify OpenACC routine clauses.
    3689              : 
    3690              :    Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
    3691              :    if it has already been marked in compatible way, and -1 if incompatible.
    3692              :    Upon returning, the chain of clauses will contain exactly one clause
    3693              :    specifying the level of parallelism.  */
    3694              : 
    3695              : int
    3696         1219 : oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc,
    3697              :                              const char *routine_str)
    3698              : {
    3699         1219 :   tree c_level = NULL_TREE;
    3700         1219 :   tree c_nohost = NULL_TREE;
    3701         1219 :   tree c_p = NULL_TREE;
    3702         3627 :   for (tree c = *clauses; c; c_p = c, c = OMP_CLAUSE_CHAIN (c))
    3703         2408 :     switch (OMP_CLAUSE_CODE (c))
    3704              :       {
    3705         2309 :       case OMP_CLAUSE_GANG:
    3706         2309 :       case OMP_CLAUSE_WORKER:
    3707         2309 :       case OMP_CLAUSE_VECTOR:
    3708         2309 :       case OMP_CLAUSE_SEQ:
    3709         2309 :         if (c_level == NULL_TREE)
    3710              :           c_level = c;
    3711         1496 :         else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_CODE (c_level))
    3712              :           {
    3713              :             /* This has already been diagnosed in the front ends.  */
    3714              :             /* Drop the duplicate clause.  */
    3715          352 :             gcc_checking_assert (c_p != NULL_TREE);
    3716          352 :             OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
    3717          352 :             c = c_p;
    3718              :           }
    3719              :         else
    3720              :           {
    3721         1144 :             error_at (OMP_CLAUSE_LOCATION (c),
    3722              :                       "%qs specifies a conflicting level of parallelism",
    3723         1144 :                       omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
    3724         1144 :             inform (OMP_CLAUSE_LOCATION (c_level),
    3725              :                     "... to the previous %qs clause here",
    3726         1144 :                     omp_clause_code_name[OMP_CLAUSE_CODE (c_level)]);
    3727              :             /* Drop the conflicting clause.  */
    3728         1144 :             gcc_checking_assert (c_p != NULL_TREE);
    3729         1144 :             OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
    3730         1144 :             c = c_p;
    3731              :           }
    3732              :         break;
    3733              :       case OMP_CLAUSE_NOHOST:
    3734              :         /* Don't worry about duplicate clauses here.  */
    3735              :         c_nohost = c;
    3736              :         break;
    3737            0 :       default:
    3738            0 :         gcc_unreachable ();
    3739              :       }
    3740         1219 :   if (c_level == NULL_TREE)
    3741              :     {
    3742              :       /* Default to an implicit 'seq' clause.  */
    3743          406 :       c_level = build_omp_clause (loc, OMP_CLAUSE_SEQ);
    3744          406 :       OMP_CLAUSE_CHAIN (c_level) = *clauses;
    3745          406 :       *clauses = c_level;
    3746              :     }
    3747              :   /* In *clauses, we now have exactly one clause specifying the level of
    3748              :      parallelism.  */
    3749              : 
    3750         1219 :   tree attr
    3751         1219 :     = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl));
    3752         1219 :   if (attr != NULL_TREE)
    3753              :     {
    3754              :       /* Diagnose if "#pragma omp declare target" has also been applied.  */
    3755          429 :       if (TREE_VALUE (attr) == NULL_TREE)
    3756              :         {
    3757              :           /* See <https://gcc.gnu.org/PR93465>; the semantics of combining
    3758              :              OpenACC and OpenMP 'target' are not clear.  */
    3759           32 :           error_at (loc,
    3760              :                     "cannot apply %qs to %qD, which has also been"
    3761              :                     " marked with an OpenMP 'declare target' directive",
    3762              :                     routine_str, fndecl);
    3763              :           /* Incompatible.  */
    3764           32 :           return -1;
    3765              :         }
    3766              : 
    3767              :       /* If a "#pragma acc routine" has already been applied, just verify
    3768              :          this one for compatibility.  */
    3769              :       /* Collect previous directive's clauses.  */
    3770              :       tree c_level_p = NULL_TREE;
    3771              :       tree c_nohost_p = NULL_TREE;
    3772          850 :       for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c))
    3773          453 :         switch (OMP_CLAUSE_CODE (c))
    3774              :           {
    3775          397 :           case OMP_CLAUSE_GANG:
    3776          397 :           case OMP_CLAUSE_WORKER:
    3777          397 :           case OMP_CLAUSE_VECTOR:
    3778          397 :           case OMP_CLAUSE_SEQ:
    3779          397 :             gcc_checking_assert (c_level_p == NULL_TREE);
    3780              :             c_level_p = c;
    3781              :             break;
    3782           56 :           case OMP_CLAUSE_NOHOST:
    3783           56 :             gcc_checking_assert (c_nohost_p == NULL_TREE);
    3784              :             c_nohost_p = c;
    3785              :             break;
    3786            0 :           default:
    3787            0 :             gcc_unreachable ();
    3788              :           }
    3789          397 :       gcc_checking_assert (c_level_p != NULL_TREE);
    3790              :       /* ..., and compare to current directive's, which we've already collected
    3791              :          above.  */
    3792          397 :       tree c_diag;
    3793          397 :       tree c_diag_p;
    3794              :       /* Matching level of parallelism?  */
    3795          397 :       if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
    3796              :         {
    3797           97 :           c_diag = c_level;
    3798           97 :           c_diag_p = c_level_p;
    3799           97 :           goto incompatible;
    3800              :         }
    3801              :       /* Matching 'nohost' clauses?  */
    3802          300 :       if ((c_nohost == NULL_TREE) != (c_nohost_p == NULL_TREE))
    3803              :         {
    3804           56 :           c_diag = c_nohost;
    3805           56 :           c_diag_p = c_nohost_p;
    3806           56 :           goto incompatible;
    3807              :         }
    3808              :       /* Compatible.  */
    3809              :       return 1;
    3810              : 
    3811          153 :     incompatible:
    3812          153 :       if (c_diag != NULL_TREE)
    3813          125 :         error_at (OMP_CLAUSE_LOCATION (c_diag),
    3814              :                   "incompatible %qs clause when applying"
    3815              :                   " %qs to %qD, which has already been"
    3816              :                   " marked with an OpenACC 'routine' directive",
    3817          125 :                   omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)],
    3818              :                   routine_str, fndecl);
    3819           28 :       else if (c_diag_p != NULL_TREE)
    3820           28 :         error_at (loc,
    3821              :                   "missing %qs clause when applying"
    3822              :                   " %qs to %qD, which has already been"
    3823              :                   " marked with an OpenACC 'routine' directive",
    3824           28 :                   omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)],
    3825              :                   routine_str, fndecl);
    3826              :       else
    3827            0 :         gcc_unreachable ();
    3828          153 :       if (c_diag_p != NULL_TREE)
    3829          125 :         inform (OMP_CLAUSE_LOCATION (c_diag_p),
    3830              :                 "... with %qs clause here",
    3831          125 :                 omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]);
    3832              :       else
    3833              :         {
    3834              :           /* In the front ends, we don't preserve location information for the
    3835              :              OpenACC routine directive itself.  However, that of c_level_p
    3836              :              should be close.  */
    3837           28 :           location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p);
    3838           28 :           inform (loc_routine, "... without %qs clause near to here",
    3839           28 :                   omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]);
    3840              :         }
    3841              :       /* Incompatible.  */
    3842          153 :       return -1;
    3843              :     }
    3844              : 
    3845              :   return 0;
    3846              : }
    3847              : 
    3848              : /*  Process the OpenACC 'routine' directive clauses to generate an attribute
    3849              :     for the level of parallelism.  All dimensions have a size of zero
    3850              :     (dynamic).  TREE_PURPOSE is set to indicate whether that dimension
    3851              :     can have a loop partitioned on it.  non-zero indicates
    3852              :     yes, zero indicates no.  By construction once a non-zero has been
    3853              :     reached, further inner dimensions must also be non-zero.  We set
    3854              :     TREE_VALUE to zero for the dimensions that may be partitioned and
    3855              :     1 for the other ones -- if a loop is (erroneously) spawned at
    3856              :     an outer level, we don't want to try and partition it.  */
    3857              : 
    3858              : tree
    3859         1137 : oacc_build_routine_dims (tree clauses)
    3860              : {
    3861              :   /* Must match GOMP_DIM ordering.  */
    3862         1137 :   static const omp_clause_code ids[]
    3863              :     = {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
    3864         1137 :   int ix;
    3865         1137 :   int level = -1;
    3866              : 
    3867         2317 :   for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
    3868         2301 :     for (ix = GOMP_DIM_MAX + 1; ix--;)
    3869         2258 :       if (OMP_CLAUSE_CODE (clauses) == ids[ix])
    3870              :         {
    3871              :           level = ix;
    3872              :           break;
    3873              :         }
    3874         1137 :   gcc_checking_assert (level >= 0);
    3875              : 
    3876              :   tree dims = NULL_TREE;
    3877              : 
    3878         4548 :   for (ix = GOMP_DIM_MAX; ix--;)
    3879         3411 :     dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
    3880         3411 :                       build_int_cst (integer_type_node, ix < level), dims);
    3881              : 
    3882         1137 :   return dims;
    3883              : }
    3884              : 
    3885              : /* Retrieve the oacc function attrib and return it.  Non-oacc
    3886              :    functions will return NULL.  */
    3887              : 
    3888              : tree
    3889       351987 : oacc_get_fn_attrib (tree fn)
    3890              : {
    3891       351987 :   return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
    3892              : }
    3893              : 
    3894              : /* Return true if FN is an OpenMP or OpenACC offloading function.  */
    3895              : 
    3896              : bool
    3897          561 : offloading_function_p (tree fn)
    3898              : {
    3899          561 :   tree attrs = DECL_ATTRIBUTES (fn);
    3900          561 :   return (lookup_attribute ("omp declare target", attrs)
    3901          561 :           || lookup_attribute ("omp target entrypoint", attrs));
    3902              : }
    3903              : 
    3904              : /* Extract an oacc execution dimension from FN.  FN must be an
    3905              :    offloaded function or routine that has already had its execution
    3906              :    dimensions lowered to the target-specific values.  */
    3907              : 
    3908              : int
    3909        62574 : oacc_get_fn_dim_size (tree fn, int axis)
    3910              : {
    3911        62574 :   tree attrs = oacc_get_fn_attrib (fn);
    3912              : 
    3913        62574 :   gcc_assert (axis < GOMP_DIM_MAX);
    3914              : 
    3915        62574 :   tree dims = TREE_VALUE (attrs);
    3916       127135 :   while (axis--)
    3917        64561 :     dims = TREE_CHAIN (dims);
    3918              : 
    3919        62574 :   int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
    3920              : 
    3921        62574 :   return size;
    3922              : }
    3923              : 
    3924              : /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
    3925              :    IFN_GOACC_DIM_SIZE call.  */
    3926              : 
    3927              : int
    3928        93969 : oacc_get_ifn_dim_arg (const gimple *stmt)
    3929              : {
    3930        93969 :   gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
    3931              :                        || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
    3932        93969 :   tree arg = gimple_call_arg (stmt, 0);
    3933        93969 :   HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
    3934              : 
    3935        93969 :   gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
    3936        93969 :   return (int) axis;
    3937              : }
    3938              : 
    3939              : /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
    3940              :    as appropriate.  */
    3941              : 
    3942              : tree
    3943       294934 : omp_build_component_ref (tree obj, tree field)
    3944              : {
    3945       294934 :   tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
    3946       294934 :   if (TREE_THIS_VOLATILE (field))
    3947           62 :     TREE_THIS_VOLATILE (ret) |= 1;
    3948       294934 :   if (TREE_READONLY (field))
    3949            0 :     TREE_READONLY (ret) |= 1;
    3950       294934 :   return ret;
    3951              : }
    3952              : 
    3953              : /* Return true if NAME is the name of an omp_* runtime API call.  */
    3954              : bool
    3955         8216 : omp_runtime_api_procname (const char *name)
    3956              : {
    3957         8216 :   if (!startswith (name, "omp_"))
    3958              :     return false;
    3959              : 
    3960              :   static const char *omp_runtime_apis[] =
    3961              :     {
    3962              :       /* This array has 3 sections.  First omp_* calls that don't
    3963              :          have any suffixes; this implies bind(C) either in the
    3964              :          specification or implementation choice.  */
    3965              :       "aligned_alloc",
    3966              :       "aligned_calloc",
    3967              :       "alloc",
    3968              :       "calloc",
    3969              :       "free",
    3970              :       "get_device_distances",
    3971              :       "get_interop_int",
    3972              :       "get_interop_ptr",
    3973              :       "get_mapped_ptr",
    3974              :       "get_num_interop_properties",
    3975              :       "get_num_teams_dim",
    3976              :       "get_num_threads_dim",
    3977              :       "get_supported_teams_dim",
    3978              :       "get_supported_threads_dim",
    3979              :       "get_team_num_dim",
    3980              :       "get_thread_limit_dim",
    3981              :       "get_thread_num_dim",
    3982              :       "realloc",
    3983              :       "target_alloc",
    3984              :       "target_associate_ptr",
    3985              :       "target_disassociate_ptr",
    3986              :       "target_free",
    3987              :       "target_is_accessible",
    3988              :       "target_is_present",
    3989              :       "target_memcpy",
    3990              :       "target_memcpy_async",
    3991              :       "target_memcpy_rect",
    3992              :       "target_memcpy_rect_async",
    3993              :       NULL,
    3994              :       /* Now omp_* calls that are available as omp_* and omp_*_; however, the
    3995              :          DECL_NAME is always omp_* without tailing underscore.  */
    3996              :       "capture_affinity",
    3997              :       "destroy_allocator",
    3998              :       "destroy_lock",
    3999              :       "destroy_nest_lock",
    4000              :       "display_affinity",
    4001              :       "fulfill_event",
    4002              :       "get_active_level",
    4003              :       "get_affinity_format",
    4004              :       "get_cancellation",
    4005              :       "get_default_allocator",
    4006              :       "get_default_device",
    4007              :       "get_device_from_uid",
    4008              :       "get_device_num",
    4009              :       "get_dynamic",
    4010              :       "get_initial_device",
    4011              :       "get_interop_name",
    4012              :       "get_interop_rc_desc",
    4013              :       "get_interop_str",
    4014              :       "get_interop_type_desc",
    4015              :       "get_level",
    4016              :       "get_max_active_levels",
    4017              :       "get_max_task_priority",
    4018              :       "get_max_teams",
    4019              :       "get_max_threads",
    4020              :       "get_nested",
    4021              :       "get_num_devices",
    4022              :       "get_num_places",
    4023              :       "get_num_procs",
    4024              :       "get_num_teams",
    4025              :       "get_num_threads",
    4026              :       "get_partition_num_places",
    4027              :       "get_place_num",
    4028              :       "get_proc_bind",
    4029              :       "get_supported_active_league_dims",
    4030              :       "get_supported_active_levels",
    4031              :       "get_supported_active_team_dims",
    4032              :       "get_team_num",
    4033              :       "get_teams_thread_limit",
    4034              :       "get_thread_limit",
    4035              :       "get_thread_num",
    4036              :       "get_wtick",
    4037              :       "get_wtime",
    4038              :       "in_explicit_task",
    4039              :       "in_final",
    4040              :       "in_parallel",
    4041              :       "init_lock",
    4042              :       "init_nest_lock",
    4043              :       "is_initial_device",
    4044              :       "pause_resource",
    4045              :       "pause_resource_all",
    4046              :       "set_affinity_format",
    4047              :       "set_default_allocator",
    4048              :       "set_lock",
    4049              :       "set_nest_lock",
    4050              :       "test_lock",
    4051              :       "test_nest_lock",
    4052              :       "unset_lock",
    4053              :       "unset_nest_lock",
    4054              :       NULL,
    4055              :       /* And finally calls available as omp_*, omp_*_ and omp_*_8_; however,
    4056              :          as DECL_NAME only omp_* and omp_*_8 appear.  */
    4057              :       "control_tool",
    4058              :       "display_env",
    4059              :       "get_ancestor_thread_num",
    4060              :       "get_uid_from_device",
    4061              :       "get_partition_place_nums",
    4062              :       "get_place_num_procs",
    4063              :       "get_place_proc_ids",
    4064              :       "get_schedule",
    4065              :       "get_team_size",
    4066              :       "init_allocator",
    4067              :       "set_default_device",
    4068              :       "set_dynamic",
    4069              :       "set_max_active_levels",
    4070              :       "set_nested",
    4071              :       "set_num_teams",
    4072              :       "set_num_threads",
    4073              :       "set_schedule",
    4074              :       "set_teams_thread_limit",
    4075              :       "target_memset"
    4076              :     };
    4077              : 
    4078              :   int mode = 0;
    4079        50618 :   for (unsigned i = 0; i < ARRAY_SIZE (omp_runtime_apis); i++)
    4080              :     {
    4081        50617 :       if (omp_runtime_apis[i] == NULL)
    4082              :         {
    4083          843 :           mode++;
    4084          843 :           continue;
    4085              :         }
    4086        49774 :       size_t len = strlen (omp_runtime_apis[i]);
    4087        49774 :       if (strncmp (name + 4, omp_runtime_apis[i], len) == 0
    4088          995 :           && (name[4 + len] == '\0'
    4089            3 :               || (mode > 1 && strcmp (name + 4 + len, "_8") == 0)))
    4090              :         return true;
    4091              :     }
    4092              :   return false;
    4093              : }
    4094              : 
    4095              : /* Return true if FNDECL is an omp_* runtime API call.  */
    4096              : 
    4097              : bool
    4098         9445 : omp_runtime_api_call (const_tree fndecl)
    4099              : {
    4100         9445 :   tree declname = DECL_NAME (fndecl);
    4101         9445 :   if (!declname
    4102         9445 :       || (DECL_CONTEXT (fndecl) != NULL_TREE
    4103         6869 :           && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
    4104        17326 :       || !TREE_PUBLIC (fndecl))
    4105              :     return false;
    4106         7738 :   return omp_runtime_api_procname (IDENTIFIER_POINTER (declname));
    4107              : }
    4108              : 
    4109              : /* See "Additional Definitions for the OpenMP API Specification" document;
    4110              :    associated IDs are 1, 2, ...  */
    4111              : static const char* omp_interop_fr_str[] = {"cuda", "cuda_driver", "opencl",
    4112              :                                            "sycl", "hip", "level_zero", "hsa"};
    4113              : 
    4114              : /* Returns the foreign-runtime ID if found or 0 otherwise.  */
    4115              : 
    4116              : char
    4117          523 : omp_get_fr_id_from_name (const char *str)
    4118              : {
    4119          523 :   static_assert (GOMP_INTEROP_IFR_LAST == ARRAY_SIZE (omp_interop_fr_str), "");
    4120              : 
    4121         2005 :   for (unsigned i = 0; i < ARRAY_SIZE (omp_interop_fr_str); ++i)
    4122         1965 :     if (!strcmp (str, omp_interop_fr_str[i]))
    4123          483 :       return i + 1;
    4124              :   return GOMP_INTEROP_IFR_UNKNOWN;
    4125              : }
    4126              : 
    4127              : /* Returns the string value to a foreign-runtime integer value or NULL if value
    4128              :    is not known.  */
    4129              : 
    4130              : const char *
    4131          386 : omp_get_name_from_fr_id (int fr_id)
    4132              : {
    4133          386 :   if (fr_id < 1 || fr_id > (int) ARRAY_SIZE (omp_interop_fr_str))
    4134              :     return "<unknown>";
    4135          272 :   return omp_interop_fr_str[fr_id-1];
    4136              : }
    4137              : 
    4138              : namespace omp_addr_tokenizer {
    4139              : 
    4140              : /* We scan an expression by recursive descent, and build a vector of
    4141              :    "omp_addr_token *" pointers representing a "parsed" version of the
    4142              :    expression.  The grammar we use is something like this:
    4143              : 
    4144              :      expr0::
    4145              :        expr [section-access]
    4146              : 
    4147              :      expr::
    4148              :          structured-expr access-method
    4149              :        | array-base access-method
    4150              : 
    4151              :      structured-expr::
    4152              :        structure-base component-selector
    4153              : 
    4154              :      arbitrary-expr::
    4155              :        (anything else)
    4156              : 
    4157              :      structure-base::
    4158              :          DECL access-method
    4159              :        | structured-expr access-method
    4160              :        | arbitrary-expr access-method
    4161              : 
    4162              :      array-base::
    4163              :          DECL
    4164              :        | arbitrary-expr
    4165              : 
    4166              :      access-method::
    4167              :          DIRECT
    4168              :        | REF
    4169              :        | POINTER
    4170              :        | REF_TO_POINTER
    4171              :        | POINTER_OFFSET
    4172              :        | REF_TO_POINTER_OFFSET
    4173              :        | INDEXED_ARRAY
    4174              :        | INDEXED_REF_TO_ARRAY
    4175              :        | index-expr
    4176              : 
    4177              :      index-expr::
    4178              :          INDEX_EXPR access-method
    4179              : 
    4180              :      component-selector::
    4181              :          component-selector COMPONENT_REF
    4182              :        | component-selector ARRAY_REF
    4183              :        | COMPONENT_REF
    4184              : 
    4185              :    This tokenized form is then used both in parsing, for OpenMP clause
    4186              :    expansion (for C and C++) and in gimplify.cc for sibling-list handling
    4187              :    (for C, C++ and Fortran).  */
    4188              : 
    4189        33925 : omp_addr_token::omp_addr_token (token_type t, tree e)
    4190        33925 :   : type(t), expr(e)
    4191              : {
    4192        33925 : }
    4193              : 
    4194       128163 : omp_addr_token::omp_addr_token (access_method_kinds k, tree e)
    4195       128163 :   : type(ACCESS_METHOD), expr(e)
    4196              : {
    4197       128163 :   u.access_kind = k;
    4198       128163 : }
    4199              : 
    4200        96488 : omp_addr_token::omp_addr_token (token_type t, structure_base_kinds k, tree e)
    4201        96488 :   : type(t), expr(e)
    4202              : {
    4203        96488 :   u.structure_base_kind = k;
    4204        96488 : }
    4205              : 
    4206              : static bool
    4207        96492 : omp_parse_component_selector (tree *expr0)
    4208              : {
    4209        96492 :   tree expr = *expr0;
    4210        96492 :   tree last_component = NULL_TREE;
    4211              : 
    4212        96492 :   while (TREE_CODE (expr) == COMPONENT_REF
    4213       142655 :          || TREE_CODE (expr) == ARRAY_REF)
    4214              :     {
    4215        46163 :       if (TREE_CODE (expr) == COMPONENT_REF)
    4216        42686 :         last_component = expr;
    4217              : 
    4218        46163 :       expr = TREE_OPERAND (expr, 0);
    4219              : 
    4220        46163 :       if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
    4221              :         break;
    4222              :     }
    4223              : 
    4224        96492 :   if (!last_component)
    4225              :     return false;
    4226              : 
    4227        33925 :   *expr0 = last_component;
    4228        33925 :   return true;
    4229              : }
    4230              : 
    4231              : /* This handles references that have had convert_from_reference called on
    4232              :    them, and also those that haven't.  */
    4233              : 
    4234              : static bool
    4235       167349 : omp_parse_ref (tree *expr0)
    4236              : {
    4237       167349 :   tree expr = *expr0;
    4238              : 
    4239       167349 :   if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)
    4240              :     return true;
    4241       163317 :   else if ((TREE_CODE (expr) == INDIRECT_REF
    4242       120088 :             || (TREE_CODE (expr) == MEM_REF
    4243            2 :                 && integer_zerop (TREE_OPERAND (expr, 1))))
    4244       163319 :            && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
    4245              :     {
    4246         9417 :       *expr0 = TREE_OPERAND (expr, 0);
    4247         9417 :       return true;
    4248              :     }
    4249              : 
    4250              :   return false;
    4251              : }
    4252              : 
    4253              : static bool
    4254       118574 : omp_parse_pointer (tree *expr0, bool *has_offset)
    4255              : {
    4256       118574 :   tree expr = *expr0;
    4257              : 
    4258       118574 :   *has_offset = false;
    4259              : 
    4260       118574 :   if ((TREE_CODE (expr) == INDIRECT_REF
    4261        87534 :        || (TREE_CODE (expr) == MEM_REF
    4262            1 :            && integer_zerop (TREE_OPERAND (expr, 1))))
    4263       118575 :       && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == POINTER_TYPE)
    4264              :     {
    4265        31041 :       expr = TREE_OPERAND (expr, 0);
    4266              : 
    4267              :       /* The Fortran FE sometimes emits a no-op cast here.  */
    4268        31041 :       STRIP_NOPS (expr);
    4269              : 
    4270        34405 :       while (1)
    4271              :         {
    4272        34405 :           if (TREE_CODE (expr) == COMPOUND_EXPR)
    4273              :             {
    4274          101 :               expr = TREE_OPERAND (expr, 1);
    4275          101 :               STRIP_NOPS (expr);
    4276              :             }
    4277        34304 :           else if (TREE_CODE (expr) == SAVE_EXPR)
    4278           89 :             expr = TREE_OPERAND (expr, 0);
    4279        34215 :           else if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
    4280              :             {
    4281         3174 :               *has_offset = true;
    4282         3174 :               expr = TREE_OPERAND (expr, 0);
    4283              :             }
    4284              :           else
    4285              :             break;
    4286              :         }
    4287              : 
    4288        31041 :       STRIP_NOPS (expr);
    4289              : 
    4290        31041 :       *expr0 = expr;
    4291        31041 :       return true;
    4292              :     }
    4293              : 
    4294              :   return false;
    4295              : }
    4296              : 
    4297              : static void
    4298       128163 : omp_parse_access_method (tree *expr0, enum access_method_kinds *kind)
    4299              : {
    4300       128163 :   tree expr = *expr0;
    4301       128163 :   bool has_offset;
    4302              : 
    4303       128163 :   if (omp_parse_ref (&expr))
    4304         9589 :     *kind = ACCESS_REF;
    4305       118574 :   else if (omp_parse_pointer (&expr, &has_offset))
    4306              :     {
    4307        31041 :       if (omp_parse_ref (&expr))
    4308         5574 :         *kind = has_offset ? ACCESS_REF_TO_POINTER_OFFSET
    4309              :                            : ACCESS_REF_TO_POINTER;
    4310              :       else
    4311        53334 :         *kind = has_offset ? ACCESS_POINTER_OFFSET : ACCESS_POINTER;
    4312              :     }
    4313        87533 :   else if (TREE_CODE (expr) == ARRAY_REF)
    4314              :     {
    4315        16590 :       while (TREE_CODE (expr) == ARRAY_REF)
    4316         8445 :         expr = TREE_OPERAND (expr, 0);
    4317         8145 :       if (omp_parse_ref (&expr))
    4318          689 :         *kind = ACCESS_INDEXED_REF_TO_ARRAY;
    4319              :       else
    4320         7456 :         *kind = ACCESS_INDEXED_ARRAY;
    4321              :     }
    4322              :   else
    4323        79388 :     *kind = ACCESS_DIRECT;
    4324              : 
    4325       128163 :   STRIP_NOPS (expr);
    4326              : 
    4327       128163 :   *expr0 = expr;
    4328       128163 : }
    4329              : 
    4330              : static void
    4331       128163 : omp_parse_access_methods (vec<omp_addr_token *> &addr_tokens, tree *expr0)
    4332              : {
    4333       128163 :   tree expr = *expr0;
    4334       128163 :   enum access_method_kinds kind;
    4335       128163 :   tree am_expr;
    4336              : 
    4337       128163 :   omp_parse_access_method (&expr, &kind);
    4338       128163 :   am_expr = expr;
    4339              : 
    4340       128163 :   if (TREE_CODE (expr) == INDIRECT_REF
    4341       128163 :       || TREE_CODE (expr) == MEM_REF
    4342       125390 :       || TREE_CODE (expr) == ARRAY_REF)
    4343         3172 :     omp_parse_access_methods (addr_tokens, &expr);
    4344              : 
    4345       128163 :   addr_tokens.safe_push (new omp_addr_token (kind, am_expr));
    4346              : 
    4347       128163 :   *expr0 = expr;
    4348       128163 : }
    4349              : 
    4350              : static bool omp_parse_structured_expr (vec<omp_addr_token *> &, tree *);
    4351              : 
    4352              : static bool
    4353        96488 : omp_parse_structure_base (vec<omp_addr_token *> &addr_tokens,
    4354              :                           tree *expr0, structure_base_kinds *kind,
    4355              :                           vec<omp_addr_token *> &base_access_tokens,
    4356              :                           bool allow_structured = true)
    4357              : {
    4358        96488 :   tree expr = *expr0;
    4359              : 
    4360        96488 :   if (allow_structured)
    4361        33925 :     omp_parse_access_methods (base_access_tokens, &expr);
    4362              : 
    4363        96488 :   if (DECL_P (expr))
    4364              :     {
    4365        90491 :       *kind = BASE_DECL;
    4366        90491 :       return true;
    4367              :     }
    4368              : 
    4369         5997 :   if (allow_structured && omp_parse_structured_expr (addr_tokens, &expr))
    4370              :     {
    4371         5422 :       *kind = BASE_COMPONENT_EXPR;
    4372         5422 :       *expr0 = expr;
    4373         5422 :       return true;
    4374              :     }
    4375              : 
    4376          575 :   *kind = BASE_ARBITRARY_EXPR;
    4377          575 :   *expr0 = expr;
    4378          575 :   return true;
    4379              : }
    4380              : 
    4381              : static bool
    4382        96492 : omp_parse_structured_expr (vec<omp_addr_token *> &addr_tokens, tree *expr0)
    4383              : {
    4384        96492 :   tree expr = *expr0;
    4385        96492 :   tree base_component = NULL_TREE;
    4386        96492 :   structure_base_kinds struct_base_kind;
    4387        96492 :   auto_vec<omp_addr_token *> base_access_tokens;
    4388              : 
    4389        96492 :   if (omp_parse_component_selector (&expr))
    4390        33925 :     base_component = expr;
    4391              :   else
    4392              :     return false;
    4393              : 
    4394        33925 :   gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
    4395        33925 :   expr = TREE_OPERAND (expr, 0);
    4396              : 
    4397        33925 :   tree structure_base = expr;
    4398              : 
    4399        33925 :   if (!omp_parse_structure_base (addr_tokens, &expr, &struct_base_kind,
    4400              :                                  base_access_tokens))
    4401              :     return false;
    4402              : 
    4403        33925 :   addr_tokens.safe_push (new omp_addr_token (STRUCTURE_BASE, struct_base_kind,
    4404        33925 :                                              structure_base));
    4405        33925 :   addr_tokens.safe_splice (base_access_tokens);
    4406        33925 :   addr_tokens.safe_push (new omp_addr_token (COMPONENT_SELECTOR,
    4407        33925 :                                              base_component));
    4408              : 
    4409        33925 :   *expr0 = expr;
    4410              : 
    4411        33925 :   return true;
    4412        96492 : }
    4413              : 
    4414              : static bool
    4415        62563 : omp_parse_array_expr (vec<omp_addr_token *> &addr_tokens, tree *expr0)
    4416              : {
    4417        62563 :   tree expr = *expr0;
    4418        62563 :   structure_base_kinds s_kind;
    4419        62563 :   auto_vec<omp_addr_token *> base_access_tokens;
    4420              : 
    4421        62563 :   if (!omp_parse_structure_base (addr_tokens, &expr, &s_kind,
    4422              :                                  base_access_tokens, false))
    4423              :     return false;
    4424              : 
    4425        62563 :   addr_tokens.safe_push (new omp_addr_token (ARRAY_BASE, s_kind, expr));
    4426        62563 :   addr_tokens.safe_splice (base_access_tokens);
    4427              : 
    4428        62563 :   *expr0 = expr;
    4429        62563 :   return true;
    4430        62563 : }
    4431              : 
    4432              : /* Return TRUE if the ACCESS_METHOD token at index 'i' has a further
    4433              :    ACCESS_METHOD chained after it (e.g., if we're processing an expression
    4434              :    containing multiple pointer indirections).  */
    4435              : 
    4436              : bool
    4437        48555 : omp_access_chain_p (vec<omp_addr_token *> &addr_tokens, unsigned i)
    4438              : {
    4439        48555 :   gcc_assert (addr_tokens[i]->type == ACCESS_METHOD);
    4440        48555 :   return (i + 1 < addr_tokens.length ()
    4441        48555 :           && addr_tokens[i + 1]->type == ACCESS_METHOD);
    4442              : }
    4443              : 
    4444              : /* Return the address of the object accessed by the ACCESS_METHOD token
    4445              :    at 'i': either of the next access method's expr, or of EXPR if we're at
    4446              :    the end of the list of tokens.  */
    4447              : 
    4448              : tree
    4449         4591 : omp_accessed_addr (vec<omp_addr_token *> &addr_tokens, unsigned i, tree expr)
    4450              : {
    4451         4591 :   if (i + 1 < addr_tokens.length ())
    4452           68 :     return build_fold_addr_expr (addr_tokens[i + 1]->expr);
    4453              :   else
    4454         4523 :     return build_fold_addr_expr (expr);
    4455              : }
    4456              : 
    4457              : } /* namespace omp_addr_tokenizer.  */
    4458              : 
    4459              : bool
    4460        91066 : omp_parse_expr (vec<omp_addr_token *> &addr_tokens, tree expr)
    4461              : {
    4462        91066 :   using namespace omp_addr_tokenizer;
    4463        91066 :   auto_vec<omp_addr_token *> expr_access_tokens;
    4464              : 
    4465        91066 :   omp_parse_access_methods (expr_access_tokens, &expr);
    4466              : 
    4467        91066 :   if (omp_parse_structured_expr (addr_tokens, &expr))
    4468              :     ;
    4469        62563 :   else if (omp_parse_array_expr (addr_tokens, &expr))
    4470              :     ;
    4471              :   else
    4472              :     return false;
    4473              : 
    4474        91066 :   addr_tokens.safe_splice (expr_access_tokens);
    4475              : 
    4476        91066 :   return true;
    4477        91066 : }
    4478              : 
    4479              : DEBUG_FUNCTION void
    4480            0 : debug_omp_tokenized_addr (vec<omp_addr_token *> &addr_tokens,
    4481              :                           bool with_exprs)
    4482              : {
    4483            0 :   using namespace omp_addr_tokenizer;
    4484            0 :   const char *sep = with_exprs ? "  " : "";
    4485              : 
    4486            0 :   for (auto e : addr_tokens)
    4487              :     {
    4488            0 :       const char *pfx = "";
    4489              : 
    4490            0 :       fputs (sep, stderr);
    4491              : 
    4492            0 :       switch (e->type)
    4493              :         {
    4494            0 :         case COMPONENT_SELECTOR:
    4495            0 :           fputs ("component_selector", stderr);
    4496            0 :           break;
    4497            0 :         case ACCESS_METHOD:
    4498            0 :           switch (e->u.access_kind)
    4499              :             {
    4500            0 :             case ACCESS_DIRECT:
    4501            0 :               fputs ("access_direct", stderr);
    4502            0 :               break;
    4503            0 :             case ACCESS_REF:
    4504            0 :               fputs ("access_ref", stderr);
    4505            0 :               break;
    4506            0 :             case ACCESS_POINTER:
    4507            0 :               fputs ("access_pointer", stderr);
    4508            0 :               break;
    4509            0 :             case ACCESS_POINTER_OFFSET:
    4510            0 :               fputs ("access_pointer_offset", stderr);
    4511            0 :               break;
    4512            0 :             case ACCESS_REF_TO_POINTER:
    4513            0 :               fputs ("access_ref_to_pointer", stderr);
    4514            0 :               break;
    4515            0 :             case ACCESS_REF_TO_POINTER_OFFSET:
    4516            0 :               fputs ("access_ref_to_pointer_offset", stderr);
    4517            0 :               break;
    4518            0 :             case ACCESS_INDEXED_ARRAY:
    4519            0 :               fputs ("access_indexed_array", stderr);
    4520            0 :               break;
    4521            0 :             case ACCESS_INDEXED_REF_TO_ARRAY:
    4522            0 :               fputs ("access_indexed_ref_to_array", stderr);
    4523            0 :               break;
    4524              :             }
    4525              :           break;
    4526            0 :         case ARRAY_BASE:
    4527            0 :         case STRUCTURE_BASE:
    4528            0 :           pfx = e->type == ARRAY_BASE ? "array_" : "struct_";
    4529            0 :           switch (e->u.structure_base_kind)
    4530              :             {
    4531            0 :             case BASE_DECL:
    4532            0 :               fprintf (stderr, "%sbase_decl", pfx);
    4533            0 :               break;
    4534            0 :             case BASE_COMPONENT_EXPR:
    4535            0 :               fputs ("base_component_expr", stderr);
    4536            0 :               break;
    4537            0 :             case BASE_ARBITRARY_EXPR:
    4538            0 :               fprintf (stderr, "%sbase_arbitrary_expr", pfx);
    4539            0 :               break;
    4540              :             }
    4541              :           break;
    4542              :         }
    4543            0 :       if (with_exprs)
    4544              :         {
    4545            0 :           fputs (" [", stderr);
    4546            0 :           print_generic_expr (stderr, e->expr);
    4547            0 :           fputc (']', stderr);
    4548            0 :           sep = ",\n  ";
    4549              :         }
    4550              :       else
    4551              :         sep = " ";
    4552              :     }
    4553              : 
    4554            0 :   fputs ("\n", stderr);
    4555            0 : }
    4556              : 
    4557              : /* Return number of iterations of loop I in FOR_STMT.  If PSTEP is non-NULL,
    4558              :    *PSTEP will be the loop step.  */
    4559              : 
    4560              : tree
    4561         2632 : omp_loop_number_of_iterations (tree for_stmt, int i, tree *pstep)
    4562              : {
    4563         2632 :   tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
    4564         2632 :   gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
    4565         2632 :   tree decl = TREE_OPERAND (t, 0);
    4566         2632 :   tree n1 = TREE_OPERAND (t, 1);
    4567         2632 :   tree type = TREE_TYPE (decl);
    4568         2632 :   tree cond = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
    4569         2632 :   gcc_assert (COMPARISON_CLASS_P (cond));
    4570         2632 :   gcc_assert (TREE_OPERAND (cond, 0) == decl);
    4571         2632 :   tree_code cond_code = TREE_CODE (cond);
    4572         2632 :   tree n2 = TREE_OPERAND (cond, 1);
    4573         2632 :   t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
    4574         2632 :   tree step = NULL_TREE;
    4575         2632 :   switch (TREE_CODE (t))
    4576              :     {
    4577         1141 :     case PREINCREMENT_EXPR:
    4578         1141 :     case POSTINCREMENT_EXPR:
    4579         1141 :       gcc_assert (!POINTER_TYPE_P (type));
    4580         1141 :       gcc_assert (TREE_OPERAND (t, 0) == decl);
    4581         1141 :       step = build_int_cst (type, 1);
    4582         1141 :       break;
    4583           42 :     case PREDECREMENT_EXPR:
    4584           42 :     case POSTDECREMENT_EXPR:
    4585           42 :       gcc_assert (!POINTER_TYPE_P (type));
    4586           42 :       gcc_assert (TREE_OPERAND (t, 0) == decl);
    4587           42 :       step = build_int_cst (type, -1);
    4588           42 :       break;
    4589         1449 :     case MODIFY_EXPR:
    4590         1449 :       gcc_assert (TREE_OPERAND (t, 0) == decl);
    4591         1449 :       t = TREE_OPERAND (t, 1);
    4592         1449 :       switch (TREE_CODE (t))
    4593              :         {
    4594         1374 :         case PLUS_EXPR:
    4595         1374 :           if (TREE_OPERAND (t, 1) == decl)
    4596              :             {
    4597            3 :               TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
    4598            3 :               TREE_OPERAND (t, 0) = decl;
    4599              :             }
    4600              :           /* FALLTHRU */
    4601              :         case POINTER_PLUS_EXPR:
    4602              :         case MINUS_EXPR:
    4603         1449 :           step = omp_get_for_step_from_incr (EXPR_LOCATION (t), t);
    4604         1449 :           break;
    4605            0 :         default:
    4606            0 :           gcc_unreachable ();
    4607              :         }
    4608         1449 :       break;
    4609            0 :     default:
    4610            0 :       gcc_unreachable ();
    4611              :     }
    4612         2632 :   omp_adjust_for_condition (EXPR_LOCATION (for_stmt), &cond_code, &n2,
    4613              :                             decl, step);
    4614         2632 :   if (pstep)
    4615         2094 :     *pstep = step;
    4616         2632 :   if (INTEGRAL_TYPE_P (type)
    4617         2632 :       && TYPE_PRECISION (type) < TYPE_PRECISION (long_long_integer_type_node))
    4618              :     {
    4619         2523 :       n1 = fold_convert (long_long_integer_type_node, n1);
    4620         2523 :       n2 = fold_convert (long_long_integer_type_node, n2);
    4621         2523 :       step = fold_convert (long_long_integer_type_node, step);
    4622              :     }
    4623         2632 :   if (cond_code == LT_EXPR
    4624          156 :       || POINTER_TYPE_P (type)
    4625         2768 :       || !TYPE_UNSIGNED (TREE_TYPE (n1)))
    4626              :     {
    4627         2632 :       if (POINTER_TYPE_P (type))
    4628           60 :         t = fold_build2 (POINTER_DIFF_EXPR, ssizetype, n2, n1);
    4629              :       else
    4630         2572 :         t = fold_build2 (MINUS_EXPR, TREE_TYPE (n1), n2, n1);
    4631         2632 :       t = fold_build2 (CEIL_DIV_EXPR, TREE_TYPE (t), t, step);
    4632              :     }
    4633              :   else
    4634              :     {
    4635            0 :       t = fold_build2 (MINUS_EXPR, type, n1, n2);
    4636            0 :       t = fold_build2 (CEIL_DIV_EXPR, type, t,
    4637              :                        fold_build1 (NEGATE_EXPR, type, step));
    4638              :     }
    4639         2632 :   return t;
    4640              : }
    4641              : 
    4642              : /* Tile transformation:
    4643              :    Original loop:
    4644              : 
    4645              :   #pragma omp tile sizes(16, 32)
    4646              :   for (i = 0; i < k; ++i)
    4647              :     for (j = 0; j < 128; j += 2)
    4648              :       {
    4649              :         baz (i, j);
    4650              :       }
    4651              : 
    4652              :    Transformed loop:
    4653              :   #pragma omp tile sizes(16, 32)
    4654              :   for (i.0 = 0; i.0 < k; i.0 += 16)
    4655              :     for (j.0 = 0; j.0 < 128; j.0 += 64)
    4656              :       {
    4657              :         i = i.0;
    4658              :         i.1 = MIN_EXPR <i.0 + 16, k>;
    4659              :         goto <D.2783>;
    4660              :         <D.2782>:;
    4661              :         j = j.0;
    4662              :         j.1 = j.0 + 32;
    4663              :         goto <D.2786>;
    4664              :         <D.2785>:;
    4665              :         {
    4666              :           baz (i, j);
    4667              :         }
    4668              :         j += 2;
    4669              :         <D.2786>:;
    4670              :         if (j < j.1) goto <D.2785>; else goto <D.2787>;
    4671              :         <D.2787>:;
    4672              :         ++i;
    4673              :         <D.2783>:;
    4674              :         if (i < i.1) goto <D.2782>; else goto <D.2784>;
    4675              :         <D.2784>:;
    4676              :       }
    4677              : 
    4678              :    where the grid loops have canonical form, but the inner
    4679              :    loops don't and so are immediately lowered.  */
    4680              : 
    4681              : static void
    4682         1953 : omp_apply_tile (tree for_stmt, tree sizes, int size)
    4683              : {
    4684         1953 :   tree pre_body = NULL_TREE, post_body = NULL_TREE;
    4685         1953 :   tree orig_sizes = sizes;
    4686         1953 :   if (OMP_FOR_NON_RECTANGULAR (for_stmt))
    4687              :     {
    4688           51 :       error_at (EXPR_LOCATION (for_stmt), "non-rectangular %<tile%>");
    4689           51 :       return;
    4690              :     }
    4691         4424 :   for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
    4692              :     {
    4693         2522 :       if (orig_sizes)
    4694              :         {
    4695         1734 :           size = tree_to_uhwi (TREE_VALUE (sizes));
    4696         1734 :           sizes = TREE_CHAIN (sizes);
    4697              :         }
    4698         2522 :       if (size == 1)
    4699          428 :         continue;
    4700         2094 :       if (OMP_FOR_ORIG_DECLS (for_stmt) == NULL_TREE)
    4701              :         {
    4702          517 :           OMP_FOR_ORIG_DECLS (for_stmt)
    4703          517 :             = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)));
    4704         1178 :           for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
    4705              :             {
    4706          661 :               gcc_assert (TREE_CODE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j))
    4707              :                           == MODIFY_EXPR);
    4708          661 :               TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), j)
    4709         1322 :                 = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j), 0);
    4710              :             }
    4711              :         }
    4712         2094 :       tree step;
    4713         2094 :       tree iters = omp_loop_number_of_iterations (for_stmt, i, &step);
    4714         2094 :       tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
    4715         2094 :       tree decl = TREE_OPERAND (t, 0);
    4716         2094 :       tree type = TREE_TYPE (decl);
    4717         2094 :       tree griddecl = create_tmp_var_raw (type);
    4718         2094 :       DECL_CONTEXT (griddecl) = current_function_decl;
    4719         2094 :       t = build1 (DECL_EXPR, void_type_node, griddecl);
    4720         2094 :       append_to_statement_list (t, &OMP_FOR_PRE_BODY (for_stmt));
    4721         2094 :       TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i), 0) = griddecl;
    4722         2094 :       TREE_PRIVATE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i)) = 1;
    4723         2094 :       tree cond = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
    4724         2094 :       TREE_OPERAND (cond, 0) = griddecl;
    4725         2094 :       tree ub = save_expr (TREE_OPERAND (cond, 1));
    4726         2094 :       TREE_OPERAND (cond, 1) = ub;
    4727         2094 :       t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
    4728         2094 :       if (TREE_CODE (cond) == NE_EXPR)
    4729              :         {
    4730          163 :           tree_code cond_code = TREE_CODE (cond);
    4731          163 :           omp_adjust_for_condition (EXPR_LOCATION (for_stmt), &cond_code,
    4732              :                                     &ub, griddecl, step);
    4733          163 :           TREE_SET_CODE (cond, cond_code);
    4734              :         }
    4735         2094 :       step = save_expr (step);
    4736         2094 :       tree gridstep = fold_build2 (MULT_EXPR, TREE_TYPE (step),
    4737              :                                    step, build_int_cst (TREE_TYPE (step),
    4738              :                                                         size));
    4739         2094 :       if (POINTER_TYPE_P (type))
    4740           52 :         t = build2 (POINTER_PLUS_EXPR, type, griddecl,
    4741              :                     fold_convert (sizetype, gridstep));
    4742              :       else
    4743         2042 :         t = build2 (PLUS_EXPR, type, griddecl, gridstep);
    4744         2094 :       t = build2 (MODIFY_EXPR, type, griddecl, t);
    4745         2094 :       TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
    4746         2094 :       t = build2 (MODIFY_EXPR, type, decl, griddecl);
    4747         2094 :       append_to_statement_list (t, &pre_body);
    4748         2094 :       if (POINTER_TYPE_P (type))
    4749           52 :         t = build2 (POINTER_PLUS_EXPR, type, griddecl,
    4750              :                     fold_convert (sizetype, gridstep));
    4751              :       else
    4752         2042 :         t = build2 (PLUS_EXPR, type, griddecl, gridstep);
    4753         2094 :       bool minmax_needed = true;
    4754         2094 :       if (TREE_CODE (iters) == INTEGER_CST)
    4755              :         {
    4756         1130 :           wide_int witers = wi::to_wide (iters);
    4757         1130 :           wide_int wsize = wide_int::from (size, witers.get_precision (),
    4758         1130 :                                            TYPE_SIGN (TREE_TYPE (iters)));
    4759         1130 :           if (wi::multiple_of_p (witers, wsize, TYPE_SIGN (TREE_TYPE (iters))))
    4760          412 :             minmax_needed = false;
    4761         1130 :         }
    4762         1130 :       if (minmax_needed)
    4763         1682 :         switch (TREE_CODE (cond))
    4764              :           {
    4765          251 :           case LE_EXPR:
    4766          251 :             if (POINTER_TYPE_P (type))
    4767            4 :               t = build2 (MIN_EXPR, type, t,
    4768              :                           build2 (POINTER_PLUS_EXPR, type, ub, size_int (1)));
    4769              :             else
    4770          247 :               t = build2 (MIN_EXPR, type, t,
    4771              :                           build2 (PLUS_EXPR, type, ub, build_one_cst (type)));
    4772              :             break;
    4773         1375 :           case LT_EXPR:
    4774         1375 :             t = build2 (MIN_EXPR, type, t, ub);
    4775         1375 :             break;
    4776           28 :           case GE_EXPR:
    4777           28 :             if (POINTER_TYPE_P (type))
    4778            8 :               t = build2 (MAX_EXPR, type, t,
    4779              :                           build2 (POINTER_PLUS_EXPR, type, ub, size_int (-1)));
    4780              :             else
    4781           20 :               t = build2 (MAX_EXPR, type, t,
    4782              :                           build2 (PLUS_EXPR, type, ub,
    4783              :                                   build_minus_one_cst (type)));
    4784              :             break;
    4785           28 :           case GT_EXPR:
    4786           28 :             t = build2 (MAX_EXPR, type, t, ub);
    4787           28 :             break;
    4788            0 :           default:
    4789            0 :             gcc_unreachable ();
    4790              :           }
    4791         2094 :       tree end = create_tmp_var_raw (type);
    4792         2094 :       DECL_CONTEXT (end) = current_function_decl;
    4793         2094 :       end = build4 (TARGET_EXPR, type, end, t, NULL_TREE, NULL_TREE);
    4794         2094 :       TREE_SIDE_EFFECTS (end) = 1;
    4795         2094 :       append_to_statement_list (end, &pre_body);
    4796         2094 :       tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
    4797         2094 :       tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
    4798         2094 :       t = build1 (GOTO_EXPR, void_type_node, lab2);
    4799         2094 :       append_to_statement_list (t, &pre_body);
    4800         2094 :       t = build1 (LABEL_EXPR, void_type_node, lab1);
    4801         2094 :       append_to_statement_list (t, &pre_body);
    4802         2094 :       tree this_post_body = NULL_TREE;
    4803         2094 :       if (POINTER_TYPE_P (type))
    4804           52 :         t = build2 (POINTER_PLUS_EXPR, type, decl,
    4805              :                     fold_convert (sizetype, step));
    4806              :       else
    4807         2042 :         t = build2 (PLUS_EXPR, type, decl, step);
    4808         2094 :       t = build2 (MODIFY_EXPR, type, decl, t);
    4809         2094 :       append_to_statement_list (t, &this_post_body);
    4810         2094 :       t = build1 (LABEL_EXPR, void_type_node, lab2);
    4811         2094 :       append_to_statement_list (t, &this_post_body);
    4812         2160 :       t = build2 ((TREE_CODE (cond) == LT_EXPR || TREE_CODE (cond) == LE_EXPR)
    4813              :                   ? LT_EXPR : GT_EXPR, boolean_type_node, decl, end);
    4814         2094 :       if (orig_sizes == NULL_TREE)
    4815              :         {
    4816          740 :           gcc_assert (i == 0);
    4817          740 :           t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t,
    4818              :                       build_int_cst (integer_type_node,
    4819              :                                      annot_expr_unroll_kind),
    4820          740 :                       build_int_cst (integer_type_node, size));
    4821              :         }
    4822         2094 :       t = build3 (COND_EXPR, void_type_node, t,
    4823              :                   build1 (GOTO_EXPR, void_type_node, lab1), NULL_TREE);
    4824         2094 :       append_to_statement_list (t, &this_post_body);
    4825         2094 :       append_to_statement_list (post_body, &this_post_body);
    4826         2094 :       post_body = this_post_body;
    4827              :     }
    4828         1902 :   if (pre_body || post_body)
    4829              :     {
    4830         1609 :       append_to_statement_list (OMP_FOR_BODY (for_stmt), &pre_body);
    4831         1609 :       append_to_statement_list (post_body, &pre_body);
    4832         1609 :       OMP_FOR_BODY (for_stmt) = pre_body;
    4833              :     }
    4834              : }
    4835              : 
    4836              : /* Callback for walk_tree to find nested loop transforming construct.  */
    4837              : 
    4838              : static tree
    4839         9281 : find_nested_loop_xform (tree *tp, int *walk_subtrees, void *data)
    4840              : {
    4841         9281 :   tree **pdata = (tree **) data;
    4842         9281 :   *walk_subtrees = 0;
    4843         9281 :   switch (TREE_CODE (*tp))
    4844              :     {
    4845         1982 :     case OMP_TILE:
    4846         1982 :     case OMP_UNROLL:
    4847         1982 :       pdata[1] = tp;
    4848         1982 :       return *tp;
    4849         2615 :     case BIND_EXPR:
    4850         2615 :       if (BIND_EXPR_VARS (*tp)
    4851         2615 :           || (BIND_EXPR_BLOCK (*tp)
    4852         1304 :               && BLOCK_VARS (BIND_EXPR_BLOCK (*tp))))
    4853         1311 :         pdata[0] = tp;
    4854         2615 :       *walk_subtrees = 1;
    4855         2615 :       break;
    4856          420 :     case STATEMENT_LIST:
    4857          420 :       if (!tsi_one_before_end_p (tsi_start (*tp)))
    4858          420 :         pdata[0] = tp;
    4859          420 :       *walk_subtrees = 1;
    4860          420 :       break;
    4861           32 :     case TRY_FINALLY_EXPR:
    4862           32 :     case CLEANUP_POINT_EXPR:
    4863           32 :       pdata[0] = tp;
    4864           32 :       *walk_subtrees = 1;
    4865           32 :       break;
    4866              :     default:
    4867              :       break;
    4868              :     }
    4869              :   return NULL;
    4870              : }
    4871              : 
    4872              : /* Main entry point for performing OpenMP loop transformations.  */
    4873              : 
    4874              : void
    4875        60583 : omp_maybe_apply_loop_xforms (tree *expr_p, tree for_clauses)
    4876              : {
    4877        60583 :   tree for_stmt = *expr_p;
    4878              : 
    4879        60583 :   switch (TREE_CODE (for_stmt))
    4880              :     {
    4881         3908 :     case OMP_TILE:
    4882         3908 :     case OMP_UNROLL:
    4883         3908 :       if (OMP_LOOPXFORM_LOWERED (for_stmt))
    4884              :         return;
    4885              :       break;
    4886              :     default:
    4887              :       break;
    4888              :     }
    4889              : 
    4890              :   tree *inner_expr_p = expr_p;
    4891              :   tree inner_for_stmt = for_stmt;
    4892       143053 :   for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
    4893              :     {
    4894              :       /* If some loop nest needs one or more loops in canonical form
    4895              :          from nested loop transforming constructs, first perform the
    4896              :          loop transformation on the nested construct and then move over
    4897              :          the corresponding loops in canonical form from the inner construct
    4898              :          to the outer one.  */
    4899        84187 :       if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE)
    4900              :         {
    4901         1511 :           if (inner_for_stmt == for_stmt
    4902         2998 :               && omp_find_clause (for_clauses ? for_clauses
    4903         1487 :                                   : OMP_FOR_CLAUSES (for_stmt),
    4904              :                                   OMP_CLAUSE_ORDERED))
    4905              :             {
    4906           73 :               error_at (EXPR_LOCATION (for_stmt),
    4907              :                         "%<ordered%> clause used with generated loops");
    4908           73 :               *expr_p = void_node;
    4909           73 :               return;
    4910              :             }
    4911         1438 :           tree *data[2] = { NULL, NULL };
    4912         1438 :           walk_tree (&OMP_FOR_BODY (inner_for_stmt),
    4913              :                      find_nested_loop_xform, &data, NULL);
    4914         1438 :           gcc_assert (data[1]);
    4915         1438 :           if (data[0])
    4916              :             {
    4917              :               /* If there is a BIND_EXPR declaring some vars, or statement
    4918              :                  list with more than one stmt etc., move the intervening
    4919              :                  code around the outermost loop.  */
    4920         1003 :               tree t = *inner_expr_p;
    4921         1003 :               *inner_expr_p = OMP_FOR_BODY (inner_for_stmt);
    4922         1003 :               OMP_FOR_BODY (inner_for_stmt) = *data[1];
    4923         1003 :               *data[1] = t;
    4924         1003 :               inner_expr_p = data[1];
    4925         1003 :               data[1] = &OMP_FOR_BODY (inner_for_stmt);
    4926              :             }
    4927         1438 :           inner_for_stmt = *data[1];
    4928              : 
    4929         1438 :           omp_maybe_apply_loop_xforms (data[1], NULL_TREE);
    4930         1438 :           if (*data[1] != inner_for_stmt)
    4931              :             {
    4932          544 :               tree *data2[2] = { NULL, NULL };
    4933          544 :               walk_tree (data[1], find_nested_loop_xform, &data2, NULL);
    4934          544 :               gcc_assert (data2[1]
    4935              :                           && *data2[1] == inner_for_stmt
    4936              :                           && data2[0]);
    4937          544 :               tree t = *inner_expr_p;
    4938          544 :               *inner_expr_p = *data[1];
    4939          544 :               *data[1] = *data2[1];
    4940          544 :               *data2[1] = t;
    4941          544 :               inner_expr_p = data2[1];
    4942              :             }
    4943         1438 :           tree clauses = OMP_FOR_CLAUSES (inner_for_stmt);
    4944         1438 :           gcc_checking_assert (TREE_CODE (inner_for_stmt) != OMP_UNROLL
    4945              :                                || omp_find_clause (clauses,
    4946              :                                                    OMP_CLAUSE_PARTIAL));
    4947         1438 :           append_to_statement_list (OMP_FOR_PRE_BODY (inner_for_stmt),
    4948              :                                     &OMP_FOR_PRE_BODY (for_stmt));
    4949         1438 :           OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
    4950         1438 :           if (OMP_FOR_ORIG_DECLS (for_stmt) == NULL_TREE
    4951         1438 :               && OMP_FOR_ORIG_DECLS (inner_for_stmt) != NULL_TREE)
    4952              :             {
    4953          619 :               OMP_FOR_ORIG_DECLS (for_stmt)
    4954          619 :                 = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)));
    4955         1456 :               for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
    4956              :                    j++)
    4957              :                 {
    4958          837 :                   if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j) == NULL_TREE)
    4959          712 :                     continue;
    4960          125 :                   gcc_assert (TREE_CODE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt),
    4961              :                                                        j)) == MODIFY_EXPR);
    4962          125 :                   TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), j)
    4963          250 :                     = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j),
    4964              :                                     0);
    4965              :                 }
    4966              :             }
    4967         3094 :           for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt));
    4968              :                ++j)
    4969              :             {
    4970         1919 :               if (i + j == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
    4971              :                 break;
    4972         1656 :               if (OMP_FOR_ORIG_DECLS (for_stmt))
    4973              :                 {
    4974         1571 :                   if (OMP_FOR_ORIG_DECLS (inner_for_stmt))
    4975              :                     {
    4976         1571 :                       TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i + j)
    4977         1571 :                         = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
    4978              :                                         j);
    4979         1571 :                       TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), j)
    4980         1571 :                         = NULL_TREE;
    4981              :                     }
    4982              :                   else
    4983              :                     {
    4984            0 :                       tree t = TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j);
    4985            0 :                       gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
    4986            0 :                       TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i + j)
    4987            0 :                         = TREE_OPERAND (t, 0);
    4988              :                     }
    4989              :                 }
    4990         1656 :               TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i + j)
    4991         1656 :                 = TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j);
    4992         1656 :               TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i + j)
    4993         1656 :                 = TREE_VEC_ELT (OMP_FOR_COND (inner_for_stmt), j);
    4994         1656 :               TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i + j)
    4995         1656 :                 = TREE_VEC_ELT (OMP_FOR_INCR (inner_for_stmt), j);
    4996         1656 :               TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j) = NULL_TREE;
    4997         1656 :               TREE_VEC_ELT (OMP_FOR_COND (inner_for_stmt), j) = NULL_TREE;
    4998         1656 :               TREE_VEC_ELT (OMP_FOR_INCR (inner_for_stmt), j) = NULL_TREE;
    4999              :             }
    5000              :         }
    5001              :     }
    5002              : 
    5003        58866 :   switch (TREE_CODE (for_stmt))
    5004              :     {
    5005         1165 :     case OMP_TILE:
    5006         1165 :       tree sizes;
    5007         1165 :       sizes = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_SIZES);
    5008         1165 :       omp_apply_tile (for_stmt, OMP_CLAUSE_SIZES_LIST (sizes), 0);
    5009         1165 :       OMP_LOOPXFORM_LOWERED (for_stmt) = 1;
    5010         1165 :       break;
    5011         1099 :     case OMP_UNROLL:
    5012         1099 :       tree partial;
    5013         1099 :       partial = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
    5014              :                                  OMP_CLAUSE_PARTIAL);
    5015         1099 :       if (partial)
    5016          788 :         omp_apply_tile (for_stmt, NULL_TREE,
    5017          788 :                         OMP_CLAUSE_PARTIAL_EXPR (partial)
    5018          604 :                         ? tree_to_shwi (OMP_CLAUSE_PARTIAL_EXPR (partial))
    5019              :                         : 8);
    5020          311 :       else if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL))
    5021              :         {
    5022          269 :           tree iters = omp_loop_number_of_iterations (for_stmt, 0, NULL);
    5023          269 :           if (TREE_CODE (iters) != INTEGER_CST)
    5024           12 :             error_at (EXPR_LOCATION (for_stmt),
    5025              :                       "non-constant iteration count of %<unroll full%> loop");
    5026              :         }
    5027         1099 :       OMP_LOOPXFORM_LOWERED (for_stmt) = 1;
    5028         1099 :       break;
    5029              :     default:
    5030              :       break;
    5031              :     }
    5032              : }
    5033              : 
    5034              : /* The next group of functions support merging of context selectors for
    5035              :    nested "begin declare variant" directives.  The spec says:
    5036              : 
    5037              :      ...the effective context selectors of the outer directive are
    5038              :      appended to the context selector of the inner directive to form the
    5039              :      effective context selector of the inner directive.  If a
    5040              :      trait-set-selector is present on both directives, the trait-selector
    5041              :      list of the outer directive is appended to the trait-selector list
    5042              :      of the inner directive after equivalent trait-selectors have been
    5043              :      removed from the outer list.
    5044              : 
    5045              :    In other words, there is no requirement to combine non-equivalent
    5046              :    trait-selectors according to their peculiar semantics, such as allowing
    5047              :    "any" as a wildcard, ANDing trait-property-expressions of "condition" trait
    5048              :    property expressions together, etc.  Also there is no special provision for
    5049              :    treating the "construct" selector as an ordered list.
    5050              : 
    5051              :    Note that the spec does not explicitly say what "equivalent" means;
    5052              :    whether the properties and score of the trait-selectors must be identical,
    5053              :    or only the name of the trait-selector.  This code assumes the former
    5054              :    except for the construct trait set where the order of selectors
    5055              :    is significant (so that it is *not* equivalent to have the same
    5056              :    trait-selector appearing in a different order in the list).  */
    5057              : 
    5058              : /* Copy traits from FROM_TS and push them onto TAIL.  */
    5059              : 
    5060              : static tree
    5061           36 : omp_copy_trait_set (tree from_ts, tree tail)
    5062              : {
    5063           92 :   for (tree ts = from_ts; ts; ts = TREE_CHAIN (ts))
    5064          112 :     tail = make_trait_selector (OMP_TS_CODE (ts), OMP_TS_SCORE (ts),
    5065           56 :                                 OMP_TS_PROPERTIES (ts), tail);
    5066           36 :   return nreverse (tail);
    5067              : }
    5068              : 
    5069              : /* Return true if trait selectors TS1 and TS2 for set TSS are "equivalent".  */
    5070              : 
    5071              : static bool
    5072            8 : omp_trait_selectors_equivalent (tree ts1, tree ts2, enum omp_tss_code tss)
    5073              : {
    5074            8 :   if (OMP_TS_CODE (ts1) != OMP_TS_CODE (ts2))
    5075              :     return false;
    5076              : 
    5077            8 :   tree score1 = OMP_TS_SCORE (ts1);
    5078            8 :   tree score2 = OMP_TS_SCORE (ts2);
    5079            0 :   if ((score1 && score2 && !simple_cst_equal (score1, score2))
    5080            8 :       || (score1 && !score2)
    5081           16 :       || (!score1 && score2))
    5082            0 :     return false;
    5083              : 
    5084           16 :   return (omp_context_selector_props_compare (tss, OMP_TS_CODE (ts1),
    5085            8 :                                               OMP_TS_PROPERTIES (ts1),
    5086            8 :                                               OMP_TS_PROPERTIES (ts2))
    5087            8 :           == 0);
    5088              : }
    5089              : 
    5090              : /* Merge lists of the trait selectors OUTER_TS and INNER_TS for selector set
    5091              :    TSS: "the trait-selector list of the outer directive is appended to the
    5092              :    trait-selector list of the inner directive after equivalent trait-selectors
    5093              :    have been removed from the outer list".  */
    5094              : 
    5095              : static tree
    5096           20 : omp_combine_trait_sets (tree outer_ts, tree inner_ts, enum omp_tss_code tss)
    5097              : {
    5098           20 :   unsigned HOST_WIDE_INT inner_traits = 0;
    5099           20 :   tree to_list = NULL_TREE;
    5100              : 
    5101           40 :   for (tree inner = inner_ts; inner; inner = TREE_CHAIN (inner))
    5102              :     {
    5103           20 :       omp_ts_code ts_code = OMP_TS_CODE (inner);
    5104           20 :       inner_traits |= 1 << ts_code;
    5105           20 :       to_list
    5106           20 :         = make_trait_selector (ts_code, OMP_TS_SCORE (inner),
    5107           20 :                                unshare_expr (OMP_TS_PROPERTIES (inner)),
    5108              :                                to_list);
    5109              :     }
    5110              : 
    5111           48 :   for (tree outer = outer_ts; outer; outer = TREE_CHAIN (outer))
    5112              :     {
    5113           28 :       omp_ts_code ts_code = OMP_TS_CODE (outer);
    5114           28 :       bool remove = false;
    5115           28 :       if (inner_traits & (1 << ts_code))
    5116            8 :         for (tree inner = inner_ts; inner; inner = TREE_CHAIN (inner))
    5117            8 :           if (OMP_TS_CODE (inner) == ts_code)
    5118              :             {
    5119            8 :               if (omp_trait_selectors_equivalent (inner, outer, tss))
    5120              :                 remove = true;
    5121              :               break;
    5122              :             }
    5123              :       if (!remove)
    5124           20 :         to_list
    5125           20 :           = make_trait_selector (ts_code, OMP_TS_SCORE (outer),
    5126           20 :                                  unshare_expr (OMP_TS_PROPERTIES (outer)),
    5127              :                                  to_list);
    5128              :     }
    5129              : 
    5130           20 :   return nreverse (to_list);
    5131              : }
    5132              : 
    5133              : /* Merge context selector INNER_CTX with OUTER_CTX.  LOC and DIRECTIVE are
    5134              :    used for error checking.  Returns the merged context, or error_mark_node
    5135              :    if the contexts cannot be merged.  */
    5136              : 
    5137              : tree
    5138           36 : omp_merge_context_selectors (location_t loc, tree outer_ctx, tree inner_ctx,
    5139              :                              enum omp_ctx_directive directive)
    5140              : {
    5141           36 :   tree merged_ctx = NULL_TREE;
    5142              : 
    5143           36 :   if (inner_ctx == error_mark_node || outer_ctx == error_mark_node)
    5144              :     return error_mark_node;
    5145              : 
    5146          216 :   for (unsigned i = OMP_TRAIT_SET_CONSTRUCT; i != OMP_TRAIT_SET_LAST; i++)
    5147              :     {
    5148          180 :       omp_tss_code tss_code = static_cast<omp_tss_code>(i);
    5149          180 :       tree outer_ts = omp_get_context_selector_list (outer_ctx, tss_code);
    5150          180 :       tree inner_ts = omp_get_context_selector_list (inner_ctx, tss_code);
    5151          180 :       tree merged_ts = NULL_TREE;
    5152              : 
    5153          180 :       if (inner_ts && outer_ts)
    5154           20 :         merged_ts = omp_combine_trait_sets (outer_ts, inner_ts, tss_code);
    5155          160 :       else if (inner_ts)
    5156           16 :         merged_ts = omp_copy_trait_set (inner_ts, NULL_TREE);
    5157          144 :       else if (outer_ts)
    5158           20 :         merged_ts = omp_copy_trait_set (outer_ts, NULL_TREE);
    5159              : 
    5160           56 :       if (merged_ts)
    5161           56 :         merged_ctx = make_trait_set_selector (tss_code, merged_ts,
    5162              :                                               merged_ctx);
    5163              :     }
    5164              : 
    5165           36 :   merged_ctx = nreverse (merged_ctx);
    5166           36 :   return omp_check_context_selector (loc, merged_ctx, directive);
    5167              : }
    5168              : 
    5169              : /* Remove duplicate and merge clauses mapping the same variable. This function
    5170              :    is called twice: FIRST in the C and C++ front-ends before any clause
    5171              :    expansion happens, then in the gimplifier before gathering groups. This is
    5172              :    because it is easier to process most clauses earlier but some duplicates
    5173              :    still get introduced during the early clause expansion in the front-ends. */
    5174              : 
    5175              : tree
    5176        91746 : omp_remove_duplicate_maps (tree clauses, bool first)
    5177              : {
    5178        91746 :   if (clauses == NULL_TREE)
    5179              :     return NULL_TREE;
    5180              : 
    5181        70170 :   tree outlist = NULL_TREE;
    5182        70170 :   tree *outlist_p = &outlist;
    5183        70170 :   bool remove = false;
    5184        70170 :   tree c1;
    5185       235342 :   for (c1 = clauses; OMP_CLAUSE_CHAIN (c1) != NULL_TREE;
    5186        82586 :        c1 = OMP_CLAUSE_CHAIN (c1))
    5187              :     {
    5188        82586 :       if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_MAP)
    5189              :         {
    5190        58243 :           *outlist_p = c1;
    5191        58243 :           outlist_p = &OMP_CLAUSE_CHAIN (*outlist_p);
    5192        58243 :           continue;
    5193              :         }
    5194              : 
    5195       124116 :       for (tree c2 = OMP_CLAUSE_CHAIN (c1); c2 != NULL_TREE;
    5196        99773 :            c2 = OMP_CLAUSE_CHAIN (c2))
    5197              :         {
    5198        99985 :           if (OMP_CLAUSE_CODE (c2) != OMP_CLAUSE_MAP)
    5199        18198 :             continue;
    5200              : 
    5201        81787 :           bool maybe_dup_found
    5202        81787 :             = (OMP_CLAUSE_CODE (c1) == OMP_CLAUSE_CODE (c2)
    5203        81787 :                && ((/* In the current state, a map clause decl is not supposed
    5204              :                        to be NULL; but let's be defensive.  */
    5205        81787 :                     OMP_CLAUSE_DECL (c1) == NULL_TREE
    5206            0 :                     && OMP_CLAUSE_DECL (c2) == NULL_TREE)
    5207        81787 :                    || operand_equal_p (OMP_CLAUSE_DECL (c1),
    5208        81787 :                                        OMP_CLAUSE_DECL (c2)))
    5209          970 :                && ((/* The clause size is generally not known right after
    5210              :                        parsing.  */
    5211          970 :                     OMP_CLAUSE_SIZE (c1) == NULL_TREE
    5212          308 :                     && OMP_CLAUSE_SIZE (c2) == NULL_TREE)
    5213          673 :                    || (OMP_CLAUSE_SIZE (c1) != NULL_TREE
    5214          662 :                        && OMP_CLAUSE_SIZE (c2) != NULL_TREE
    5215          344 :                        && operand_equal_p (OMP_CLAUSE_SIZE (c1),
    5216          344 :                                            OMP_CLAUSE_SIZE (c2))))
    5217        82310 :                && ((OMP_CLAUSE_ITERATORS (c1) == NULL_TREE
    5218          523 :                     && OMP_CLAUSE_ITERATORS (c2) == NULL_TREE)
    5219            0 :                    || operand_equal_p (OMP_CLAUSE_ITERATORS (c1),
    5220        99773 :                                        OMP_CLAUSE_ITERATORS (c2))));
    5221          523 :           if (maybe_dup_found)
    5222              :             {
    5223          523 :               if (first)
    5224              :                 {
    5225          234 :                   if (OMP_CLAUSE_MAP_KIND (c1) == OMP_CLAUSE_MAP_KIND (c2))
    5226              :                     {
    5227              :                       remove = true;
    5228              :                       break;
    5229              :                     }
    5230          126 :                   else if ((OMP_CLAUSE_MAP_KIND (c1) & ~GOMP_MAP_TOFROM)
    5231          126 :                            == (OMP_CLAUSE_MAP_KIND (c2) & ~GOMP_MAP_TOFROM))
    5232              :                     {
    5233           93 :                       OMP_CLAUSE_SET_MAP_KIND (c2,
    5234              :                                                (OMP_CLAUSE_MAP_KIND (c1)
    5235              :                                                 | OMP_CLAUSE_MAP_KIND (c2)));
    5236           93 :                       remove = true;
    5237           93 :                       break;
    5238              :                     }
    5239              :                 }
    5240              :               /* When called from the gimplifier, remove duplicate map clauses
    5241              :                  with identical kind only when the bits above
    5242              :                  GOMP_MAP_FLAG_SPECIAL_2 are unset - as clauses with those flags
    5243              :                  set may need to be present multiple times.  */
    5244          289 :               else if (OMP_CLAUSE_MAP_KIND (c1) == OMP_CLAUSE_MAP_KIND (c2)
    5245          289 :                        && (OMP_CLAUSE_MAP_KIND (c1) & ~0b11111) == 0)
    5246              :                 {
    5247              :                   remove = true;
    5248              :                   break;
    5249              :                 }
    5250              :             }
    5251              :         }
    5252        24343 :       if (remove)
    5253              :         remove = false;
    5254              :       else
    5255              :         {
    5256        24131 :           *outlist_p = c1;
    5257        24131 :           outlist_p = &OMP_CLAUSE_CHAIN (*outlist_p);
    5258              :         }
    5259              :     }
    5260        70170 :   *outlist_p = c1;
    5261        70170 :   return outlist;
    5262              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.