LCOV - code coverage report
Current view: top level - gcc - optabs-tree.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.5 % 285 255
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 13 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Tree-based target query functions relating to optabs
       2              :    Copyright (C) 1987-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "target.h"
      25              : #include "insn-codes.h"
      26              : #include "rtl.h"
      27              : #include "tree.h"
      28              : #include "memmodel.h"
      29              : #include "optabs.h"
      30              : #include "optabs-tree.h"
      31              : #include "stor-layout.h"
      32              : #include "internal-fn.h"
      33              : 
      34              : /* Return the optab used for computing the operation given by the tree code,
      35              :    CODE and the tree EXP.  This function is not always usable (for example, it
      36              :    cannot give complete results for multiplication or division) but probably
      37              :    ought to be relied on more widely throughout the expander.  */
      38              : optab
      39     10032987 : optab_for_tree_code (enum tree_code code, const_tree type,
      40              :                      enum optab_subtype subtype)
      41              : {
      42     10032987 :   bool trapv;
      43     10032987 :   switch (code)
      44              :     {
      45              :     case BIT_AND_EXPR:
      46              :       return and_optab;
      47              : 
      48       226793 :     case BIT_IOR_EXPR:
      49       226793 :       return ior_optab;
      50              : 
      51         7016 :     case BIT_NOT_EXPR:
      52         7016 :       return one_cmpl_optab;
      53              : 
      54        50532 :     case BIT_XOR_EXPR:
      55        50532 :       return xor_optab;
      56              : 
      57         2720 :     case MULT_HIGHPART_EXPR:
      58         2720 :       return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab;
      59              : 
      60           42 :     case CEIL_MOD_EXPR:
      61           42 :     case FLOOR_MOD_EXPR:
      62           42 :     case ROUND_MOD_EXPR:
      63              :       /* {s,u}mod_optab implements TRUNC_MOD_EXPR.  For scalar modes,
      64              :          expansion has code to adjust TRUNC_MOD_EXPR into the desired other
      65              :          modes, but for vector modes it does not.  The adjustment code
      66              :          should be instead emitted in tree-vect-patterns.cc.  */
      67           42 :       if (VECTOR_TYPE_P (type))
      68              :         return unknown_optab;
      69              :       /* FALLTHRU */
      70        39152 :     case TRUNC_MOD_EXPR:
      71        39152 :       return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
      72              : 
      73           18 :     case CEIL_DIV_EXPR:
      74           18 :     case FLOOR_DIV_EXPR:
      75           18 :     case ROUND_DIV_EXPR:
      76              :       /* {,u}{s,u}div_optab implements {TRUNC,EXACT}_DIV_EXPR or RDIV_EXPR.
      77              :          For scalar modes, expansion has code to adjust TRUNC_DIV_EXPR
      78              :          into the desired other modes, but for vector modes it does not.
      79              :          The adjustment code should be instead emitted in
      80              :          tree-vect-patterns.cc.  */
      81           18 :       if (VECTOR_TYPE_P (type))
      82              :         return unknown_optab;
      83              :       /* FALLTHRU */
      84        33398 :     case RDIV_EXPR:
      85        33398 :       gcc_assert (FLOAT_TYPE_P (type)
      86              :                   || ALL_FIXED_POINT_MODE_P (TYPE_MODE (type)));
      87              :       /* FALLTHRU */
      88        80964 :     case TRUNC_DIV_EXPR:
      89        80964 :     case EXACT_DIV_EXPR:
      90        80964 :       if (TYPE_SATURATING (type))
      91            0 :         return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
      92        80964 :       return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
      93              : 
      94       692956 :     case LSHIFT_EXPR:
      95       692956 :       if (VECTOR_TYPE_P (type))
      96              :         {
      97       692922 :           if (subtype == optab_vector)
      98       334669 :             return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
      99              : 
     100       358253 :           gcc_assert (subtype == optab_scalar);
     101              :         }
     102       358287 :       if (TYPE_SATURATING (type))
     103            0 :         return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
     104              :       return ashl_optab;
     105              : 
     106       226915 :     case RSHIFT_EXPR:
     107       226915 :       if (VECTOR_TYPE_P (type))
     108              :         {
     109       226888 :           if (subtype == optab_vector)
     110       108804 :             return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
     111              : 
     112       118084 :           gcc_assert (subtype == optab_scalar);
     113              :         }
     114       118111 :       return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
     115              : 
     116          387 :     case LROTATE_EXPR:
     117          387 :       if (VECTOR_TYPE_P (type))
     118              :         {
     119          387 :           if (subtype == optab_vector)
     120              :             return vrotl_optab;
     121              : 
     122          155 :           gcc_assert (subtype == optab_scalar);
     123              :         }
     124              :       return rotl_optab;
     125              : 
     126        12497 :     case RROTATE_EXPR:
     127        12497 :       if (VECTOR_TYPE_P (type))
     128              :         {
     129        12497 :           if (subtype == optab_vector)
     130              :             return vrotr_optab;
     131              : 
     132         6340 :           gcc_assert (subtype == optab_scalar);
     133              :         }
     134              :       return rotr_optab;
     135              : 
     136        88862 :     case MAX_EXPR:
     137        88862 :       return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
     138              : 
     139        45457 :     case MIN_EXPR:
     140        45457 :       return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
     141              : 
     142              :     case POINTER_PLUS_EXPR:
     143              :       return add_optab;
     144              : 
     145              :     case POINTER_DIFF_EXPR:
     146              :       return sub_optab;
     147              : 
     148            0 :     case REALIGN_LOAD_EXPR:
     149            0 :       return vec_realign_load_optab;
     150              : 
     151         1619 :     case WIDEN_SUM_EXPR:
     152         1619 :       return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
     153              : 
     154         1388 :     case DOT_PROD_EXPR:
     155         1388 :       {
     156         1388 :         if (subtype == optab_vector_mixed_sign)
     157              :           return usdot_prod_optab;
     158              : 
     159         1015 :         return (TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab);
     160              :       }
     161              : 
     162          540 :     case SAD_EXPR:
     163          540 :       return TYPE_UNSIGNED (type) ? usad_optab : ssad_optab;
     164              : 
     165        33333 :     case WIDEN_MULT_PLUS_EXPR:
     166        33333 :       return (TYPE_UNSIGNED (type)
     167        33333 :               ? (TYPE_SATURATING (type)
     168        23731 :                  ? usmadd_widen_optab : umadd_widen_optab)
     169         9602 :               : (TYPE_SATURATING (type)
     170         9602 :                  ? ssmadd_widen_optab : smadd_widen_optab));
     171              : 
     172          861 :     case WIDEN_MULT_MINUS_EXPR:
     173          861 :       return (TYPE_UNSIGNED (type)
     174          861 :               ? (TYPE_SATURATING (type)
     175          470 :                  ? usmsub_widen_optab : umsub_widen_optab)
     176          391 :               : (TYPE_SATURATING (type)
     177          391 :                  ? ssmsub_widen_optab : smsub_widen_optab));
     178              : 
     179        79358 :     case VEC_WIDEN_MULT_HI_EXPR:
     180        79358 :       return (TYPE_UNSIGNED (type)
     181        79358 :               ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab);
     182              : 
     183        79351 :     case VEC_WIDEN_MULT_LO_EXPR:
     184        79351 :       return (TYPE_UNSIGNED (type)
     185        79351 :               ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab);
     186              : 
     187       169453 :     case VEC_WIDEN_MULT_EVEN_EXPR:
     188       169453 :       return (TYPE_UNSIGNED (type)
     189       169453 :               ? vec_widen_umult_even_optab : vec_widen_smult_even_optab);
     190              : 
     191       169453 :     case VEC_WIDEN_MULT_ODD_EXPR:
     192       169453 :       return (TYPE_UNSIGNED (type)
     193       169453 :               ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab);
     194              : 
     195         9309 :     case VEC_WIDEN_LSHIFT_HI_EXPR:
     196         9309 :       return (TYPE_UNSIGNED (type)
     197         9309 :               ? vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab);
     198              : 
     199         9309 :     case VEC_WIDEN_LSHIFT_LO_EXPR:
     200         9309 :       return (TYPE_UNSIGNED (type)
     201         9309 :               ? vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab);
     202              : 
     203        53165 :     case VEC_UNPACK_HI_EXPR:
     204        53165 :       return (TYPE_UNSIGNED (type)
     205        53165 :               ? vec_unpacku_hi_optab : vec_unpacks_hi_optab);
     206              : 
     207        53143 :     case VEC_UNPACK_LO_EXPR:
     208        53143 :       return (TYPE_UNSIGNED (type)
     209        53143 :               ? vec_unpacku_lo_optab : vec_unpacks_lo_optab);
     210              : 
     211         8099 :     case VEC_UNPACK_FLOAT_HI_EXPR:
     212              :       /* The signedness is determined from input operand.  */
     213         8099 :       return (TYPE_UNSIGNED (type)
     214         8099 :               ? vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab);
     215              : 
     216         8099 :     case VEC_UNPACK_FLOAT_LO_EXPR:
     217              :       /* The signedness is determined from input operand.  */
     218         8099 :       return (TYPE_UNSIGNED (type)
     219         8099 :               ? vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab);
     220              : 
     221          237 :     case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
     222              :       /* The signedness is determined from output operand.  */
     223          237 :       return (TYPE_UNSIGNED (type)
     224          237 :               ? vec_unpack_ufix_trunc_hi_optab
     225              :               : vec_unpack_sfix_trunc_hi_optab);
     226              : 
     227          237 :     case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
     228              :       /* The signedness is determined from output operand.  */
     229          237 :       return (TYPE_UNSIGNED (type)
     230          237 :               ? vec_unpack_ufix_trunc_lo_optab
     231              :               : vec_unpack_sfix_trunc_lo_optab);
     232              : 
     233        56409 :     case VEC_PACK_TRUNC_EXPR:
     234        56409 :       return vec_pack_trunc_optab;
     235              : 
     236            0 :     case VEC_PACK_SAT_EXPR:
     237            0 :       return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
     238              : 
     239          877 :     case VEC_PACK_FIX_TRUNC_EXPR:
     240              :       /* The signedness is determined from output operand.  */
     241          877 :       return (TYPE_UNSIGNED (type)
     242          877 :               ? vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab);
     243              : 
     244          241 :     case VEC_PACK_FLOAT_EXPR:
     245              :       /* The signedness is determined from input operand.  */
     246          241 :       return (TYPE_UNSIGNED (type)
     247          241 :               ? vec_packu_float_optab : vec_packs_float_optab);
     248              : 
     249            0 :     case VEC_DUPLICATE_EXPR:
     250            0 :       return vec_duplicate_optab;
     251              : 
     252            0 :     case VEC_SERIES_EXPR:
     253            0 :       return vec_series_optab;
     254              : 
     255      6411092 :     default:
     256      6411092 :       break;
     257              :     }
     258              : 
     259      6411092 :   trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
     260      6411092 :   switch (code)
     261              :     {
     262      4450764 :     case PLUS_EXPR:
     263      4450764 :       if (TYPE_SATURATING (type))
     264            0 :         return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
     265      4450764 :       return trapv ? addv_optab : add_optab;
     266              : 
     267       911301 :     case MINUS_EXPR:
     268       911301 :       if (TYPE_SATURATING (type))
     269            0 :         return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
     270       911301 :       return trapv ? subv_optab : sub_optab;
     271              : 
     272       890962 :     case MULT_EXPR:
     273       890962 :       if (TYPE_SATURATING (type))
     274            0 :         return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
     275       890962 :       return trapv ? smulv_optab : smul_optab;
     276              : 
     277        65731 :     case NEGATE_EXPR:
     278        65731 :       if (TYPE_SATURATING (type))
     279            0 :         return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
     280        65731 :       return trapv ? negv_optab : neg_optab;
     281              : 
     282         2138 :     case ABS_EXPR:
     283         2138 :       return trapv ? absv_optab : abs_optab;
     284              : 
     285              :     case ABSU_EXPR:
     286              :       return abs_optab;
     287              :     default:
     288              :       return unknown_optab;
     289              :     }
     290              : }
     291              : 
     292              : /* Check whether an operation represented by CODE is a 'half' widening operation
     293              :    in which the input vector type has half the number of bits of the output
     294              :    vector type e.g. V8QI->V8HI.
     295              : 
     296              :    This is handled by widening the inputs using NOP_EXPRs then using a
     297              :    non-widening stmt e.g. MINUS_EXPR.  RTL fusing converts these to the widening
     298              :    hardware instructions if supported.
     299              : 
     300              :    The more typical case (handled in supportable_widening_operation) is where
     301              :    the input vector type has the same number of bits as the output vector type.
     302              :    In this case half the elements of the input vectors must be processed at a
     303              :    time into respective vector outputs with elements twice as wide i.e. a
     304              :    'hi'/'lo' pair using codes such as VEC_WIDEN_MINUS_HI/LO.
     305              : 
     306              :    Supported widening operations:
     307              :     WIDEN_MULT_EXPR
     308              :     WIDEN_LSHIFT_EXPR
     309              : 
     310              :    Output:
     311              :    - CODE1 - The non-widened code, which will be used after the inputs are
     312              :      converted to the wide type.  */
     313              : bool
     314          243 : supportable_half_widening_operation (enum tree_code code, tree vectype_out,
     315              :                                      tree vectype_in, enum tree_code *code1)
     316              : {
     317          243 :   machine_mode m1,m2;
     318          243 :   enum tree_code dummy_code;
     319          243 :   optab op;
     320              : 
     321          243 :   gcc_assert (VECTOR_TYPE_P (vectype_out) && VECTOR_TYPE_P (vectype_in));
     322              : 
     323          243 :   m1 = TYPE_MODE (vectype_out);
     324          243 :   m2 = TYPE_MODE (vectype_in);
     325              : 
     326          243 :   if (!VECTOR_MODE_P (m1) || !VECTOR_MODE_P (m2))
     327              :     return false;
     328              : 
     329          243 :   if (maybe_ne (TYPE_VECTOR_SUBPARTS (vectype_in),
     330          486 :                   TYPE_VECTOR_SUBPARTS (vectype_out)))
     331              :     return false;
     332              : 
     333          243 :   switch (code)
     334              :     {
     335            0 :     case WIDEN_LSHIFT_EXPR:
     336            0 :       *code1 = LSHIFT_EXPR;
     337            0 :       break;
     338          243 :     case WIDEN_MULT_EXPR:
     339          243 :       *code1 = MULT_EXPR;
     340          243 :       break;
     341              :     default:
     342              :       return false;
     343              :     }
     344              : 
     345          243 :   if (!supportable_convert_operation (NOP_EXPR, vectype_out, vectype_in,
     346              :                                      &dummy_code))
     347              :     return false;
     348              : 
     349          209 :   op = optab_for_tree_code (*code1, vectype_out, optab_vector);
     350          209 :   return (optab_handler (op, TYPE_MODE (vectype_out)) != CODE_FOR_nothing);
     351              : }
     352              : 
     353              : /* Function supportable_convert_operation
     354              : 
     355              :    Check whether an operation represented by the code CODE is a
     356              :    convert operation that is supported by the target platform in
     357              :    vector form (i.e., when operating on arguments of type VECTYPE_IN
     358              :    producing a result of type VECTYPE_OUT).
     359              : 
     360              :    Convert operations we currently support directly are FIX_TRUNC and FLOAT.
     361              :    This function checks if these operations are supported
     362              :    by the target platform directly (via vector tree-codes).
     363              : 
     364              :    Output:
     365              :    - CODE1 is code of vector operation to be used when
     366              :    vectorizing the operation, if available.  */
     367              : 
     368              : bool
     369        72332 : supportable_convert_operation (enum tree_code code,
     370              :                                tree vectype_out, tree vectype_in,
     371              :                                enum tree_code *code1)
     372              : {
     373        72332 :   machine_mode m1,m2;
     374        72332 :   bool truncp;
     375              : 
     376        72332 :   gcc_assert (VECTOR_TYPE_P (vectype_out) && VECTOR_TYPE_P (vectype_in));
     377              : 
     378        72332 :   m1 = TYPE_MODE (vectype_out);
     379        72332 :   m2 = TYPE_MODE (vectype_in);
     380              : 
     381        72332 :   if (!VECTOR_MODE_P (m1) || !VECTOR_MODE_P (m2))
     382              :     return false;
     383              : 
     384              :   /* First check if we can done conversion directly.  */
     385        72175 :   if ((code == FIX_TRUNC_EXPR
     386         1164 :        && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp)
     387              :           != CODE_FOR_nothing)
     388        72475 :       || (code == FLOAT_EXPR
     389         6528 :           && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
     390              :              != CODE_FOR_nothing))
     391              :     {
     392         6959 :       *code1 = code;
     393         6959 :       return true;
     394              :     }
     395              : 
     396       130432 :   if (GET_MODE_UNIT_PRECISION (m1) > GET_MODE_UNIT_PRECISION (m2)
     397        65216 :       && can_extend_p (m1, m2, TYPE_UNSIGNED (vectype_in)))
     398              :     {
     399         6449 :       *code1 = code;
     400         6449 :       return true;
     401              :     }
     402              : 
     403       117534 :   if (GET_MODE_UNIT_PRECISION (m1) < GET_MODE_UNIT_PRECISION (m2)
     404        64192 :       && convert_optab_handler (trunc_optab, m1, m2) != CODE_FOR_nothing)
     405              :     {
     406         3422 :       *code1 = code;
     407         3422 :       return true;
     408              :     }
     409              : 
     410              :   return false;
     411              : }
     412              : 
     413              : /* Return true iff vec_cmp_optab/vec_cmpu_optab can handle a vector comparison
     414              :    for code CODE, comparing operands of type VALUE_TYPE and producing a result
     415              :    of type MASK_TYPE.  */
     416              : 
     417              : static bool
     418      1316706 : vec_cmp_icode_p (tree value_type, tree mask_type, enum tree_code code)
     419              : {
     420      1316706 :   enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (value_type));
     421      1316706 :   if (rcode == UNKNOWN)
     422              :     return false;
     423              : 
     424      1316706 :   return can_vec_cmp_compare_p (rcode, TYPE_MODE (value_type),
     425      2633412 :                                 TYPE_MODE (mask_type));
     426              : }
     427              : 
     428              : /* Return true iff vec_cmpeq_optab can handle a vector comparison for code
     429              :    CODE, comparing operands of type VALUE_TYPE and producing a result of type
     430              :    MASK_TYPE.  */
     431              : 
     432              : static bool
     433       362051 : vec_cmp_eq_icode_p (tree value_type, tree mask_type, enum tree_code code)
     434              : {
     435       362051 :   if (code != EQ_EXPR && code != NE_EXPR)
     436              :     return false;
     437              : 
     438       180155 :   return get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
     439       180155 :          != CODE_FOR_nothing;
     440              : }
     441              : 
     442              : /* Return TRUE if appropriate vector insn is available
     443              :    for vector comparison expr with vector type VALUE_TYPE
     444              :    and resulting mask with MASK_TYPE.  */
     445              : 
     446              : bool
     447      1316706 : expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
     448              : {
     449      1316706 :   return vec_cmp_icode_p (value_type, mask_type, code)
     450      1316706 :          || vec_cmp_eq_icode_p (value_type, mask_type, code);
     451              : }
     452              : 
     453              : /* Return TRUE iff, appropriate vector insns are available
     454              :    for vector cond expr with vector type VALUE_TYPE and a comparison
     455              :    with operand vector types in CMP_OP_TYPE.  */
     456              : 
     457              : bool
     458        95304 : expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
     459              : {
     460        95304 :   if (VECTOR_BOOLEAN_TYPE_P (cmp_op_type)
     461       285912 :       && get_vcond_mask_icode (TYPE_MODE (value_type),
     462        95304 :                                TYPE_MODE (cmp_op_type)) != CODE_FOR_nothing)
     463              :     return true;
     464              : 
     465              :   return false;
     466              : }
     467              : 
     468              : /* Use the current target and options to initialize
     469              :    TREE_OPTIMIZATION_OPTABS (OPTNODE).  */
     470              : 
     471              : void
     472      1650796 : init_tree_optimization_optabs (tree optnode)
     473              : {
     474              :   /* Quick exit if we have already computed optabs for this target.  */
     475      1650796 :   if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs)
     476              :     return;
     477              : 
     478              :   /* Forget any previous information and set up for the current target.  */
     479        23889 :   TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs;
     480        23889 :   struct target_optabs *tmp_optabs = (struct target_optabs *)
     481        23889 :     TREE_OPTIMIZATION_OPTABS (optnode);
     482        23889 :   if (tmp_optabs)
     483          436 :     memset (tmp_optabs, 0, sizeof (struct target_optabs));
     484              :   else
     485        23453 :     tmp_optabs = ggc_cleared_alloc<target_optabs> ();
     486              : 
     487              :   /* Generate a new set of optabs into tmp_optabs.  */
     488        23889 :   init_all_optabs (tmp_optabs);
     489              : 
     490              :   /* If the optabs changed, record it.  */
     491        23889 :   if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
     492        10469 :     TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
     493              :   else
     494              :     {
     495        13420 :       TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
     496        13420 :       ggc_free (tmp_optabs);
     497              :     }
     498              : }
     499              : 
     500              : /* Return TRUE if the target has support for vector right shift of an
     501              :    operand of type TYPE.  If OT_TYPE is OPTAB_DEFAULT, check for existence
     502              :    of a shift by either a scalar or a vector.  Otherwise, check only
     503              :    for a shift that matches OT_TYPE.  */
     504              : 
     505              : bool
     506       272964 : target_supports_op_p (tree type, enum tree_code code,
     507              :                       enum optab_subtype ot_subtype)
     508              : {
     509       272964 :   optab ot = optab_for_tree_code (code, type, ot_subtype);
     510       272964 :   return ot != unknown_optab && can_implement_p (ot, TYPE_MODE (type));
     511              : }
     512              : 
     513              : /* Return true if the target has support for masked load/store.
     514              :    We can support masked load/store by either mask{load,store}
     515              :    or mask_len_{load,store}.
     516              :    This helper function checks whether target supports masked
     517              :    load/store and return corresponding IFN in the last argument
     518              :    (IFN_MASK_{LOAD,STORE} or IFN_MASK_LEN_{LOAD,STORE}).
     519              :    If there is support and ELSVALS is nonzero store the possible else values
     520              :    in the vector it points to.  */
     521              : 
     522              : bool
     523       234013 : target_supports_mask_load_store_p (machine_mode mode, machine_mode mask_mode,
     524              :                                    bool is_load, internal_fn *ifn,
     525              :                                    vec<int> *elsvals)
     526              : {
     527       234013 :   optab op = is_load ? maskload_optab : maskstore_optab;
     528        54594 :   optab len_op = is_load ? mask_len_load_optab : mask_len_store_optab;
     529       234013 :   enum insn_code icode;
     530       234013 :   if ((icode = convert_optab_handler (op, mode, mask_mode))
     531              :       != CODE_FOR_nothing)
     532              :     {
     533        71853 :       if (ifn)
     534         2163 :         *ifn = is_load ? IFN_MASK_LOAD : IFN_MASK_STORE;
     535        71853 :       if (elsvals && is_load)
     536        45974 :         get_supported_else_vals (icode,
     537        45974 :                                  internal_fn_else_index (IFN_MASK_LOAD),
     538              :                                  *elsvals);
     539        71853 :       return true;
     540              :     }
     541       162160 :   else if ((icode = convert_optab_handler (len_op, mode, mask_mode))
     542              :            != CODE_FOR_nothing)
     543              :     {
     544            0 :       if (ifn)
     545            0 :         *ifn = is_load ? IFN_MASK_LEN_LOAD : IFN_MASK_LEN_STORE;
     546            0 :       if (elsvals && is_load)
     547            0 :         get_supported_else_vals (icode,
     548            0 :                                  internal_fn_else_index (IFN_MASK_LEN_LOAD),
     549              :                                  *elsvals);
     550            0 :       return true;
     551              :     }
     552              :   return false;
     553              : }
     554              : 
     555              : /* Return true if target supports vector masked load/store for mode.
     556              :    An additional output in the last argument which is the IFN pointer.
     557              :    We set IFN as MASK_{LOAD,STORE} or MASK_LEN_{LOAD,STORE} according
     558              :    which optab is supported in the target.
     559              :    If there is support and ELSVALS is nonzero store the possible else values
     560              :    in the vector it points to.  */
     561              : 
     562              : bool
     563       212832 : can_vec_mask_load_store_p (machine_mode mode,
     564              :                            machine_mode mask_mode,
     565              :                            bool is_load,
     566              :                            internal_fn *ifn,
     567              :                            vec<int> *elsvals)
     568              : {
     569       212832 :   machine_mode vmode;
     570              : 
     571              :   /* If mode is vector mode, check it directly.  */
     572       212832 :   if (VECTOR_MODE_P (mode))
     573       200896 :     return target_supports_mask_load_store_p (mode, mask_mode, is_load, ifn,
     574       200896 :                                               elsvals);
     575              : 
     576              :   /* Otherwise, return true if there is some vector mode with
     577              :      the mask load/store supported.  */
     578              : 
     579              :   /* See if there is any chance the mask load or store might be
     580              :      vectorized.  If not, punt.  */
     581        11936 :   scalar_mode smode;
     582        11936 :   if (!is_a <scalar_mode> (mode, &smode))
     583              :     return false;
     584              : 
     585        11936 :   vmode = targetm.vectorize.preferred_simd_mode (smode);
     586         2263 :   if (VECTOR_MODE_P (vmode)
     587        11758 :       && targetm.vectorize.get_mask_mode (vmode).exists (&mask_mode)
     588        23694 :       && target_supports_mask_load_store_p (vmode, mask_mode, is_load, ifn,
     589              :                                             elsvals))
     590         2237 :     return true;
     591              : 
     592         9699 :   auto_vector_modes vector_modes;
     593         9699 :   targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
     594        56783 :   for (machine_mode base_mode : vector_modes)
     595        27686 :     if (related_vector_mode (base_mode, smode).exists (&vmode)
     596        49045 :         && targetm.vectorize.get_mask_mode (vmode).exists (&mask_mode)
     597        21359 :         && target_supports_mask_load_store_p (vmode, mask_mode, is_load, ifn,
     598              :                                               elsvals))
     599            0 :       return true;
     600              :   return false;
     601         9699 : }
     602              : 
     603              : /* Return true if the target has support for len load/store.
     604              :    We can support len load/store by either len_{load,store}
     605              :    or mask_len_{load,store}.
     606              :    This helper function checks whether target supports len
     607              :    load/store and return corresponding IFN in the last argument
     608              :    (IFN_LEN_{LOAD,STORE} or IFN_MASK_LEN_{LOAD,STORE}).
     609              :    If there is support and ELSVALS is nonzero store thepossible
     610              :    else values in the vector it points to.  */
     611              : 
     612              : static bool
     613       393602 : target_supports_len_load_store_p (machine_mode mode, bool is_load,
     614              :                                   internal_fn *ifn, vec<int> *elsvals)
     615              : {
     616       393602 :   optab op = is_load ? len_load_optab : len_store_optab;
     617        91440 :   optab masked_op = is_load ? mask_len_load_optab : mask_len_store_optab;
     618       393602 :   internal_fn which_ifn;
     619              : 
     620       393602 :   enum insn_code icode;
     621       393602 :   if ((icode = direct_optab_handler (op, mode)) != CODE_FOR_nothing)
     622              :     {
     623            0 :       which_ifn = is_load ? IFN_LEN_LOAD : IFN_LEN_STORE;
     624              :     }
     625       393602 :   machine_mode mask_mode;
     626       393602 :   if (!icode
     627       787204 :       && targetm.vectorize.get_mask_mode (mode).exists (&mask_mode)
     628       393602 :       && ((icode = convert_optab_handler (masked_op, mode, mask_mode))
     629              :           != CODE_FOR_nothing))
     630            0 :     which_ifn = is_load ? IFN_MASK_LEN_LOAD : IFN_MASK_LEN_STORE;
     631              : 
     632       393602 :   if (icode && elsvals && is_load)
     633            0 :     get_supported_else_vals (icode, internal_fn_else_index (which_ifn),
     634              :                              *elsvals);
     635              : 
     636       393602 :   if (icode && ifn)
     637            0 :     *ifn = which_ifn;
     638       393602 :   return icode;
     639              : }
     640              : 
     641              : /* If target supports vector load/store with length for vector mode MODE,
     642              :    return the corresponding vector mode, otherwise return opt_machine_mode ().
     643              :    There are two flavors for vector load/store with length, one is to measure
     644              :    length with bytes, the other is to measure length with lanes.
     645              :    As len_{load,store} optabs point out, for the flavor with bytes, we use
     646              :    VnQI to wrap the other supportable same size vector modes.
     647              :    An additional output in the last argument which is the IFN pointer.
     648              :    We set IFN as LEN_{LOAD,STORE} or MASK_LEN_{LOAD,STORE} according
     649              :    which optab is supported in the target.
     650              :    If there is support and ELSVALS is nonzero store the possible else values
     651              :    in the vector it points to.  */
     652              : 
     653              : opt_machine_mode
     654       196802 : get_len_load_store_mode (machine_mode mode, bool is_load, internal_fn *ifn,
     655              :                          vec<int> *elsvals)
     656              : {
     657       196802 :   gcc_assert (VECTOR_MODE_P (mode));
     658              : 
     659              :   /* Check if length in lanes supported for this mode directly.  */
     660       196802 :   if (target_supports_len_load_store_p (mode, is_load, ifn, elsvals))
     661            0 :     return mode;
     662              : 
     663              :   /* Check if length in bytes supported for same vector size VnQI.  */
     664       196802 :   machine_mode vmode;
     665       393604 :   poly_uint64 nunits = GET_MODE_SIZE (mode);
     666       196802 :   if (related_vector_mode (mode, QImode, nunits).exists (&vmode)
     667       196800 :       && target_supports_len_load_store_p (vmode, is_load, ifn, elsvals))
     668            0 :     return vmode;
     669              : 
     670       196802 :   return opt_machine_mode ();
     671              : }
        

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.