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