LCOV - code coverage report
Current view: top level - gcc - optabs-query.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.0 % 300 258
Test Date: 2024-12-21 13:15:12 Functions: 96.6 % 29 28
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* IR-agnostic target query functions relating to optabs
       2                 :             :    Copyright (C) 1987-2024 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 "optabs-query.h"
      27                 :             : #include "optabs-libfuncs.h"
      28                 :             : #include "insn-config.h"
      29                 :             : #include "rtl.h"
      30                 :             : #include "recog.h"
      31                 :             : #include "vec-perm-indices.h"
      32                 :             : #include "internal-fn.h"
      33                 :             : #include "memmodel.h"
      34                 :             : #include "optabs.h"
      35                 :             : 
      36                 :             : struct target_optabs default_target_optabs;
      37                 :             : struct target_optabs *this_fn_optabs = &default_target_optabs;
      38                 :             : #if SWITCHABLE_TARGET
      39                 :             : struct target_optabs *this_target_optabs = &default_target_optabs;
      40                 :             : #endif
      41                 :             : 
      42                 :             : /* Return the insn used to perform conversion OP from mode FROM_MODE
      43                 :             :    to mode TO_MODE; return CODE_FOR_nothing if the target does not have
      44                 :             :    such an insn, or if it is unsuitable for optimization type OPT_TYPE.  */
      45                 :             : 
      46                 :             : insn_code
      47                 :        5612 : convert_optab_handler (convert_optab optab, machine_mode to_mode,
      48                 :             :                        machine_mode from_mode, optimization_type opt_type)
      49                 :             : {
      50                 :        5612 :   insn_code icode = convert_optab_handler (optab, to_mode, from_mode);
      51                 :        5612 :   if (icode == CODE_FOR_nothing
      52                 :        5612 :       || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type))
      53                 :        5030 :     return CODE_FOR_nothing;
      54                 :             :   return icode;
      55                 :             : }
      56                 :             : 
      57                 :             : /* Return the insn used to implement mode MODE of OP; return
      58                 :             :    CODE_FOR_nothing if the target does not have such an insn,
      59                 :             :    or if it is unsuitable for optimization type OPT_TYPE.  */
      60                 :             : 
      61                 :             : insn_code
      62                 :     4825254 : direct_optab_handler (convert_optab optab, machine_mode mode,
      63                 :             :                       optimization_type opt_type)
      64                 :             : {
      65                 :     4825254 :   insn_code icode = direct_optab_handler (optab, mode);
      66                 :     4825254 :   if (icode == CODE_FOR_nothing
      67                 :     4825254 :       || !targetm.optab_supported_p (optab, mode, mode, opt_type))
      68                 :     4622313 :     return CODE_FOR_nothing;
      69                 :             :   return icode;
      70                 :             : }
      71                 :             : 
      72                 :             : /* Enumerates the possible types of structure operand to an
      73                 :             :    extraction_insn.  */
      74                 :             : enum extraction_type { ET_unaligned_mem, ET_reg };
      75                 :             : 
      76                 :             : /* Check whether insv, extv or extzv pattern ICODE can be used for an
      77                 :             :    insertion or extraction of type TYPE on a structure of mode MODE.
      78                 :             :    Return true if so and fill in *INSN accordingly.  STRUCT_OP is the
      79                 :             :    operand number of the structure (the first sign_extract or zero_extract
      80                 :             :    operand) and FIELD_OP is the operand number of the field (the other
      81                 :             :    side of the set from the sign_extract or zero_extract).  */
      82                 :             : 
      83                 :             : static bool
      84                 :           0 : get_traditional_extraction_insn (extraction_insn *insn,
      85                 :             :                                  enum extraction_type type,
      86                 :             :                                  machine_mode mode,
      87                 :             :                                  enum insn_code icode,
      88                 :             :                                  int struct_op, int field_op)
      89                 :             : {
      90                 :           0 :   const struct insn_data_d *data = &insn_data[icode];
      91                 :             : 
      92                 :           0 :   machine_mode struct_mode = data->operand[struct_op].mode;
      93                 :           0 :   if (struct_mode == VOIDmode)
      94                 :           0 :     struct_mode = word_mode;
      95                 :           0 :   if (mode != struct_mode)
      96                 :             :     return false;
      97                 :             : 
      98                 :           0 :   machine_mode field_mode = data->operand[field_op].mode;
      99                 :           0 :   if (field_mode == VOIDmode)
     100                 :           0 :     field_mode = word_mode;
     101                 :             : 
     102                 :           0 :   machine_mode pos_mode = data->operand[struct_op + 2].mode;
     103                 :           0 :   if (pos_mode == VOIDmode)
     104                 :           0 :     pos_mode = word_mode;
     105                 :             : 
     106                 :           0 :   insn->icode = icode;
     107                 :           0 :   insn->field_mode = as_a <scalar_int_mode> (field_mode);
     108                 :           0 :   if (type == ET_unaligned_mem)
     109                 :           0 :     insn->struct_mode = byte_mode;
     110                 :           0 :   else if (struct_mode == BLKmode)
     111                 :           0 :     insn->struct_mode = opt_scalar_int_mode ();
     112                 :             :   else
     113                 :           0 :     insn->struct_mode = as_a <scalar_int_mode> (struct_mode);
     114                 :           0 :   insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
     115                 :           0 :   return true;
     116                 :             : }
     117                 :             : 
     118                 :             : /* Return true if an optab exists to perform an insertion or extraction
     119                 :             :    of type TYPE in mode MODE.  Describe the instruction in *INSN if so.
     120                 :             : 
     121                 :             :    REG_OPTAB is the optab to use for register structures and
     122                 :             :    MISALIGN_OPTAB is the optab to use for misaligned memory structures.
     123                 :             :    POS_OP is the operand number of the bit position.  */
     124                 :             : 
     125                 :             : static bool
     126                 :     3393738 : get_optab_extraction_insn (class extraction_insn *insn,
     127                 :             :                            enum extraction_type type,
     128                 :             :                            machine_mode mode, direct_optab reg_optab,
     129                 :             :                            direct_optab misalign_optab, int pos_op)
     130                 :             : {
     131                 :     3393738 :   direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
     132                 :     3393738 :   enum insn_code icode = direct_optab_handler (optab, mode);
     133                 :     3393738 :   if (icode == CODE_FOR_nothing)
     134                 :             :     return false;
     135                 :             : 
     136                 :     1494730 :   const struct insn_data_d *data = &insn_data[icode];
     137                 :             : 
     138                 :     1494730 :   machine_mode pos_mode = data->operand[pos_op].mode;
     139                 :     1494730 :   if (pos_mode == VOIDmode)
     140                 :           0 :     pos_mode = word_mode;
     141                 :             : 
     142                 :     1494730 :   insn->icode = icode;
     143                 :     1494730 :   insn->field_mode = as_a <scalar_int_mode> (mode);
     144                 :     1494730 :   if (type == ET_unaligned_mem)
     145                 :           0 :     insn->struct_mode = opt_scalar_int_mode ();
     146                 :             :   else
     147                 :     1494730 :     insn->struct_mode = insn->field_mode;
     148                 :     1494730 :   insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
     149                 :     1494730 :   return true;
     150                 :             : }
     151                 :             : 
     152                 :             : /* Return true if an instruction exists to perform an insertion or
     153                 :             :    extraction (PATTERN says which) of type TYPE in mode MODE.
     154                 :             :    Describe the instruction in *INSN if so.  */
     155                 :             : 
     156                 :             : static bool
     157                 :     3393738 : get_extraction_insn (extraction_insn *insn,
     158                 :             :                      enum extraction_pattern pattern,
     159                 :             :                      enum extraction_type type,
     160                 :             :                      machine_mode mode)
     161                 :             : {
     162                 :     3393738 :   switch (pattern)
     163                 :             :     {
     164                 :      545496 :     case EP_insv:
     165                 :      545496 :       if (targetm.have_insv ()
     166                 :      545496 :           && get_traditional_extraction_insn (insn, type, mode,
     167                 :             :                                               targetm.code_for_insv, 0, 3))
     168                 :             :         return true;
     169                 :      545496 :       return get_optab_extraction_insn (insn, type, mode, insv_optab,
     170                 :      545496 :                                         insvmisalign_optab, 2);
     171                 :             : 
     172                 :      734261 :     case EP_extv:
     173                 :      734261 :       if (targetm.have_extv ()
     174                 :      734261 :           && get_traditional_extraction_insn (insn, type, mode,
     175                 :             :                                               targetm.code_for_extv, 1, 0))
     176                 :             :         return true;
     177                 :      734261 :       return get_optab_extraction_insn (insn, type, mode, extv_optab,
     178                 :      734261 :                                         extvmisalign_optab, 3);
     179                 :             : 
     180                 :     2113981 :     case EP_extzv:
     181                 :     2113981 :       if (targetm.have_extzv ()
     182                 :     2113981 :           && get_traditional_extraction_insn (insn, type, mode,
     183                 :             :                                               targetm.code_for_extzv, 1, 0))
     184                 :             :         return true;
     185                 :     2113981 :       return get_optab_extraction_insn (insn, type, mode, extzv_optab,
     186                 :     2113981 :                                         extzvmisalign_optab, 3);
     187                 :             : 
     188                 :           0 :     default:
     189                 :           0 :       gcc_unreachable ();
     190                 :             :     }
     191                 :             : }
     192                 :             : 
     193                 :             : /* Return true if an instruction exists to access a field of mode
     194                 :             :    FIELDMODE in a structure that has STRUCT_BITS significant bits.
     195                 :             :    Describe the "best" such instruction in *INSN if so.  PATTERN and
     196                 :             :    TYPE describe the type of insertion or extraction we want to perform.
     197                 :             : 
     198                 :             :    For an insertion, the number of significant structure bits includes
     199                 :             :    all bits of the target.  For an extraction, it need only include the
     200                 :             :    most significant bit of the field.  Larger widths are acceptable
     201                 :             :    in both cases.  */
     202                 :             : 
     203                 :             : static bool
     204                 :     1817224 : get_best_extraction_insn (extraction_insn *insn,
     205                 :             :                           enum extraction_pattern pattern,
     206                 :             :                           enum extraction_type type,
     207                 :             :                           unsigned HOST_WIDE_INT struct_bits,
     208                 :             :                           machine_mode field_mode)
     209                 :             : {
     210                 :     1817224 :   opt_scalar_int_mode mode_iter;
     211                 :             : 
     212                 :     3716232 :   FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits))
     213                 :             :     {
     214                 :     3393738 :       scalar_int_mode mode = mode_iter.require ();
     215                 :     3393738 :       if (get_extraction_insn (insn, pattern, type, mode))
     216                 :             :         {
     217                 :     1494730 :           FOR_EACH_MODE_FROM (mode_iter, mode)
     218                 :             :             {
     219                 :     1494730 :               mode = mode_iter.require ();
     220                 :     2989460 :               if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode))
     221                 :     1494730 :                   || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
     222                 :             :                                                     field_mode))
     223                 :             :                 break;
     224                 :           0 :               get_extraction_insn (insn, pattern, type, mode);
     225                 :             :             }
     226                 :     1494730 :           return true;
     227                 :             :         }
     228                 :             :     }
     229                 :             :   return false;
     230                 :             : }
     231                 :             : 
     232                 :             : /* Return true if an instruction exists to access a field of mode
     233                 :             :    FIELDMODE in a register structure that has STRUCT_BITS significant bits.
     234                 :             :    Describe the "best" such instruction in *INSN if so.  PATTERN describes
     235                 :             :    the type of insertion or extraction we want to perform.
     236                 :             : 
     237                 :             :    For an insertion, the number of significant structure bits includes
     238                 :             :    all bits of the target.  For an extraction, it need only include the
     239                 :             :    most significant bit of the field.  Larger widths are acceptable
     240                 :             :    in both cases.  */
     241                 :             : 
     242                 :             : bool
     243                 :     1610832 : get_best_reg_extraction_insn (extraction_insn *insn,
     244                 :             :                               enum extraction_pattern pattern,
     245                 :             :                               unsigned HOST_WIDE_INT struct_bits,
     246                 :             :                               machine_mode field_mode)
     247                 :             : {
     248                 :     1610832 :   return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
     249                 :     1610832 :                                    field_mode);
     250                 :             : }
     251                 :             : 
     252                 :             : /* Return true if an instruction exists to access a field of BITSIZE
     253                 :             :    bits starting BITNUM bits into a memory structure.  Describe the
     254                 :             :    "best" such instruction in *INSN if so.  PATTERN describes the type
     255                 :             :    of insertion or extraction we want to perform and FIELDMODE is the
     256                 :             :    natural mode of the extracted field.
     257                 :             : 
     258                 :             :    The instructions considered here only access bytes that overlap
     259                 :             :    the bitfield; they do not touch any surrounding bytes.  */
     260                 :             : 
     261                 :             : bool
     262                 :      206392 : get_best_mem_extraction_insn (extraction_insn *insn,
     263                 :             :                               enum extraction_pattern pattern,
     264                 :             :                               HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
     265                 :             :                               machine_mode field_mode)
     266                 :             : {
     267                 :      206392 :   unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
     268                 :      206392 :                                         + bitsize
     269                 :      206392 :                                         + BITS_PER_UNIT - 1);
     270                 :      206392 :   struct_bits -= struct_bits % BITS_PER_UNIT;
     271                 :      206392 :   return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
     272                 :      206392 :                                    struct_bits, field_mode);
     273                 :             : }
     274                 :             : 
     275                 :             : /* Return the insn code used to extend FROM_MODE to TO_MODE.
     276                 :             :    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
     277                 :             :    no such operation exists, CODE_FOR_nothing will be returned.  */
     278                 :             : 
     279                 :             : enum insn_code
     280                 :     5153755 : can_extend_p (machine_mode to_mode, machine_mode from_mode,
     281                 :             :               int unsignedp)
     282                 :             : {
     283                 :     5153755 :   if (unsignedp < 0 && targetm.have_ptr_extend ())
     284                 :           0 :     return targetm.code_for_ptr_extend;
     285                 :             : 
     286                 :     5153755 :   convert_optab tab = unsignedp ? zext_optab : sext_optab;
     287                 :     5153755 :   return convert_optab_handler (tab, to_mode, from_mode);
     288                 :             : }
     289                 :             : 
     290                 :             : /* Return the insn code to convert fixed-point mode FIXMODE to floating-point
     291                 :             :    mode FLTMODE, or CODE_FOR_nothing if no such instruction exists.
     292                 :             :    UNSIGNEDP specifies whether FIXMODE is unsigned.  */
     293                 :             : 
     294                 :             : enum insn_code
     295                 :      363361 : can_float_p (machine_mode fltmode, machine_mode fixmode,
     296                 :             :              int unsignedp)
     297                 :             : {
     298                 :      363361 :   convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
     299                 :      363361 :   return convert_optab_handler (tab, fltmode, fixmode);
     300                 :             : }
     301                 :             : 
     302                 :             : /* Return the insn code to convert floating-point mode FLTMODE to fixed-point
     303                 :             :    mode FIXMODE, or CODE_FOR_nothing if no such instruction exists.
     304                 :             :    UNSIGNEDP specifies whether FIXMODE is unsigned.
     305                 :             : 
     306                 :             :    On a successful return, set *TRUNCP_PTR to true if it is necessary to
     307                 :             :    output an explicit FTRUNC before the instruction.  */
     308                 :             : 
     309                 :             : enum insn_code
     310                 :      250579 : can_fix_p (machine_mode fixmode, machine_mode fltmode,
     311                 :             :            int unsignedp, bool *truncp_ptr)
     312                 :             : {
     313                 :      250579 :   convert_optab tab;
     314                 :      250579 :   enum insn_code icode;
     315                 :             : 
     316                 :      250579 :   tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
     317                 :      250579 :   icode = convert_optab_handler (tab, fixmode, fltmode);
     318                 :      250579 :   if (icode != CODE_FOR_nothing)
     319                 :             :     {
     320                 :       50392 :       *truncp_ptr = false;
     321                 :       50392 :       return icode;
     322                 :             :     }
     323                 :             : 
     324                 :             :   /* FIXME: This requires a port to define both FIX and FTRUNC pattern
     325                 :             :      for this to work.  We need to rework the fix* and ftrunc* patterns
     326                 :             :      and documentation.  */
     327                 :      200187 :   tab = unsignedp ? ufix_optab : sfix_optab;
     328                 :      200187 :   icode = convert_optab_handler (tab, fixmode, fltmode);
     329                 :      200187 :   if (icode != CODE_FOR_nothing
     330                 :      200187 :       && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
     331                 :             :     {
     332                 :           0 :       *truncp_ptr = true;
     333                 :           0 :       return icode;
     334                 :             :     }
     335                 :             : 
     336                 :             :   return CODE_FOR_nothing;
     337                 :             : }
     338                 :             : 
     339                 :             : /* Return nonzero if a conditional move of mode MODE is supported.
     340                 :             : 
     341                 :             :    This function is for combine so it can tell whether an insn that looks
     342                 :             :    like a conditional move is actually supported by the hardware.  If we
     343                 :             :    guess wrong we lose a bit on optimization, but that's it.  */
     344                 :             : /* ??? sparc64 supports conditionally moving integers values based on fp
     345                 :             :    comparisons, and vice versa.  How do we handle them?  */
     346                 :             : 
     347                 :             : bool
     348                 :     1219111 : can_conditionally_move_p (machine_mode mode)
     349                 :             : {
     350                 :     1219111 :   return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing;
     351                 :             : }
     352                 :             : 
     353                 :             : /* If a target doesn't implement a permute on a vector with multibyte
     354                 :             :    elements, we can try to do the same permute on byte elements.
     355                 :             :    If this makes sense for vector mode MODE then return the appropriate
     356                 :             :    byte vector mode.  */
     357                 :             : 
     358                 :             : opt_machine_mode
     359                 :      712550 : qimode_for_vec_perm (machine_mode mode)
     360                 :             : {
     361                 :     1425100 :   if (GET_MODE_INNER (mode) != QImode)
     362                 :     1340406 :     return related_vector_mode (mode, QImode, GET_MODE_SIZE (mode));
     363                 :       42347 :   return opt_machine_mode ();
     364                 :             : }
     365                 :             : 
     366                 :             : /* Return true if selector SEL can be represented in the integer
     367                 :             :    equivalent of vector mode MODE.  */
     368                 :             : 
     369                 :             : bool
     370                 :     1351718 : selector_fits_mode_p (machine_mode mode, const vec_perm_indices &sel)
     371                 :             : {
     372                 :     1351718 :   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE_INNER (mode));
     373                 :     1351718 :   return (mask == HOST_WIDE_INT_M1U
     374                 :     1351718 :           || sel.all_in_range_p (0, mask + 1));
     375                 :             : }
     376                 :             : 
     377                 :             : /* Return true if VEC_PERM_EXPRs with variable selector operands can be
     378                 :             :    expanded using SIMD extensions of the CPU.  MODE is the mode of the
     379                 :             :    vectors being permuted.  */
     380                 :             : 
     381                 :             : bool
     382                 :         862 : can_vec_perm_var_p (machine_mode mode)
     383                 :             : {
     384                 :             :   /* If the target doesn't implement a vector mode for the vector type,
     385                 :             :      then no operations are supported.  */
     386                 :         862 :   if (!VECTOR_MODE_P (mode))
     387                 :             :     return false;
     388                 :             : 
     389                 :         611 :   if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
     390                 :             :     return true;
     391                 :             : 
     392                 :             :   /* We allow fallback to a QI vector mode, and adjust the mask.  */
     393                 :         600 :   machine_mode qimode;
     394                 :         600 :   if (!qimode_for_vec_perm (mode).exists (&qimode)
     395                 :         968 :       || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1))
     396                 :         116 :     return false;
     397                 :             : 
     398                 :         484 :   if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
     399                 :             :     return false;
     400                 :             : 
     401                 :             :   /* In order to support the lowering of variable permutations,
     402                 :             :      we need to support shifts and adds.  */
     403                 :           0 :   if (GET_MODE_UNIT_SIZE (mode) > 2
     404                 :           0 :       && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
     405                 :           0 :       && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
     406                 :             :     return false;
     407                 :           0 :   if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
     408                 :             :     return false;
     409                 :             : 
     410                 :             :   return true;
     411                 :             : }
     412                 :             : 
     413                 :             : /* Return true if the target directly supports VEC_PERM_EXPRs on vectors
     414                 :             :    of mode OP_MODE and result vector of mode MODE using the selector SEL.
     415                 :             :    ALLOW_VARIABLE_P is true if it is acceptable to force the selector into a
     416                 :             :    register and use a variable permute (if the target supports that).
     417                 :             : 
     418                 :             :    Note that additional permutations representing whole-vector shifts may
     419                 :             :    also be handled via the vec_shr or vec_shl optab, but only where the
     420                 :             :    second input vector is entirely constant zeroes; this case is not dealt
     421                 :             :    with here.  */
     422                 :             : 
     423                 :             : bool
     424                 :      783049 : can_vec_perm_const_p (machine_mode mode, machine_mode op_mode,
     425                 :             :                       const vec_perm_indices &sel, bool allow_variable_p)
     426                 :             : {
     427                 :             :   /* If the target doesn't implement a vector mode for the vector type,
     428                 :             :      then no operations are supported.  */
     429                 :      783049 :   if (!VECTOR_MODE_P (mode))
     430                 :             :     return false;
     431                 :             : 
     432                 :             :   /* It's probably cheaper to test for the variable case first.  */
     433                 :      781027 :   if (op_mode == mode && allow_variable_p && selector_fits_mode_p (mode, sel))
     434                 :             :     {
     435                 :      738946 :       if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
     436                 :      783049 :         return true;
     437                 :             : 
     438                 :             :       /* Unlike can_vec_perm_var_p, we don't need to test for optabs
     439                 :             :          related computing the QImode selector, since that happens at
     440                 :             :          compile time.  */
     441                 :      648440 :       machine_mode qimode;
     442                 :      648440 :       if (qimode_for_vec_perm (mode).exists (&qimode))
     443                 :             :         {
     444                 :      612772 :           vec_perm_indices qimode_indices;
     445                 :     1225544 :           qimode_indices.new_expanded_vector (sel, GET_MODE_UNIT_SIZE (mode));
     446                 :      612772 :           if (selector_fits_mode_p (qimode, qimode_indices)
     447                 :      612772 :               && (direct_optab_handler (vec_perm_optab, qimode)
     448                 :             :                   != CODE_FOR_nothing))
     449                 :          18 :             return true;
     450                 :      612772 :         }
     451                 :             :     }
     452                 :             : 
     453                 :      690503 :   if (targetm.vectorize.vec_perm_const != NULL)
     454                 :             :     {
     455                 :      690503 :       if (targetm.vectorize.vec_perm_const (mode, op_mode, NULL_RTX, NULL_RTX,
     456                 :             :                                             NULL_RTX, sel))
     457                 :             :         return true;
     458                 :             : 
     459                 :             :       /* ??? For completeness, we ought to check the QImode version of
     460                 :             :          vec_perm_const_optab.  But all users of this implicit lowering
     461                 :             :          feature implement the variable vec_perm_optab, and the ia64
     462                 :             :          port specifically doesn't want us to lower V2SF operations
     463                 :             :          into integer operations.  */
     464                 :             :     }
     465                 :             : 
     466                 :             :   return false;
     467                 :             : }
     468                 :             : 
     469                 :             : /* Find a widening optab even if it doesn't widen as much as we want.
     470                 :             :    E.g. if from_mode is HImode, and to_mode is DImode, and there is no
     471                 :             :    direct HI->SI insn, then return SI->DI, if that exists.  */
     472                 :             : 
     473                 :             : enum insn_code
     474                 :      282895 : find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
     475                 :             :                                       machine_mode from_mode,
     476                 :             :                                       machine_mode *found_mode)
     477                 :             : {
     478                 :      282895 :   machine_mode limit_mode = to_mode;
     479                 :      282895 :   if (is_a <scalar_int_mode> (from_mode))
     480                 :             :     {
     481                 :      282405 :       gcc_checking_assert (is_a <scalar_int_mode> (to_mode)
     482                 :             :                            && known_lt (GET_MODE_PRECISION (from_mode),
     483                 :             :                                         GET_MODE_PRECISION (to_mode)));
     484                 :             :       /* The modes after FROM_MODE are all MODE_INT, so the only
     485                 :             :          MODE_PARTIAL_INT mode we consider is FROM_MODE itself.
     486                 :             :          If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing
     487                 :             :          MODE_INT.  */
     488                 :      282405 :       if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT)
     489                 :           0 :         limit_mode = GET_MODE_WIDER_MODE (limit_mode).require ();
     490                 :             :     }
     491                 :         490 :   else if (is_a <scalar_int_mode> (to_mode))
     492                 :             :     {
     493                 :           0 :       gcc_checking_assert (VECTOR_MODE_P (from_mode)
     494                 :             :                            && GET_MODE_INNER (from_mode) < to_mode);
     495                 :             :       limit_mode = from_mode;
     496                 :             :     }
     497                 :             :   else
     498                 :         490 :     gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode)
     499                 :             :                          && from_mode < to_mode);
     500                 :      527297 :   FOR_EACH_MODE (from_mode, from_mode, limit_mode)
     501                 :             :     {
     502                 :      301412 :       enum insn_code handler = convert_optab_handler (op, to_mode, from_mode);
     503                 :             : 
     504                 :      301412 :       if (handler != CODE_FOR_nothing)
     505                 :             :         {
     506                 :       57010 :           if (found_mode)
     507                 :       10209 :             *found_mode = from_mode;
     508                 :       57010 :           return handler;
     509                 :             :         }
     510                 :             :     }
     511                 :             : 
     512                 :             :   return CODE_FOR_nothing;
     513                 :             : }
     514                 :             : 
     515                 :             : /* Return non-zero if a highpart multiply is supported or can be synthesized.
     516                 :             :    For the benefit of expand_mult_highpart, the return value is 1 for direct,
     517                 :             :    2 for integral widening, 3 for even/odd widening, 4 for hi/lo widening.  */
     518                 :             : 
     519                 :             : int
     520                 :       88609 : can_mult_highpart_p (machine_mode mode, bool uns_p)
     521                 :             : {
     522                 :       88609 :   optab op;
     523                 :       88609 :   scalar_int_mode int_mode, wider_mode;
     524                 :             : 
     525                 :       88609 :   op = uns_p ? umul_highpart_optab : smul_highpart_optab;
     526                 :       88609 :   if (optab_handler (op, mode) != CODE_FOR_nothing)
     527                 :             :     return 1;
     528                 :             : 
     529                 :             :   /* If the mode is integral, synth from widening or larger operations.  */
     530                 :       83315 :   if (is_a <scalar_int_mode> (mode, &int_mode)
     531                 :        4781 :       && GET_MODE_WIDER_MODE (int_mode).exists (&wider_mode))
     532                 :             :     {
     533                 :        4781 :       op = uns_p ? umul_widen_optab : smul_widen_optab;
     534                 :        4781 :       if (convert_optab_handler (op, wider_mode, mode) != CODE_FOR_nothing)
     535                 :             :         return 2;
     536                 :             : 
     537                 :             :       /* The test on the size comes from expmed_mult_highpart_optab.  */
     538                 :        4781 :       if (optab_handler (smul_optab, wider_mode) != CODE_FOR_nothing
     539                 :        4781 :           && GET_MODE_BITSIZE (int_mode) - 1 < BITS_PER_WORD)
     540                 :             :         return 2;
     541                 :             :     }
     542                 :             : 
     543                 :             :   /* If the mode is an integral vector, synth from widening operations.  */
     544                 :       83315 :   if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
     545                 :             :     return 0;
     546                 :             : 
     547                 :      157068 :   poly_int64 nunits = GET_MODE_NUNITS (mode);
     548                 :             : 
     549                 :       78534 :   op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
     550                 :       78534 :   if (optab_handler (op, mode) != CODE_FOR_nothing)
     551                 :             :     {
     552                 :       21106 :       op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
     553                 :       21106 :       if (optab_handler (op, mode) != CODE_FOR_nothing)
     554                 :             :         {
     555                 :             :           /* The encoding has 2 interleaved stepped patterns.  */
     556                 :       21106 :           vec_perm_builder sel (nunits, 2, 3);
     557                 :      147742 :           for (unsigned int i = 0; i < 6; ++i)
     558                 :      253272 :             sel.quick_push (!BYTES_BIG_ENDIAN
     559                 :      126636 :                             + (i & ~1)
     560                 :      126636 :                             + ((i & 1) ? nunits : 0));
     561                 :       21106 :           vec_perm_indices indices (sel, 2, nunits);
     562                 :       21106 :           if (can_vec_perm_const_p (mode, mode, indices))
     563                 :       21106 :             return 3;
     564                 :       21106 :         }
     565                 :             :     }
     566                 :             : 
     567                 :       57428 :   op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
     568                 :       57428 :   if (optab_handler (op, mode) != CODE_FOR_nothing)
     569                 :             :     {
     570                 :         334 :       op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
     571                 :         334 :       if (optab_handler (op, mode) != CODE_FOR_nothing)
     572                 :             :         {
     573                 :             :           /* The encoding has a single stepped pattern.  */
     574                 :         334 :           vec_perm_builder sel (nunits, 1, 3);
     575                 :        1336 :           for (unsigned int i = 0; i < 3; ++i)
     576                 :        1002 :             sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1));
     577                 :         334 :           vec_perm_indices indices (sel, 2, nunits);
     578                 :         334 :           if (can_vec_perm_const_p (mode, mode, indices))
     579                 :         334 :             return 4;
     580                 :         334 :         }
     581                 :             :     }
     582                 :             : 
     583                 :             :   return 0;
     584                 :             : }
     585                 :             : 
     586                 :             : /* Return true if there is a compare_and_swap pattern.  */
     587                 :             : 
     588                 :             : bool
     589                 :       97264 : can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
     590                 :             : {
     591                 :       97264 :   enum insn_code icode;
     592                 :             : 
     593                 :             :   /* Check for __atomic_compare_and_swap.  */
     594                 :       97264 :   icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
     595                 :       97264 :   if (icode != CODE_FOR_nothing)
     596                 :             :     return true;
     597                 :             : 
     598                 :             :   /* Check for __sync_compare_and_swap.  */
     599                 :         130 :   icode = optab_handler (sync_compare_and_swap_optab, mode);
     600                 :         130 :   if (icode != CODE_FOR_nothing)
     601                 :             :     return true;
     602                 :         130 :   if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
     603                 :             :     return true;
     604                 :             : 
     605                 :             :   /* No inline compare and swap.  */
     606                 :             :   return false;
     607                 :             : }
     608                 :             : 
     609                 :             : /* Return true if an atomic exchange can be performed.  */
     610                 :             : 
     611                 :             : bool
     612                 :          88 : can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
     613                 :             : {
     614                 :          88 :   enum insn_code icode;
     615                 :             : 
     616                 :             :   /* Check for __atomic_exchange.  */
     617                 :          88 :   icode = direct_optab_handler (atomic_exchange_optab, mode);
     618                 :          88 :   if (icode != CODE_FOR_nothing)
     619                 :             :     return true;
     620                 :             : 
     621                 :             :   /* Don't check __sync_test_and_set, as on some platforms that
     622                 :             :      has reduced functionality.  Targets that really do support
     623                 :             :      a proper exchange should simply be updated to the __atomics.  */
     624                 :             : 
     625                 :           0 :   return can_compare_and_swap_p (mode, allow_libcall);
     626                 :             : }
     627                 :             : 
     628                 :             : /* Return true if an atomic load can be performed without falling back to
     629                 :             :    a compare-and-swap.  */
     630                 :             : 
     631                 :             : bool
     632                 :      152452 : can_atomic_load_p (machine_mode mode)
     633                 :             : {
     634                 :      152452 :   enum insn_code icode;
     635                 :             : 
     636                 :             :   /* Does the target supports the load directly?  */
     637                 :      152452 :   icode = direct_optab_handler (atomic_load_optab, mode);
     638                 :      152452 :   if (icode != CODE_FOR_nothing)
     639                 :             :     return true;
     640                 :             : 
     641                 :             :   /* If the size of the object is greater than word size on this target,
     642                 :             :      then we assume that a load will not be atomic.  Also see
     643                 :             :      expand_atomic_load.  */
     644                 :        4046 :   return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD);
     645                 :             : }
     646                 :             : 
     647                 :             : /* Determine whether "1 << x" is relatively cheap in word_mode.  */
     648                 :             : 
     649                 :             : bool
     650                 :     1036976 : lshift_cheap_p (bool speed_p)
     651                 :             : {
     652                 :             :   /* FIXME: This should be made target dependent via this "this_target"
     653                 :             :      mechanism, similar to e.g. can_copy_init_p in gcse.cc.  */
     654                 :     1036976 :   static bool init[2] = { false, false };
     655                 :     1036976 :   static bool cheap[2] = { true, true };
     656                 :             : 
     657                 :             :   /* If the targer has no lshift in word_mode, the operation will most
     658                 :             :      probably not be cheap.  ??? Does GCC even work for such targets?  */
     659                 :     1036976 :   if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
     660                 :             :     return false;
     661                 :             : 
     662                 :     1036976 :   if (!init[speed_p])
     663                 :             :     {
     664                 :       39160 :       rtx reg = gen_raw_REG (word_mode, 10000);
     665                 :       39160 :       int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
     666                 :             :                                word_mode, speed_p);
     667                 :       39160 :       cheap[speed_p] = cost < COSTS_N_INSNS (3);
     668                 :       39160 :       init[speed_p] = true;
     669                 :             :     }
     670                 :             : 
     671                 :     1036976 :   return cheap[speed_p];
     672                 :             : }
     673                 :             : 
     674                 :             : /* If MODE is not VOIDmode, return true if vector conversion optab OP supports
     675                 :             :    that mode, given that the second mode is always an integer vector.
     676                 :             :    If MODE is VOIDmode, return true if OP supports any vector mode.  */
     677                 :             : 
     678                 :             : static enum insn_code
     679                 :      100221 : supported_vec_convert_optab (optab op, machine_mode mode)
     680                 :             : {
     681                 :      100221 :   int start = mode == VOIDmode ? 0 : mode;
     682                 :      100221 :   int end = mode == VOIDmode ? MAX_MACHINE_MODE - 1 : mode;
     683                 :      100221 :   enum insn_code icode = CODE_FOR_nothing;
     684                 :      200442 :   for (int i = start; i <= end; ++i)
     685                 :      100221 :     if (VECTOR_MODE_P ((machine_mode) i))
     686                 :     3207072 :       for (int j = MIN_MODE_VECTOR_INT; j < MAX_MODE_VECTOR_INT; ++j)
     687                 :             :         {
     688                 :     6213702 :           if ((icode
     689                 :     3106851 :                = convert_optab_handler (op, (machine_mode) i,
     690                 :             :                                         (machine_mode) j)) != CODE_FOR_nothing)
     691                 :             :             return icode;
     692                 :             :         }
     693                 :             : 
     694                 :             :   return icode;
     695                 :             : }
     696                 :             : 
     697                 :             : /* If MODE is not VOIDmode, return true if vec_gather_load is available for
     698                 :             :    that mode.  If MODE is VOIDmode, return true if gather_load is available
     699                 :             :    for at least one vector mode.
     700                 :             :    In that case, and if ELSVALS is nonzero, store the supported else values
     701                 :             :    into the vector it points to.  */
     702                 :             : 
     703                 :             : bool
     704                 :       90361 : supports_vec_gather_load_p (machine_mode mode, vec<int> *elsvals)
     705                 :             : {
     706                 :       90361 :   enum insn_code icode = CODE_FOR_nothing;
     707                 :       90361 :   if (!this_fn_optabs->supports_vec_gather_load[mode] || elsvals)
     708                 :             :     {
     709                 :             :       /* Try the masked variants first.  In case we later decide that we
     710                 :             :          need a mask after all (thus requiring an else operand) we need
     711                 :             :          to query it below and we cannot do that when using the
     712                 :             :          non-masked optab.  */
     713                 :       26837 :       icode = supported_vec_convert_optab (mask_gather_load_optab, mode);
     714                 :       26837 :       if (icode == CODE_FOR_nothing)
     715                 :       26837 :         icode = supported_vec_convert_optab (mask_len_gather_load_optab, mode);
     716                 :       26837 :       if (icode == CODE_FOR_nothing)
     717                 :       26837 :         icode = supported_vec_convert_optab (gather_load_optab, mode);
     718                 :       53674 :       this_fn_optabs->supports_vec_gather_load[mode]
     719                 :       53674 :         = (icode != CODE_FOR_nothing) ? 1 : -1;
     720                 :             :     }
     721                 :             : 
     722                 :             :   /* For gather the optab's operand indices do not match the IFN's because
     723                 :             :      the latter does not have the extension operand (operand 3).  It is
     724                 :             :      implicitly added during expansion so we use the IFN's else index + 1.
     725                 :             :      */
     726                 :       90361 :   if (elsvals && icode != CODE_FOR_nothing)
     727                 :           0 :     get_supported_else_vals
     728                 :           0 :       (icode, internal_fn_else_index (IFN_MASK_GATHER_LOAD) + 1, *elsvals);
     729                 :             : 
     730                 :       90361 :   return this_fn_optabs->supports_vec_gather_load[mode] > 0;
     731                 :             : }
     732                 :             : 
     733                 :             : /* If MODE is not VOIDmode, return true if vec_scatter_store is available for
     734                 :             :    that mode.  If MODE is VOIDmode, return true if scatter_store is available
     735                 :             :    for at least one vector mode.  */
     736                 :             : 
     737                 :             : bool
     738                 :       69431 : supports_vec_scatter_store_p (machine_mode mode)
     739                 :             : {
     740                 :       69431 :   enum insn_code icode;
     741                 :       69431 :   if (!this_fn_optabs->supports_vec_scatter_store[mode])
     742                 :             :     {
     743                 :        6570 :       icode = supported_vec_convert_optab (scatter_store_optab, mode);
     744                 :        6570 :       if (icode == CODE_FOR_nothing)
     745                 :        6570 :         icode = supported_vec_convert_optab (mask_scatter_store_optab, mode);
     746                 :        6570 :       if (icode == CODE_FOR_nothing)
     747                 :        6570 :         icode = supported_vec_convert_optab (mask_len_scatter_store_optab,
     748                 :             :                                               mode);
     749                 :       13140 :       this_fn_optabs->supports_vec_scatter_store[mode]
     750                 :        6570 :         = (icode != CODE_FOR_nothing) ? 1 : -1;
     751                 :             :     }
     752                 :             : 
     753                 :       69431 :   return this_fn_optabs->supports_vec_scatter_store[mode] > 0;
     754                 :             : }
     755                 :             : 
     756                 :             : /* Whether we can extract part of the vector mode MODE as
     757                 :             :    (scalar or vector) mode EXTR_MODE.  */
     758                 :             : 
     759                 :             : bool
     760                 :        4074 : can_vec_extract (machine_mode mode, machine_mode extr_mode)
     761                 :             : {
     762                 :        4074 :   unsigned m;
     763                 :        2406 :   if (!VECTOR_MODE_P (mode)
     764                 :        8148 :       || !constant_multiple_p (GET_MODE_SIZE (mode),
     765                 :        4074 :                                GET_MODE_SIZE (extr_mode), &m))
     766                 :             :     return false;
     767                 :             : 
     768                 :        4074 :   if (convert_optab_handler (vec_extract_optab, mode, extr_mode)
     769                 :             :       != CODE_FOR_nothing)
     770                 :             :     return true;
     771                 :             : 
     772                 :             :   /* Besides a direct vec_extract we can also use an element extract from
     773                 :             :      an integer vector mode with elements of the size of the extr_mode.  */
     774                 :        1504 :   scalar_int_mode imode;
     775                 :        1504 :   machine_mode vmode;
     776                 :        3008 :   if (!int_mode_for_size (GET_MODE_BITSIZE (extr_mode), 0).exists (&imode)
     777                 :        3008 :       || !related_vector_mode (mode, imode, m).exists (&vmode)
     778                 :        1504 :       || (convert_optab_handler (vec_extract_optab, vmode, imode)
     779                 :             :           == CODE_FOR_nothing))
     780                 :           0 :     return false;
     781                 :             :   /* We assume we can pun mode to vmode and imode to extr_mode.  */
     782                 :             :   return true;
     783                 :             : }
     784                 :             : 
     785                 :             : /* OP is either neg_optab or abs_optab and FMODE is the floating-point inner
     786                 :             :    mode of MODE.  Check whether we can implement OP for mode MODE by using
     787                 :             :    xor_optab to flip the sign bit (for neg_optab) or and_optab to clear the
     788                 :             :    sign bit (for abs_optab).  If so, return the integral mode that should be
     789                 :             :    used to do the operation and set *BITPOS to the index of the sign bit
     790                 :             :    (counting from the lsb).  */
     791                 :             : 
     792                 :             : opt_machine_mode
     793                 :          55 : get_absneg_bit_mode (optab op, machine_mode mode,
     794                 :             :                      scalar_float_mode fmode, int *bitpos)
     795                 :             : {
     796                 :             :   /* The format has to have a simple sign bit.  */
     797                 :          55 :   auto fmt = REAL_MODE_FORMAT (fmode);
     798                 :          55 :   if (fmt == NULL)
     799                 :           0 :     return {};
     800                 :             : 
     801                 :          55 :   *bitpos = fmt->signbit_rw;
     802                 :          55 :   if (*bitpos < 0)
     803                 :           0 :     return {};
     804                 :             : 
     805                 :             :   /* Don't create negative zeros if the format doesn't support them.  */
     806                 :          55 :   if (op == neg_optab && !fmt->has_signed_zero)
     807                 :           0 :     return {};
     808                 :             : 
     809                 :          55 :   if (VECTOR_MODE_P (mode))
     810                 :           4 :     return related_int_vector_mode (mode);
     811                 :             : 
     812                 :         102 :   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
     813                 :          68 :     return int_mode_for_mode (fmode);
     814                 :             : 
     815                 :          17 :   return word_mode;
     816                 :             : }
     817                 :             : 
     818                 :             : /* Return true if we can implement OP for mode MODE directly, without resorting
     819                 :             :    to a libfunc.   This usually means that OP will be implemented inline.
     820                 :             : 
     821                 :             :    Note that this function cannot tell whether the target pattern chooses to
     822                 :             :    use libfuncs internally.  */
     823                 :             : 
     824                 :             : bool
     825                 :     4790122 : can_open_code_p (optab op, machine_mode mode)
     826                 :             : {
     827                 :     4790122 :   if (optab_handler (op, mode) != CODE_FOR_nothing)
     828                 :             :     return true;
     829                 :             : 
     830                 :     1771285 :   if (op == umul_highpart_optab)
     831                 :         956 :     return can_mult_highpart_p (mode, true);
     832                 :             : 
     833                 :     1770329 :   if (op == smul_highpart_optab)
     834                 :        1372 :     return can_mult_highpart_p (mode, false);
     835                 :             : 
     836                 :     1768957 :   machine_mode new_mode;
     837                 :     1768957 :   scalar_float_mode fmode;
     838                 :     1768957 :   int bitpos;
     839                 :     1768957 :   if ((op == neg_optab || op == abs_optab)
     840                 :         857 :       && is_a<scalar_float_mode> (GET_MODE_INNER (mode), &fmode)
     841                 :     1768957 :       && get_absneg_bit_mode (op, mode, fmode, &bitpos).exists (&new_mode)
     842                 :     1768958 :       && can_implement_p (op == neg_optab ? xor_optab : and_optab, new_mode))
     843                 :           1 :     return true;
     844                 :             : 
     845                 :             :   return false;
     846                 :             : }
     847                 :             : 
     848                 :             : /* Return true if we can implement OP for mode MODE in some way, either by
     849                 :             :    open-coding it or by calling a libfunc.  */
     850                 :             : 
     851                 :             : bool
     852                 :     4790122 : can_implement_p (optab op, machine_mode mode)
     853                 :             : {
     854                 :     4790122 :   return can_open_code_p (op, mode) || optab_libfunc (op, mode);
     855                 :             : }
        

Generated by: LCOV version 2.1-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.