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

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.