LCOV - code coverage report
Current view: top level - gcc - optabs-query.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 218 258 84.5 %
Date: 2020-04-04 11:58:09 Functions: 25 26 96.2 %
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-2020 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                 :            : 
      33                 :            : struct target_optabs default_target_optabs;
      34                 :            : struct target_optabs *this_fn_optabs = &default_target_optabs;
      35                 :            : #if SWITCHABLE_TARGET
      36                 :            : struct target_optabs *this_target_optabs = &default_target_optabs;
      37                 :            : #endif
      38                 :            : 
      39                 :            : /* Return the insn used to perform conversion OP from mode FROM_MODE
      40                 :            :    to mode TO_MODE; return CODE_FOR_nothing if the target does not have
      41                 :            :    such an insn, or if it is unsuitable for optimization type OPT_TYPE.  */
      42                 :            : 
      43                 :            : insn_code
      44                 :      13795 : convert_optab_handler (convert_optab optab, machine_mode to_mode,
      45                 :            :                        machine_mode from_mode, optimization_type opt_type)
      46                 :            : {
      47                 :      13795 :   insn_code icode = convert_optab_handler (optab, to_mode, from_mode);
      48                 :      13795 :   if (icode == CODE_FOR_nothing
      49                 :      13795 :       || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type))
      50                 :      13795 :     return CODE_FOR_nothing;
      51                 :            :   return icode;
      52                 :            : }
      53                 :            : 
      54                 :            : /* Return the insn used to implement mode MODE of OP; return
      55                 :            :    CODE_FOR_nothing if the target does not have such an insn,
      56                 :            :    or if it is unsuitable for optimization type OPT_TYPE.  */
      57                 :            : 
      58                 :            : insn_code
      59                 :     561571 : direct_optab_handler (convert_optab optab, machine_mode mode,
      60                 :            :                       optimization_type opt_type)
      61                 :            : {
      62                 :     561571 :   insn_code icode = direct_optab_handler (optab, mode);
      63                 :     561571 :   if (icode == CODE_FOR_nothing
      64                 :     561571 :       || !targetm.optab_supported_p (optab, mode, mode, opt_type))
      65                 :     487719 :     return CODE_FOR_nothing;
      66                 :            :   return icode;
      67                 :            : }
      68                 :            : 
      69                 :            : /* Enumerates the possible types of structure operand to an
      70                 :            :    extraction_insn.  */
      71                 :            : enum extraction_type { ET_unaligned_mem, ET_reg };
      72                 :            : 
      73                 :            : /* Check whether insv, extv or extzv pattern ICODE can be used for an
      74                 :            :    insertion or extraction of type TYPE on a structure of mode MODE.
      75                 :            :    Return true if so and fill in *INSN accordingly.  STRUCT_OP is the
      76                 :            :    operand number of the structure (the first sign_extract or zero_extract
      77                 :            :    operand) and FIELD_OP is the operand number of the field (the other
      78                 :            :    side of the set from the sign_extract or zero_extract).  */
      79                 :            : 
      80                 :            : static bool
      81                 :          0 : get_traditional_extraction_insn (extraction_insn *insn,
      82                 :            :                                  enum extraction_type type,
      83                 :            :                                  machine_mode mode,
      84                 :            :                                  enum insn_code icode,
      85                 :            :                                  int struct_op, int field_op)
      86                 :            : {
      87                 :          0 :   const struct insn_data_d *data = &insn_data[icode];
      88                 :            : 
      89                 :          0 :   machine_mode struct_mode = data->operand[struct_op].mode;
      90                 :          0 :   if (struct_mode == VOIDmode)
      91                 :          0 :     struct_mode = word_mode;
      92                 :          0 :   if (mode != struct_mode)
      93                 :            :     return false;
      94                 :            : 
      95                 :          0 :   machine_mode field_mode = data->operand[field_op].mode;
      96                 :          0 :   if (field_mode == VOIDmode)
      97                 :          0 :     field_mode = word_mode;
      98                 :            : 
      99                 :          0 :   machine_mode pos_mode = data->operand[struct_op + 2].mode;
     100                 :          0 :   if (pos_mode == VOIDmode)
     101                 :          0 :     pos_mode = word_mode;
     102                 :            : 
     103                 :          0 :   insn->icode = icode;
     104                 :          0 :   insn->field_mode = as_a <scalar_int_mode> (field_mode);
     105                 :          0 :   if (type == ET_unaligned_mem)
     106                 :          0 :     insn->struct_mode = byte_mode;
     107                 :          0 :   else if (struct_mode == BLKmode)
     108                 :          0 :     insn->struct_mode = opt_scalar_int_mode ();
     109                 :            :   else
     110                 :          0 :     insn->struct_mode = as_a <scalar_int_mode> (struct_mode);
     111                 :          0 :   insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
     112                 :          0 :   return true;
     113                 :            : }
     114                 :            : 
     115                 :            : /* Return true if an optab exists to perform an insertion or extraction
     116                 :            :    of type TYPE in mode MODE.  Describe the instruction in *INSN if so.
     117                 :            : 
     118                 :            :    REG_OPTAB is the optab to use for register structures and
     119                 :            :    MISALIGN_OPTAB is the optab to use for misaligned memory structures.
     120                 :            :    POS_OP is the operand number of the bit position.  */
     121                 :            : 
     122                 :            : static bool
     123                 :    2383990 : get_optab_extraction_insn (class extraction_insn *insn,
     124                 :            :                            enum extraction_type type,
     125                 :            :                            machine_mode mode, direct_optab reg_optab,
     126                 :            :                            direct_optab misalign_optab, int pos_op)
     127                 :            : {
     128                 :    2383990 :   direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
     129                 :    2383990 :   enum insn_code icode = direct_optab_handler (optab, mode);
     130                 :    2383990 :   if (icode == CODE_FOR_nothing)
     131                 :            :     return false;
     132                 :            : 
     133                 :     920392 :   const struct insn_data_d *data = &insn_data[icode];
     134                 :            : 
     135                 :     920392 :   machine_mode pos_mode = data->operand[pos_op].mode;
     136                 :     920392 :   if (pos_mode == VOIDmode)
     137                 :          0 :     pos_mode = word_mode;
     138                 :            : 
     139                 :     920392 :   insn->icode = icode;
     140                 :     920392 :   insn->field_mode = as_a <scalar_int_mode> (mode);
     141                 :     920392 :   if (type == ET_unaligned_mem)
     142                 :          0 :     insn->struct_mode = opt_scalar_int_mode ();
     143                 :            :   else
     144                 :     920392 :     insn->struct_mode = insn->field_mode;
     145                 :     920392 :   insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
     146                 :     920392 :   return true;
     147                 :            : }
     148                 :            : 
     149                 :            : /* Return true if an instruction exists to perform an insertion or
     150                 :            :    extraction (PATTERN says which) of type TYPE in mode MODE.
     151                 :            :    Describe the instruction in *INSN if so.  */
     152                 :            : 
     153                 :            : static bool
     154                 :    2383990 : get_extraction_insn (extraction_insn *insn,
     155                 :            :                      enum extraction_pattern pattern,
     156                 :            :                      enum extraction_type type,
     157                 :            :                      machine_mode mode)
     158                 :            : {
     159                 :    2383990 :   switch (pattern)
     160                 :            :     {
     161                 :     310480 :     case EP_insv:
     162                 :     310480 :       if (targetm.have_insv ()
     163                 :     310480 :           && get_traditional_extraction_insn (insn, type, mode,
     164                 :            :                                               targetm.code_for_insv, 0, 3))
     165                 :            :         return true;
     166                 :     310480 :       return get_optab_extraction_insn (insn, type, mode, insv_optab,
     167                 :     310480 :                                         insvmisalign_optab, 2);
     168                 :            : 
     169                 :     641031 :     case EP_extv:
     170                 :     641031 :       if (targetm.have_extv ()
     171                 :     641031 :           && get_traditional_extraction_insn (insn, type, mode,
     172                 :            :                                               targetm.code_for_extv, 1, 0))
     173                 :            :         return true;
     174                 :     641031 :       return get_optab_extraction_insn (insn, type, mode, extv_optab,
     175                 :     641031 :                                         extvmisalign_optab, 3);
     176                 :            : 
     177                 :    1432480 :     case EP_extzv:
     178                 :    1432480 :       if (targetm.have_extzv ()
     179                 :    1432480 :           && get_traditional_extraction_insn (insn, type, mode,
     180                 :            :                                               targetm.code_for_extzv, 1, 0))
     181                 :            :         return true;
     182                 :    1432480 :       return get_optab_extraction_insn (insn, type, mode, extzv_optab,
     183                 :    1432480 :                                         extzvmisalign_optab, 3);
     184                 :            : 
     185                 :          0 :     default:
     186                 :          0 :       gcc_unreachable ();
     187                 :            :     }
     188                 :            : }
     189                 :            : 
     190                 :            : /* Return true if an instruction exists to access a field of mode
     191                 :            :    FIELDMODE in a structure that has STRUCT_BITS significant bits.
     192                 :            :    Describe the "best" such instruction in *INSN if so.  PATTERN and
     193                 :            :    TYPE describe the type of insertion or extraction we want to perform.
     194                 :            : 
     195                 :            :    For an insertion, the number of significant structure bits includes
     196                 :            :    all bits of the target.  For an extraction, it need only include the
     197                 :            :    most significant bit of the field.  Larger widths are acceptable
     198                 :            :    in both cases.  */
     199                 :            : 
     200                 :            : static bool
     201                 :    1206040 : get_best_extraction_insn (extraction_insn *insn,
     202                 :            :                           enum extraction_pattern pattern,
     203                 :            :                           enum extraction_type type,
     204                 :            :                           unsigned HOST_WIDE_INT struct_bits,
     205                 :            :                           machine_mode field_mode)
     206                 :            : {
     207                 :    1206040 :   opt_scalar_int_mode mode_iter;
     208                 :    2669640 :   FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits))
     209                 :            :     {
     210                 :    2383990 :       scalar_int_mode mode = mode_iter.require ();
     211                 :    2383990 :       if (get_extraction_insn (insn, pattern, type, mode))
     212                 :            :         {
     213                 :     920392 :           FOR_EACH_MODE_FROM (mode_iter, mode)
     214                 :            :             {
     215                 :     920392 :               mode = mode_iter.require ();
     216                 :    2761180 :               if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode))
     217                 :     920392 :                   || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
     218                 :            :                                                     field_mode))
     219                 :            :                 break;
     220                 :          0 :               get_extraction_insn (insn, pattern, type, mode);
     221                 :            :             }
     222                 :     920392 :           return true;
     223                 :            :         }
     224                 :            :     }
     225                 :            :   return false;
     226                 :            : }
     227                 :            : 
     228                 :            : /* Return true if an instruction exists to access a field of mode
     229                 :            :    FIELDMODE in a register structure that has STRUCT_BITS significant bits.
     230                 :            :    Describe the "best" such instruction in *INSN if so.  PATTERN describes
     231                 :            :    the type of insertion or extraction we want to perform.
     232                 :            : 
     233                 :            :    For an insertion, the number of significant structure bits includes
     234                 :            :    all bits of the target.  For an extraction, it need only include the
     235                 :            :    most significant bit of the field.  Larger widths are acceptable
     236                 :            :    in both cases.  */
     237                 :            : 
     238                 :            : bool
     239                 :    1079820 : get_best_reg_extraction_insn (extraction_insn *insn,
     240                 :            :                               enum extraction_pattern pattern,
     241                 :            :                               unsigned HOST_WIDE_INT struct_bits,
     242                 :            :                               machine_mode field_mode)
     243                 :            : {
     244                 :    1079820 :   return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
     245                 :    1079820 :                                    field_mode);
     246                 :            : }
     247                 :            : 
     248                 :            : /* Return true if an instruction exists to access a field of BITSIZE
     249                 :            :    bits starting BITNUM bits into a memory structure.  Describe the
     250                 :            :    "best" such instruction in *INSN if so.  PATTERN describes the type
     251                 :            :    of insertion or extraction we want to perform and FIELDMODE is the
     252                 :            :    natural mode of the extracted field.
     253                 :            : 
     254                 :            :    The instructions considered here only access bytes that overlap
     255                 :            :    the bitfield; they do not touch any surrounding bytes.  */
     256                 :            : 
     257                 :            : bool
     258                 :     126224 : get_best_mem_extraction_insn (extraction_insn *insn,
     259                 :            :                               enum extraction_pattern pattern,
     260                 :            :                               HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
     261                 :            :                               machine_mode field_mode)
     262                 :            : {
     263                 :     126224 :   unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
     264                 :     126224 :                                         + bitsize
     265                 :     126224 :                                         + BITS_PER_UNIT - 1);
     266                 :     126224 :   struct_bits -= struct_bits % BITS_PER_UNIT;
     267                 :     126224 :   return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
     268                 :     126224 :                                    struct_bits, field_mode);
     269                 :            : }
     270                 :            : 
     271                 :            : /* Return the insn code used to extend FROM_MODE to TO_MODE.
     272                 :            :    UNSIGNEDP specifies zero-extension instead of sign-extension.  If
     273                 :            :    no such operation exists, CODE_FOR_nothing will be returned.  */
     274                 :            : 
     275                 :            : enum insn_code
     276                 :    1463580 : can_extend_p (machine_mode to_mode, machine_mode from_mode,
     277                 :            :               int unsignedp)
     278                 :            : {
     279                 :    1463580 :   if (unsignedp < 0 && targetm.have_ptr_extend ())
     280                 :          0 :     return targetm.code_for_ptr_extend;
     281                 :            : 
     282                 :    1463580 :   convert_optab tab = unsignedp ? zext_optab : sext_optab;
     283                 :    1463580 :   return convert_optab_handler (tab, to_mode, from_mode);
     284                 :            : }
     285                 :            : 
     286                 :            : /* Return the insn code to convert fixed-point mode FIXMODE to floating-point
     287                 :            :    mode FLTMODE, or CODE_FOR_nothing if no such instruction exists.
     288                 :            :    UNSIGNEDP specifies whether FIXMODE is unsigned.  */
     289                 :            : 
     290                 :            : enum insn_code
     291                 :     234259 : can_float_p (machine_mode fltmode, machine_mode fixmode,
     292                 :            :              int unsignedp)
     293                 :            : {
     294                 :     234259 :   convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
     295                 :     234259 :   return convert_optab_handler (tab, fltmode, fixmode);
     296                 :            : }
     297                 :            : 
     298                 :            : /* Return the insn code to convert floating-point mode FLTMODE to fixed-point
     299                 :            :    mode FIXMODE, or CODE_FOR_nothing if no such instruction exists.
     300                 :            :    UNSIGNEDP specifies whether FIXMODE is unsigned.
     301                 :            : 
     302                 :            :    On a successful return, set *TRUNCP_PTR to true if it is necessary to
     303                 :            :    output an explicit FTRUNC before the instruction.  */
     304                 :            : 
     305                 :            : enum insn_code
     306                 :     228152 : can_fix_p (machine_mode fixmode, machine_mode fltmode,
     307                 :            :            int unsignedp, bool *truncp_ptr)
     308                 :            : {
     309                 :     228152 :   convert_optab tab;
     310                 :     228152 :   enum insn_code icode;
     311                 :            : 
     312                 :     228152 :   tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
     313                 :     228152 :   icode = convert_optab_handler (tab, fixmode, fltmode);
     314                 :     228152 :   if (icode != CODE_FOR_nothing)
     315                 :            :     {
     316                 :      45964 :       *truncp_ptr = false;
     317                 :      45964 :       return icode;
     318                 :            :     }
     319                 :            : 
     320                 :            :   /* FIXME: This requires a port to define both FIX and FTRUNC pattern
     321                 :            :      for this to work.  We need to rework the fix* and ftrunc* patterns
     322                 :            :      and documentation.  */
     323                 :     182188 :   tab = unsignedp ? ufix_optab : sfix_optab;
     324                 :     182188 :   icode = convert_optab_handler (tab, fixmode, fltmode);
     325                 :     182188 :   if (icode != CODE_FOR_nothing
     326                 :     182188 :       && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
     327                 :            :     {
     328                 :          0 :       *truncp_ptr = true;
     329                 :          0 :       return icode;
     330                 :            :     }
     331                 :            : 
     332                 :            :   return CODE_FOR_nothing;
     333                 :            : }
     334                 :            : 
     335                 :            : /* Return nonzero if a conditional move of mode MODE is supported.
     336                 :            : 
     337                 :            :    This function is for combine so it can tell whether an insn that looks
     338                 :            :    like a conditional move is actually supported by the hardware.  If we
     339                 :            :    guess wrong we lose a bit on optimization, but that's it.  */
     340                 :            : /* ??? sparc64 supports conditionally moving integers values based on fp
     341                 :            :    comparisons, and vice versa.  How do we handle them?  */
     342                 :            : 
     343                 :            : bool
     344                 :     494059 : can_conditionally_move_p (machine_mode mode)
     345                 :            : {
     346                 :     494059 :   return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing;
     347                 :            : }
     348                 :            : 
     349                 :            : /* If a target doesn't implement a permute on a vector with multibyte
     350                 :            :    elements, we can try to do the same permute on byte elements.
     351                 :            :    If this makes sense for vector mode MODE then return the appropriate
     352                 :            :    byte vector mode.  */
     353                 :            : 
     354                 :            : opt_machine_mode
     355                 :      82509 : qimode_for_vec_perm (machine_mode mode)
     356                 :            : {
     357                 :     165018 :   if (GET_MODE_INNER (mode) != QImode)
     358                 :     147078 :     return related_vector_mode (mode, QImode, GET_MODE_SIZE (mode));
     359                 :       8970 :   return opt_machine_mode ();
     360                 :            : }
     361                 :            : 
     362                 :            : /* Return true if selector SEL can be represented in the integer
     363                 :            :    equivalent of vector mode MODE.  */
     364                 :            : 
     365                 :            : bool
     366                 :     138604 : selector_fits_mode_p (machine_mode mode, const vec_perm_indices &sel)
     367                 :            : {
     368                 :     277208 :   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE_INNER (mode));
     369                 :     138604 :   return (mask == HOST_WIDE_INT_M1U
     370                 :     138604 :           || sel.all_in_range_p (0, mask + 1));
     371                 :            : }
     372                 :            : 
     373                 :            : /* Return true if VEC_PERM_EXPRs with variable selector operands can be
     374                 :            :    expanded using SIMD extensions of the CPU.  MODE is the mode of the
     375                 :            :    vectors being permuted.  */
     376                 :            : 
     377                 :            : bool
     378                 :        993 : can_vec_perm_var_p (machine_mode mode)
     379                 :            : {
     380                 :            :   /* If the target doesn't implement a vector mode for the vector type,
     381                 :            :      then no operations are supported.  */
     382                 :        993 :   if (!VECTOR_MODE_P (mode))
     383                 :            :     return false;
     384                 :            : 
     385                 :        631 :   if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
     386                 :            :     return true;
     387                 :            : 
     388                 :            :   /* We allow fallback to a QI vector mode, and adjust the mask.  */
     389                 :        629 :   machine_mode qimode;
     390                 :        629 :   if (!qimode_for_vec_perm (mode).exists (&qimode)
     391                 :       1122 :       || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1))
     392                 :        136 :     return false;
     393                 :            : 
     394                 :        493 :   if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
     395                 :            :     return false;
     396                 :            : 
     397                 :            :   /* In order to support the lowering of variable permutations,
     398                 :            :      we need to support shifts and adds.  */
     399                 :          0 :   if (GET_MODE_UNIT_SIZE (mode) > 2
     400                 :          0 :       && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
     401                 :          0 :       && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
     402                 :            :     return false;
     403                 :          0 :   if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
     404                 :          0 :     return false;
     405                 :            : 
     406                 :            :   return true;
     407                 :            : }
     408                 :            : 
     409                 :            : /* Return true if the target directly supports VEC_PERM_EXPRs on vectors
     410                 :            :    of mode MODE using the selector SEL.  ALLOW_VARIABLE_P is true if it
     411                 :            :    is acceptable to force the selector into a register and use a variable
     412                 :            :    permute (if the target supports that).
     413                 :            : 
     414                 :            :    Note that additional permutations representing whole-vector shifts may
     415                 :            :    also be handled via the vec_shr or vec_shl optab, but only where the
     416                 :            :    second input vector is entirely constant zeroes; this case is not dealt
     417                 :            :    with here.  */
     418                 :            : 
     419                 :            : bool
     420                 :     109946 : can_vec_perm_const_p (machine_mode mode, const vec_perm_indices &sel,
     421                 :            :                       bool allow_variable_p)
     422                 :            : {
     423                 :            :   /* If the target doesn't implement a vector mode for the vector type,
     424                 :            :      then no operations are supported.  */
     425                 :     109946 :   if (!VECTOR_MODE_P (mode))
     426                 :            :     return false;
     427                 :            : 
     428                 :            :   /* It's probably cheaper to test for the variable case first.  */
     429                 :     107940 :   if (allow_variable_p && selector_fits_mode_p (mode, sel))
     430                 :            :     {
     431                 :     101526 :       if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
     432                 :     109946 :         return true;
     433                 :            : 
     434                 :            :       /* Unlike can_vec_perm_var_p, we don't need to test for optabs
     435                 :            :          related computing the QImode selector, since that happens at
     436                 :            :          compile time.  */
     437                 :      43475 :       machine_mode qimode;
     438                 :      43475 :       if (qimode_for_vec_perm (mode).exists (&qimode))
     439                 :            :         {
     440                 :      74156 :           vec_perm_indices qimode_indices;
     441                 :      74156 :           qimode_indices.new_expanded_vector (sel, GET_MODE_UNIT_SIZE (mode));
     442                 :      37078 :           if (selector_fits_mode_p (qimode, qimode_indices)
     443                 :      37078 :               && (direct_optab_handler (vec_perm_optab, qimode)
     444                 :            :                   != CODE_FOR_nothing))
     445                 :          0 :             return true;
     446                 :            :         }
     447                 :            :     }
     448                 :            : 
     449                 :      49889 :   if (targetm.vectorize.vec_perm_const != NULL)
     450                 :            :     {
     451                 :      49889 :       if (targetm.vectorize.vec_perm_const (mode, NULL_RTX, NULL_RTX,
     452                 :            :                                             NULL_RTX, sel))
     453                 :      42467 :         return true;
     454                 :            : 
     455                 :            :       /* ??? For completeness, we ought to check the QImode version of
     456                 :            :          vec_perm_const_optab.  But all users of this implicit lowering
     457                 :            :          feature implement the variable vec_perm_optab, and the ia64
     458                 :            :          port specifically doesn't want us to lower V2SF operations
     459                 :            :          into integer operations.  */
     460                 :            :     }
     461                 :            : 
     462                 :            :   return false;
     463                 :            : }
     464                 :            : 
     465                 :            : /* Find a widening optab even if it doesn't widen as much as we want.
     466                 :            :    E.g. if from_mode is HImode, and to_mode is DImode, and there is no
     467                 :            :    direct HI->SI insn, then return SI->DI, if that exists.  */
     468                 :            : 
     469                 :            : enum insn_code
     470                 :     124608 : find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
     471                 :            :                                       machine_mode from_mode,
     472                 :            :                                       machine_mode *found_mode)
     473                 :            : {
     474                 :     124608 :   machine_mode limit_mode = to_mode;
     475                 :     124608 :   if (is_a <scalar_int_mode> (from_mode))
     476                 :            :     {
     477                 :     124295 :       gcc_checking_assert (is_a <scalar_int_mode> (to_mode)
     478                 :            :                            && known_lt (GET_MODE_PRECISION (from_mode),
     479                 :            :                                         GET_MODE_PRECISION (to_mode)));
     480                 :            :       /* The modes after FROM_MODE are all MODE_INT, so the only
     481                 :            :          MODE_PARTIAL_INT mode we consider is FROM_MODE itself.
     482                 :            :          If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing
     483                 :            :          MODE_INT.  */
     484                 :     124295 :       if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT)
     485                 :          0 :         limit_mode = GET_MODE_WIDER_MODE (limit_mode).require ();
     486                 :            :     }
     487                 :            :   else
     488                 :        313 :     gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode)
     489                 :            :                          && from_mode < to_mode);
     490                 :     261149 :   FOR_EACH_MODE (from_mode, from_mode, limit_mode)
     491                 :            :     {
     492                 :     173181 :       enum insn_code handler = convert_optab_handler (op, to_mode, from_mode);
     493                 :            : 
     494                 :     173181 :       if (handler != CODE_FOR_nothing)
     495                 :            :         {
     496                 :      36640 :           if (found_mode)
     497                 :       1287 :             *found_mode = from_mode;
     498                 :      36640 :           return handler;
     499                 :            :         }
     500                 :            :     }
     501                 :            : 
     502                 :            :   return CODE_FOR_nothing;
     503                 :            : }
     504                 :            : 
     505                 :            : /* Return non-zero if a highpart multiply is supported of can be synthisized.
     506                 :            :    For the benefit of expand_mult_highpart, the return value is 1 for direct,
     507                 :            :    2 for even/odd widening, and 3 for hi/lo widening.  */
     508                 :            : 
     509                 :            : int
     510                 :       7325 : can_mult_highpart_p (machine_mode mode, bool uns_p)
     511                 :            : {
     512                 :       7325 :   optab op;
     513                 :            : 
     514                 :       7325 :   op = uns_p ? umul_highpart_optab : smul_highpart_optab;
     515                 :       7325 :   if (optab_handler (op, mode) != CODE_FOR_nothing)
     516                 :            :     return 1;
     517                 :            : 
     518                 :            :   /* If the mode is an integral vector, synth from widening operations.  */
     519                 :       6855 :   if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
     520                 :            :     return 0;
     521                 :            : 
     522                 :       3504 :   poly_int64 nunits = GET_MODE_NUNITS (mode);
     523                 :            : 
     524                 :       1752 :   op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
     525                 :       1752 :   if (optab_handler (op, mode) != CODE_FOR_nothing)
     526                 :            :     {
     527                 :       1400 :       op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
     528                 :       1400 :       if (optab_handler (op, mode) != CODE_FOR_nothing)
     529                 :            :         {
     530                 :            :           /* The encoding has 2 interleaved stepped patterns.  */
     531                 :       2495 :           vec_perm_builder sel (nunits, 2, 3);
     532                 :       9800 :           for (unsigned int i = 0; i < 6; ++i)
     533                 :       8400 :             sel.quick_push (!BYTES_BIG_ENDIAN
     534                 :       8400 :                             + (i & ~1)
     535                 :       8400 :                             + ((i & 1) ? nunits : 0));
     536                 :       2495 :           vec_perm_indices indices (sel, 2, nunits);
     537                 :       1400 :           if (can_vec_perm_const_p (mode, indices))
     538                 :        610 :             return 2;
     539                 :            :         }
     540                 :            :     }
     541                 :            : 
     542                 :       1447 :   op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
     543                 :       1447 :   if (optab_handler (op, mode) != CODE_FOR_nothing)
     544                 :            :     {
     545                 :       1166 :       op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
     546                 :       1166 :       if (optab_handler (op, mode) != CODE_FOR_nothing)
     547                 :            :         {
     548                 :            :           /* The encoding has a single stepped pattern.  */
     549                 :       1166 :           vec_perm_builder sel (nunits, 1, 3);
     550                 :       4664 :           for (unsigned int i = 0; i < 3; ++i)
     551                 :       3498 :             sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1));
     552                 :       1166 :           vec_perm_indices indices (sel, 2, nunits);
     553                 :       1166 :           if (can_vec_perm_const_p (mode, indices))
     554                 :       2332 :             return 3;
     555                 :            :         }
     556                 :            :     }
     557                 :            : 
     558                 :            :   return 0;
     559                 :            : }
     560                 :            : 
     561                 :            : /* Return true if target supports vector masked load/store for mode.  */
     562                 :            : 
     563                 :            : bool
     564                 :      36166 : can_vec_mask_load_store_p (machine_mode mode,
     565                 :            :                            machine_mode mask_mode,
     566                 :            :                            bool is_load)
     567                 :            : {
     568                 :      36166 :   optab op = is_load ? maskload_optab : maskstore_optab;
     569                 :      36166 :   machine_mode vmode;
     570                 :            : 
     571                 :            :   /* If mode is vector mode, check it directly.  */
     572                 :      36166 :   if (VECTOR_MODE_P (mode))
     573                 :      34327 :     return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing;
     574                 :            : 
     575                 :            :   /* Otherwise, return true if there is some vector mode with
     576                 :            :      the mask load/store supported.  */
     577                 :            : 
     578                 :            :   /* See if there is any chance the mask load or store might be
     579                 :            :      vectorized.  If not, punt.  */
     580                 :       1839 :   scalar_mode smode;
     581                 :       1839 :   if (!is_a <scalar_mode> (mode, &smode))
     582                 :            :     return false;
     583                 :            : 
     584                 :       1839 :   vmode = targetm.vectorize.preferred_simd_mode (smode);
     585                 :       1839 :   if (!VECTOR_MODE_P (vmode))
     586                 :            :     return false;
     587                 :            : 
     588                 :       1833 :   if (targetm.vectorize.get_mask_mode (vmode).exists (&mask_mode)
     589                 :       1833 :       && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
     590                 :        761 :     return true;
     591                 :            : 
     592                 :       1072 :   auto_vector_modes vector_modes;
     593                 :       1072 :   targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
     594                 :       6718 :   for (unsigned int i = 0; i < vector_modes.length (); ++i)
     595                 :            :     {
     596                 :       4574 :       poly_uint64 cur = GET_MODE_SIZE (vector_modes[i]);
     597                 :       2287 :       poly_uint64 nunits;
     598                 :       4574 :       if (!multiple_p (cur, GET_MODE_SIZE (smode), &nunits))
     599                 :          0 :         continue;
     600                 :       2287 :       if (mode_for_vector (smode, nunits).exists (&vmode)
     601                 :       2268 :           && VECTOR_MODE_P (vmode)
     602                 :       4555 :           && targetm.vectorize.get_mask_mode (vmode).exists (&mask_mode)
     603                 :       2268 :           && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
     604                 :          0 :         return true;
     605                 :            :     }
     606                 :            :   return false;
     607                 :            : }
     608                 :            : 
     609                 :            : /* Return true if there is a compare_and_swap pattern.  */
     610                 :            : 
     611                 :            : bool
     612                 :      39167 : can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
     613                 :            : {
     614                 :      39167 :   enum insn_code icode;
     615                 :            : 
     616                 :            :   /* Check for __atomic_compare_and_swap.  */
     617                 :      39167 :   icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
     618                 :      39167 :   if (icode != CODE_FOR_nothing)
     619                 :            :     return true;
     620                 :            : 
     621                 :            :   /* Check for __sync_compare_and_swap.  */
     622                 :        108 :   icode = optab_handler (sync_compare_and_swap_optab, mode);
     623                 :        108 :   if (icode != CODE_FOR_nothing)
     624                 :            :     return true;
     625                 :        108 :   if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
     626                 :          0 :     return true;
     627                 :            : 
     628                 :            :   /* No inline compare and swap.  */
     629                 :            :   return false;
     630                 :            : }
     631                 :            : 
     632                 :            : /* Return true if an atomic exchange can be performed.  */
     633                 :            : 
     634                 :            : bool
     635                 :         82 : can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
     636                 :            : {
     637                 :         82 :   enum insn_code icode;
     638                 :            : 
     639                 :            :   /* Check for __atomic_exchange.  */
     640                 :         82 :   icode = direct_optab_handler (atomic_exchange_optab, mode);
     641                 :         82 :   if (icode != CODE_FOR_nothing)
     642                 :            :     return true;
     643                 :            : 
     644                 :            :   /* Don't check __sync_test_and_set, as on some platforms that
     645                 :            :      has reduced functionality.  Targets that really do support
     646                 :            :      a proper exchange should simply be updated to the __atomics.  */
     647                 :            : 
     648                 :          0 :   return can_compare_and_swap_p (mode, allow_libcall);
     649                 :            : }
     650                 :            : 
     651                 :            : /* Return true if an atomic load can be performed without falling back to
     652                 :            :    a compare-and-swap.  */
     653                 :            : 
     654                 :            : bool
     655                 :      84374 : can_atomic_load_p (machine_mode mode)
     656                 :            : {
     657                 :      84374 :   enum insn_code icode;
     658                 :            : 
     659                 :            :   /* Does the target supports the load directly?  */
     660                 :      84374 :   icode = direct_optab_handler (atomic_load_optab, mode);
     661                 :      84374 :   if (icode != CODE_FOR_nothing)
     662                 :            :     return true;
     663                 :            : 
     664                 :            :   /* If the size of the object is greater than word size on this target,
     665                 :            :      then we assume that a load will not be atomic.  Also see
     666                 :            :      expand_atomic_load.  */
     667                 :       3233 :   return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD);
     668                 :            : }
     669                 :            : 
     670                 :            : /* Determine whether "1 << x" is relatively cheap in word_mode.  */
     671                 :            : 
     672                 :            : bool
     673                 :     665195 : lshift_cheap_p (bool speed_p)
     674                 :            : {
     675                 :            :   /* FIXME: This should be made target dependent via this "this_target"
     676                 :            :      mechanism, similar to e.g. can_copy_init_p in gcse.c.  */
     677                 :     665195 :   static bool init[2] = { false, false };
     678                 :     665195 :   static bool cheap[2] = { true, true };
     679                 :            : 
     680                 :            :   /* If the targer has no lshift in word_mode, the operation will most
     681                 :            :      probably not be cheap.  ??? Does GCC even work for such targets?  */
     682                 :     665195 :   if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
     683                 :            :     return false;
     684                 :            : 
     685                 :     665195 :   if (!init[speed_p])
     686                 :            :     {
     687                 :      28675 :       rtx reg = gen_raw_REG (word_mode, 10000);
     688                 :      28675 :       int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
     689                 :            :                                word_mode, speed_p);
     690                 :      28675 :       cheap[speed_p] = cost < COSTS_N_INSNS (3);
     691                 :      28675 :       init[speed_p] = true;
     692                 :            :     }
     693                 :            : 
     694                 :     665195 :   return cheap[speed_p];
     695                 :            : }
     696                 :            : 
     697                 :            : /* Return true if vector conversion optab OP supports at least one mode,
     698                 :            :    given that the second mode is always an integer vector.  */
     699                 :            : 
     700                 :            : static bool
     701                 :       1937 : supports_vec_convert_optab_p (optab op)
     702                 :            : {
     703                 :     216944 :   for (int i = 0; i < NUM_MACHINE_MODES; ++i)
     704                 :     215007 :     if (VECTOR_MODE_P ((machine_mode) i))
     705                 :    2913250 :       for (int j = MIN_MODE_VECTOR_INT; j < MAX_MODE_VECTOR_INT; ++j)
     706                 :    2822210 :         if (convert_optab_handler (op, (machine_mode) i,
     707                 :            :                                    (machine_mode) j) != CODE_FOR_nothing)
     708                 :            :           return true;
     709                 :            : 
     710                 :            :   return false;
     711                 :            : }
     712                 :            : 
     713                 :            : /* Return true if vec_gather_load is available for at least one vector
     714                 :            :    mode.  */
     715                 :            : 
     716                 :            : bool
     717                 :      10194 : supports_vec_gather_load_p ()
     718                 :            : {
     719                 :      10194 :   if (this_fn_optabs->supports_vec_gather_load_cached)
     720                 :       8896 :     return this_fn_optabs->supports_vec_gather_load;
     721                 :            : 
     722                 :       1298 :   this_fn_optabs->supports_vec_gather_load_cached = true;
     723                 :            : 
     724                 :       1298 :   this_fn_optabs->supports_vec_gather_load
     725                 :       1298 :     = supports_vec_convert_optab_p (gather_load_optab);
     726                 :            : 
     727                 :       1298 :   return this_fn_optabs->supports_vec_gather_load;
     728                 :            : }
     729                 :            : 
     730                 :            : /* Return true if vec_scatter_store is available for at least one vector
     731                 :            :    mode.  */
     732                 :            : 
     733                 :            : bool
     734                 :       4586 : supports_vec_scatter_store_p ()
     735                 :            : {
     736                 :       4586 :   if (this_fn_optabs->supports_vec_scatter_store_cached)
     737                 :       3947 :     return this_fn_optabs->supports_vec_scatter_store;
     738                 :            : 
     739                 :        639 :   this_fn_optabs->supports_vec_scatter_store_cached = true;
     740                 :            : 
     741                 :        639 :   this_fn_optabs->supports_vec_scatter_store
     742                 :        639 :     = supports_vec_convert_optab_p (scatter_store_optab);
     743                 :            : 
     744                 :        639 :   return this_fn_optabs->supports_vec_scatter_store;
     745                 :            : }
     746                 :            : 

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.