LCOV - code coverage report
Current view: top level - gcc - internal-fn.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 71.6 % 2366 1694
Test Date: 2024-04-13 14:00:49 Functions: 60.9 % 156 95
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Internal functions.
       2                 :             :    Copyright (C) 2011-2024 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it under
       7                 :             : the terms of the GNU General Public License as published by the Free
       8                 :             : Software Foundation; either version 3, or (at your option) any later
       9                 :             : version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : #include "config.h"
      21                 :             : #include "system.h"
      22                 :             : #include "coretypes.h"
      23                 :             : #include "backend.h"
      24                 :             : #include "target.h"
      25                 :             : #include "rtl.h"
      26                 :             : #include "tree.h"
      27                 :             : #include "gimple.h"
      28                 :             : #include "predict.h"
      29                 :             : #include "stringpool.h"
      30                 :             : #include "tree-vrp.h"
      31                 :             : #include "tree-ssanames.h"
      32                 :             : #include "expmed.h"
      33                 :             : #include "memmodel.h"
      34                 :             : #include "optabs.h"
      35                 :             : #include "emit-rtl.h"
      36                 :             : #include "diagnostic-core.h"
      37                 :             : #include "fold-const.h"
      38                 :             : #include "internal-fn.h"
      39                 :             : #include "stor-layout.h"
      40                 :             : #include "dojump.h"
      41                 :             : #include "expr.h"
      42                 :             : #include "stringpool.h"
      43                 :             : #include "attribs.h"
      44                 :             : #include "asan.h"
      45                 :             : #include "ubsan.h"
      46                 :             : #include "recog.h"
      47                 :             : #include "builtins.h"
      48                 :             : #include "optabs-tree.h"
      49                 :             : #include "gimple-ssa.h"
      50                 :             : #include "tree-phinodes.h"
      51                 :             : #include "ssa-iterators.h"
      52                 :             : #include "explow.h"
      53                 :             : #include "rtl-iter.h"
      54                 :             : #include "gimple-range.h"
      55                 :             : #include "fold-const-call.h"
      56                 :             : 
      57                 :             : /* For lang_hooks.types.type_for_mode.  */
      58                 :             : #include "langhooks.h"
      59                 :             : 
      60                 :             : /* The names of each internal function, indexed by function number.  */
      61                 :             : const char *const internal_fn_name_array[] = {
      62                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
      63                 :             : #include "internal-fn.def"
      64                 :             :   "<invalid-fn>"
      65                 :             : };
      66                 :             : 
      67                 :             : /* The ECF_* flags of each internal function, indexed by function number.  */
      68                 :             : const int internal_fn_flags_array[] = {
      69                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
      70                 :             : #include "internal-fn.def"
      71                 :             :   0
      72                 :             : };
      73                 :             : 
      74                 :             : /* Return the internal function called NAME, or IFN_LAST if there's
      75                 :             :    no such function.  */
      76                 :             : 
      77                 :             : internal_fn
      78                 :           3 : lookup_internal_fn (const char *name)
      79                 :             : {
      80                 :           3 :   typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
      81                 :           3 :   static name_to_fn_map_type *name_to_fn_map;
      82                 :             : 
      83                 :           3 :   if (!name_to_fn_map)
      84                 :             :     {
      85                 :           2 :       name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
      86                 :         538 :       for (unsigned int i = 0; i < IFN_LAST; ++i)
      87                 :        1072 :         name_to_fn_map->put (internal_fn_name (internal_fn (i)),
      88                 :         536 :                              internal_fn (i));
      89                 :             :     }
      90                 :           3 :   internal_fn *entry = name_to_fn_map->get (name);
      91                 :           3 :   return entry ? *entry : IFN_LAST;
      92                 :             : }
      93                 :             : 
      94                 :             : /* Geven an internal_fn IFN that is a widening function, return its
      95                 :             :    corresponding LO and HI internal_fns.  */
      96                 :             : 
      97                 :             : extern void
      98                 :       48734 : lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi)
      99                 :             : {
     100                 :       48734 :   gcc_assert (widening_fn_p (ifn));
     101                 :             : 
     102                 :       48734 :   switch (ifn)
     103                 :             :     {
     104                 :           0 :     default:
     105                 :           0 :       gcc_unreachable ();
     106                 :             : #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
     107                 :             : #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T)   \
     108                 :             :     case IFN_##NAME:                                            \
     109                 :             :       *lo = internal_fn (IFN_##NAME##_LO);                      \
     110                 :             :       *hi = internal_fn (IFN_##NAME##_HI);                      \
     111                 :             :       break;
     112                 :             : #include "internal-fn.def"
     113                 :             :     }
     114                 :       48734 : }
     115                 :             : 
     116                 :             : /* Given an internal_fn IFN that is a widening function, return its
     117                 :             :    corresponding _EVEN and _ODD internal_fns in *EVEN and *ODD.  */
     118                 :             : 
     119                 :             : extern void
     120                 :       48734 : lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even,
     121                 :             :                             internal_fn *odd)
     122                 :             : {
     123                 :       48734 :   gcc_assert (widening_fn_p (ifn));
     124                 :             : 
     125                 :       48734 :   switch (ifn)
     126                 :             :     {
     127                 :           0 :     default:
     128                 :           0 :       gcc_unreachable ();
     129                 :             : #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
     130                 :             : #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T)   \
     131                 :             :     case IFN_##NAME:                                            \
     132                 :             :       *even = internal_fn (IFN_##NAME##_EVEN);                  \
     133                 :             :       *odd = internal_fn (IFN_##NAME##_ODD);                    \
     134                 :             :       break;
     135                 :             : #include "internal-fn.def"
     136                 :             :     }
     137                 :       48734 : }
     138                 :             : 
     139                 :             : 
     140                 :             : /* Fnspec of each internal function, indexed by function number.  */
     141                 :             : const_tree internal_fn_fnspec_array[IFN_LAST + 1];
     142                 :             : 
     143                 :             : void
     144                 :      280151 : init_internal_fns ()
     145                 :             : {
     146                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
     147                 :             :   if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
     148                 :             :     build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
     149                 :             : #include "internal-fn.def"
     150                 :      280151 :   internal_fn_fnspec_array[IFN_LAST] = 0;
     151                 :      280151 : }
     152                 :             : 
     153                 :             : /* Create static initializers for the information returned by
     154                 :             :    direct_internal_fn.  */
     155                 :             : #define not_direct { -2, -2, false }
     156                 :             : #define mask_load_direct { -1, 2, false }
     157                 :             : #define load_lanes_direct { -1, -1, false }
     158                 :             : #define mask_load_lanes_direct { -1, -1, false }
     159                 :             : #define gather_load_direct { 3, 1, false }
     160                 :             : #define len_load_direct { -1, -1, false }
     161                 :             : #define mask_len_load_direct { -1, 4, false }
     162                 :             : #define mask_store_direct { 3, 2, false }
     163                 :             : #define store_lanes_direct { 0, 0, false }
     164                 :             : #define mask_store_lanes_direct { 0, 0, false }
     165                 :             : #define vec_cond_mask_direct { 1, 0, false }
     166                 :             : #define vec_cond_mask_len_direct { 1, 1, false }
     167                 :             : #define vec_cond_direct { 2, 0, false }
     168                 :             : #define scatter_store_direct { 3, 1, false }
     169                 :             : #define len_store_direct { 3, 3, false }
     170                 :             : #define mask_len_store_direct { 4, 5, false }
     171                 :             : #define vec_set_direct { 3, 3, false }
     172                 :             : #define vec_extract_direct { 0, -1, false }
     173                 :             : #define unary_direct { 0, 0, true }
     174                 :             : #define unary_convert_direct { -1, 0, true }
     175                 :             : #define binary_direct { 0, 0, true }
     176                 :             : #define ternary_direct { 0, 0, true }
     177                 :             : #define cond_unary_direct { 1, 1, true }
     178                 :             : #define cond_binary_direct { 1, 1, true }
     179                 :             : #define cond_ternary_direct { 1, 1, true }
     180                 :             : #define cond_len_unary_direct { 1, 1, true }
     181                 :             : #define cond_len_binary_direct { 1, 1, true }
     182                 :             : #define cond_len_ternary_direct { 1, 1, true }
     183                 :             : #define while_direct { 0, 2, false }
     184                 :             : #define fold_extract_direct { 2, 2, false }
     185                 :             : #define fold_len_extract_direct { 2, 2, false }
     186                 :             : #define fold_left_direct { 1, 1, false }
     187                 :             : #define mask_fold_left_direct { 1, 1, false }
     188                 :             : #define mask_len_fold_left_direct { 1, 1, false }
     189                 :             : #define check_ptrs_direct { 0, 0, false }
     190                 :             : 
     191                 :             : const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
     192                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
     193                 :             : #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
     194                 :             : #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
     195                 :             :                                      UNSIGNED_OPTAB, TYPE) TYPE##_direct,
     196                 :             : #include "internal-fn.def"
     197                 :             :   not_direct
     198                 :             : };
     199                 :             : 
     200                 :             : /* Expand STMT using instruction ICODE.  The instruction has NOUTPUTS
     201                 :             :    output operands and NINPUTS input operands, where NOUTPUTS is either
     202                 :             :    0 or 1.  The output operand (if any) comes first, followed by the
     203                 :             :    NINPUTS input operands.  */
     204                 :             : 
     205                 :             : static void
     206                 :       70900 : expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
     207                 :             :                       unsigned int ninputs)
     208                 :             : {
     209                 :       70900 :   gcc_assert (icode != CODE_FOR_nothing);
     210                 :             : 
     211                 :       70900 :   expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
     212                 :       70900 :   unsigned int opno = 0;
     213                 :       70900 :   rtx lhs_rtx = NULL_RTX;
     214                 :       70900 :   tree lhs = gimple_call_lhs (stmt);
     215                 :             : 
     216                 :       70900 :   if (noutputs)
     217                 :             :     {
     218                 :       70900 :       gcc_assert (noutputs == 1);
     219                 :       70900 :       if (lhs)
     220                 :       70900 :         lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     221                 :             : 
     222                 :             :       /* Do not assign directly to a promoted subreg, since there is no
     223                 :             :          guarantee that the instruction will leave the upper bits of the
     224                 :             :          register in the state required by SUBREG_PROMOTED_SIGN.  */
     225                 :       70900 :       rtx dest = lhs_rtx;
     226                 :       70900 :       if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
     227                 :             :         dest = NULL_RTX;
     228                 :       70900 :       create_output_operand (&ops[opno], dest,
     229                 :       70900 :                              insn_data[icode].operand[opno].mode);
     230                 :       70900 :       opno += 1;
     231                 :             :     }
     232                 :             :   else
     233                 :           0 :     gcc_assert (!lhs);
     234                 :             : 
     235                 :      200737 :   for (unsigned int i = 0; i < ninputs; ++i)
     236                 :             :     {
     237                 :      129837 :       tree rhs = gimple_call_arg (stmt, i);
     238                 :      129837 :       tree rhs_type = TREE_TYPE (rhs);
     239                 :      129837 :       rtx rhs_rtx = expand_normal (rhs);
     240                 :      129837 :       if (INTEGRAL_TYPE_P (rhs_type))
     241                 :        7154 :         create_convert_operand_from (&ops[opno], rhs_rtx,
     242                 :        7154 :                                      TYPE_MODE (rhs_type),
     243                 :        7154 :                                      TYPE_UNSIGNED (rhs_type));
     244                 :      122683 :       else if (TREE_CODE (rhs) == SSA_NAME
     245                 :       98460 :                && SSA_NAME_IS_DEFAULT_DEF (rhs)
     246                 :      126913 :                && VAR_P (SSA_NAME_VAR (rhs)))
     247                 :         147 :         create_undefined_input_operand (&ops[opno], TYPE_MODE (rhs_type));
     248                 :       43450 :       else if (VECTOR_BOOLEAN_TYPE_P (rhs_type)
     249                 :        1102 :                && SCALAR_INT_MODE_P (TYPE_MODE (rhs_type))
     250                 :      123638 :                && maybe_ne (GET_MODE_PRECISION (TYPE_MODE (rhs_type)),
     251                 :        1102 :                             TYPE_VECTOR_SUBPARTS (rhs_type).to_constant ()))
     252                 :             :         {
     253                 :             :           /* Ensure that the vector bitmasks do not have excess bits.  */
     254                 :         222 :           int nunits = TYPE_VECTOR_SUBPARTS (rhs_type).to_constant ();
     255                 :         222 :           rtx tmp = expand_binop (TYPE_MODE (rhs_type), and_optab, rhs_rtx,
     256                 :         222 :                                   GEN_INT ((HOST_WIDE_INT_1U << nunits) - 1),
     257                 :             :                                   NULL_RTX, true, OPTAB_WIDEN);
     258                 :         222 :           create_input_operand (&ops[opno], tmp, TYPE_MODE (rhs_type));
     259                 :             :         }
     260                 :             :       else
     261                 :      122314 :         create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
     262                 :      129837 :       opno += 1;
     263                 :             :     }
     264                 :             : 
     265                 :       70900 :   gcc_assert (opno == noutputs + ninputs);
     266                 :       70900 :   expand_insn (icode, opno, ops);
     267                 :       70900 :   if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
     268                 :             :     {
     269                 :             :       /* If the return value has an integral type, convert the instruction
     270                 :             :          result to that type.  This is useful for things that return an
     271                 :             :          int regardless of the size of the input.  If the instruction result
     272                 :             :          is smaller than required, assume that it is signed.
     273                 :             : 
     274                 :             :          If the return value has a nonintegral type, its mode must match
     275                 :             :          the instruction result.  */
     276                 :        4391 :       if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
     277                 :             :         {
     278                 :             :           /* If this is a scalar in a register that is stored in a wider
     279                 :             :              mode than the declared mode, compute the result into its
     280                 :             :              declared mode and then convert to the wider mode.  */
     281                 :           0 :           gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
     282                 :           0 :           rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
     283                 :           0 :           convert_move (SUBREG_REG (lhs_rtx), tmp,
     284                 :           0 :                         SUBREG_PROMOTED_SIGN (lhs_rtx));
     285                 :             :         }
     286                 :        4391 :       else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
     287                 :          34 :         emit_move_insn (lhs_rtx, ops[0].value);
     288                 :             :       else
     289                 :             :         {
     290                 :        4357 :           gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
     291                 :        4357 :           convert_move (lhs_rtx, ops[0].value, 0);
     292                 :             :         }
     293                 :             :     }
     294                 :       70900 : }
     295                 :             : 
     296                 :             : /* ARRAY_TYPE is an array of vector modes.  Return the associated insn
     297                 :             :    for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none.  */
     298                 :             : 
     299                 :             : static enum insn_code
     300                 :           0 : get_multi_vector_move (tree array_type, convert_optab optab)
     301                 :             : {
     302                 :           0 :   machine_mode imode;
     303                 :           0 :   machine_mode vmode;
     304                 :             : 
     305                 :           0 :   gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
     306                 :           0 :   imode = TYPE_MODE (array_type);
     307                 :           0 :   vmode = TYPE_MODE (TREE_TYPE (array_type));
     308                 :             : 
     309                 :           0 :   return convert_optab_handler (optab, imode, vmode);
     310                 :             : }
     311                 :             : 
     312                 :             : /* Add mask and len arguments according to the STMT.  */
     313                 :             : 
     314                 :             : static unsigned int
     315                 :        1743 : add_mask_and_len_args (expand_operand *ops, unsigned int opno, gcall *stmt)
     316                 :             : {
     317                 :        1743 :   internal_fn ifn = gimple_call_internal_fn (stmt);
     318                 :        1743 :   int len_index = internal_fn_len_index (ifn);
     319                 :             :   /* BIAS is always consecutive next of LEN.  */
     320                 :        1743 :   int bias_index = len_index + 1;
     321                 :        1743 :   int mask_index = internal_fn_mask_index (ifn);
     322                 :             :   /* The order of arguments are always {len,bias,mask}.  */
     323                 :        1743 :   if (mask_index >= 0)
     324                 :             :     {
     325                 :        1743 :       tree mask = gimple_call_arg (stmt, mask_index);
     326                 :        1743 :       rtx mask_rtx = expand_normal (mask);
     327                 :             : 
     328                 :        1743 :       tree mask_type = TREE_TYPE (mask);
     329                 :        1743 :       if (VECTOR_BOOLEAN_TYPE_P (mask_type)
     330                 :        1743 :           && SCALAR_INT_MODE_P (TYPE_MODE (mask_type))
     331                 :        3006 :           && maybe_ne (GET_MODE_PRECISION (TYPE_MODE (mask_type)),
     332                 :        2795 :                        TYPE_VECTOR_SUBPARTS (mask_type).to_constant ()))
     333                 :             :         {
     334                 :             :           /* Ensure that the vector bitmasks do not have excess bits.  */
     335                 :         211 :           int nunits = TYPE_VECTOR_SUBPARTS (mask_type).to_constant ();
     336                 :         211 :           mask_rtx = expand_binop (TYPE_MODE (mask_type), and_optab, mask_rtx,
     337                 :         211 :                                    GEN_INT ((HOST_WIDE_INT_1U << nunits) - 1),
     338                 :             :                                    NULL_RTX, true, OPTAB_WIDEN);
     339                 :             :         }
     340                 :             : 
     341                 :        1743 :       create_input_operand (&ops[opno++], mask_rtx,
     342                 :        1743 :                             TYPE_MODE (TREE_TYPE (mask)));
     343                 :             :     }
     344                 :        1743 :   if (len_index >= 0)
     345                 :             :     {
     346                 :           0 :       tree len = gimple_call_arg (stmt, len_index);
     347                 :           0 :       rtx len_rtx = expand_normal (len);
     348                 :           0 :       create_convert_operand_from (&ops[opno++], len_rtx,
     349                 :           0 :                                    TYPE_MODE (TREE_TYPE (len)),
     350                 :           0 :                                    TYPE_UNSIGNED (TREE_TYPE (len)));
     351                 :           0 :       tree biast = gimple_call_arg (stmt, bias_index);
     352                 :           0 :       rtx bias = expand_normal (biast);
     353                 :           0 :       create_input_operand (&ops[opno++], bias, QImode);
     354                 :             :     }
     355                 :        1743 :   return opno;
     356                 :             : }
     357                 :             : 
     358                 :             : /* Expand LOAD_LANES call STMT using optab OPTAB.  */
     359                 :             : 
     360                 :             : static void
     361                 :           0 : expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
     362                 :             : {
     363                 :           0 :   class expand_operand ops[2];
     364                 :           0 :   tree type, lhs, rhs;
     365                 :           0 :   rtx target, mem;
     366                 :             : 
     367                 :           0 :   lhs = gimple_call_lhs (stmt);
     368                 :           0 :   rhs = gimple_call_arg (stmt, 0);
     369                 :           0 :   type = TREE_TYPE (lhs);
     370                 :             : 
     371                 :           0 :   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     372                 :           0 :   mem = expand_normal (rhs);
     373                 :             : 
     374                 :           0 :   gcc_assert (MEM_P (mem));
     375                 :           0 :   PUT_MODE (mem, TYPE_MODE (type));
     376                 :             : 
     377                 :           0 :   create_output_operand (&ops[0], target, TYPE_MODE (type));
     378                 :           0 :   create_fixed_operand (&ops[1], mem);
     379                 :           0 :   expand_insn (get_multi_vector_move (type, optab), 2, ops);
     380                 :           0 :   if (!rtx_equal_p (target, ops[0].value))
     381                 :           0 :     emit_move_insn (target, ops[0].value);
     382                 :           0 : }
     383                 :             : 
     384                 :             : /* Expand STORE_LANES call STMT using optab OPTAB.  */
     385                 :             : 
     386                 :             : static void
     387                 :           0 : expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
     388                 :             : {
     389                 :           0 :   class expand_operand ops[2];
     390                 :           0 :   tree type, lhs, rhs;
     391                 :           0 :   rtx target, reg;
     392                 :             : 
     393                 :           0 :   lhs = gimple_call_lhs (stmt);
     394                 :           0 :   rhs = gimple_call_arg (stmt, 0);
     395                 :           0 :   type = TREE_TYPE (rhs);
     396                 :             : 
     397                 :           0 :   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     398                 :           0 :   reg = expand_normal (rhs);
     399                 :             : 
     400                 :           0 :   gcc_assert (MEM_P (target));
     401                 :           0 :   PUT_MODE (target, TYPE_MODE (type));
     402                 :             : 
     403                 :           0 :   create_fixed_operand (&ops[0], target);
     404                 :           0 :   create_input_operand (&ops[1], reg, TYPE_MODE (type));
     405                 :           0 :   expand_insn (get_multi_vector_move (type, optab), 2, ops);
     406                 :           0 : }
     407                 :             : 
     408                 :             : static void
     409                 :           0 : expand_ANNOTATE (internal_fn, gcall *)
     410                 :             : {
     411                 :           0 :   gcc_unreachable ();
     412                 :             : }
     413                 :             : 
     414                 :             : /* This should get expanded in omp_device_lower pass.  */
     415                 :             : 
     416                 :             : static void
     417                 :           0 : expand_GOMP_USE_SIMT (internal_fn, gcall *)
     418                 :             : {
     419                 :           0 :   gcc_unreachable ();
     420                 :             : }
     421                 :             : 
     422                 :             : /* This should get expanded in omp_device_lower pass.  */
     423                 :             : 
     424                 :             : static void
     425                 :           0 : expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
     426                 :             : {
     427                 :           0 :   gcc_unreachable ();
     428                 :             : }
     429                 :             : 
     430                 :             : /* Allocate per-lane storage and begin non-uniform execution region.  */
     431                 :             : 
     432                 :             : static void
     433                 :           0 : expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
     434                 :             : {
     435                 :           0 :   rtx target;
     436                 :           0 :   tree lhs = gimple_call_lhs (stmt);
     437                 :           0 :   if (lhs)
     438                 :           0 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     439                 :             :   else
     440                 :           0 :     target = gen_reg_rtx (Pmode);
     441                 :           0 :   rtx size = expand_normal (gimple_call_arg (stmt, 0));
     442                 :           0 :   rtx align = expand_normal (gimple_call_arg (stmt, 1));
     443                 :           0 :   class expand_operand ops[3];
     444                 :           0 :   create_output_operand (&ops[0], target, Pmode);
     445                 :           0 :   create_input_operand (&ops[1], size, Pmode);
     446                 :           0 :   create_input_operand (&ops[2], align, Pmode);
     447                 :           0 :   gcc_assert (targetm.have_omp_simt_enter ());
     448                 :           0 :   expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
     449                 :           0 :   if (!rtx_equal_p (target, ops[0].value))
     450                 :           0 :     emit_move_insn (target, ops[0].value);
     451                 :           0 : }
     452                 :             : 
     453                 :             : /* Deallocate per-lane storage and leave non-uniform execution region.  */
     454                 :             : 
     455                 :             : static void
     456                 :           0 : expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
     457                 :             : {
     458                 :           0 :   gcc_checking_assert (!gimple_call_lhs (stmt));
     459                 :           0 :   rtx arg = expand_normal (gimple_call_arg (stmt, 0));
     460                 :           0 :   class expand_operand ops[1];
     461                 :           0 :   create_input_operand (&ops[0], arg, Pmode);
     462                 :           0 :   gcc_assert (targetm.have_omp_simt_exit ());
     463                 :           0 :   expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
     464                 :           0 : }
     465                 :             : 
     466                 :             : /* Lane index on SIMT targets: thread index in the warp on NVPTX.  On targets
     467                 :             :    without SIMT execution this should be expanded in omp_device_lower pass.  */
     468                 :             : 
     469                 :             : static void
     470                 :           0 : expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
     471                 :             : {
     472                 :           0 :   tree lhs = gimple_call_lhs (stmt);
     473                 :           0 :   if (!lhs)
     474                 :             :     return;
     475                 :             : 
     476                 :           0 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     477                 :           0 :   gcc_assert (targetm.have_omp_simt_lane ());
     478                 :           0 :   emit_insn (targetm.gen_omp_simt_lane (target));
     479                 :             : }
     480                 :             : 
     481                 :             : /* This should get expanded in omp_device_lower pass.  */
     482                 :             : 
     483                 :             : static void
     484                 :           0 : expand_GOMP_SIMT_VF (internal_fn, gcall *)
     485                 :             : {
     486                 :           0 :   gcc_unreachable ();
     487                 :             : }
     488                 :             : 
     489                 :             : /* This should get expanded in omp_device_lower pass.  */
     490                 :             : 
     491                 :             : static void
     492                 :           0 : expand_GOMP_TARGET_REV (internal_fn, gcall *)
     493                 :             : {
     494                 :           0 :   gcc_unreachable ();
     495                 :             : }
     496                 :             : 
     497                 :             : /* Lane index of the first SIMT lane that supplies a non-zero argument.
     498                 :             :    This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
     499                 :             :    lane that executed the last iteration for handling OpenMP lastprivate.  */
     500                 :             : 
     501                 :             : static void
     502                 :           0 : expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
     503                 :             : {
     504                 :           0 :   tree lhs = gimple_call_lhs (stmt);
     505                 :           0 :   if (!lhs)
     506                 :           0 :     return;
     507                 :             : 
     508                 :           0 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     509                 :           0 :   rtx cond = expand_normal (gimple_call_arg (stmt, 0));
     510                 :           0 :   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
     511                 :           0 :   class expand_operand ops[2];
     512                 :           0 :   create_output_operand (&ops[0], target, mode);
     513                 :           0 :   create_input_operand (&ops[1], cond, mode);
     514                 :           0 :   gcc_assert (targetm.have_omp_simt_last_lane ());
     515                 :           0 :   expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
     516                 :           0 :   if (!rtx_equal_p (target, ops[0].value))
     517                 :           0 :     emit_move_insn (target, ops[0].value);
     518                 :             : }
     519                 :             : 
     520                 :             : /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered".  */
     521                 :             : 
     522                 :             : static void
     523                 :           0 : expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
     524                 :             : {
     525                 :           0 :   tree lhs = gimple_call_lhs (stmt);
     526                 :           0 :   if (!lhs)
     527                 :           0 :     return;
     528                 :             : 
     529                 :           0 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     530                 :           0 :   rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
     531                 :           0 :   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
     532                 :           0 :   class expand_operand ops[2];
     533                 :           0 :   create_output_operand (&ops[0], target, mode);
     534                 :           0 :   create_input_operand (&ops[1], ctr, mode);
     535                 :           0 :   gcc_assert (targetm.have_omp_simt_ordered ());
     536                 :           0 :   expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
     537                 :           0 :   if (!rtx_equal_p (target, ops[0].value))
     538                 :           0 :     emit_move_insn (target, ops[0].value);
     539                 :             : }
     540                 :             : 
     541                 :             : /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
     542                 :             :    any lane supplies a non-zero argument.  */
     543                 :             : 
     544                 :             : static void
     545                 :           0 : expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
     546                 :             : {
     547                 :           0 :   tree lhs = gimple_call_lhs (stmt);
     548                 :           0 :   if (!lhs)
     549                 :           0 :     return;
     550                 :             : 
     551                 :           0 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     552                 :           0 :   rtx cond = expand_normal (gimple_call_arg (stmt, 0));
     553                 :           0 :   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
     554                 :           0 :   class expand_operand ops[2];
     555                 :           0 :   create_output_operand (&ops[0], target, mode);
     556                 :           0 :   create_input_operand (&ops[1], cond, mode);
     557                 :           0 :   gcc_assert (targetm.have_omp_simt_vote_any ());
     558                 :           0 :   expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
     559                 :           0 :   if (!rtx_equal_p (target, ops[0].value))
     560                 :           0 :     emit_move_insn (target, ops[0].value);
     561                 :             : }
     562                 :             : 
     563                 :             : /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
     564                 :             :    is destination lane index XOR given offset.  */
     565                 :             : 
     566                 :             : static void
     567                 :           0 : expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
     568                 :             : {
     569                 :           0 :   tree lhs = gimple_call_lhs (stmt);
     570                 :           0 :   if (!lhs)
     571                 :           0 :     return;
     572                 :             : 
     573                 :           0 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     574                 :           0 :   rtx src = expand_normal (gimple_call_arg (stmt, 0));
     575                 :           0 :   rtx idx = expand_normal (gimple_call_arg (stmt, 1));
     576                 :           0 :   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
     577                 :           0 :   class expand_operand ops[3];
     578                 :           0 :   create_output_operand (&ops[0], target, mode);
     579                 :           0 :   create_input_operand (&ops[1], src, mode);
     580                 :           0 :   create_input_operand (&ops[2], idx, SImode);
     581                 :           0 :   gcc_assert (targetm.have_omp_simt_xchg_bfly ());
     582                 :           0 :   expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
     583                 :           0 :   if (!rtx_equal_p (target, ops[0].value))
     584                 :           0 :     emit_move_insn (target, ops[0].value);
     585                 :             : }
     586                 :             : 
     587                 :             : /* Exchange between SIMT lanes according to given source lane index.  */
     588                 :             : 
     589                 :             : static void
     590                 :           0 : expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
     591                 :             : {
     592                 :           0 :   tree lhs = gimple_call_lhs (stmt);
     593                 :           0 :   if (!lhs)
     594                 :           0 :     return;
     595                 :             : 
     596                 :           0 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
     597                 :           0 :   rtx src = expand_normal (gimple_call_arg (stmt, 0));
     598                 :           0 :   rtx idx = expand_normal (gimple_call_arg (stmt, 1));
     599                 :           0 :   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
     600                 :           0 :   class expand_operand ops[3];
     601                 :           0 :   create_output_operand (&ops[0], target, mode);
     602                 :           0 :   create_input_operand (&ops[1], src, mode);
     603                 :           0 :   create_input_operand (&ops[2], idx, SImode);
     604                 :           0 :   gcc_assert (targetm.have_omp_simt_xchg_idx ());
     605                 :           0 :   expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
     606                 :           0 :   if (!rtx_equal_p (target, ops[0].value))
     607                 :           0 :     emit_move_insn (target, ops[0].value);
     608                 :             : }
     609                 :             : 
     610                 :             : /* This should get expanded in adjust_simduid_builtins.  */
     611                 :             : 
     612                 :             : static void
     613                 :           0 : expand_GOMP_SIMD_LANE (internal_fn, gcall *)
     614                 :             : {
     615                 :           0 :   gcc_unreachable ();
     616                 :             : }
     617                 :             : 
     618                 :             : /* This should get expanded in adjust_simduid_builtins.  */
     619                 :             : 
     620                 :             : static void
     621                 :           0 : expand_GOMP_SIMD_VF (internal_fn, gcall *)
     622                 :             : {
     623                 :           0 :   gcc_unreachable ();
     624                 :             : }
     625                 :             : 
     626                 :             : /* This should get expanded in adjust_simduid_builtins.  */
     627                 :             : 
     628                 :             : static void
     629                 :           0 : expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
     630                 :             : {
     631                 :           0 :   gcc_unreachable ();
     632                 :             : }
     633                 :             : 
     634                 :             : /* This should get expanded in adjust_simduid_builtins.  */
     635                 :             : 
     636                 :             : static void
     637                 :           0 : expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
     638                 :             : {
     639                 :           0 :   gcc_unreachable ();
     640                 :             : }
     641                 :             : 
     642                 :             : /* This should get expanded in adjust_simduid_builtins.  */
     643                 :             : 
     644                 :             : static void
     645                 :           0 : expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
     646                 :             : {
     647                 :           0 :   gcc_unreachable ();
     648                 :             : }
     649                 :             : 
     650                 :             : /* This should get expanded in the sanopt pass.  */
     651                 :             : 
     652                 :             : static void
     653                 :           0 : expand_UBSAN_NULL (internal_fn, gcall *)
     654                 :             : {
     655                 :           0 :   gcc_unreachable ();
     656                 :             : }
     657                 :             : 
     658                 :             : /* This should get expanded in the sanopt pass.  */
     659                 :             : 
     660                 :             : static void
     661                 :           0 : expand_UBSAN_BOUNDS (internal_fn, gcall *)
     662                 :             : {
     663                 :           0 :   gcc_unreachable ();
     664                 :             : }
     665                 :             : 
     666                 :             : /* This should get expanded in the sanopt pass.  */
     667                 :             : 
     668                 :             : static void
     669                 :           0 : expand_UBSAN_VPTR (internal_fn, gcall *)
     670                 :             : {
     671                 :           0 :   gcc_unreachable ();
     672                 :             : }
     673                 :             : 
     674                 :             : /* This should get expanded in the sanopt pass.  */
     675                 :             : 
     676                 :             : static void
     677                 :           0 : expand_UBSAN_PTR (internal_fn, gcall *)
     678                 :             : {
     679                 :           0 :   gcc_unreachable ();
     680                 :             : }
     681                 :             : 
     682                 :             : /* This should get expanded in the sanopt pass.  */
     683                 :             : 
     684                 :             : static void
     685                 :           0 : expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
     686                 :             : {
     687                 :           0 :   gcc_unreachable ();
     688                 :             : }
     689                 :             : 
     690                 :             : /* This should get expanded in the sanopt pass.  */
     691                 :             : 
     692                 :             : static void
     693                 :           0 : expand_HWASAN_CHECK (internal_fn, gcall *)
     694                 :             : {
     695                 :           0 :   gcc_unreachable ();
     696                 :             : }
     697                 :             : 
     698                 :             : /* For hwasan stack tagging:
     699                 :             :    Clear tags on the dynamically allocated space.
     700                 :             :    For use after an object dynamically allocated on the stack goes out of
     701                 :             :    scope.  */
     702                 :             : static void
     703                 :           0 : expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
     704                 :             : {
     705                 :           0 :   gcc_assert (Pmode == ptr_mode);
     706                 :           0 :   tree restored_position = gimple_call_arg (gc, 0);
     707                 :           0 :   rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
     708                 :             :                                   EXPAND_NORMAL);
     709                 :           0 :   rtx func = init_one_libfunc ("__hwasan_tag_memory");
     710                 :           0 :   rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
     711                 :             :                                  stack_pointer_rtx, NULL_RTX, 0,
     712                 :             :                                  OPTAB_WIDEN);
     713                 :           0 :   emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
     714                 :           0 :                            virtual_stack_dynamic_rtx, Pmode,
     715                 :           0 :                            HWASAN_STACK_BACKGROUND, QImode,
     716                 :           0 :                            off, Pmode);
     717                 :           0 : }
     718                 :             : 
     719                 :             : /* For hwasan stack tagging:
     720                 :             :    Return a tag to be used for a dynamic allocation.  */
     721                 :             : static void
     722                 :           0 : expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
     723                 :             : {
     724                 :           0 :   tree tag = gimple_call_lhs (gc);
     725                 :           0 :   rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
     726                 :           0 :   machine_mode mode = GET_MODE (target);
     727                 :           0 :   gcc_assert (mode == QImode);
     728                 :             : 
     729                 :           0 :   rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
     730                 :           0 :   gcc_assert (base_tag);
     731                 :           0 :   rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
     732                 :           0 :   rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
     733                 :             :                                         target, /* unsignedp = */1,
     734                 :             :                                         OPTAB_WIDEN);
     735                 :           0 :   chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
     736                 :             : 
     737                 :             :   /* Really need to put the tag into the `target` RTX.  */
     738                 :           0 :   if (chosen_tag != target)
     739                 :             :     {
     740                 :           0 :       rtx temp = chosen_tag;
     741                 :           0 :       gcc_assert (GET_MODE (chosen_tag) == mode);
     742                 :           0 :       emit_move_insn (target, temp);
     743                 :             :     }
     744                 :             : 
     745                 :           0 :   hwasan_increment_frame_tag ();
     746                 :           0 : }
     747                 :             : 
     748                 :             : /* For hwasan stack tagging:
     749                 :             :    Tag a region of space in the shadow stack according to the base pointer of
     750                 :             :    an object on the stack.  N.b. the length provided in the internal call is
     751                 :             :    required to be aligned to HWASAN_TAG_GRANULE_SIZE.  */
     752                 :             : static void
     753                 :           0 : expand_HWASAN_MARK (internal_fn, gcall *gc)
     754                 :             : {
     755                 :           0 :   gcc_assert (ptr_mode == Pmode);
     756                 :           0 :   HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
     757                 :           0 :   bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
     758                 :             : 
     759                 :           0 :   tree base = gimple_call_arg (gc, 1);
     760                 :           0 :   gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
     761                 :           0 :   rtx base_rtx = expand_normal (base);
     762                 :             : 
     763                 :           0 :   rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
     764                 :           0 :     : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
     765                 :           0 :   rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
     766                 :             : 
     767                 :           0 :   tree len = gimple_call_arg (gc, 2);
     768                 :           0 :   rtx r_len = expand_normal (len);
     769                 :             : 
     770                 :           0 :   rtx func = init_one_libfunc ("__hwasan_tag_memory");
     771                 :           0 :   emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
     772                 :           0 :                      tag, QImode, r_len, Pmode);
     773                 :           0 : }
     774                 :             : 
     775                 :             : /* For hwasan stack tagging:
     776                 :             :    Store a tag into a pointer.  */
     777                 :             : static void
     778                 :           0 : expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
     779                 :             : {
     780                 :           0 :   gcc_assert (ptr_mode == Pmode);
     781                 :           0 :   tree g_target = gimple_call_lhs (gc);
     782                 :           0 :   tree g_ptr = gimple_call_arg (gc, 0);
     783                 :           0 :   tree g_tag = gimple_call_arg (gc, 1);
     784                 :             : 
     785                 :           0 :   rtx ptr = expand_normal (g_ptr);
     786                 :           0 :   rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
     787                 :           0 :   rtx target = expand_normal (g_target);
     788                 :             : 
     789                 :           0 :   rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
     790                 :           0 :   rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
     791                 :           0 :   if (tagged_value != target)
     792                 :           0 :     emit_move_insn (target, tagged_value);
     793                 :           0 : }
     794                 :             : 
     795                 :             : /* This should get expanded in the sanopt pass.  */
     796                 :             : 
     797                 :             : static void
     798                 :           0 : expand_ASAN_CHECK (internal_fn, gcall *)
     799                 :             : {
     800                 :           0 :   gcc_unreachable ();
     801                 :             : }
     802                 :             : 
     803                 :             : /* This should get expanded in the sanopt pass.  */
     804                 :             : 
     805                 :             : static void
     806                 :           0 : expand_ASAN_MARK (internal_fn, gcall *)
     807                 :             : {
     808                 :           0 :   gcc_unreachable ();
     809                 :             : }
     810                 :             : 
     811                 :             : /* This should get expanded in the sanopt pass.  */
     812                 :             : 
     813                 :             : static void
     814                 :           0 : expand_ASAN_POISON (internal_fn, gcall *)
     815                 :             : {
     816                 :           0 :   gcc_unreachable ();
     817                 :             : }
     818                 :             : 
     819                 :             : /* This should get expanded in the sanopt pass.  */
     820                 :             : 
     821                 :             : static void
     822                 :           0 : expand_ASAN_POISON_USE (internal_fn, gcall *)
     823                 :             : {
     824                 :           0 :   gcc_unreachable ();
     825                 :             : }
     826                 :             : 
     827                 :             : /* This should get expanded in the tsan pass.  */
     828                 :             : 
     829                 :             : static void
     830                 :           0 : expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
     831                 :             : {
     832                 :           0 :   gcc_unreachable ();
     833                 :             : }
     834                 :             : 
     835                 :             : /* This should get expanded in the lower pass.  */
     836                 :             : 
     837                 :             : static void
     838                 :          25 : expand_FALLTHROUGH (internal_fn, gcall *call)
     839                 :             : {
     840                 :          25 :   error_at (gimple_location (call),
     841                 :             :             "invalid use of attribute %<fallthrough%>");
     842                 :          25 : }
     843                 :             : 
     844                 :             : /* Return minimum precision needed to represent all values
     845                 :             :    of ARG in SIGNed integral type.  */
     846                 :             : 
     847                 :             : static int
     848                 :      160306 : get_min_precision (tree arg, signop sign)
     849                 :             : {
     850                 :      160306 :   int prec = TYPE_PRECISION (TREE_TYPE (arg));
     851                 :      160306 :   int cnt = 0;
     852                 :      160306 :   signop orig_sign = sign;
     853                 :      160306 :   if (TREE_CODE (arg) == INTEGER_CST)
     854                 :             :     {
     855                 :       40732 :       int p;
     856                 :       40732 :       if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
     857                 :             :         {
     858                 :       14679 :           widest_int w = wi::to_widest (arg);
     859                 :       14679 :           w = wi::ext (w, prec, sign);
     860                 :       14679 :           p = wi::min_precision (w, sign);
     861                 :       14679 :         }
     862                 :             :       else
     863                 :       26053 :         p = wi::min_precision (wi::to_wide (arg), sign);
     864                 :       40732 :       return MIN (p, prec);
     865                 :             :     }
     866                 :      119574 :   while (CONVERT_EXPR_P (arg)
     867                 :        7123 :          && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
     868                 :      133820 :          && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
     869                 :             :     {
     870                 :        7123 :       arg = TREE_OPERAND (arg, 0);
     871                 :        7123 :       if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
     872                 :             :         {
     873                 :         418 :           if (TYPE_UNSIGNED (TREE_TYPE (arg)))
     874                 :             :             sign = UNSIGNED;
     875                 :         393 :           else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
     876                 :           0 :             return prec + (orig_sign != sign);
     877                 :         418 :           prec = TYPE_PRECISION (TREE_TYPE (arg));
     878                 :             :         }
     879                 :        7123 :       if (++cnt > 30)
     880                 :           0 :         return prec + (orig_sign != sign);
     881                 :             :     }
     882                 :      119574 :   if (CONVERT_EXPR_P (arg)
     883                 :           0 :       && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
     884                 :      119574 :       && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
     885                 :             :     {
     886                 :             :       /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
     887                 :             :          If y_2's min precision is smaller than prec, return that.  */
     888                 :           0 :       int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
     889                 :           0 :       if (oprec < prec)
     890                 :           0 :         return oprec + (orig_sign != sign);
     891                 :             :     }
     892                 :      119574 :   if (TREE_CODE (arg) != SSA_NAME)
     893                 :           0 :     return prec + (orig_sign != sign);
     894                 :      119574 :   value_range r;
     895                 :      244879 :   while (!get_global_range_query ()->range_of_expr (r, arg)
     896                 :      125305 :          || r.varying_p ()
     897                 :      136874 :          || r.undefined_p ())
     898                 :             :     {
     899                 :      113737 :       gimple *g = SSA_NAME_DEF_STMT (arg);
     900                 :      113737 :       if (is_gimple_assign (g)
     901                 :      113737 :           && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
     902                 :             :         {
     903                 :        6688 :           tree t = gimple_assign_rhs1 (g);
     904                 :       13376 :           if (INTEGRAL_TYPE_P (TREE_TYPE (t))
     905                 :       12452 :               && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
     906                 :             :             {
     907                 :        5738 :               arg = t;
     908                 :        5738 :               if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
     909                 :             :                 {
     910                 :        5289 :                   if (TYPE_UNSIGNED (TREE_TYPE (arg)))
     911                 :             :                     sign = UNSIGNED;
     912                 :        2932 :                   else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
     913                 :           7 :                     return prec + (orig_sign != sign);
     914                 :        5282 :                   prec = TYPE_PRECISION (TREE_TYPE (arg));
     915                 :             :                 }
     916                 :        5731 :               if (++cnt > 30)
     917                 :           0 :                 return prec + (orig_sign != sign);
     918                 :        5731 :               continue;
     919                 :             :             }
     920                 :             :         }
     921                 :      107999 :       return prec + (orig_sign != sign);
     922                 :             :     }
     923                 :       11568 :   if (sign == TYPE_SIGN (TREE_TYPE (arg)))
     924                 :             :     {
     925                 :       11042 :       int p1 = wi::min_precision (r.lower_bound (), sign);
     926                 :       11042 :       int p2 = wi::min_precision (r.upper_bound (), sign);
     927                 :       11042 :       p1 = MAX (p1, p2);
     928                 :       11042 :       prec = MIN (prec, p1);
     929                 :             :     }
     930                 :        1028 :   else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
     931                 :             :     {
     932                 :         498 :       int p = wi::min_precision (r.upper_bound (), UNSIGNED);
     933                 :         498 :       prec = MIN (prec, p);
     934                 :             :     }
     935                 :       11568 :   return prec + (orig_sign != sign);
     936                 :      119574 : }
     937                 :             : 
     938                 :             : /* Helper for expand_*_overflow.  Set the __imag__ part to true
     939                 :             :    (1 except for signed:1 type, in which case store -1).  */
     940                 :             : 
     941                 :             : static void
     942                 :       83713 : expand_arith_set_overflow (tree lhs, rtx target)
     943                 :             : {
     944                 :       83713 :   if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
     945                 :       83713 :       && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
     946                 :         204 :     write_complex_part (target, constm1_rtx, true, false);
     947                 :             :   else
     948                 :       83509 :     write_complex_part (target, const1_rtx, true, false);
     949                 :       83713 : }
     950                 :             : 
     951                 :             : /* Helper for expand_*_overflow.  Store RES into the __real__ part
     952                 :             :    of TARGET.  If RES has larger MODE than __real__ part of TARGET,
     953                 :             :    set the __imag__ part to 1 if RES doesn't fit into it.  Similarly
     954                 :             :    if LHS has smaller precision than its mode.  */
     955                 :             : 
     956                 :             : static void
     957                 :       73680 : expand_arith_overflow_result_store (tree lhs, rtx target,
     958                 :             :                                     scalar_int_mode mode, rtx res)
     959                 :             : {
     960                 :       73680 :   scalar_int_mode tgtmode
     961                 :      147360 :     = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
     962                 :       73680 :   rtx lres = res;
     963                 :       73680 :   if (tgtmode != mode)
     964                 :             :     {
     965                 :       18858 :       rtx_code_label *done_label = gen_label_rtx ();
     966                 :       18858 :       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
     967                 :       18858 :       lres = convert_modes (tgtmode, mode, res, uns);
     968                 :       18858 :       gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
     969                 :       18858 :       do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
     970                 :             :                                EQ, true, mode, NULL_RTX, NULL, done_label,
     971                 :             :                                profile_probability::very_likely ());
     972                 :       18858 :       expand_arith_set_overflow (lhs, target);
     973                 :       18858 :       emit_label (done_label);
     974                 :             :     }
     975                 :       73680 :   int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
     976                 :       73680 :   int tgtprec = GET_MODE_PRECISION (tgtmode);
     977                 :       73680 :   if (prec < tgtprec)
     978                 :             :     {
     979                 :        3545 :       rtx_code_label *done_label = gen_label_rtx ();
     980                 :        3545 :       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
     981                 :        3545 :       res = lres;
     982                 :        3545 :       if (uns)
     983                 :             :         {
     984                 :        2008 :           rtx mask
     985                 :        2008 :             = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
     986                 :             :                                     tgtmode);
     987                 :        2008 :           lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
     988                 :             :                                       true, OPTAB_LIB_WIDEN);
     989                 :             :         }
     990                 :             :       else
     991                 :             :         {
     992                 :        1537 :           lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
     993                 :             :                                NULL_RTX, 1);
     994                 :        1537 :           lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
     995                 :             :                                NULL_RTX, 0);
     996                 :             :         }
     997                 :        3545 :       do_compare_rtx_and_jump (res, lres,
     998                 :             :                                EQ, true, tgtmode, NULL_RTX, NULL, done_label,
     999                 :             :                                profile_probability::very_likely ());
    1000                 :        3545 :       expand_arith_set_overflow (lhs, target);
    1001                 :        3545 :       emit_label (done_label);
    1002                 :             :     }
    1003                 :       73680 :   write_complex_part (target, lres, false, false);
    1004                 :       73680 : }
    1005                 :             : 
    1006                 :             : /* Helper for expand_*_overflow.  Store RES into TARGET.  */
    1007                 :             : 
    1008                 :             : static void
    1009                 :        5083 : expand_ubsan_result_store (tree lhs, rtx target, scalar_int_mode mode,
    1010                 :             :                            rtx res, rtx_code_label *do_error)
    1011                 :             : {
    1012                 :        5083 :   if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE
    1013                 :        5083 :       && TYPE_PRECISION (TREE_TYPE (lhs)) < GET_MODE_PRECISION (mode))
    1014                 :             :     {
    1015                 :          54 :       int uns = TYPE_UNSIGNED (TREE_TYPE (lhs));
    1016                 :          54 :       int prec = TYPE_PRECISION (TREE_TYPE (lhs));
    1017                 :          54 :       int tgtprec = GET_MODE_PRECISION (mode);
    1018                 :          54 :       rtx resc = gen_reg_rtx (mode), lres;
    1019                 :          54 :       emit_move_insn (resc, res);
    1020                 :          54 :       if (uns)
    1021                 :             :         {
    1022                 :           0 :           rtx mask
    1023                 :           0 :             = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
    1024                 :             :                                     mode);
    1025                 :           0 :           lres = expand_simple_binop (mode, AND, res, mask, NULL_RTX,
    1026                 :             :                                       true, OPTAB_LIB_WIDEN);
    1027                 :             :         }
    1028                 :             :       else
    1029                 :             :         {
    1030                 :          54 :           lres = expand_shift (LSHIFT_EXPR, mode, res, tgtprec - prec,
    1031                 :             :                                NULL_RTX, 1);
    1032                 :          54 :           lres = expand_shift (RSHIFT_EXPR, mode, lres, tgtprec - prec,
    1033                 :             :                                NULL_RTX, 0);
    1034                 :             :         }
    1035                 :          54 :       if (lres != res)
    1036                 :          54 :         emit_move_insn (res, lres);
    1037                 :          54 :       do_compare_rtx_and_jump (res, resc,
    1038                 :             :                                NE, true, mode, NULL_RTX, NULL, do_error,
    1039                 :             :                                profile_probability::very_unlikely ());
    1040                 :             :     }
    1041                 :        5083 :   if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
    1042                 :             :     /* If this is a scalar in a register that is stored in a wider mode   
    1043                 :             :        than the declared mode, compute the result into its declared mode
    1044                 :             :        and then convert to the wider mode.  Our value is the computed
    1045                 :             :        expression.  */
    1046                 :           0 :     convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
    1047                 :             :   else
    1048                 :        5083 :     emit_move_insn (target, res);
    1049                 :        5083 : }
    1050                 :             : 
    1051                 :             : /* Add sub/add overflow checking to the statement STMT.
    1052                 :             :    CODE says whether the operation is +, or -.  */
    1053                 :             : 
    1054                 :             : void
    1055                 :       40983 : expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
    1056                 :             :                         tree arg0, tree arg1, bool unsr_p, bool uns0_p,
    1057                 :             :                         bool uns1_p, bool is_ubsan, tree *datap)
    1058                 :             : {
    1059                 :       40983 :   rtx res, target = NULL_RTX;
    1060                 :       40983 :   tree fn;
    1061                 :       40983 :   rtx_code_label *done_label = gen_label_rtx ();
    1062                 :       40983 :   rtx_code_label *do_error = gen_label_rtx ();
    1063                 :       40983 :   do_pending_stack_adjust ();
    1064                 :       40983 :   rtx op0 = expand_normal (arg0);
    1065                 :       40983 :   rtx op1 = expand_normal (arg1);
    1066                 :       40983 :   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
    1067                 :       40983 :   int prec = GET_MODE_PRECISION (mode);
    1068                 :       40983 :   rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
    1069                 :       40983 :   bool do_xor = false;
    1070                 :             : 
    1071                 :       40983 :   if (is_ubsan)
    1072                 :        3673 :     gcc_assert (!unsr_p && !uns0_p && !uns1_p);
    1073                 :             : 
    1074                 :       40983 :   if (lhs)
    1075                 :             :     {
    1076                 :       40407 :       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    1077                 :       40407 :       if (!is_ubsan)
    1078                 :       37310 :         write_complex_part (target, const0_rtx, true, false);
    1079                 :             :     }
    1080                 :             : 
    1081                 :             :   /* We assume both operands and result have the same precision
    1082                 :             :      here (GET_MODE_BITSIZE (mode)), S stands for signed type
    1083                 :             :      with that precision, U for unsigned type with that precision,
    1084                 :             :      sgn for unsigned most significant bit in that precision.
    1085                 :             :      s1 is signed first operand, u1 is unsigned first operand,
    1086                 :             :      s2 is signed second operand, u2 is unsigned second operand,
    1087                 :             :      sr is signed result, ur is unsigned result and the following
    1088                 :             :      rules say how to compute result (which is always result of
    1089                 :             :      the operands as if both were unsigned, cast to the right
    1090                 :             :      signedness) and how to compute whether operation overflowed.
    1091                 :             : 
    1092                 :             :      s1 + s2 -> sr
    1093                 :             :         res = (S) ((U) s1 + (U) s2)
    1094                 :             :         ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
    1095                 :             :      s1 - s2 -> sr
    1096                 :             :         res = (S) ((U) s1 - (U) s2)
    1097                 :             :         ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
    1098                 :             :      u1 + u2 -> ur
    1099                 :             :         res = u1 + u2
    1100                 :             :         ovf = res < u1 (or jump on carry, but RTL opts will handle it)
    1101                 :             :      u1 - u2 -> ur
    1102                 :             :         res = u1 - u2
    1103                 :             :         ovf = res > u1 (or jump on carry, but RTL opts will handle it)
    1104                 :             :      s1 + u2 -> sr
    1105                 :             :         res = (S) ((U) s1 + u2)
    1106                 :             :         ovf = ((U) res ^ sgn) < u2
    1107                 :             :      s1 + u2 -> ur
    1108                 :             :         t1 = (S) (u2 ^ sgn)
    1109                 :             :         t2 = s1 + t1
    1110                 :             :         res = (U) t2 ^ sgn
    1111                 :             :         ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
    1112                 :             :      s1 - u2 -> sr
    1113                 :             :         res = (S) ((U) s1 - u2)
    1114                 :             :         ovf = u2 > ((U) s1 ^ sgn)
    1115                 :             :      s1 - u2 -> ur
    1116                 :             :         res = (U) s1 - u2
    1117                 :             :         ovf = s1 < 0 || u2 > (U) s1
    1118                 :             :      u1 - s2 -> sr
    1119                 :             :         res = u1 - (U) s2
    1120                 :             :         ovf = u1 >= ((U) s2 ^ sgn)
    1121                 :             :      u1 - s2 -> ur
    1122                 :             :         t1 = u1 ^ sgn
    1123                 :             :         t2 = t1 - (U) s2
    1124                 :             :         res = t2 ^ sgn
    1125                 :             :         ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
    1126                 :             :      s1 + s2 -> ur
    1127                 :             :         res = (U) s1 + (U) s2
    1128                 :             :         ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
    1129                 :             :      u1 + u2 -> sr
    1130                 :             :         res = (S) (u1 + u2)
    1131                 :             :         ovf = (U) res < u2 || res < 0
    1132                 :             :      u1 - u2 -> sr
    1133                 :             :         res = (S) (u1 - u2)
    1134                 :             :         ovf = u1 >= u2 ? res < 0 : res >= 0
    1135                 :             :      s1 - s2 -> ur
    1136                 :             :         res = (U) s1 - (U) s2
    1137                 :             :         ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0)  */
    1138                 :             : 
    1139                 :       40983 :   if (code == PLUS_EXPR && uns0_p && !uns1_p)
    1140                 :             :     {
    1141                 :             :       /* PLUS_EXPR is commutative, if operand signedness differs,
    1142                 :             :          canonicalize to the first operand being signed and second
    1143                 :             :          unsigned to simplify following code.  */
    1144                 :         784 :       std::swap (op0, op1);
    1145                 :         784 :       std::swap (arg0, arg1);
    1146                 :         784 :       uns0_p = false;
    1147                 :         784 :       uns1_p = true;
    1148                 :             :     }
    1149                 :             : 
    1150                 :             :   /* u1 +- u2 -> ur  */
    1151                 :       40983 :   if (uns0_p && uns1_p && unsr_p)
    1152                 :             :     {
    1153                 :       22191 :       insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
    1154                 :             :                                        : usubv4_optab, mode);
    1155                 :       17060 :       if (icode != CODE_FOR_nothing)
    1156                 :             :         {
    1157                 :       16231 :           class expand_operand ops[4];
    1158                 :       16231 :           rtx_insn *last = get_last_insn ();
    1159                 :             : 
    1160                 :       16231 :           res = gen_reg_rtx (mode);
    1161                 :       16231 :           create_output_operand (&ops[0], res, mode);
    1162                 :       16231 :           create_input_operand (&ops[1], op0, mode);
    1163                 :       16231 :           create_input_operand (&ops[2], op1, mode);
    1164                 :       16231 :           create_fixed_operand (&ops[3], do_error);
    1165                 :       16231 :           if (maybe_expand_insn (icode, 4, ops))
    1166                 :             :             {
    1167                 :       16231 :               last = get_last_insn ();
    1168                 :       16231 :               if (profile_status_for_fn (cfun) != PROFILE_ABSENT
    1169                 :       13936 :                   && JUMP_P (last)
    1170                 :       13936 :                   && any_condjump_p (last)
    1171                 :       30167 :                   && !find_reg_note (last, REG_BR_PROB, 0))
    1172                 :       13936 :                 add_reg_br_prob_note (last,
    1173                 :             :                                       profile_probability::very_unlikely ());
    1174                 :       16231 :               emit_jump (done_label);
    1175                 :       16231 :               goto do_error_label;
    1176                 :             :             }
    1177                 :             : 
    1178                 :           0 :           delete_insns_since (last);
    1179                 :             :         }
    1180                 :             : 
    1181                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1182                 :             :          unsigned.  */
    1183                 :        1658 :       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
    1184                 :             :                           op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
    1185                 :         829 :       rtx tem = op0;
    1186                 :             :       /* For PLUS_EXPR, the operation is commutative, so we can pick
    1187                 :             :          operand to compare against.  For prec <= BITS_PER_WORD, I think
    1188                 :             :          preferring REG operand is better over CONST_INT, because
    1189                 :             :          the CONST_INT might enlarge the instruction or CSE would need
    1190                 :             :          to figure out we'd already loaded it into a register before.
    1191                 :             :          For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
    1192                 :             :          as then the multi-word comparison can be perhaps simplified.  */
    1193                 :         829 :       if (code == PLUS_EXPR
    1194                 :           0 :           && (prec <= BITS_PER_WORD
    1195                 :           0 :               ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
    1196                 :           0 :               : CONST_SCALAR_INT_P (op1)))
    1197                 :         829 :         tem = op1;
    1198                 :        1658 :       do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
    1199                 :             :                                true, mode, NULL_RTX, NULL, done_label,
    1200                 :             :                                profile_probability::very_likely ());
    1201                 :         829 :       goto do_error_label;
    1202                 :             :     }
    1203                 :             : 
    1204                 :             :   /* s1 +- u2 -> sr  */
    1205                 :       23923 :   if (!uns0_p && uns1_p && !unsr_p)
    1206                 :             :     {
    1207                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1208                 :             :          unsigned.  */
    1209                 :        2514 :       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
    1210                 :             :                           op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
    1211                 :        2514 :       rtx tem = expand_binop (mode, add_optab,
    1212                 :             :                               code == PLUS_EXPR ? res : op0, sgn,
    1213                 :             :                               NULL_RTX, false, OPTAB_LIB_WIDEN);
    1214                 :        1582 :       do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
    1215                 :             :                                done_label, profile_probability::very_likely ());
    1216                 :        1582 :       goto do_error_label;
    1217                 :             :     }
    1218                 :             : 
    1219                 :             :   /* s1 + u2 -> ur  */
    1220                 :       22341 :   if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
    1221                 :             :     {
    1222                 :        1692 :       op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
    1223                 :             :                           OPTAB_LIB_WIDEN);
    1224                 :             :       /* As we've changed op1, we have to avoid using the value range
    1225                 :             :          for the original argument.  */
    1226                 :        1692 :       arg1 = error_mark_node;
    1227                 :        1692 :       do_xor = true;
    1228                 :        1692 :       goto do_signed;
    1229                 :             :     }
    1230                 :             : 
    1231                 :             :   /* u1 - s2 -> ur  */
    1232                 :       20649 :   if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
    1233                 :             :     {
    1234                 :         845 :       op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
    1235                 :             :                           OPTAB_LIB_WIDEN);
    1236                 :             :       /* As we've changed op0, we have to avoid using the value range
    1237                 :             :          for the original argument.  */
    1238                 :         845 :       arg0 = error_mark_node;
    1239                 :         845 :       do_xor = true;
    1240                 :         845 :       goto do_signed;
    1241                 :             :     }
    1242                 :             : 
    1243                 :             :   /* s1 - u2 -> ur  */
    1244                 :       19804 :   if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
    1245                 :             :     {
    1246                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1247                 :             :          unsigned.  */
    1248                 :        1374 :       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
    1249                 :             :                           OPTAB_LIB_WIDEN);
    1250                 :        1374 :       int pos_neg = get_range_pos_neg (arg0);
    1251                 :        1374 :       if (pos_neg == 2)
    1252                 :             :         /* If ARG0 is known to be always negative, this is always overflow.  */
    1253                 :          39 :         emit_jump (do_error);
    1254                 :        1335 :       else if (pos_neg == 3)
    1255                 :             :         /* If ARG0 is not known to be always positive, check at runtime.  */
    1256                 :        1335 :         do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
    1257                 :             :                                  NULL, do_error, profile_probability::very_unlikely ());
    1258                 :        1374 :       do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
    1259                 :             :                                done_label, profile_probability::very_likely ());
    1260                 :        1374 :       goto do_error_label;
    1261                 :             :     }
    1262                 :             : 
    1263                 :             :   /* u1 - s2 -> sr  */
    1264                 :       18430 :   if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
    1265                 :             :     {
    1266                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1267                 :             :          unsigned.  */
    1268                 :         481 :       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
    1269                 :             :                           OPTAB_LIB_WIDEN);
    1270                 :         481 :       rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
    1271                 :             :                               OPTAB_LIB_WIDEN);
    1272                 :         481 :       do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
    1273                 :             :                                done_label, profile_probability::very_likely ());
    1274                 :         481 :       goto do_error_label;
    1275                 :             :     }
    1276                 :             : 
    1277                 :             :   /* u1 + u2 -> sr  */
    1278                 :       17949 :   if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
    1279                 :             :     {
    1280                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1281                 :             :          unsigned.  */
    1282                 :        1192 :       res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
    1283                 :             :                           OPTAB_LIB_WIDEN);
    1284                 :        1192 :       do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
    1285                 :             :                                NULL, do_error, profile_probability::very_unlikely ());
    1286                 :        1192 :       rtx tem = op1;
    1287                 :             :       /* The operation is commutative, so we can pick operand to compare
    1288                 :             :          against.  For prec <= BITS_PER_WORD, I think preferring REG operand
    1289                 :             :          is better over CONST_INT, because the CONST_INT might enlarge the
    1290                 :             :          instruction or CSE would need to figure out we'd already loaded it
    1291                 :             :          into a register before.  For prec > BITS_PER_WORD, I think CONST_INT
    1292                 :             :          might be more beneficial, as then the multi-word comparison can be
    1293                 :             :          perhaps simplified.  */
    1294                 :        1192 :       if (prec <= BITS_PER_WORD
    1295                 :        1192 :           ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
    1296                 :         408 :           : CONST_SCALAR_INT_P (op0))
    1297                 :        1192 :         tem = op0;
    1298                 :        1192 :       do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
    1299                 :             :                                done_label, profile_probability::very_likely ());
    1300                 :        1192 :       goto do_error_label;
    1301                 :             :     }
    1302                 :             : 
    1303                 :             :   /* s1 +- s2 -> ur  */
    1304                 :       16757 :   if (!uns0_p && !uns1_p && unsr_p)
    1305                 :             :     {
    1306                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1307                 :             :          unsigned.  */
    1308                 :        3831 :       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
    1309                 :             :                           op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
    1310                 :        2592 :       int pos_neg = get_range_pos_neg (arg1);
    1311                 :        2592 :       if (code == PLUS_EXPR)
    1312                 :             :         {
    1313                 :        1353 :           int pos_neg0 = get_range_pos_neg (arg0);
    1314                 :        1353 :           if (pos_neg0 != 3 && pos_neg == 3)
    1315                 :             :             {
    1316                 :             :               std::swap (op0, op1);
    1317                 :        2592 :               pos_neg = pos_neg0;
    1318                 :             :             }
    1319                 :             :         }
    1320                 :        2592 :       rtx tem;
    1321                 :        2592 :       if (pos_neg != 3)
    1322                 :             :         {
    1323                 :        1585 :           tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
    1324                 :             :                                     ? and_optab : ior_optab,
    1325                 :             :                               op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
    1326                 :         935 :           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
    1327                 :             :                                    NULL, done_label, profile_probability::very_likely ());
    1328                 :             :         }
    1329                 :             :       else
    1330                 :             :         {
    1331                 :        1657 :           rtx_code_label *do_ior_label = gen_label_rtx ();
    1332                 :        2360 :           do_compare_rtx_and_jump (op1, const0_rtx,
    1333                 :             :                                    code == MINUS_EXPR ? GE : LT, false, mode,
    1334                 :             :                                    NULL_RTX, NULL, do_ior_label,
    1335                 :             :                                    profile_probability::even ());
    1336                 :        1657 :           tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
    1337                 :             :                               OPTAB_LIB_WIDEN);
    1338                 :        1657 :           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
    1339                 :             :                                    NULL, done_label, profile_probability::very_likely ());
    1340                 :        1657 :           emit_jump (do_error);
    1341                 :        1657 :           emit_label (do_ior_label);
    1342                 :        1657 :           tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
    1343                 :             :                               OPTAB_LIB_WIDEN);
    1344                 :        1657 :           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
    1345                 :             :                                    NULL, done_label, profile_probability::very_likely ());
    1346                 :             :         }
    1347                 :        2592 :       goto do_error_label;
    1348                 :             :     }
    1349                 :             : 
    1350                 :             :   /* u1 - u2 -> sr  */
    1351                 :       14165 :   if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
    1352                 :             :     {
    1353                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1354                 :             :          unsigned.  */
    1355                 :        1727 :       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
    1356                 :             :                           OPTAB_LIB_WIDEN);
    1357                 :        1727 :       rtx_code_label *op0_geu_op1 = gen_label_rtx ();
    1358                 :        1727 :       do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
    1359                 :             :                                op0_geu_op1, profile_probability::even ());
    1360                 :        1727 :       do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
    1361                 :             :                                NULL, done_label, profile_probability::very_likely ());
    1362                 :        1727 :       emit_jump (do_error);
    1363                 :        1727 :       emit_label (op0_geu_op1);
    1364                 :        1727 :       do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
    1365                 :             :                                NULL, done_label, profile_probability::very_likely ());
    1366                 :        1727 :       goto do_error_label;
    1367                 :             :     }
    1368                 :             : 
    1369                 :       12438 :   gcc_assert (!uns0_p && !uns1_p && !unsr_p);
    1370                 :             : 
    1371                 :             :   /* s1 +- s2 -> sr  */
    1372                 :       12438 :  do_signed:
    1373                 :       14975 :   {
    1374                 :       21737 :     insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
    1375                 :             :                                      : subv4_optab, mode);
    1376                 :       14975 :     if (icode != CODE_FOR_nothing)
    1377                 :             :       {
    1378                 :       14975 :         class expand_operand ops[4];
    1379                 :       14975 :         rtx_insn *last = get_last_insn ();
    1380                 :             : 
    1381                 :       14975 :         res = gen_reg_rtx (mode);
    1382                 :       14975 :         create_output_operand (&ops[0], res, mode);
    1383                 :       14975 :         create_input_operand (&ops[1], op0, mode);
    1384                 :       14975 :         create_input_operand (&ops[2], op1, mode);
    1385                 :       14975 :         create_fixed_operand (&ops[3], do_error);
    1386                 :       14975 :         if (maybe_expand_insn (icode, 4, ops))
    1387                 :             :           {
    1388                 :       14975 :             last = get_last_insn ();
    1389                 :       14975 :             if (profile_status_for_fn (cfun) != PROFILE_ABSENT
    1390                 :        9653 :                 && JUMP_P (last)
    1391                 :        9653 :                 && any_condjump_p (last)
    1392                 :       24628 :                 && !find_reg_note (last, REG_BR_PROB, 0))
    1393                 :        9653 :               add_reg_br_prob_note (last, 
    1394                 :             :                                     profile_probability::very_unlikely ());
    1395                 :       14975 :             emit_jump (done_label);
    1396                 :       14975 :             goto do_error_label;
    1397                 :             :           }
    1398                 :             : 
    1399                 :           0 :         delete_insns_since (last);
    1400                 :             :       }
    1401                 :             : 
    1402                 :             :     /* Compute the operation.  On RTL level, the addition is always
    1403                 :             :        unsigned.  */
    1404                 :           0 :     res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
    1405                 :             :                         op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
    1406                 :             : 
    1407                 :             :     /* If we can prove that one of the arguments (for MINUS_EXPR only
    1408                 :             :        the second operand, as subtraction is not commutative) is always
    1409                 :             :        non-negative or always negative, we can do just one comparison
    1410                 :             :        and conditional jump.  */
    1411                 :           0 :     int pos_neg = get_range_pos_neg (arg1);
    1412                 :           0 :     if (code == PLUS_EXPR)
    1413                 :             :       {
    1414                 :           0 :         int pos_neg0 = get_range_pos_neg (arg0);
    1415                 :           0 :         if (pos_neg0 != 3 && pos_neg == 3)
    1416                 :             :           {
    1417                 :             :             std::swap (op0, op1);
    1418                 :           0 :             pos_neg = pos_neg0;
    1419                 :             :           }
    1420                 :             :       }
    1421                 :             : 
    1422                 :             :     /* Addition overflows if and only if the two operands have the same sign,
    1423                 :             :        and the result has the opposite sign.  Subtraction overflows if and
    1424                 :             :        only if the two operands have opposite sign, and the subtrahend has
    1425                 :             :        the same sign as the result.  Here 0 is counted as positive.  */
    1426                 :           0 :     if (pos_neg == 3)
    1427                 :             :       {
    1428                 :             :         /* Compute op0 ^ op1 (operands have opposite sign).  */
    1429                 :           0 :         rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
    1430                 :             :                                    OPTAB_LIB_WIDEN);
    1431                 :             : 
    1432                 :             :         /* Compute res ^ op1 (result and 2nd operand have opposite sign).  */
    1433                 :           0 :         rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
    1434                 :             :                                     OPTAB_LIB_WIDEN);
    1435                 :             : 
    1436                 :           0 :         rtx tem;
    1437                 :           0 :         if (code == PLUS_EXPR)
    1438                 :             :           {
    1439                 :             :             /* Compute (res ^ op1) & ~(op0 ^ op1).  */
    1440                 :           0 :             tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
    1441                 :           0 :             tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
    1442                 :             :                                 OPTAB_LIB_WIDEN);
    1443                 :             :           }
    1444                 :             :         else
    1445                 :             :           {
    1446                 :             :             /* Compute (op0 ^ op1) & ~(res ^ op1).  */
    1447                 :           0 :             tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
    1448                 :           0 :             tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
    1449                 :             :                                 OPTAB_LIB_WIDEN);
    1450                 :             :           }
    1451                 :             : 
    1452                 :             :         /* No overflow if the result has bit sign cleared.  */
    1453                 :           0 :         do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
    1454                 :             :                                  NULL, done_label, profile_probability::very_likely ());
    1455                 :             :       }
    1456                 :             : 
    1457                 :             :     /* Compare the result of the operation with the first operand.
    1458                 :             :        No overflow for addition if second operand is positive and result
    1459                 :             :        is larger or second operand is negative and result is smaller.
    1460                 :             :        Likewise for subtraction with sign of second operand flipped.  */
    1461                 :             :     else
    1462                 :           0 :       do_compare_rtx_and_jump (res, op0,
    1463                 :           0 :                                (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
    1464                 :             :                                false, mode, NULL_RTX, NULL, done_label,
    1465                 :             :                                profile_probability::very_likely ());
    1466                 :             :   }
    1467                 :             : 
    1468                 :       40983 :  do_error_label:
    1469                 :       40983 :   emit_label (do_error);
    1470                 :       40983 :   if (is_ubsan)
    1471                 :             :     {
    1472                 :             :       /* Expand the ubsan builtin call.  */
    1473                 :        3673 :       push_temp_slots ();
    1474                 :        3673 :       fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
    1475                 :             :                                          arg0, arg1, datap);
    1476                 :        3673 :       expand_normal (fn);
    1477                 :        3673 :       pop_temp_slots ();
    1478                 :        3673 :       do_pending_stack_adjust ();
    1479                 :             :     }
    1480                 :       37310 :   else if (lhs)
    1481                 :       37310 :     expand_arith_set_overflow (lhs, target);
    1482                 :             : 
    1483                 :             :   /* We're done.  */
    1484                 :       40983 :   emit_label (done_label);
    1485                 :             : 
    1486                 :       40983 :   if (lhs)
    1487                 :             :     {
    1488                 :       40407 :       if (is_ubsan)
    1489                 :        3097 :         expand_ubsan_result_store (lhs, target, mode, res, do_error);
    1490                 :             :       else
    1491                 :             :         {
    1492                 :       37310 :           if (do_xor)
    1493                 :        2537 :             res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
    1494                 :             :                                 OPTAB_LIB_WIDEN);
    1495                 :             : 
    1496                 :       37310 :           expand_arith_overflow_result_store (lhs, target, mode, res);
    1497                 :             :         }
    1498                 :             :     }
    1499                 :       40983 : }
    1500                 :             : 
    1501                 :             : /* Add negate overflow checking to the statement STMT.  */
    1502                 :             : 
    1503                 :             : static void
    1504                 :        1025 : expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
    1505                 :             :                      tree *datap)
    1506                 :             : {
    1507                 :        1025 :   rtx res, op1;
    1508                 :        1025 :   tree fn;
    1509                 :        1025 :   rtx_code_label *done_label, *do_error;
    1510                 :        1025 :   rtx target = NULL_RTX;
    1511                 :             : 
    1512                 :        1025 :   done_label = gen_label_rtx ();
    1513                 :        1025 :   do_error = gen_label_rtx ();
    1514                 :             : 
    1515                 :        1025 :   do_pending_stack_adjust ();
    1516                 :        1025 :   op1 = expand_normal (arg1);
    1517                 :             : 
    1518                 :        1025 :   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
    1519                 :        1025 :   if (lhs)
    1520                 :             :     {
    1521                 :         881 :       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    1522                 :         881 :       if (!is_ubsan)
    1523                 :         402 :         write_complex_part (target, const0_rtx, true, false);
    1524                 :             :     }
    1525                 :             : 
    1526                 :        1025 :   enum insn_code icode = optab_handler (negv3_optab, mode);
    1527                 :        1025 :   if (icode != CODE_FOR_nothing)
    1528                 :             :     {
    1529                 :         946 :       class expand_operand ops[3];
    1530                 :         946 :       rtx_insn *last = get_last_insn ();
    1531                 :             : 
    1532                 :         946 :       res = gen_reg_rtx (mode);
    1533                 :         946 :       create_output_operand (&ops[0], res, mode);
    1534                 :         946 :       create_input_operand (&ops[1], op1, mode);
    1535                 :         946 :       create_fixed_operand (&ops[2], do_error);
    1536                 :         946 :       if (maybe_expand_insn (icode, 3, ops))
    1537                 :             :         {
    1538                 :         946 :           last = get_last_insn ();
    1539                 :         946 :           if (profile_status_for_fn (cfun) != PROFILE_ABSENT
    1540                 :         608 :               && JUMP_P (last)
    1541                 :         608 :               && any_condjump_p (last)
    1542                 :        1554 :               && !find_reg_note (last, REG_BR_PROB, 0))
    1543                 :         608 :             add_reg_br_prob_note (last, 
    1544                 :             :                                   profile_probability::very_unlikely ());
    1545                 :         946 :           emit_jump (done_label);
    1546                 :             :         }
    1547                 :             :       else
    1548                 :             :         {
    1549                 :           0 :           delete_insns_since (last);
    1550                 :           0 :           icode = CODE_FOR_nothing;
    1551                 :             :         }
    1552                 :             :     }
    1553                 :             : 
    1554                 :         946 :   if (icode == CODE_FOR_nothing)
    1555                 :             :     {
    1556                 :             :       /* Compute the operation.  On RTL level, the addition is always
    1557                 :             :          unsigned.  */
    1558                 :          79 :       res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
    1559                 :             : 
    1560                 :             :       /* Compare the operand with the most negative value.  */
    1561                 :          79 :       rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
    1562                 :          79 :       do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
    1563                 :             :                                done_label, profile_probability::very_likely ());
    1564                 :             :     }
    1565                 :             : 
    1566                 :        1025 :   emit_label (do_error);
    1567                 :        1025 :   if (is_ubsan)
    1568                 :             :     {
    1569                 :             :       /* Expand the ubsan builtin call.  */
    1570                 :         623 :       push_temp_slots ();
    1571                 :         623 :       fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
    1572                 :             :                                          arg1, NULL_TREE, datap);
    1573                 :         623 :       expand_normal (fn);
    1574                 :         623 :       pop_temp_slots ();
    1575                 :         623 :       do_pending_stack_adjust ();
    1576                 :             :     }
    1577                 :         402 :   else if (lhs)
    1578                 :         402 :     expand_arith_set_overflow (lhs, target);
    1579                 :             : 
    1580                 :             :   /* We're done.  */
    1581                 :        1025 :   emit_label (done_label);
    1582                 :             : 
    1583                 :        1025 :   if (lhs)
    1584                 :             :     {
    1585                 :         881 :       if (is_ubsan)
    1586                 :         479 :         expand_ubsan_result_store (lhs, target, mode, res, do_error);
    1587                 :             :       else
    1588                 :         402 :         expand_arith_overflow_result_store (lhs, target, mode, res);
    1589                 :             :     }
    1590                 :        1025 : }
    1591                 :             : 
    1592                 :             : /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
    1593                 :             :    mode MODE can be expanded without using a libcall.  */
    1594                 :             : 
    1595                 :             : static bool
    1596                 :           0 : can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
    1597                 :             :                                 rtx op0, rtx op1, bool uns)
    1598                 :             : {
    1599                 :           0 :   if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
    1600                 :             :       != CODE_FOR_nothing)
    1601                 :             :     return true;
    1602                 :             :     
    1603                 :           0 :   if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
    1604                 :             :       != CODE_FOR_nothing)
    1605                 :             :     return true;
    1606                 :             : 
    1607                 :           0 :   rtx_insn *last = get_last_insn ();
    1608                 :           0 :   if (CONSTANT_P (op0))
    1609                 :           0 :     op0 = convert_modes (wmode, mode, op0, uns);
    1610                 :             :   else
    1611                 :           0 :     op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
    1612                 :           0 :   if (CONSTANT_P (op1))
    1613                 :           0 :     op1 = convert_modes (wmode, mode, op1, uns);
    1614                 :             :   else
    1615                 :           0 :     op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
    1616                 :           0 :   rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
    1617                 :           0 :   delete_insns_since (last);
    1618                 :           0 :   return ret != NULL_RTX;
    1619                 :             : } 
    1620                 :             : 
    1621                 :             : /* Add mul overflow checking to the statement STMT.  */
    1622                 :             : 
    1623                 :             : static void
    1624                 :       19075 : expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
    1625                 :             :                      bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
    1626                 :             :                      tree *datap)
    1627                 :             : {
    1628                 :       19075 :   rtx res, op0, op1;
    1629                 :       19075 :   tree fn, type;
    1630                 :       19075 :   rtx_code_label *done_label, *do_error;
    1631                 :       19075 :   rtx target = NULL_RTX;
    1632                 :       19075 :   signop sign;
    1633                 :       19075 :   enum insn_code icode;
    1634                 :             : 
    1635                 :       19075 :   done_label = gen_label_rtx ();
    1636                 :       19075 :   do_error = gen_label_rtx ();
    1637                 :             : 
    1638                 :       19075 :   do_pending_stack_adjust ();
    1639                 :       19075 :   op0 = expand_normal (arg0);
    1640                 :       19075 :   op1 = expand_normal (arg1);
    1641                 :             : 
    1642                 :       19075 :   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
    1643                 :       19075 :   bool uns = unsr_p;
    1644                 :       19075 :   if (lhs)
    1645                 :             :     {
    1646                 :       18919 :       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    1647                 :       18919 :       if (!is_ubsan)
    1648                 :       17412 :         write_complex_part (target, const0_rtx, true, false);
    1649                 :             :     }
    1650                 :             : 
    1651                 :       17568 :   if (is_ubsan)
    1652                 :        1663 :     gcc_assert (!unsr_p && !uns0_p && !uns1_p);
    1653                 :             : 
    1654                 :             :   /* We assume both operands and result have the same precision
    1655                 :             :      here (GET_MODE_BITSIZE (mode)), S stands for signed type
    1656                 :             :      with that precision, U for unsigned type with that precision,
    1657                 :             :      sgn for unsigned most significant bit in that precision.
    1658                 :             :      s1 is signed first operand, u1 is unsigned first operand,
    1659                 :             :      s2 is signed second operand, u2 is unsigned second operand,
    1660                 :             :      sr is signed result, ur is unsigned result and the following
    1661                 :             :      rules say how to compute result (which is always result of
    1662                 :             :      the operands as if both were unsigned, cast to the right
    1663                 :             :      signedness) and how to compute whether operation overflowed.
    1664                 :             :      main_ovf (false) stands for jump on signed multiplication
    1665                 :             :      overflow or the main algorithm with uns == false.
    1666                 :             :      main_ovf (true) stands for jump on unsigned multiplication
    1667                 :             :      overflow or the main algorithm with uns == true.
    1668                 :             : 
    1669                 :             :      s1 * s2 -> sr
    1670                 :             :         res = (S) ((U) s1 * (U) s2)
    1671                 :             :         ovf = main_ovf (false)
    1672                 :             :      u1 * u2 -> ur
    1673                 :             :         res = u1 * u2
    1674                 :             :         ovf = main_ovf (true)
    1675                 :             :      s1 * u2 -> ur
    1676                 :             :         res = (U) s1 * u2
    1677                 :             :         ovf = (s1 < 0 && u2) || main_ovf (true)
    1678                 :             :      u1 * u2 -> sr
    1679                 :             :         res = (S) (u1 * u2)
    1680                 :             :         ovf = res < 0 || main_ovf (true)
    1681                 :             :      s1 * u2 -> sr
    1682                 :             :         res = (S) ((U) s1 * u2)
    1683                 :             :         ovf = (S) u2 >= 0 ? main_ovf (false)
    1684                 :             :                           : (s1 != 0 && (s1 != -1 || u2 != (U) res))
    1685                 :             :      s1 * s2 -> ur
    1686                 :             :         t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
    1687                 :             :         t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
    1688                 :             :         res = t1 * t2
    1689                 :             :         ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true)  */
    1690                 :             : 
    1691                 :       19075 :   if (uns0_p && !uns1_p)
    1692                 :             :     {
    1693                 :             :       /* Multiplication is commutative, if operand signedness differs,
    1694                 :             :          canonicalize to the first operand being signed and second
    1695                 :             :          unsigned to simplify following code.  */
    1696                 :        1542 :       std::swap (op0, op1);
    1697                 :        1542 :       std::swap (arg0, arg1);
    1698                 :        1542 :       uns0_p = false;
    1699                 :        1542 :       uns1_p = true;
    1700                 :             :     }
    1701                 :             : 
    1702                 :       19075 :   int pos_neg0 = get_range_pos_neg (arg0);
    1703                 :       19075 :   int pos_neg1 = get_range_pos_neg (arg1);
    1704                 :             :   /* Unsigned types with smaller than mode precision, even if they have most
    1705                 :             :      significant bit set, are still zero-extended.  */
    1706                 :       19075 :   if (uns0_p && TYPE_PRECISION (TREE_TYPE (arg0)) < GET_MODE_PRECISION (mode))
    1707                 :             :     pos_neg0 = 1;
    1708                 :       19075 :   if (uns1_p && TYPE_PRECISION (TREE_TYPE (arg1)) < GET_MODE_PRECISION (mode))
    1709                 :             :     pos_neg1 = 1;
    1710                 :             : 
    1711                 :             :   /* s1 * u2 -> ur  */
    1712                 :       19075 :   if (!uns0_p && uns1_p && unsr_p)
    1713                 :             :     {
    1714                 :        2278 :       switch (pos_neg0)
    1715                 :             :         {
    1716                 :           0 :         case 1:
    1717                 :             :           /* If s1 is non-negative, just perform normal u1 * u2 -> ur.  */
    1718                 :        1859 :           goto do_main;
    1719                 :         314 :         case 2:
    1720                 :             :           /* If s1 is negative, avoid the main code, just multiply and
    1721                 :             :              signal overflow if op1 is not 0.  */
    1722                 :         314 :           struct separate_ops ops;
    1723                 :         314 :           ops.code = MULT_EXPR;
    1724                 :         314 :           ops.type = TREE_TYPE (arg1);
    1725                 :         314 :           ops.op0 = make_tree (ops.type, op0);
    1726                 :         314 :           ops.op1 = make_tree (ops.type, op1);
    1727                 :         314 :           ops.op2 = NULL_TREE;
    1728                 :         314 :           ops.location = loc;
    1729                 :         314 :           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    1730                 :         314 :           do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
    1731                 :             :                                    NULL, done_label, profile_probability::very_likely ());
    1732                 :         419 :           goto do_error_label;
    1733                 :        1964 :         case 3:
    1734                 :        3928 :           if (get_min_precision (arg1, UNSIGNED)
    1735                 :        1964 :               + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
    1736                 :             :             {
    1737                 :             :               /* If the first operand is sign extended from narrower type, the
    1738                 :             :                  second operand is zero extended from narrower type and
    1739                 :             :                  the sum of the two precisions is smaller or equal to the
    1740                 :             :                  result precision: if the first argument is at runtime
    1741                 :             :                  non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
    1742                 :             :                  and there will be no overflow, if the first argument is
    1743                 :             :                  negative and the second argument zero, the result will be
    1744                 :             :                  0 and there will be no overflow, if the first argument is
    1745                 :             :                  negative and the second argument positive, the result when
    1746                 :             :                  treated as signed will be negative (minimum -0x7f80 or
    1747                 :             :                  -0x7f..f80..0) there will be always overflow.  So, do
    1748                 :             :                  res = (U) (s1 * u2)
    1749                 :             :                  ovf = (S) res < 0  */
    1750                 :         105 :               struct separate_ops ops;
    1751                 :         105 :               ops.code = MULT_EXPR;
    1752                 :         105 :               ops.type
    1753                 :         105 :                 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
    1754                 :             :                                                   1);
    1755                 :         105 :               ops.op0 = make_tree (ops.type, op0);
    1756                 :         105 :               ops.op1 = make_tree (ops.type, op1);
    1757                 :         105 :               ops.op2 = NULL_TREE;
    1758                 :         105 :               ops.location = loc;
    1759                 :         105 :               res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    1760                 :         105 :               do_compare_rtx_and_jump (res, const0_rtx, GE, false,
    1761                 :             :                                        mode, NULL_RTX, NULL, done_label,
    1762                 :             :                                        profile_probability::very_likely ());
    1763                 :         105 :               goto do_error_label;
    1764                 :             :             }
    1765                 :        1859 :           rtx_code_label *do_main_label;
    1766                 :        1859 :           do_main_label = gen_label_rtx ();
    1767                 :        1859 :           do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
    1768                 :             :                                    NULL, do_main_label, profile_probability::very_likely ());
    1769                 :        1859 :           do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
    1770                 :             :                                    NULL, do_main_label, profile_probability::very_likely ());
    1771                 :        1859 :           expand_arith_set_overflow (lhs, target);
    1772                 :        1859 :           emit_label (do_main_label);
    1773                 :        1859 :           goto do_main;
    1774                 :           0 :         default:
    1775                 :           0 :           gcc_unreachable ();
    1776                 :             :         }
    1777                 :             :     }
    1778                 :             : 
    1779                 :             :   /* u1 * u2 -> sr  */
    1780                 :       16797 :   if (uns0_p && uns1_p && !unsr_p)
    1781                 :             :     {
    1782                 :        1363 :       if ((pos_neg0 | pos_neg1) == 1)
    1783                 :             :         {
    1784                 :             :           /* If both arguments are zero extended from narrower types,
    1785                 :             :              the MSB will be clear on both and so we can pretend it is
    1786                 :             :              a normal s1 * s2 -> sr multiplication.  */
    1787                 :             :           uns0_p = false;
    1788                 :             :           uns1_p = false;
    1789                 :             :         }
    1790                 :             :       else
    1791                 :         957 :         uns = true;
    1792                 :             :       /* Rest of handling of this case after res is computed.  */
    1793                 :        1363 :       goto do_main;
    1794                 :             :     }
    1795                 :             : 
    1796                 :             :   /* s1 * u2 -> sr  */
    1797                 :       15434 :   if (!uns0_p && uns1_p && !unsr_p)
    1798                 :             :     {
    1799                 :        1781 :       switch (pos_neg1)
    1800                 :             :         {
    1801                 :          59 :         case 1:
    1802                 :        1332 :           goto do_main;
    1803                 :         449 :         case 2:
    1804                 :             :           /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
    1805                 :             :              avoid the main code, just multiply and signal overflow
    1806                 :             :              unless 0 * u2 or -1 * ((U) Smin).  */
    1807                 :         449 :           struct separate_ops ops;
    1808                 :         449 :           ops.code = MULT_EXPR;
    1809                 :         449 :           ops.type = TREE_TYPE (arg1);
    1810                 :         449 :           ops.op0 = make_tree (ops.type, op0);
    1811                 :         449 :           ops.op1 = make_tree (ops.type, op1);
    1812                 :         449 :           ops.op2 = NULL_TREE;
    1813                 :         449 :           ops.location = loc;
    1814                 :         449 :           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    1815                 :         449 :           do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
    1816                 :             :                                    NULL, done_label, profile_probability::very_likely ());
    1817                 :         449 :           do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
    1818                 :             :                                    NULL, do_error, profile_probability::very_unlikely ());
    1819                 :         449 :           int prec;
    1820                 :         449 :           prec = GET_MODE_PRECISION (mode);
    1821                 :         449 :           rtx sgn;
    1822                 :         449 :           sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
    1823                 :         449 :           do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
    1824                 :             :                                    NULL, done_label, profile_probability::very_likely ());
    1825                 :         449 :           goto do_error_label;
    1826                 :        1273 :         case 3:
    1827                 :             :           /* Rest of handling of this case after res is computed.  */
    1828                 :        1273 :           goto do_main;
    1829                 :           0 :         default:
    1830                 :           0 :           gcc_unreachable ();
    1831                 :             :         }
    1832                 :             :     }
    1833                 :             : 
    1834                 :             :   /* s1 * s2 -> ur  */
    1835                 :       13653 :   if (!uns0_p && !uns1_p && unsr_p)
    1836                 :             :     {
    1837                 :        2347 :       rtx tem;
    1838                 :        2347 :       switch (pos_neg0 | pos_neg1)
    1839                 :             :         {
    1840                 :           0 :         case 1: /* Both operands known to be non-negative.  */
    1841                 :           0 :           goto do_main;
    1842                 :          12 :         case 2: /* Both operands known to be negative.  */
    1843                 :          12 :           op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
    1844                 :          12 :           op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
    1845                 :             :           /* Avoid looking at arg0/arg1 ranges, as we've changed
    1846                 :             :              the arguments.  */
    1847                 :          12 :           arg0 = error_mark_node;
    1848                 :          12 :           arg1 = error_mark_node;
    1849                 :          12 :           goto do_main;
    1850                 :        2335 :         case 3:
    1851                 :        2335 :           if ((pos_neg0 ^ pos_neg1) == 3)
    1852                 :             :             {
    1853                 :             :               /* If one operand is known to be negative and the other
    1854                 :             :                  non-negative, this overflows always, unless the non-negative
    1855                 :             :                  one is 0.  Just do normal multiply and set overflow
    1856                 :             :                  unless one of the operands is 0.  */
    1857                 :           0 :               struct separate_ops ops;
    1858                 :           0 :               ops.code = MULT_EXPR;
    1859                 :           0 :               ops.type
    1860                 :           0 :                 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
    1861                 :             :                                                   1);
    1862                 :           0 :               ops.op0 = make_tree (ops.type, op0);
    1863                 :           0 :               ops.op1 = make_tree (ops.type, op1);
    1864                 :           0 :               ops.op2 = NULL_TREE;
    1865                 :           0 :               ops.location = loc;
    1866                 :           0 :               res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    1867                 :           0 :               do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
    1868                 :             :                                        true, mode, NULL_RTX, NULL, done_label,
    1869                 :             :                                        profile_probability::very_likely ());
    1870                 :           0 :               goto do_error_label;
    1871                 :             :             }
    1872                 :        4670 :           if (get_min_precision (arg0, SIGNED)
    1873                 :        2335 :               + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
    1874                 :             :             {
    1875                 :             :               /* If both operands are sign extended from narrower types and
    1876                 :             :                  the sum of the two precisions is smaller or equal to the
    1877                 :             :                  result precision: if both arguments are at runtime
    1878                 :             :                  non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
    1879                 :             :                  and there will be no overflow, if both arguments are negative,
    1880                 :             :                  maximum result will be 0x40..00 and there will be no overflow
    1881                 :             :                  either, if one argument is positive and the other argument
    1882                 :             :                  negative, the result when treated as signed will be negative
    1883                 :             :                  and there will be always overflow, and if one argument is
    1884                 :             :                  zero and the other negative the result will be zero and no
    1885                 :             :                  overflow.  So, do
    1886                 :             :                  res = (U) (s1 * s2)
    1887                 :             :                  ovf = (S) res < 0  */
    1888                 :         238 :               struct separate_ops ops;
    1889                 :         238 :               ops.code = MULT_EXPR;
    1890                 :         238 :               ops.type
    1891                 :         238 :                 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
    1892                 :             :                                                   1);
    1893                 :         238 :               ops.op0 = make_tree (ops.type, op0);
    1894                 :         238 :               ops.op1 = make_tree (ops.type, op1);
    1895                 :         238 :               ops.op2 = NULL_TREE;
    1896                 :         238 :               ops.location = loc;
    1897                 :         238 :               res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    1898                 :         238 :               do_compare_rtx_and_jump (res, const0_rtx, GE, false,
    1899                 :             :                                        mode, NULL_RTX, NULL, done_label,
    1900                 :             :                                        profile_probability::very_likely ());
    1901                 :         238 :               goto do_error_label;
    1902                 :             :             }
    1903                 :             :           /* The general case, do all the needed comparisons at runtime.  */
    1904                 :        2097 :           rtx_code_label *do_main_label, *after_negate_label;
    1905                 :        2097 :           rtx rop0, rop1;
    1906                 :        2097 :           rop0 = gen_reg_rtx (mode);
    1907                 :        2097 :           rop1 = gen_reg_rtx (mode);
    1908                 :        2097 :           emit_move_insn (rop0, op0);
    1909                 :        2097 :           emit_move_insn (rop1, op1);
    1910                 :        2097 :           op0 = rop0;
    1911                 :        2097 :           op1 = rop1;
    1912                 :        2097 :           do_main_label = gen_label_rtx ();
    1913                 :        2097 :           after_negate_label = gen_label_rtx ();
    1914                 :        2097 :           tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
    1915                 :             :                               OPTAB_LIB_WIDEN);
    1916                 :        2097 :           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
    1917                 :             :                                    NULL, after_negate_label, profile_probability::very_likely ());
    1918                 :             :           /* Both arguments negative here, negate them and continue with
    1919                 :             :              normal unsigned overflow checking multiplication.  */
    1920                 :        2097 :           emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
    1921                 :             :                                             NULL_RTX, false));
    1922                 :        2097 :           emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
    1923                 :             :                                             NULL_RTX, false));
    1924                 :             :           /* Avoid looking at arg0/arg1 ranges, as we might have changed
    1925                 :             :              the arguments.  */
    1926                 :        2097 :           arg0 = error_mark_node;
    1927                 :        2097 :           arg1 = error_mark_node;
    1928                 :        2097 :           emit_jump (do_main_label);
    1929                 :        2097 :           emit_label (after_negate_label);
    1930                 :        2097 :           tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
    1931                 :             :                               OPTAB_LIB_WIDEN);
    1932                 :        2097 :           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
    1933                 :             :                                    NULL, do_main_label,
    1934                 :             :                                    profile_probability::very_likely ());
    1935                 :             :           /* One argument is negative here, the other positive.  This
    1936                 :             :              overflows always, unless one of the arguments is 0.  But
    1937                 :             :              if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
    1938                 :             :              is, thus we can keep do_main code oring in overflow as is.  */
    1939                 :        2097 :           if (pos_neg0 != 2)
    1940                 :        2097 :             do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
    1941                 :             :                                      NULL, do_main_label,
    1942                 :             :                                      profile_probability::very_unlikely ());
    1943                 :        2097 :           if (pos_neg1 != 2)
    1944                 :        1080 :             do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
    1945                 :             :                                      NULL, do_main_label,
    1946                 :             :                                      profile_probability::very_unlikely ());
    1947                 :        2097 :           expand_arith_set_overflow (lhs, target);
    1948                 :        2097 :           emit_label (do_main_label);
    1949                 :        2097 :           goto do_main;
    1950                 :           0 :         default:
    1951                 :           0 :           gcc_unreachable ();
    1952                 :             :         }
    1953                 :             :     }
    1954                 :             : 
    1955                 :       11306 :  do_main:
    1956                 :       17969 :   type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
    1957                 :       17969 :   sign = uns ? UNSIGNED : SIGNED;
    1958                 :       25603 :   icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
    1959                 :       17969 :   if (uns
    1960                 :       10335 :       && (integer_pow2p (arg0) || integer_pow2p (arg1))
    1961                 :       18727 :       && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
    1962                 :             :     {
    1963                 :             :       /* Optimize unsigned multiplication by power of 2 constant
    1964                 :             :          using 2 shifts, one for result, one to extract the shifted
    1965                 :             :          out bits to see if they are all zero.
    1966                 :             :          Don't do this if optimizing for size and we have umulv4_optab,
    1967                 :             :          in that case assume multiplication will be shorter.
    1968                 :             :          This is heuristics based on the single target that provides
    1969                 :             :          umulv4 right now (i?86/x86_64), if further targets add it, this
    1970                 :             :          might need to be revisited.
    1971                 :             :          Cases where both operands are constant should be folded already
    1972                 :             :          during GIMPLE, and cases where one operand is constant but not
    1973                 :             :          power of 2 are questionable, either the WIDEN_MULT_EXPR case
    1974                 :             :          below can be done without multiplication, just by shifts and adds,
    1975                 :             :          or we'd need to divide the result (and hope it actually doesn't
    1976                 :             :          really divide nor multiply) and compare the result of the division
    1977                 :             :          with the original operand.  */
    1978                 :         758 :       rtx opn0 = op0;
    1979                 :         758 :       rtx opn1 = op1;
    1980                 :         758 :       tree argn0 = arg0;
    1981                 :         758 :       tree argn1 = arg1;
    1982                 :         758 :       if (integer_pow2p (arg0))
    1983                 :             :         {
    1984                 :           0 :           std::swap (opn0, opn1);
    1985                 :           0 :           std::swap (argn0, argn1);
    1986                 :             :         }
    1987                 :         758 :       int cnt = tree_log2 (argn1);
    1988                 :         758 :       if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
    1989                 :             :         {
    1990                 :         758 :           rtx upper = const0_rtx;
    1991                 :         758 :           res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
    1992                 :         758 :           if (cnt != 0)
    1993                 :         586 :             upper = expand_shift (RSHIFT_EXPR, mode, opn0,
    1994                 :         586 :                                   GET_MODE_PRECISION (mode) - cnt,
    1995                 :             :                                   NULL_RTX, uns);
    1996                 :         758 :           do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
    1997                 :             :                                    NULL_RTX, NULL, done_label,
    1998                 :             :                                    profile_probability::very_likely ());
    1999                 :         758 :           goto do_error_label;
    2000                 :             :         }
    2001                 :             :     }
    2002                 :       17211 :   if (icode != CODE_FOR_nothing)
    2003                 :             :     {
    2004                 :       14065 :       class expand_operand ops[4];
    2005                 :       14065 :       rtx_insn *last = get_last_insn ();
    2006                 :             : 
    2007                 :       14065 :       res = gen_reg_rtx (mode);
    2008                 :       14065 :       create_output_operand (&ops[0], res, mode);
    2009                 :       14065 :       create_input_operand (&ops[1], op0, mode);
    2010                 :       14065 :       create_input_operand (&ops[2], op1, mode);
    2011                 :       14065 :       create_fixed_operand (&ops[3], do_error);
    2012                 :       14065 :       if (maybe_expand_insn (icode, 4, ops))
    2013                 :             :         {
    2014                 :       14065 :           last = get_last_insn ();
    2015                 :       14065 :           if (profile_status_for_fn (cfun) != PROFILE_ABSENT
    2016                 :        9016 :               && JUMP_P (last)
    2017                 :        9016 :               && any_condjump_p (last)
    2018                 :       23081 :               && !find_reg_note (last, REG_BR_PROB, 0))
    2019                 :        9016 :             add_reg_br_prob_note (last, 
    2020                 :             :                                   profile_probability::very_unlikely ());
    2021                 :       14065 :           emit_jump (done_label);
    2022                 :             :         }
    2023                 :             :       else
    2024                 :             :         {
    2025                 :           0 :           delete_insns_since (last);
    2026                 :           0 :           icode = CODE_FOR_nothing;
    2027                 :             :         }
    2028                 :             :     }
    2029                 :             : 
    2030                 :           0 :   if (icode == CODE_FOR_nothing)
    2031                 :             :     {
    2032                 :        3146 :       struct separate_ops ops;
    2033                 :        3146 :       int prec = GET_MODE_PRECISION (mode);
    2034                 :        3146 :       scalar_int_mode hmode, wmode;
    2035                 :        3146 :       ops.op0 = make_tree (type, op0);
    2036                 :        3146 :       ops.op1 = make_tree (type, op1);
    2037                 :        3146 :       ops.op2 = NULL_TREE;
    2038                 :        3146 :       ops.location = loc;
    2039                 :             : 
    2040                 :             :       /* Optimize unsigned overflow check where we don't use the
    2041                 :             :          multiplication result, just whether overflow happened.
    2042                 :             :          If we can do MULT_HIGHPART_EXPR, that followed by
    2043                 :             :          comparison of the result against zero is cheapest.
    2044                 :             :          We'll still compute res, but it should be DCEd later.  */
    2045                 :        3146 :       use_operand_p use;
    2046                 :        3146 :       gimple *use_stmt;
    2047                 :        3146 :       if (!is_ubsan
    2048                 :        3146 :           && lhs
    2049                 :        3125 :           && uns
    2050                 :        1999 :           && !(uns0_p && uns1_p && !unsr_p)
    2051                 :        1718 :           && can_mult_highpart_p (mode, uns) == 1
    2052                 :           0 :           && single_imm_use (lhs, &use, &use_stmt)
    2053                 :           0 :           && is_gimple_assign (use_stmt)
    2054                 :        3146 :           && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
    2055                 :           0 :         goto highpart;
    2056                 :             : 
    2057                 :        3146 :       if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
    2058                 :        3146 :           && targetm.scalar_mode_supported_p (wmode)
    2059                 :           0 :           && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
    2060                 :             :         {
    2061                 :           0 :         twoxwider:
    2062                 :           0 :           ops.code = WIDEN_MULT_EXPR;
    2063                 :           0 :           ops.type
    2064                 :           0 :             = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
    2065                 :             : 
    2066                 :           0 :           res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
    2067                 :           0 :           rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
    2068                 :             :                                      NULL_RTX, uns);
    2069                 :           0 :           hipart = convert_modes (mode, wmode, hipart, uns);
    2070                 :           0 :           res = convert_modes (mode, wmode, res, uns);
    2071                 :           0 :           if (uns)
    2072                 :             :             /* For the unsigned multiplication, there was overflow if
    2073                 :             :                HIPART is non-zero.  */
    2074                 :           0 :             do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
    2075                 :             :                                      NULL_RTX, NULL, done_label,
    2076                 :             :                                      profile_probability::very_likely ());
    2077                 :             :           else
    2078                 :             :             {
    2079                 :             :               /* RES is used more than once, place it in a pseudo.  */
    2080                 :           0 :               res = force_reg (mode, res);
    2081                 :             : 
    2082                 :           0 :               rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
    2083                 :             :                                           NULL_RTX, 0);
    2084                 :             :               /* RES is low half of the double width result, HIPART
    2085                 :             :                  the high half.  There was overflow if
    2086                 :             :                  HIPART is different from RES < 0 ? -1 : 0.  */
    2087                 :           0 :               do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
    2088                 :             :                                        NULL_RTX, NULL, done_label,
    2089                 :             :                                        profile_probability::very_likely ());
    2090                 :             :             }
    2091                 :             :         }
    2092                 :        3146 :       else if (can_mult_highpart_p (mode, uns) == 1)
    2093                 :             :         {
    2094                 :           0 :         highpart:
    2095                 :           0 :           ops.code = MULT_HIGHPART_EXPR;
    2096                 :           0 :           ops.type = type;
    2097                 :             : 
    2098                 :           0 :           rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
    2099                 :             :                                            EXPAND_NORMAL);
    2100                 :           0 :           ops.code = MULT_EXPR;
    2101                 :           0 :           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2102                 :           0 :           if (uns)
    2103                 :             :             /* For the unsigned multiplication, there was overflow if
    2104                 :             :                HIPART is non-zero.  */
    2105                 :           0 :             do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
    2106                 :             :                                      NULL_RTX, NULL, done_label,
    2107                 :             :                                      profile_probability::very_likely ());
    2108                 :             :           else
    2109                 :             :             {
    2110                 :           0 :               rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
    2111                 :             :                                           NULL_RTX, 0);
    2112                 :             :               /* RES is low half of the double width result, HIPART
    2113                 :             :                  the high half.  There was overflow if
    2114                 :             :                  HIPART is different from RES < 0 ? -1 : 0.  */
    2115                 :           0 :               do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
    2116                 :             :                                        NULL_RTX, NULL, done_label,
    2117                 :             :                                        profile_probability::very_likely ());
    2118                 :             :             }
    2119                 :             :           
    2120                 :             :         }
    2121                 :        3146 :       else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
    2122                 :        3146 :                && 2 * GET_MODE_PRECISION (hmode) == prec)
    2123                 :             :         {
    2124                 :        3146 :           rtx_code_label *large_op0 = gen_label_rtx ();
    2125                 :        3146 :           rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
    2126                 :        3146 :           rtx_code_label *one_small_one_large = gen_label_rtx ();
    2127                 :        3146 :           rtx_code_label *both_ops_large = gen_label_rtx ();
    2128                 :        3146 :           rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
    2129                 :        1147 :           rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
    2130                 :        3146 :           rtx_code_label *do_overflow = gen_label_rtx ();
    2131                 :        3146 :           rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
    2132                 :             : 
    2133                 :        3146 :           unsigned int hprec = GET_MODE_PRECISION (hmode);
    2134                 :        3146 :           rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
    2135                 :             :                                       NULL_RTX, uns);
    2136                 :        3146 :           hipart0 = convert_modes (hmode, mode, hipart0, uns);
    2137                 :        3146 :           rtx lopart0 = convert_modes (hmode, mode, op0, uns);
    2138                 :        3146 :           rtx signbit0 = const0_rtx;
    2139                 :        3146 :           if (!uns)
    2140                 :        1147 :             signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
    2141                 :             :                                      NULL_RTX, 0);
    2142                 :        3146 :           rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
    2143                 :             :                                       NULL_RTX, uns);
    2144                 :        3146 :           hipart1 = convert_modes (hmode, mode, hipart1, uns);
    2145                 :        3146 :           rtx lopart1 = convert_modes (hmode, mode, op1, uns);
    2146                 :        3146 :           rtx signbit1 = const0_rtx;
    2147                 :        3146 :           if (!uns)
    2148                 :        1147 :             signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
    2149                 :             :                                      NULL_RTX, 0);
    2150                 :             : 
    2151                 :        3146 :           res = gen_reg_rtx (mode);
    2152                 :             : 
    2153                 :             :           /* True if op0 resp. op1 are known to be in the range of
    2154                 :             :              halfstype.  */
    2155                 :        3146 :           bool op0_small_p = false;
    2156                 :        3146 :           bool op1_small_p = false;
    2157                 :             :           /* True if op0 resp. op1 are known to have all zeros or all ones
    2158                 :             :              in the upper half of bits, but are not known to be
    2159                 :             :              op{0,1}_small_p.  */
    2160                 :        3146 :           bool op0_medium_p = false;
    2161                 :        3146 :           bool op1_medium_p = false;
    2162                 :             :           /* -1 if op{0,1} is known to be negative, 0 if it is known to be
    2163                 :             :              nonnegative, 1 if unknown.  */
    2164                 :        3146 :           int op0_sign = 1;
    2165                 :        3146 :           int op1_sign = 1;
    2166                 :             : 
    2167                 :        3146 :           if (pos_neg0 == 1)
    2168                 :             :             op0_sign = 0;
    2169                 :        2998 :           else if (pos_neg0 == 2)
    2170                 :         188 :             op0_sign = -1;
    2171                 :        3146 :           if (pos_neg1 == 1)
    2172                 :             :             op1_sign = 0;
    2173                 :        2011 :           else if (pos_neg1 == 2)
    2174                 :         438 :             op1_sign = -1;
    2175                 :             : 
    2176                 :        3146 :           unsigned int mprec0 = prec;
    2177                 :        3146 :           if (arg0 != error_mark_node)
    2178                 :        2397 :             mprec0 = get_min_precision (arg0, sign);
    2179                 :        3146 :           if (mprec0 <= hprec)
    2180                 :             :             op0_small_p = true;
    2181                 :        2978 :           else if (!uns && mprec0 <= hprec + 1)
    2182                 :        3146 :             op0_medium_p = true;
    2183                 :        3146 :           unsigned int mprec1 = prec;
    2184                 :        3146 :           if (arg1 != error_mark_node)
    2185                 :        2397 :             mprec1 = get_min_precision (arg1, sign);
    2186                 :        3146 :           if (mprec1 <= hprec)
    2187                 :             :             op1_small_p = true;
    2188                 :        2599 :           else if (!uns && mprec1 <= hprec + 1)
    2189                 :        3146 :             op1_medium_p = true;
    2190                 :             : 
    2191                 :        3146 :           int smaller_sign = 1;
    2192                 :        3146 :           int larger_sign = 1;
    2193                 :        3146 :           if (op0_small_p)
    2194                 :             :             {
    2195                 :             :               smaller_sign = op0_sign;
    2196                 :             :               larger_sign = op1_sign;
    2197                 :             :             }
    2198                 :        2978 :           else if (op1_small_p)
    2199                 :             :             {
    2200                 :             :               smaller_sign = op1_sign;
    2201                 :             :               larger_sign = op0_sign;
    2202                 :             :             }
    2203                 :        2431 :           else if (op0_sign == op1_sign)
    2204                 :             :             {
    2205                 :        1495 :               smaller_sign = op0_sign;
    2206                 :        1495 :               larger_sign = op0_sign;
    2207                 :             :             }
    2208                 :             : 
    2209                 :        3146 :           if (!op0_small_p)
    2210                 :        2978 :             do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
    2211                 :             :                                      NULL_RTX, NULL, large_op0,
    2212                 :             :                                      profile_probability::unlikely ());
    2213                 :             : 
    2214                 :        3146 :           if (!op1_small_p)
    2215                 :        2599 :             do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
    2216                 :             :                                      NULL_RTX, NULL, small_op0_large_op1,
    2217                 :             :                                      profile_probability::unlikely ());
    2218                 :             : 
    2219                 :             :           /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
    2220                 :             :              hmode to mode, the multiplication will never overflow.  We can
    2221                 :             :              do just one hmode x hmode => mode widening multiplication.  */
    2222                 :        3146 :           tree halfstype = build_nonstandard_integer_type (hprec, uns);
    2223                 :        3146 :           ops.op0 = make_tree (halfstype, lopart0);
    2224                 :        3146 :           ops.op1 = make_tree (halfstype, lopart1);
    2225                 :        3146 :           ops.code = WIDEN_MULT_EXPR;
    2226                 :        3146 :           ops.type = type;
    2227                 :        3146 :           rtx thisres
    2228                 :        3146 :             = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2229                 :        3146 :           emit_move_insn (res, thisres);
    2230                 :        3146 :           emit_jump (done_label);
    2231                 :             : 
    2232                 :        3146 :           emit_label (small_op0_large_op1);
    2233                 :             : 
    2234                 :             :           /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
    2235                 :             :              but op1 is not, just swap the arguments and handle it as op1
    2236                 :             :              sign/zero extended, op0 not.  */
    2237                 :        3146 :           rtx larger = gen_reg_rtx (mode);
    2238                 :        3146 :           rtx hipart = gen_reg_rtx (hmode);
    2239                 :        3146 :           rtx lopart = gen_reg_rtx (hmode);
    2240                 :        3146 :           emit_move_insn (larger, op1);
    2241                 :        3146 :           emit_move_insn (hipart, hipart1);
    2242                 :        3146 :           emit_move_insn (lopart, lopart0);
    2243                 :        3146 :           emit_jump (one_small_one_large);
    2244                 :             : 
    2245                 :        3146 :           emit_label (large_op0);
    2246                 :             : 
    2247                 :        3146 :           if (!op1_small_p)
    2248                 :        2599 :             do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
    2249                 :             :                                      NULL_RTX, NULL, both_ops_large,
    2250                 :             :                                      profile_probability::unlikely ());
    2251                 :             : 
    2252                 :             :           /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
    2253                 :             :              but op0 is not, prepare larger, hipart and lopart pseudos and
    2254                 :             :              handle it together with small_op0_large_op1.  */
    2255                 :        3146 :           emit_move_insn (larger, op0);
    2256                 :        3146 :           emit_move_insn (hipart, hipart0);
    2257                 :        3146 :           emit_move_insn (lopart, lopart1);
    2258                 :             : 
    2259                 :        3146 :           emit_label (one_small_one_large);
    2260                 :             : 
    2261                 :             :           /* lopart is the low part of the operand that is sign extended
    2262                 :             :              to mode, larger is the other operand, hipart is the
    2263                 :             :              high part of larger and lopart0 and lopart1 are the low parts
    2264                 :             :              of both operands.
    2265                 :             :              We perform lopart0 * lopart1 and lopart * hipart widening
    2266                 :             :              multiplications.  */
    2267                 :        3146 :           tree halfutype = build_nonstandard_integer_type (hprec, 1);
    2268                 :        3146 :           ops.op0 = make_tree (halfutype, lopart0);
    2269                 :        3146 :           ops.op1 = make_tree (halfutype, lopart1);
    2270                 :        3146 :           rtx lo0xlo1
    2271                 :        3146 :             = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2272                 :             : 
    2273                 :        3146 :           ops.op0 = make_tree (halfutype, lopart);
    2274                 :        3146 :           ops.op1 = make_tree (halfutype, hipart);
    2275                 :        3146 :           rtx loxhi = gen_reg_rtx (mode);
    2276                 :        3146 :           rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2277                 :        3146 :           emit_move_insn (loxhi, tem);
    2278                 :             : 
    2279                 :        3146 :           if (!uns)
    2280                 :             :             {
    2281                 :             :               /* if (hipart < 0) loxhi -= lopart << (bitsize / 2);  */
    2282                 :        1147 :               if (larger_sign == 0)
    2283                 :          65 :                 emit_jump (after_hipart_neg);
    2284                 :        1082 :               else if (larger_sign != -1)
    2285                 :        1082 :                 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
    2286                 :             :                                          NULL_RTX, NULL, after_hipart_neg,
    2287                 :             :                                          profile_probability::even ());
    2288                 :             : 
    2289                 :        1147 :               tem = convert_modes (mode, hmode, lopart, 1);
    2290                 :        1147 :               tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
    2291                 :        1147 :               tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
    2292                 :             :                                          1, OPTAB_WIDEN);
    2293                 :        1147 :               emit_move_insn (loxhi, tem);
    2294                 :             : 
    2295                 :        1147 :               emit_label (after_hipart_neg);
    2296                 :             : 
    2297                 :             :               /* if (lopart < 0) loxhi -= larger;  */
    2298                 :        1147 :               if (smaller_sign == 0)
    2299                 :         265 :                 emit_jump (after_lopart_neg);
    2300                 :         882 :               else if (smaller_sign != -1)
    2301                 :         710 :                 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
    2302                 :             :                                          NULL_RTX, NULL, after_lopart_neg,
    2303                 :             :                                          profile_probability::even ());
    2304                 :             : 
    2305                 :        1147 :               tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
    2306                 :             :                                          1, OPTAB_WIDEN);
    2307                 :        1147 :               emit_move_insn (loxhi, tem);
    2308                 :             : 
    2309                 :        1147 :               emit_label (after_lopart_neg);
    2310                 :             :             }
    2311                 :             : 
    2312                 :             :           /* loxhi += (uns) lo0xlo1 >> (bitsize / 2);  */
    2313                 :        3146 :           tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
    2314                 :        3146 :           tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
    2315                 :             :                                      1, OPTAB_WIDEN);
    2316                 :        3146 :           emit_move_insn (loxhi, tem);
    2317                 :             : 
    2318                 :             :           /* if (loxhi >> (bitsize / 2)
    2319                 :             :                  == (hmode) loxhi >> (bitsize / 2 - 1))  (if !uns)
    2320                 :             :              if (loxhi >> (bitsize / 2) == 0               (if uns).  */
    2321                 :        3146 :           rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
    2322                 :             :                                           NULL_RTX, 0);
    2323                 :        3146 :           hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
    2324                 :        3146 :           rtx signbitloxhi = const0_rtx;
    2325                 :        3146 :           if (!uns)
    2326                 :        1147 :             signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
    2327                 :             :                                          convert_modes (hmode, mode,
    2328                 :             :                                                         loxhi, 0),
    2329                 :        1147 :                                          hprec - 1, NULL_RTX, 0);
    2330                 :             : 
    2331                 :        3146 :           do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
    2332                 :             :                                    NULL_RTX, NULL, do_overflow,
    2333                 :             :                                    profile_probability::very_unlikely ());
    2334                 :             : 
    2335                 :             :           /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1;  */
    2336                 :        3146 :           rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
    2337                 :             :                                            NULL_RTX, 1);
    2338                 :        3146 :           tem = convert_modes (mode, hmode,
    2339                 :             :                                convert_modes (hmode, mode, lo0xlo1, 1), 1);
    2340                 :             : 
    2341                 :        3146 :           tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
    2342                 :             :                                      1, OPTAB_WIDEN);
    2343                 :        3146 :           if (tem != res)
    2344                 :           0 :             emit_move_insn (res, tem);
    2345                 :        3146 :           emit_jump (done_label);
    2346                 :             : 
    2347                 :        3146 :           emit_label (both_ops_large);
    2348                 :             : 
    2349                 :             :           /* If both operands are large (not sign (!uns) or zero (uns)
    2350                 :             :              extended from hmode), then perform the full multiplication
    2351                 :             :              which will be the result of the operation.
    2352                 :             :              The only cases which don't overflow are for signed multiplication
    2353                 :             :              some cases where both hipart0 and highpart1 are 0 or -1.
    2354                 :             :              For unsigned multiplication when high parts are both non-zero
    2355                 :             :              this overflows always.  */
    2356                 :        3146 :           ops.code = MULT_EXPR;
    2357                 :        3146 :           ops.op0 = make_tree (type, op0);
    2358                 :        3146 :           ops.op1 = make_tree (type, op1);
    2359                 :        3146 :           tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2360                 :        3146 :           emit_move_insn (res, tem);
    2361                 :             : 
    2362                 :        3146 :           if (!uns)
    2363                 :             :             {
    2364                 :        1147 :               if (!op0_medium_p)
    2365                 :             :                 {
    2366                 :        1147 :                   tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
    2367                 :             :                                              NULL_RTX, 1, OPTAB_WIDEN);
    2368                 :        1147 :                   do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
    2369                 :             :                                            NULL_RTX, NULL, do_error,
    2370                 :             :                                            profile_probability::very_unlikely ());
    2371                 :             :                 }
    2372                 :             : 
    2373                 :        1147 :               if (!op1_medium_p)
    2374                 :             :                 {
    2375                 :        1147 :                   tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
    2376                 :             :                                              NULL_RTX, 1, OPTAB_WIDEN);
    2377                 :        1147 :                   do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
    2378                 :             :                                            NULL_RTX, NULL, do_error,
    2379                 :             :                                            profile_probability::very_unlikely ());
    2380                 :             :                 }
    2381                 :             : 
    2382                 :             :               /* At this point hipart{0,1} are both in [-1, 0].  If they are
    2383                 :             :                  the same, overflow happened if res is non-positive, if they
    2384                 :             :                  are different, overflow happened if res is positive.  */
    2385                 :        1147 :               if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
    2386                 :          12 :                 emit_jump (hipart_different);
    2387                 :        1135 :               else if (op0_sign == 1 || op1_sign == 1)
    2388                 :        1079 :                 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
    2389                 :             :                                          NULL_RTX, NULL, hipart_different,
    2390                 :             :                                          profile_probability::even ());
    2391                 :             : 
    2392                 :        1147 :               do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
    2393                 :             :                                        NULL_RTX, NULL, do_error,
    2394                 :             :                                        profile_probability::very_unlikely ());
    2395                 :        1147 :               emit_jump (done_label);
    2396                 :             : 
    2397                 :        1147 :               emit_label (hipart_different);
    2398                 :             : 
    2399                 :        1147 :               do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
    2400                 :             :                                        NULL_RTX, NULL, do_error,
    2401                 :             :                                        profile_probability::very_unlikely ());
    2402                 :        1147 :               emit_jump (done_label);
    2403                 :             :             }
    2404                 :             : 
    2405                 :        3146 :           emit_label (do_overflow);
    2406                 :             : 
    2407                 :             :           /* Overflow, do full multiplication and fallthru into do_error.  */
    2408                 :        3146 :           ops.op0 = make_tree (type, op0);
    2409                 :        3146 :           ops.op1 = make_tree (type, op1);
    2410                 :        3146 :           tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2411                 :        3146 :           emit_move_insn (res, tem);
    2412                 :             :         }
    2413                 :           0 :       else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
    2414                 :           0 :                && targetm.scalar_mode_supported_p (wmode))
    2415                 :             :         /* Even emitting a libcall is better than not detecting overflow
    2416                 :             :            at all.  */
    2417                 :           0 :         goto twoxwider;
    2418                 :             :       else
    2419                 :             :         {
    2420                 :           0 :           gcc_assert (!is_ubsan);
    2421                 :           0 :           ops.code = MULT_EXPR;
    2422                 :           0 :           ops.type = type;
    2423                 :           0 :           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2424                 :           0 :           emit_jump (done_label);
    2425                 :             :         }
    2426                 :             :     }
    2427                 :             : 
    2428                 :       14065 :  do_error_label:
    2429                 :       19075 :   emit_label (do_error);
    2430                 :       19075 :   if (is_ubsan)
    2431                 :             :     {
    2432                 :             :       /* Expand the ubsan builtin call.  */
    2433                 :        1663 :       push_temp_slots ();
    2434                 :        1663 :       fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
    2435                 :             :                                          arg0, arg1, datap);
    2436                 :        1663 :       expand_normal (fn);
    2437                 :        1663 :       pop_temp_slots ();
    2438                 :        1663 :       do_pending_stack_adjust ();
    2439                 :             :     }
    2440                 :       17412 :   else if (lhs)
    2441                 :       17412 :     expand_arith_set_overflow (lhs, target);
    2442                 :             : 
    2443                 :             :   /* We're done.  */
    2444                 :       19075 :   emit_label (done_label);
    2445                 :             : 
    2446                 :             :   /* u1 * u2 -> sr  */
    2447                 :       19075 :   if (uns0_p && uns1_p && !unsr_p)
    2448                 :             :     {
    2449                 :         957 :       rtx_code_label *all_done_label = gen_label_rtx ();
    2450                 :         957 :       do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
    2451                 :             :                                NULL, all_done_label, profile_probability::very_likely ());
    2452                 :         957 :       expand_arith_set_overflow (lhs, target);
    2453                 :         957 :       emit_label (all_done_label);
    2454                 :             :     }
    2455                 :             : 
    2456                 :             :   /* s1 * u2 -> sr  */
    2457                 :       19075 :   if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
    2458                 :             :     {
    2459                 :        1273 :       rtx_code_label *all_done_label = gen_label_rtx ();
    2460                 :        1273 :       rtx_code_label *set_noovf = gen_label_rtx ();
    2461                 :        1273 :       do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
    2462                 :             :                                NULL, all_done_label, profile_probability::very_likely ());
    2463                 :        1273 :       expand_arith_set_overflow (lhs, target);
    2464                 :        1273 :       do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
    2465                 :             :                                NULL, set_noovf, profile_probability::very_likely ());
    2466                 :        1273 :       do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
    2467                 :             :                                NULL, all_done_label, profile_probability::very_unlikely ());
    2468                 :        1273 :       do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
    2469                 :             :                                all_done_label, profile_probability::very_unlikely ());
    2470                 :        1273 :       emit_label (set_noovf);
    2471                 :        1273 :       write_complex_part (target, const0_rtx, true, false);
    2472                 :        1273 :       emit_label (all_done_label);
    2473                 :             :     }
    2474                 :             : 
    2475                 :       19075 :   if (lhs)
    2476                 :             :     {
    2477                 :       18919 :       if (is_ubsan)
    2478                 :        1507 :         expand_ubsan_result_store (lhs, target, mode, res, do_error);
    2479                 :             :       else
    2480                 :       17412 :         expand_arith_overflow_result_store (lhs, target, mode, res);
    2481                 :             :     }
    2482                 :       19075 : }
    2483                 :             : 
    2484                 :             : /* Expand UBSAN_CHECK_* internal function if it has vector operands.  */
    2485                 :             : 
    2486                 :             : static void
    2487                 :         598 : expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
    2488                 :             :                               tree arg0, tree arg1)
    2489                 :             : {
    2490                 :         598 :   poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
    2491                 :         598 :   rtx_code_label *loop_lab = NULL;
    2492                 :         598 :   rtx cntvar = NULL_RTX;
    2493                 :         598 :   tree cntv = NULL_TREE;
    2494                 :         598 :   tree eltype = TREE_TYPE (TREE_TYPE (arg0));
    2495                 :         598 :   tree sz = TYPE_SIZE (eltype);
    2496                 :         598 :   tree data = NULL_TREE;
    2497                 :         598 :   tree resv = NULL_TREE;
    2498                 :         598 :   rtx lhsr = NULL_RTX;
    2499                 :         598 :   rtx resvr = NULL_RTX;
    2500                 :         598 :   unsigned HOST_WIDE_INT const_cnt = 0;
    2501                 :         598 :   bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
    2502                 :             : 
    2503                 :         598 :   if (lhs)
    2504                 :             :     {
    2505                 :         598 :       optab op;
    2506                 :         598 :       lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    2507                 :         154 :       if (!VECTOR_MODE_P (GET_MODE (lhsr))
    2508                 :         444 :           || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
    2509                 :             :                                         optab_default)) == unknown_optab
    2510                 :        1042 :           || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
    2511                 :             :               == CODE_FOR_nothing))
    2512                 :             :         {
    2513                 :         154 :           if (MEM_P (lhsr))
    2514                 :         154 :             resv = make_tree (TREE_TYPE (lhs), lhsr);
    2515                 :             :           else
    2516                 :             :             {
    2517                 :           0 :               resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
    2518                 :           0 :               resv = make_tree (TREE_TYPE (lhs), resvr);
    2519                 :             :             }
    2520                 :             :         }
    2521                 :             :     }
    2522                 :         598 :   if (use_loop_p)
    2523                 :             :     {
    2524                 :         454 :       do_pending_stack_adjust ();
    2525                 :         454 :       loop_lab = gen_label_rtx ();
    2526                 :         454 :       cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
    2527                 :         454 :       cntv = make_tree (sizetype, cntvar);
    2528                 :         454 :       emit_move_insn (cntvar, const0_rtx);
    2529                 :         454 :       emit_label (loop_lab);
    2530                 :             :     }
    2531                 :         598 :   if (TREE_CODE (arg0) != VECTOR_CST)
    2532                 :             :     {
    2533                 :         502 :       rtx arg0r = expand_normal (arg0);
    2534                 :         502 :       arg0 = make_tree (TREE_TYPE (arg0), arg0r);
    2535                 :             :     }
    2536                 :         598 :   if (TREE_CODE (arg1) != VECTOR_CST)
    2537                 :             :     {
    2538                 :         586 :       rtx arg1r = expand_normal (arg1);
    2539                 :         586 :       arg1 = make_tree (TREE_TYPE (arg1), arg1r);
    2540                 :             :     }
    2541                 :        2348 :   for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
    2542                 :             :     {
    2543                 :        1030 :       tree op0, op1, res = NULL_TREE;
    2544                 :        1030 :       if (use_loop_p)
    2545                 :             :         {
    2546                 :         454 :           tree atype = build_array_type_nelts (eltype, cnt);
    2547                 :         454 :           op0 = uniform_vector_p (arg0);
    2548                 :         454 :           if (op0 == NULL_TREE)
    2549                 :             :             {
    2550                 :         382 :               op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
    2551                 :         382 :               op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
    2552                 :             :                                 NULL_TREE, NULL_TREE);
    2553                 :             :             }
    2554                 :         454 :           op1 = uniform_vector_p (arg1);
    2555                 :         454 :           if (op1 == NULL_TREE)
    2556                 :             :             {
    2557                 :         448 :               op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
    2558                 :         448 :               op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
    2559                 :             :                                 NULL_TREE, NULL_TREE);
    2560                 :             :             }
    2561                 :         454 :           if (resv)
    2562                 :             :             {
    2563                 :         154 :               res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
    2564                 :         154 :               res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
    2565                 :             :                                 NULL_TREE, NULL_TREE);
    2566                 :             :             }
    2567                 :             :         }
    2568                 :             :       else
    2569                 :             :         {
    2570                 :         576 :           tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
    2571                 :         576 :           op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
    2572                 :         576 :           op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
    2573                 :         576 :           if (resv)
    2574                 :           0 :             res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
    2575                 :             :                                    bitpos);
    2576                 :             :         }
    2577                 :        1030 :       switch (code)
    2578                 :             :         {
    2579                 :         346 :         case PLUS_EXPR:
    2580                 :         346 :           expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
    2581                 :             :                                   false, false, false, true, &data);
    2582                 :         346 :           break;
    2583                 :         504 :         case MINUS_EXPR:
    2584                 :         504 :           if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
    2585                 :         168 :             expand_neg_overflow (loc, res, op1, true, &data);
    2586                 :             :           else
    2587                 :         336 :             expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
    2588                 :             :                                     false, false, false, true, &data);
    2589                 :             :           break;
    2590                 :         180 :         case MULT_EXPR:
    2591                 :         180 :           expand_mul_overflow (loc, res, op0, op1, false, false, false,
    2592                 :             :                                true, &data);
    2593                 :         180 :           break;
    2594                 :           0 :         default:
    2595                 :           0 :           gcc_unreachable ();
    2596                 :             :         }
    2597                 :             :     }
    2598                 :         598 :   if (use_loop_p)
    2599                 :             :     {
    2600                 :         454 :       struct separate_ops ops;
    2601                 :         454 :       ops.code = PLUS_EXPR;
    2602                 :         454 :       ops.type = TREE_TYPE (cntv);
    2603                 :         454 :       ops.op0 = cntv;
    2604                 :         454 :       ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
    2605                 :         454 :       ops.op2 = NULL_TREE;
    2606                 :         454 :       ops.location = loc;
    2607                 :         454 :       rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
    2608                 :             :                                     EXPAND_NORMAL);
    2609                 :         454 :       if (ret != cntvar)
    2610                 :           0 :         emit_move_insn (cntvar, ret);
    2611                 :         454 :       rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
    2612                 :         908 :       do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
    2613                 :         454 :                                TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
    2614                 :             :                                profile_probability::very_likely ());
    2615                 :             :     }
    2616                 :         598 :   if (lhs && resv == NULL_TREE)
    2617                 :             :     {
    2618                 :         444 :       struct separate_ops ops;
    2619                 :         444 :       ops.code = code;
    2620                 :         444 :       ops.type = TREE_TYPE (arg0);
    2621                 :         444 :       ops.op0 = arg0;
    2622                 :         444 :       ops.op1 = arg1;
    2623                 :         444 :       ops.op2 = NULL_TREE;
    2624                 :         444 :       ops.location = loc;
    2625                 :         444 :       rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
    2626                 :             :                                     EXPAND_NORMAL);
    2627                 :         444 :       if (ret != lhsr)
    2628                 :           5 :         emit_move_insn (lhsr, ret);
    2629                 :             :     }
    2630                 :         154 :   else if (resvr)
    2631                 :           0 :     emit_move_insn (lhsr, resvr);
    2632                 :         598 : }
    2633                 :             : 
    2634                 :             : /* Expand UBSAN_CHECK_ADD call STMT.  */
    2635                 :             : 
    2636                 :             : static void
    2637                 :        1929 : expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
    2638                 :             : {
    2639                 :        1929 :   location_t loc = gimple_location (stmt);
    2640                 :        1929 :   tree lhs = gimple_call_lhs (stmt);
    2641                 :        1929 :   tree arg0 = gimple_call_arg (stmt, 0);
    2642                 :        1929 :   tree arg1 = gimple_call_arg (stmt, 1);
    2643                 :        1929 :   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
    2644                 :         202 :     expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
    2645                 :             :   else
    2646                 :        1727 :     expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
    2647                 :             :                             false, false, false, true, NULL);
    2648                 :        1929 : }
    2649                 :             : 
    2650                 :             : /* Expand UBSAN_CHECK_SUB call STMT.  */
    2651                 :             : 
    2652                 :             : static void
    2653                 :        2007 : expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
    2654                 :             : {
    2655                 :        2007 :   location_t loc = gimple_location (stmt);
    2656                 :        2007 :   tree lhs = gimple_call_lhs (stmt);
    2657                 :        2007 :   tree arg0 = gimple_call_arg (stmt, 0);
    2658                 :        2007 :   tree arg1 = gimple_call_arg (stmt, 1);
    2659                 :        2007 :   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
    2660                 :         288 :     expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
    2661                 :        1719 :   else if (integer_zerop (arg0))
    2662                 :         455 :     expand_neg_overflow (loc, lhs, arg1, true, NULL);
    2663                 :             :   else
    2664                 :        1264 :     expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
    2665                 :             :                             false, false, false, true, NULL);
    2666                 :        2007 : }
    2667                 :             : 
    2668                 :             : /* Expand UBSAN_CHECK_MUL call STMT.  */
    2669                 :             : 
    2670                 :             : static void
    2671                 :        1591 : expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
    2672                 :             : {
    2673                 :        1591 :   location_t loc = gimple_location (stmt);
    2674                 :        1591 :   tree lhs = gimple_call_lhs (stmt);
    2675                 :        1591 :   tree arg0 = gimple_call_arg (stmt, 0);
    2676                 :        1591 :   tree arg1 = gimple_call_arg (stmt, 1);
    2677                 :        1591 :   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
    2678                 :         108 :     expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
    2679                 :             :   else
    2680                 :        1483 :     expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
    2681                 :             :                          NULL);
    2682                 :        1591 : }
    2683                 :             : 
    2684                 :             : /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion.  */
    2685                 :             : 
    2686                 :             : static void
    2687                 :       73457 : expand_arith_overflow (enum tree_code code, gimple *stmt)
    2688                 :             : {
    2689                 :       73457 :   tree lhs = gimple_call_lhs (stmt);
    2690                 :       73457 :   if (lhs == NULL_TREE)
    2691                 :             :     return;
    2692                 :       73457 :   tree arg0 = gimple_call_arg (stmt, 0);
    2693                 :       73457 :   tree arg1 = gimple_call_arg (stmt, 1);
    2694                 :       73457 :   tree type = TREE_TYPE (TREE_TYPE (lhs));
    2695                 :       73457 :   int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
    2696                 :       73457 :   int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
    2697                 :       73457 :   int unsr_p = TYPE_UNSIGNED (type);
    2698                 :       73457 :   int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
    2699                 :       73457 :   int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
    2700                 :       73457 :   int precres = TYPE_PRECISION (type);
    2701                 :       73457 :   location_t loc = gimple_location (stmt);
    2702                 :       73457 :   if (!uns0_p && get_range_pos_neg (arg0) == 1)
    2703                 :             :     uns0_p = true;
    2704                 :       73457 :   if (!uns1_p && get_range_pos_neg (arg1) == 1)
    2705                 :             :     uns1_p = true;
    2706                 :      107881 :   int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
    2707                 :       73457 :   prec0 = MIN (prec0, pr);
    2708                 :       98717 :   pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
    2709                 :       73457 :   prec1 = MIN (prec1, pr);
    2710                 :             : 
    2711                 :             :   /* If uns0_p && uns1_p, precop is minimum needed precision
    2712                 :             :      of unsigned type to hold the exact result, otherwise
    2713                 :             :      precop is minimum needed precision of signed type to
    2714                 :             :      hold the exact result.  */
    2715                 :       73457 :   int precop;
    2716                 :       73457 :   if (code == MULT_EXPR)
    2717                 :       23449 :     precop = prec0 + prec1 + (uns0_p != uns1_p);
    2718                 :             :   else
    2719                 :             :     {
    2720                 :       50008 :       if (uns0_p == uns1_p)
    2721                 :       32998 :         precop = MAX (prec0, prec1) + 1;
    2722                 :       17010 :       else if (uns0_p)
    2723                 :        5815 :         precop = MAX (prec0 + 1, prec1) + 1;
    2724                 :             :       else
    2725                 :       11195 :         precop = MAX (prec0, prec1 + 1) + 1;
    2726                 :             :     }
    2727                 :       73457 :   int orig_precres = precres;
    2728                 :             : 
    2729                 :       92861 :   do
    2730                 :             :     {
    2731                 :       92861 :       if ((uns0_p && uns1_p)
    2732                 :       92861 :           ? ((precop + !unsr_p) <= precres
    2733                 :             :              /* u1 - u2 -> ur can overflow, no matter what precision
    2734                 :             :                 the result has.  */
    2735                 :       35049 :              && (code != MINUS_EXPR || !unsr_p))
    2736                 :       57812 :           : (!unsr_p && precop <= precres))
    2737                 :             :         {
    2738                 :             :           /* The infinity precision result will always fit into result.  */
    2739                 :       18556 :           rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    2740                 :       18556 :           write_complex_part (target, const0_rtx, true, false);
    2741                 :       18556 :           scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
    2742                 :       18556 :           struct separate_ops ops;
    2743                 :       18556 :           ops.code = code;
    2744                 :       18556 :           ops.type = type;
    2745                 :       18556 :           ops.op0 = fold_convert_loc (loc, type, arg0);
    2746                 :       18556 :           ops.op1 = fold_convert_loc (loc, type, arg1);
    2747                 :       18556 :           ops.op2 = NULL_TREE;
    2748                 :       18556 :           ops.location = loc;
    2749                 :       18556 :           rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    2750                 :       18556 :           expand_arith_overflow_result_store (lhs, target, mode, tem);
    2751                 :       18556 :           return;
    2752                 :             :         }
    2753                 :             : 
    2754                 :             :       /* For operations with low precision, if target doesn't have them, start
    2755                 :             :          with precres widening right away, otherwise do it only if the most
    2756                 :             :          simple cases can't be used.  */
    2757                 :       74305 :       const int min_precision = targetm.min_arithmetic_precision ();
    2758                 :       74305 :       if (orig_precres == precres && precres < min_precision)
    2759                 :             :         ;
    2760                 :       73037 :       else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
    2761                 :       22251 :                 && prec1 <= precres)
    2762                 :       50790 :           || ((!uns0_p || !uns1_p) && !unsr_p
    2763                 :       20741 :               && prec0 + uns0_p <= precres
    2764                 :       17540 :               && prec1 + uns1_p <= precres))
    2765                 :             :         {
    2766                 :       35647 :           arg0 = fold_convert_loc (loc, type, arg0);
    2767                 :       35647 :           arg1 = fold_convert_loc (loc, type, arg1);
    2768                 :       35647 :           switch (code)
    2769                 :             :             {
    2770                 :        9850 :             case MINUS_EXPR:
    2771                 :        9850 :               if (integer_zerop (arg0) && !unsr_p)
    2772                 :             :                 {
    2773                 :         402 :                   expand_neg_overflow (loc, lhs, arg1, false, NULL);
    2774                 :         402 :                   return;
    2775                 :             :                 }
    2776                 :             :               /* FALLTHRU */
    2777                 :       25602 :             case PLUS_EXPR:
    2778                 :       25602 :               expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
    2779                 :             :                                       unsr_p, unsr_p, false, NULL);
    2780                 :       25602 :               return;
    2781                 :        9643 :             case MULT_EXPR:
    2782                 :        9643 :               expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
    2783                 :             :                                    unsr_p, unsr_p, false, NULL);
    2784                 :        9643 :               return;
    2785                 :           0 :             default:
    2786                 :           0 :               gcc_unreachable ();
    2787                 :             :             }
    2788                 :             :         }
    2789                 :             : 
    2790                 :             :       /* For sub-word operations, retry with a wider type first.  */
    2791                 :       38661 :       if (orig_precres == precres && precop <= BITS_PER_WORD)
    2792                 :             :         {
    2793                 :       19518 :           int p = MAX (min_precision, precop);
    2794                 :       19518 :           scalar_int_mode m = smallest_int_mode_for_size (p);
    2795                 :       19518 :           tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
    2796                 :             :                                                         uns0_p && uns1_p
    2797                 :       19518 :                                                         && unsr_p);
    2798                 :       19518 :           p = TYPE_PRECISION (optype);
    2799                 :       19518 :           if (p > precres)
    2800                 :             :             {
    2801                 :       18807 :               precres = p;
    2802                 :       18807 :               unsr_p = TYPE_UNSIGNED (optype);
    2803                 :       18807 :               type = optype;
    2804                 :       18807 :               continue;
    2805                 :             :             }
    2806                 :             :         }
    2807                 :             : 
    2808                 :       19851 :       if (prec0 <= precres && prec1 <= precres)
    2809                 :             :         {
    2810                 :       19254 :           tree types[2];
    2811                 :       19254 :           if (unsr_p)
    2812                 :             :             {
    2813                 :       11128 :               types[0] = build_nonstandard_integer_type (precres, 0);
    2814                 :       11128 :               types[1] = type;
    2815                 :             :             }
    2816                 :             :           else
    2817                 :             :             {
    2818                 :        8126 :               types[0] = type;
    2819                 :        8126 :               types[1] = build_nonstandard_integer_type (precres, 1);
    2820                 :             :             }
    2821                 :       19254 :           arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
    2822                 :       19254 :           arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
    2823                 :       19254 :           if (code != MULT_EXPR)
    2824                 :       11485 :             expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
    2825                 :             :                                     uns0_p, uns1_p, false, NULL);
    2826                 :             :           else
    2827                 :        7769 :             expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
    2828                 :             :                                  uns0_p, uns1_p, false, NULL);
    2829                 :       19254 :           return;
    2830                 :             :         }
    2831                 :             : 
    2832                 :             :       /* Retry with a wider type.  */
    2833                 :         597 :       if (orig_precres == precres)
    2834                 :             :         {
    2835                 :         597 :           int p = MAX (prec0, prec1);
    2836                 :         597 :           scalar_int_mode m = smallest_int_mode_for_size (p);
    2837                 :         597 :           tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
    2838                 :             :                                                         uns0_p && uns1_p
    2839                 :         597 :                                                         && unsr_p);
    2840                 :         597 :           p = TYPE_PRECISION (optype);
    2841                 :         597 :           if (p > precres)
    2842                 :             :             {
    2843                 :         597 :               precres = p;
    2844                 :         597 :               unsr_p = TYPE_UNSIGNED (optype);
    2845                 :         597 :               type = optype;
    2846                 :         597 :               continue;
    2847                 :             :             }
    2848                 :             :         }
    2849                 :             : 
    2850                 :           0 :       gcc_unreachable ();
    2851                 :             :     }
    2852                 :             :   while (1);
    2853                 :             : }
    2854                 :             : 
    2855                 :             : /* Expand ADD_OVERFLOW STMT.  */
    2856                 :             : 
    2857                 :             : static void
    2858                 :       26493 : expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
    2859                 :             : {
    2860                 :       26493 :   expand_arith_overflow (PLUS_EXPR, stmt);
    2861                 :       26493 : }
    2862                 :             : 
    2863                 :             : /* Expand SUB_OVERFLOW STMT.  */
    2864                 :             : 
    2865                 :             : static void
    2866                 :       23515 : expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
    2867                 :             : {
    2868                 :       23515 :   expand_arith_overflow (MINUS_EXPR, stmt);
    2869                 :       23515 : }
    2870                 :             : 
    2871                 :             : /* Expand MUL_OVERFLOW STMT.  */
    2872                 :             : 
    2873                 :             : static void
    2874                 :       23449 : expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
    2875                 :             : {
    2876                 :       23449 :   expand_arith_overflow (MULT_EXPR, stmt);
    2877                 :       23449 : }
    2878                 :             : 
    2879                 :             : /* Expand UADDC STMT.  */
    2880                 :             : 
    2881                 :             : static void
    2882                 :       14760 : expand_UADDC (internal_fn ifn, gcall *stmt)
    2883                 :             : {
    2884                 :       14760 :   tree lhs = gimple_call_lhs (stmt);
    2885                 :       14760 :   tree arg1 = gimple_call_arg (stmt, 0);
    2886                 :       14760 :   tree arg2 = gimple_call_arg (stmt, 1);
    2887                 :       14760 :   tree arg3 = gimple_call_arg (stmt, 2);
    2888                 :       14760 :   tree type = TREE_TYPE (arg1);
    2889                 :       14760 :   machine_mode mode = TYPE_MODE (type);
    2890                 :       20791 :   insn_code icode = optab_handler (ifn == IFN_UADDC
    2891                 :             :                                    ? uaddc5_optab : usubc5_optab, mode);
    2892                 :       14760 :   rtx op1 = expand_normal (arg1);
    2893                 :       14760 :   rtx op2 = expand_normal (arg2);
    2894                 :       14760 :   rtx op3 = expand_normal (arg3);
    2895                 :       14760 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    2896                 :       14760 :   rtx re = gen_reg_rtx (mode);
    2897                 :       14760 :   rtx im = gen_reg_rtx (mode);
    2898                 :       14760 :   class expand_operand ops[5];
    2899                 :       14760 :   create_output_operand (&ops[0], re, mode);
    2900                 :       14760 :   create_output_operand (&ops[1], im, mode);
    2901                 :       14760 :   create_input_operand (&ops[2], op1, mode);
    2902                 :       14760 :   create_input_operand (&ops[3], op2, mode);
    2903                 :       14760 :   create_input_operand (&ops[4], op3, mode);
    2904                 :       14760 :   expand_insn (icode, 5, ops);
    2905                 :       14760 :   write_complex_part (target, re, false, false);
    2906                 :       14760 :   write_complex_part (target, im, true, false);
    2907                 :       14760 : }
    2908                 :             : 
    2909                 :             : /* Expand USUBC STMT.  */
    2910                 :             : 
    2911                 :             : static void
    2912                 :        6031 : expand_USUBC (internal_fn ifn, gcall *stmt)
    2913                 :             : {
    2914                 :        6031 :   expand_UADDC (ifn, stmt);
    2915                 :        6031 : }
    2916                 :             : 
    2917                 :             : /* This should get folded in tree-vectorizer.cc.  */
    2918                 :             : 
    2919                 :             : static void
    2920                 :           0 : expand_LOOP_VECTORIZED (internal_fn, gcall *)
    2921                 :             : {
    2922                 :           0 :   gcc_unreachable ();
    2923                 :             : }
    2924                 :             : 
    2925                 :             : /* This should get folded in tree-vectorizer.cc.  */
    2926                 :             : 
    2927                 :             : static void
    2928                 :           0 : expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
    2929                 :             : {
    2930                 :           0 :   gcc_unreachable ();
    2931                 :             : }
    2932                 :             : 
    2933                 :             : /* Return a memory reference of type TYPE for argument INDEX of STMT.
    2934                 :             :    Use argument INDEX + 1 to derive the second (TBAA) operand.  */
    2935                 :             : 
    2936                 :             : static tree
    2937                 :        1743 : expand_call_mem_ref (tree type, gcall *stmt, int index)
    2938                 :             : {
    2939                 :        1743 :   tree addr = gimple_call_arg (stmt, index);
    2940                 :        1743 :   tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
    2941                 :        1743 :   unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
    2942                 :        1743 :   if (TYPE_ALIGN (type) != align)
    2943                 :         880 :     type = build_aligned_type (type, align);
    2944                 :             : 
    2945                 :        1743 :   tree tmp = addr;
    2946                 :        1743 :   if (TREE_CODE (tmp) == SSA_NAME)
    2947                 :             :     {
    2948                 :        1019 :       gimple *def = SSA_NAME_DEF_STMT (tmp);
    2949                 :        1019 :       if (gimple_assign_single_p (def))
    2950                 :         393 :         tmp = gimple_assign_rhs1 (def);
    2951                 :             :     }
    2952                 :             : 
    2953                 :        1743 :   if (TREE_CODE (tmp) == ADDR_EXPR)
    2954                 :             :     {
    2955                 :        1113 :       tree mem = TREE_OPERAND (tmp, 0);
    2956                 :        1113 :       if (TREE_CODE (mem) == TARGET_MEM_REF
    2957                 :        1113 :           && types_compatible_p (TREE_TYPE (mem), type))
    2958                 :             :         {
    2959                 :         389 :           tree offset = TMR_OFFSET (mem);
    2960                 :         389 :           if (type != TREE_TYPE (mem)
    2961                 :         140 :               || alias_ptr_type != TREE_TYPE (offset)
    2962                 :         529 :               || !integer_zerop (offset))
    2963                 :             :             {
    2964                 :         276 :               mem = copy_node (mem);
    2965                 :         276 :               TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
    2966                 :         276 :                                                    wi::to_poly_wide (offset));
    2967                 :         276 :               TREE_TYPE (mem) = type;
    2968                 :             :             }
    2969                 :         389 :           return mem;
    2970                 :             :         }
    2971                 :             :     }
    2972                 :             : 
    2973                 :        1354 :   return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
    2974                 :             : }
    2975                 :             : 
    2976                 :             : /* Expand MASK_LOAD{,_LANES}, MASK_LEN_LOAD or LEN_LOAD call STMT using optab
    2977                 :             :  * OPTAB.  */
    2978                 :             : 
    2979                 :             : static void
    2980                 :         547 : expand_partial_load_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
    2981                 :             : {
    2982                 :         547 :   int i = 0;
    2983                 :         547 :   class expand_operand ops[5];
    2984                 :         547 :   tree type, lhs, rhs, maskt;
    2985                 :         547 :   rtx mem, target;
    2986                 :         547 :   insn_code icode;
    2987                 :             : 
    2988                 :         547 :   maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
    2989                 :         547 :   lhs = gimple_call_lhs (stmt);
    2990                 :         547 :   if (lhs == NULL_TREE)
    2991                 :           0 :     return;
    2992                 :         547 :   type = TREE_TYPE (lhs);
    2993                 :         547 :   rhs = expand_call_mem_ref (type, stmt, 0);
    2994                 :             : 
    2995                 :         547 :   if (optab == vec_mask_load_lanes_optab
    2996                 :         547 :       || optab == vec_mask_len_load_lanes_optab)
    2997                 :           0 :     icode = get_multi_vector_move (type, optab);
    2998                 :         547 :   else if (optab == len_load_optab)
    2999                 :           0 :     icode = direct_optab_handler (optab, TYPE_MODE (type));
    3000                 :             :   else
    3001                 :         547 :     icode = convert_optab_handler (optab, TYPE_MODE (type),
    3002                 :         547 :                                    TYPE_MODE (TREE_TYPE (maskt)));
    3003                 :             : 
    3004                 :         547 :   mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3005                 :         547 :   gcc_assert (MEM_P (mem));
    3006                 :             :   /* The built MEM_REF does not accurately reflect that the load
    3007                 :             :      is only partial.  Clear it.  */
    3008                 :         547 :   set_mem_expr (mem, NULL_TREE);
    3009                 :         547 :   clear_mem_offset (mem);
    3010                 :         547 :   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3011                 :         547 :   create_output_operand (&ops[i++], target, TYPE_MODE (type));
    3012                 :         547 :   create_fixed_operand (&ops[i++], mem);
    3013                 :         547 :   i = add_mask_and_len_args (ops, i, stmt);
    3014                 :         547 :   expand_insn (icode, i, ops);
    3015                 :             : 
    3016                 :         547 :   if (!rtx_equal_p (target, ops[0].value))
    3017                 :           0 :     emit_move_insn (target, ops[0].value);
    3018                 :             : }
    3019                 :             : 
    3020                 :             : #define expand_mask_load_optab_fn expand_partial_load_optab_fn
    3021                 :             : #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
    3022                 :             : #define expand_len_load_optab_fn expand_partial_load_optab_fn
    3023                 :             : #define expand_mask_len_load_optab_fn expand_partial_load_optab_fn
    3024                 :             : 
    3025                 :             : /* Expand MASK_STORE{,_LANES}, MASK_LEN_STORE or LEN_STORE call STMT using optab
    3026                 :             :  * OPTAB.  */
    3027                 :             : 
    3028                 :             : static void
    3029                 :        1196 : expand_partial_store_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
    3030                 :             : {
    3031                 :        1196 :   int i = 0;
    3032                 :        1196 :   class expand_operand ops[5];
    3033                 :        1196 :   tree type, lhs, rhs, maskt;
    3034                 :        1196 :   rtx mem, reg;
    3035                 :        1196 :   insn_code icode;
    3036                 :             : 
    3037                 :        1196 :   maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
    3038                 :        1196 :   rhs = gimple_call_arg (stmt, internal_fn_stored_value_index (ifn));
    3039                 :        1196 :   type = TREE_TYPE (rhs);
    3040                 :        1196 :   lhs = expand_call_mem_ref (type, stmt, 0);
    3041                 :             : 
    3042                 :        1196 :   if (optab == vec_mask_store_lanes_optab
    3043                 :        1196 :       || optab == vec_mask_len_store_lanes_optab)
    3044                 :           0 :     icode = get_multi_vector_move (type, optab);
    3045                 :        1196 :   else if (optab == len_store_optab)
    3046                 :           0 :     icode = direct_optab_handler (optab, TYPE_MODE (type));
    3047                 :             :   else
    3048                 :        1196 :     icode = convert_optab_handler (optab, TYPE_MODE (type),
    3049                 :        1196 :                                    TYPE_MODE (TREE_TYPE (maskt)));
    3050                 :             : 
    3051                 :        1196 :   mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3052                 :        1196 :   gcc_assert (MEM_P (mem));
    3053                 :             :   /* The built MEM_REF does not accurately reflect that the store
    3054                 :             :      is only partial.  Clear it.  */
    3055                 :        1196 :   set_mem_expr (mem, NULL_TREE);
    3056                 :        1196 :   clear_mem_offset (mem);
    3057                 :        1196 :   reg = expand_normal (rhs);
    3058                 :        1196 :   create_fixed_operand (&ops[i++], mem);
    3059                 :        1196 :   create_input_operand (&ops[i++], reg, TYPE_MODE (type));
    3060                 :        1196 :   i = add_mask_and_len_args (ops, i, stmt);
    3061                 :        1196 :   expand_insn (icode, i, ops);
    3062                 :        1196 : }
    3063                 :             : 
    3064                 :             : #define expand_mask_store_optab_fn expand_partial_store_optab_fn
    3065                 :             : #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
    3066                 :             : #define expand_len_store_optab_fn expand_partial_store_optab_fn
    3067                 :             : #define expand_mask_len_store_optab_fn expand_partial_store_optab_fn
    3068                 :             : 
    3069                 :             : /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
    3070                 :             :    The expansion of STMT happens based on OPTAB table associated.  */
    3071                 :             : 
    3072                 :             : static void
    3073                 :        8670 : expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
    3074                 :             : {
    3075                 :        8670 :   class expand_operand ops[6];
    3076                 :        8670 :   insn_code icode;
    3077                 :        8670 :   tree lhs = gimple_call_lhs (stmt);
    3078                 :        8670 :   tree op0a = gimple_call_arg (stmt, 0);
    3079                 :        8670 :   tree op0b = gimple_call_arg (stmt, 1);
    3080                 :        8670 :   tree op1 = gimple_call_arg (stmt, 2);
    3081                 :        8670 :   tree op2 = gimple_call_arg (stmt, 3);
    3082                 :        8670 :   enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
    3083                 :             : 
    3084                 :        8670 :   tree vec_cond_type = TREE_TYPE (lhs);
    3085                 :        8670 :   tree op_mode = TREE_TYPE (op0a);
    3086                 :        8670 :   bool unsignedp = TYPE_UNSIGNED (op_mode);
    3087                 :             : 
    3088                 :        8670 :   machine_mode mode = TYPE_MODE (vec_cond_type);
    3089                 :        8670 :   machine_mode cmp_op_mode = TYPE_MODE (op_mode);
    3090                 :             : 
    3091                 :        8670 :   icode = convert_optab_handler (optab, mode, cmp_op_mode);
    3092                 :        8670 :   rtx comparison
    3093                 :        8670 :     = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
    3094                 :             :   /* vector_compare_rtx legitimizes operands, preserve equality when
    3095                 :             :      expanding op1/op2.  */
    3096                 :        8670 :   rtx rtx_op1, rtx_op2;
    3097                 :        8670 :   if (operand_equal_p (op1, op0a))
    3098                 :         183 :     rtx_op1 = XEXP (comparison, 0);
    3099                 :        8487 :   else if (operand_equal_p (op1, op0b))
    3100                 :         160 :     rtx_op1 = XEXP (comparison, 1);
    3101                 :             :   else
    3102                 :        8327 :     rtx_op1 = expand_normal (op1);
    3103                 :        8670 :   if (operand_equal_p (op2, op0a))
    3104                 :         109 :     rtx_op2 = XEXP (comparison, 0);
    3105                 :        8561 :   else if (operand_equal_p (op2, op0b))
    3106                 :         687 :     rtx_op2 = XEXP (comparison, 1);
    3107                 :             :   else
    3108                 :        7874 :     rtx_op2 = expand_normal (op2);
    3109                 :             : 
    3110                 :        8670 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3111                 :        8670 :   create_output_operand (&ops[0], target, mode);
    3112                 :        8670 :   create_input_operand (&ops[1], rtx_op1, mode);
    3113                 :        8670 :   create_input_operand (&ops[2], rtx_op2, mode);
    3114                 :        8670 :   create_fixed_operand (&ops[3], comparison);
    3115                 :        8670 :   create_fixed_operand (&ops[4], XEXP (comparison, 0));
    3116                 :        8670 :   create_fixed_operand (&ops[5], XEXP (comparison, 1));
    3117                 :        8670 :   expand_insn (icode, 6, ops);
    3118                 :        8670 :   if (!rtx_equal_p (ops[0].value, target))
    3119                 :           0 :     emit_move_insn (target, ops[0].value);
    3120                 :        8670 : }
    3121                 :             : 
    3122                 :             : /* Expand VCOND_MASK optab internal function.
    3123                 :             :    The expansion of STMT happens based on OPTAB table associated.  */
    3124                 :             : 
    3125                 :             : static void
    3126                 :        2451 : expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
    3127                 :             : {
    3128                 :        2451 :   class expand_operand ops[4];
    3129                 :             : 
    3130                 :        2451 :   tree lhs = gimple_call_lhs (stmt);
    3131                 :        2451 :   tree op0 = gimple_call_arg (stmt, 0);
    3132                 :        2451 :   tree op1 = gimple_call_arg (stmt, 1);
    3133                 :        2451 :   tree op2 = gimple_call_arg (stmt, 2);
    3134                 :        2451 :   tree vec_cond_type = TREE_TYPE (lhs);
    3135                 :             : 
    3136                 :        2451 :   machine_mode mode = TYPE_MODE (vec_cond_type);
    3137                 :        2451 :   machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
    3138                 :        2451 :   enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
    3139                 :        2451 :   rtx mask, rtx_op1, rtx_op2;
    3140                 :             : 
    3141                 :        2451 :   gcc_assert (icode != CODE_FOR_nothing);
    3142                 :             : 
    3143                 :        2451 :   mask = expand_normal (op0);
    3144                 :        2451 :   rtx_op1 = expand_normal (op1);
    3145                 :        2451 :   rtx_op2 = expand_normal (op2);
    3146                 :             : 
    3147                 :        2451 :   mask = force_reg (mask_mode, mask);
    3148                 :        2451 :   rtx_op1 = force_reg (mode, rtx_op1);
    3149                 :             : 
    3150                 :        2451 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3151                 :        2451 :   create_output_operand (&ops[0], target, mode);
    3152                 :        2451 :   create_input_operand (&ops[1], rtx_op1, mode);
    3153                 :        2451 :   create_input_operand (&ops[2], rtx_op2, mode);
    3154                 :        2451 :   create_input_operand (&ops[3], mask, mask_mode);
    3155                 :        2451 :   expand_insn (icode, 4, ops);
    3156                 :        2451 :   if (!rtx_equal_p (ops[0].value, target))
    3157                 :           0 :     emit_move_insn (target, ops[0].value);
    3158                 :        2451 : }
    3159                 :             : 
    3160                 :             : /* Expand VEC_SET internal functions.  */
    3161                 :             : 
    3162                 :             : static void
    3163                 :         127 : expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
    3164                 :             : {
    3165                 :         127 :   tree lhs = gimple_call_lhs (stmt);
    3166                 :         127 :   tree op0 = gimple_call_arg (stmt, 0);
    3167                 :         127 :   tree op1 = gimple_call_arg (stmt, 1);
    3168                 :         127 :   tree op2 = gimple_call_arg (stmt, 2);
    3169                 :         127 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3170                 :         127 :   rtx src = expand_normal (op0);
    3171                 :             : 
    3172                 :         127 :   machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
    3173                 :         127 :   scalar_mode innermode = GET_MODE_INNER (outermode);
    3174                 :             : 
    3175                 :         127 :   rtx value = expand_normal (op1);
    3176                 :         127 :   rtx pos = expand_normal (op2);
    3177                 :             : 
    3178                 :         127 :   class expand_operand ops[3];
    3179                 :         127 :   enum insn_code icode = optab_handler (optab, outermode);
    3180                 :             : 
    3181                 :         127 :   if (icode != CODE_FOR_nothing)
    3182                 :             :     {
    3183                 :         127 :       rtx temp = gen_reg_rtx (outermode);
    3184                 :         127 :       emit_move_insn (temp, src);
    3185                 :             : 
    3186                 :         127 :       create_fixed_operand (&ops[0], temp);
    3187                 :         127 :       create_input_operand (&ops[1], value, innermode);
    3188                 :         127 :       create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
    3189                 :             :                                    true);
    3190                 :         127 :       if (maybe_expand_insn (icode, 3, ops))
    3191                 :             :         {
    3192                 :         127 :           emit_move_insn (target, temp);
    3193                 :         127 :           return;
    3194                 :             :         }
    3195                 :             :     }
    3196                 :           0 :   gcc_unreachable ();
    3197                 :             : }
    3198                 :             : 
    3199                 :             : static void
    3200                 :        1691 : expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
    3201                 :             : {
    3202                 :        1691 : }
    3203                 :             : 
    3204                 :             : static void
    3205                 :           0 : expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
    3206                 :             : {
    3207                 :             :   /* When guessing was done, the hints should be already stripped away.  */
    3208                 :           0 :   gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
    3209                 :             : 
    3210                 :           0 :   rtx target;
    3211                 :           0 :   tree lhs = gimple_call_lhs (stmt);
    3212                 :           0 :   if (lhs)
    3213                 :           0 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3214                 :             :   else
    3215                 :           0 :     target = const0_rtx;
    3216                 :           0 :   rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
    3217                 :           0 :   if (lhs && val != target)
    3218                 :           0 :     emit_move_insn (target, val);
    3219                 :           0 : }
    3220                 :             : 
    3221                 :             : /* IFN_VA_ARG is supposed to be expanded at pass_stdarg.  So this dummy function
    3222                 :             :    should never be called.  */
    3223                 :             : 
    3224                 :             : static void
    3225                 :           0 : expand_VA_ARG (internal_fn, gcall *)
    3226                 :             : {
    3227                 :           0 :   gcc_unreachable ();
    3228                 :             : }
    3229                 :             : 
    3230                 :             : /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector.  So this
    3231                 :             :    dummy function should never be called.  */
    3232                 :             : 
    3233                 :             : static void
    3234                 :           0 : expand_VEC_CONVERT (internal_fn, gcall *)
    3235                 :             : {
    3236                 :           0 :   gcc_unreachable ();
    3237                 :             : }
    3238                 :             : 
    3239                 :             : /* Expand IFN_RAWMEMCHR internal function.  */
    3240                 :             : 
    3241                 :             : void
    3242                 :           0 : expand_RAWMEMCHR (internal_fn, gcall *stmt)
    3243                 :             : {
    3244                 :           0 :   expand_operand ops[3];
    3245                 :             : 
    3246                 :           0 :   tree lhs = gimple_call_lhs (stmt);
    3247                 :           0 :   if (!lhs)
    3248                 :           0 :     return;
    3249                 :           0 :   machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
    3250                 :           0 :   rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3251                 :           0 :   create_output_operand (&ops[0], lhs_rtx, lhs_mode);
    3252                 :             : 
    3253                 :           0 :   tree mem = gimple_call_arg (stmt, 0);
    3254                 :           0 :   rtx mem_rtx = get_memory_rtx (mem, NULL);
    3255                 :           0 :   create_fixed_operand (&ops[1], mem_rtx);
    3256                 :             : 
    3257                 :           0 :   tree pattern = gimple_call_arg (stmt, 1);
    3258                 :           0 :   machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
    3259                 :           0 :   rtx pattern_rtx = expand_normal (pattern);
    3260                 :           0 :   create_input_operand (&ops[2], pattern_rtx, mode);
    3261                 :             : 
    3262                 :           0 :   insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
    3263                 :             : 
    3264                 :           0 :   expand_insn (icode, 3, ops);
    3265                 :           0 :   if (!rtx_equal_p (lhs_rtx, ops[0].value))
    3266                 :           0 :     emit_move_insn (lhs_rtx, ops[0].value);
    3267                 :             : }
    3268                 :             : 
    3269                 :             : /* Expand the IFN_UNIQUE function according to its first argument.  */
    3270                 :             : 
    3271                 :             : static void
    3272                 :           0 : expand_UNIQUE (internal_fn, gcall *stmt)
    3273                 :             : {
    3274                 :           0 :   rtx pattern = NULL_RTX;
    3275                 :           0 :   enum ifn_unique_kind kind
    3276                 :           0 :     = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
    3277                 :             : 
    3278                 :           0 :   switch (kind)
    3279                 :             :     {
    3280                 :           0 :     default:
    3281                 :           0 :       gcc_unreachable ();
    3282                 :             : 
    3283                 :           0 :     case IFN_UNIQUE_UNSPEC:
    3284                 :           0 :       if (targetm.have_unique ())
    3285                 :           0 :         pattern = targetm.gen_unique ();
    3286                 :             :       break;
    3287                 :             : 
    3288                 :           0 :     case IFN_UNIQUE_OACC_FORK:
    3289                 :           0 :     case IFN_UNIQUE_OACC_JOIN:
    3290                 :           0 :       if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
    3291                 :             :         {
    3292                 :           0 :           tree lhs = gimple_call_lhs (stmt);
    3293                 :           0 :           rtx target = const0_rtx;
    3294                 :             : 
    3295                 :           0 :           if (lhs)
    3296                 :           0 :             target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3297                 :             : 
    3298                 :           0 :           rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
    3299                 :           0 :           rtx axis = expand_normal (gimple_call_arg (stmt, 2));
    3300                 :             : 
    3301                 :           0 :           if (kind == IFN_UNIQUE_OACC_FORK)
    3302                 :           0 :             pattern = targetm.gen_oacc_fork (target, data_dep, axis);
    3303                 :             :           else
    3304                 :           0 :             pattern = targetm.gen_oacc_join (target, data_dep, axis);
    3305                 :             :         }
    3306                 :             :       else
    3307                 :           0 :         gcc_unreachable ();
    3308                 :             :       break;
    3309                 :             :     }
    3310                 :             : 
    3311                 :           0 :   if (pattern)
    3312                 :           0 :     emit_insn (pattern);
    3313                 :           0 : }
    3314                 :             : 
    3315                 :             : /* Expand the IFN_DEFERRED_INIT function:
    3316                 :             :    LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
    3317                 :             : 
    3318                 :             :    Initialize the LHS with zero/pattern according to its second argument
    3319                 :             :    INIT_TYPE:
    3320                 :             :    if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
    3321                 :             :    if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
    3322                 :             :      to initialize;
    3323                 :             :    The LHS variable is initialized including paddings.
    3324                 :             :    The reasons to choose 0xFE for pattern initialization are:
    3325                 :             :      1. It is a non-canonical virtual address on x86_64, and at the
    3326                 :             :         high end of the i386 kernel address space.
    3327                 :             :      2. It is a very large float value (-1.694739530317379e+38).
    3328                 :             :      3. It is also an unusual number for integers.  */
    3329                 :             : #define INIT_PATTERN_VALUE  0xFE
    3330                 :             : static void
    3331                 :         525 : expand_DEFERRED_INIT (internal_fn, gcall *stmt)
    3332                 :             : {
    3333                 :         525 :   tree lhs = gimple_call_lhs (stmt);
    3334                 :         525 :   tree var_size = gimple_call_arg (stmt, 0);
    3335                 :         525 :   enum auto_init_type init_type
    3336                 :         525 :     = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
    3337                 :         525 :   bool reg_lhs = true;
    3338                 :             : 
    3339                 :         525 :   tree var_type = TREE_TYPE (lhs);
    3340                 :         525 :   gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
    3341                 :             : 
    3342                 :         525 :   if (TREE_CODE (lhs) == SSA_NAME)
    3343                 :             :     reg_lhs = true;
    3344                 :             :   else
    3345                 :             :     {
    3346                 :             :       tree lhs_base = lhs;
    3347                 :         223 :       while (handled_component_p (lhs_base))
    3348                 :           1 :         lhs_base = TREE_OPERAND (lhs_base, 0);
    3349                 :         222 :       reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
    3350                 :         222 :                  || non_mem_decl_p (lhs_base));
    3351                 :             :       /* If this expands to a register and the underlying decl is wrapped in
    3352                 :             :          a MEM_REF that just serves as an access type change expose the decl
    3353                 :             :          if it is of correct size.  This avoids a situation as in PR103271
    3354                 :             :          if the target does not support a direct move to the registers mode.  */
    3355                 :           5 :       if (reg_lhs
    3356                 :           5 :           && TREE_CODE (lhs_base) == MEM_REF
    3357                 :           5 :           && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
    3358                 :           5 :           && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
    3359                 :           5 :           && integer_zerop (TREE_OPERAND (lhs_base, 1))
    3360                 :           5 :           && tree_fits_uhwi_p (var_size)
    3361                 :           5 :           && tree_int_cst_equal
    3362                 :           5 :                (var_size,
    3363                 :           5 :                 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
    3364                 :             :         {
    3365                 :           5 :           lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
    3366                 :           5 :           var_type = TREE_TYPE (lhs);
    3367                 :             :         }
    3368                 :             :     }
    3369                 :             : 
    3370                 :         525 :   if (!reg_lhs)
    3371                 :             :     {
    3372                 :             :       /* If the variable is not in register, expand to a memset
    3373                 :             :          to initialize it.  */
    3374                 :         217 :       mark_addressable (lhs);
    3375                 :         217 :       tree var_addr = build_fold_addr_expr (lhs);
    3376                 :             : 
    3377                 :         217 :       tree value = (init_type == AUTO_INIT_PATTERN)
    3378                 :         217 :                     ? build_int_cst (integer_type_node,
    3379                 :          93 :                                      INIT_PATTERN_VALUE)
    3380                 :         217 :                     : integer_zero_node;
    3381                 :         434 :       tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
    3382                 :             :                                      3, var_addr, value, var_size);
    3383                 :             :       /* Expand this memset call.  */
    3384                 :         217 :       expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
    3385                 :             :     }
    3386                 :             :   else
    3387                 :             :     {
    3388                 :             :       /* If this variable is in a register use expand_assignment.
    3389                 :             :          For boolean scalars force zero-init.  */
    3390                 :         308 :       tree init;
    3391                 :         308 :       scalar_int_mode var_mode;
    3392                 :         308 :       if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
    3393                 :         296 :           && tree_fits_uhwi_p (var_size)
    3394                 :         296 :           && (init_type == AUTO_INIT_PATTERN
    3395                 :         203 :               || !is_gimple_reg_type (var_type))
    3396                 :          98 :           && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
    3397                 :         314 :                                 0).exists (&var_mode)
    3398                 :         406 :           && have_insn_for (SET, var_mode))
    3399                 :             :         {
    3400                 :          92 :           unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
    3401                 :          92 :           unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
    3402                 :          92 :           memset (buf, (init_type == AUTO_INIT_PATTERN
    3403                 :             :                         ? INIT_PATTERN_VALUE : 0), total_bytes);
    3404                 :          92 :           tree itype = build_nonstandard_integer_type
    3405                 :          92 :                          (total_bytes * BITS_PER_UNIT, 1);
    3406                 :          92 :           wide_int w = wi::from_buffer (buf, total_bytes);
    3407                 :          92 :           init = wide_int_to_tree (itype, w);
    3408                 :             :           /* Pun the LHS to make sure its type has constant size
    3409                 :             :              unless it is an SSA name where that's already known.  */
    3410                 :          92 :           if (TREE_CODE (lhs) != SSA_NAME)
    3411                 :           5 :             lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
    3412                 :             :           else
    3413                 :          87 :             init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
    3414                 :          92 :         }
    3415                 :             :       else
    3416                 :             :         /* Use zero-init also for variable-length sizes.  */
    3417                 :         216 :         init = build_zero_cst (var_type);
    3418                 :             : 
    3419                 :         308 :       expand_assignment (lhs, init, false);
    3420                 :             :     }
    3421                 :         525 : }
    3422                 :             : 
    3423                 :             : /* The size of an OpenACC compute dimension.  */
    3424                 :             : 
    3425                 :             : static void
    3426                 :        5301 : expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
    3427                 :             : {
    3428                 :        5301 :   tree lhs = gimple_call_lhs (stmt);
    3429                 :             : 
    3430                 :        5301 :   if (!lhs)
    3431                 :             :     return;
    3432                 :             : 
    3433                 :        5301 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3434                 :        5301 :   if (targetm.have_oacc_dim_size ())
    3435                 :             :     {
    3436                 :           0 :       rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
    3437                 :             :                              VOIDmode, EXPAND_NORMAL);
    3438                 :           0 :       emit_insn (targetm.gen_oacc_dim_size (target, dim));
    3439                 :             :     }
    3440                 :             :   else
    3441                 :        5301 :     emit_move_insn (target, GEN_INT (1));
    3442                 :             : }
    3443                 :             : 
    3444                 :             : /* The position of an OpenACC execution engine along one compute axis.  */
    3445                 :             : 
    3446                 :             : static void
    3447                 :        4181 : expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
    3448                 :             : {
    3449                 :        4181 :   tree lhs = gimple_call_lhs (stmt);
    3450                 :             : 
    3451                 :        4181 :   if (!lhs)
    3452                 :             :     return;
    3453                 :             : 
    3454                 :        4181 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3455                 :        4181 :   if (targetm.have_oacc_dim_pos ())
    3456                 :             :     {
    3457                 :           0 :       rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
    3458                 :             :                              VOIDmode, EXPAND_NORMAL);
    3459                 :           0 :       emit_insn (targetm.gen_oacc_dim_pos (target, dim));
    3460                 :             :     }
    3461                 :             :   else
    3462                 :        4181 :     emit_move_insn (target, const0_rtx);
    3463                 :             : }
    3464                 :             : 
    3465                 :             : /* This is expanded by oacc_device_lower pass.  */
    3466                 :             : 
    3467                 :             : static void
    3468                 :           0 : expand_GOACC_LOOP (internal_fn, gcall *)
    3469                 :             : {
    3470                 :           0 :   gcc_unreachable ();
    3471                 :             : }
    3472                 :             : 
    3473                 :             : /* This is expanded by oacc_device_lower pass.  */
    3474                 :             : 
    3475                 :             : static void
    3476                 :           0 : expand_GOACC_REDUCTION (internal_fn, gcall *)
    3477                 :             : {
    3478                 :           0 :   gcc_unreachable ();
    3479                 :             : }
    3480                 :             : 
    3481                 :             : /* This is expanded by oacc_device_lower pass.  */
    3482                 :             : 
    3483                 :             : static void
    3484                 :           0 : expand_GOACC_TILE (internal_fn, gcall *)
    3485                 :             : {
    3486                 :           0 :   gcc_unreachable ();
    3487                 :             : }
    3488                 :             : 
    3489                 :             : /* Set errno to EDOM.  */
    3490                 :             : 
    3491                 :             : static void
    3492                 :           0 : expand_SET_EDOM (internal_fn, gcall *)
    3493                 :             : {
    3494                 :             : #ifdef TARGET_EDOM
    3495                 :             : #ifdef GEN_ERRNO_RTX
    3496                 :             :   rtx errno_rtx = GEN_ERRNO_RTX;
    3497                 :             : #else
    3498                 :             :   rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
    3499                 :             : #endif
    3500                 :             :   emit_move_insn (errno_rtx,
    3501                 :             :                   gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
    3502                 :             : #else
    3503                 :           0 :   gcc_unreachable ();
    3504                 :             : #endif
    3505                 :             : }
    3506                 :             : 
    3507                 :             : /* Expand atomic bit test and set.  */
    3508                 :             : 
    3509                 :             : static void
    3510                 :         153 : expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
    3511                 :             : {
    3512                 :         153 :   expand_ifn_atomic_bit_test_and (call);
    3513                 :         153 : }
    3514                 :             : 
    3515                 :             : /* Expand atomic bit test and complement.  */
    3516                 :             : 
    3517                 :             : static void
    3518                 :         156 : expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
    3519                 :             : {
    3520                 :         156 :   expand_ifn_atomic_bit_test_and (call);
    3521                 :         156 : }
    3522                 :             : 
    3523                 :             : /* Expand atomic bit test and reset.  */
    3524                 :             : 
    3525                 :             : static void
    3526                 :         141 : expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
    3527                 :             : {
    3528                 :         141 :   expand_ifn_atomic_bit_test_and (call);
    3529                 :         141 : }
    3530                 :             : 
    3531                 :             : /* Expand atomic bit test and set.  */
    3532                 :             : 
    3533                 :             : static void
    3534                 :       13603 : expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
    3535                 :             : {
    3536                 :       13603 :   expand_ifn_atomic_compare_exchange (call);
    3537                 :       13603 : }
    3538                 :             : 
    3539                 :             : /* Expand atomic add fetch and cmp with 0.  */
    3540                 :             : 
    3541                 :             : static void
    3542                 :         574 : expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
    3543                 :             : {
    3544                 :         574 :   expand_ifn_atomic_op_fetch_cmp_0 (call);
    3545                 :         574 : }
    3546                 :             : 
    3547                 :             : /* Expand atomic sub fetch and cmp with 0.  */
    3548                 :             : 
    3549                 :             : static void
    3550                 :         903 : expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
    3551                 :             : {
    3552                 :         903 :   expand_ifn_atomic_op_fetch_cmp_0 (call);
    3553                 :         903 : }
    3554                 :             : 
    3555                 :             : /* Expand atomic and fetch and cmp with 0.  */
    3556                 :             : 
    3557                 :             : static void
    3558                 :         176 : expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
    3559                 :             : {
    3560                 :         176 :   expand_ifn_atomic_op_fetch_cmp_0 (call);
    3561                 :         176 : }
    3562                 :             : 
    3563                 :             : /* Expand atomic or fetch and cmp with 0.  */
    3564                 :             : 
    3565                 :             : static void
    3566                 :         112 : expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
    3567                 :             : {
    3568                 :         112 :   expand_ifn_atomic_op_fetch_cmp_0 (call);
    3569                 :         112 : }
    3570                 :             : 
    3571                 :             : /* Expand atomic xor fetch and cmp with 0.  */
    3572                 :             : 
    3573                 :             : static void
    3574                 :         176 : expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
    3575                 :             : {
    3576                 :         176 :   expand_ifn_atomic_op_fetch_cmp_0 (call);
    3577                 :         176 : }
    3578                 :             : 
    3579                 :             : /* Expand LAUNDER to assignment, lhs = arg0.  */
    3580                 :             : 
    3581                 :             : static void
    3582                 :          31 : expand_LAUNDER (internal_fn, gcall *call)
    3583                 :             : {
    3584                 :          31 :   tree lhs = gimple_call_lhs (call);
    3585                 :             : 
    3586                 :          31 :   if (!lhs)
    3587                 :             :     return;
    3588                 :             : 
    3589                 :          30 :   expand_assignment (lhs, gimple_call_arg (call, 0), false);
    3590                 :             : }
    3591                 :             : 
    3592                 :             : /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB.  */
    3593                 :             : 
    3594                 :             : static void
    3595                 :           0 : expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
    3596                 :             : {
    3597                 :           0 :   internal_fn ifn = gimple_call_internal_fn (stmt);
    3598                 :           0 :   int rhs_index = internal_fn_stored_value_index (ifn);
    3599                 :           0 :   tree base = gimple_call_arg (stmt, 0);
    3600                 :           0 :   tree offset = gimple_call_arg (stmt, 1);
    3601                 :           0 :   tree scale = gimple_call_arg (stmt, 2);
    3602                 :           0 :   tree rhs = gimple_call_arg (stmt, rhs_index);
    3603                 :             : 
    3604                 :           0 :   rtx base_rtx = expand_normal (base);
    3605                 :           0 :   rtx offset_rtx = expand_normal (offset);
    3606                 :           0 :   HOST_WIDE_INT scale_int = tree_to_shwi (scale);
    3607                 :           0 :   rtx rhs_rtx = expand_normal (rhs);
    3608                 :             : 
    3609                 :           0 :   class expand_operand ops[8];
    3610                 :           0 :   int i = 0;
    3611                 :           0 :   create_address_operand (&ops[i++], base_rtx);
    3612                 :           0 :   create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
    3613                 :           0 :   create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
    3614                 :           0 :   create_integer_operand (&ops[i++], scale_int);
    3615                 :           0 :   create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
    3616                 :           0 :   i = add_mask_and_len_args (ops, i, stmt);
    3617                 :             : 
    3618                 :           0 :   insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
    3619                 :           0 :                                            TYPE_MODE (TREE_TYPE (offset)));
    3620                 :           0 :   expand_insn (icode, i, ops);
    3621                 :           0 : }
    3622                 :             : 
    3623                 :             : /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB.  */
    3624                 :             : 
    3625                 :             : static void
    3626                 :           0 : expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
    3627                 :             : {
    3628                 :           0 :   tree lhs = gimple_call_lhs (stmt);
    3629                 :           0 :   tree base = gimple_call_arg (stmt, 0);
    3630                 :           0 :   tree offset = gimple_call_arg (stmt, 1);
    3631                 :           0 :   tree scale = gimple_call_arg (stmt, 2);
    3632                 :             : 
    3633                 :           0 :   rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3634                 :           0 :   rtx base_rtx = expand_normal (base);
    3635                 :           0 :   rtx offset_rtx = expand_normal (offset);
    3636                 :           0 :   HOST_WIDE_INT scale_int = tree_to_shwi (scale);
    3637                 :             : 
    3638                 :           0 :   int i = 0;
    3639                 :           0 :   class expand_operand ops[8];
    3640                 :           0 :   create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
    3641                 :           0 :   create_address_operand (&ops[i++], base_rtx);
    3642                 :           0 :   create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
    3643                 :           0 :   create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
    3644                 :           0 :   create_integer_operand (&ops[i++], scale_int);
    3645                 :           0 :   i = add_mask_and_len_args (ops, i, stmt);
    3646                 :           0 :   insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
    3647                 :           0 :                                            TYPE_MODE (TREE_TYPE (offset)));
    3648                 :           0 :   expand_insn (icode, i, ops);
    3649                 :           0 :   if (!rtx_equal_p (lhs_rtx, ops[0].value))
    3650                 :           0 :     emit_move_insn (lhs_rtx, ops[0].value);
    3651                 :           0 : }
    3652                 :             : 
    3653                 :             : /* Helper for expand_DIVMOD.  Return true if the sequence starting with
    3654                 :             :    INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes.  */
    3655                 :             : 
    3656                 :             : static bool
    3657                 :         839 : contains_call_div_mod (rtx_insn *insn)
    3658                 :             : {
    3659                 :         839 :   subrtx_iterator::array_type array;
    3660                 :        4817 :   for (; insn; insn = NEXT_INSN (insn))
    3661                 :        4817 :     if (CALL_P (insn))
    3662                 :             :       return true;
    3663                 :        3978 :     else if (INSN_P (insn))
    3664                 :       17792 :       FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
    3665                 :       13814 :         switch (GET_CODE (*iter))
    3666                 :             :           {
    3667                 :           0 :           case CALL:
    3668                 :           0 :           case DIV:
    3669                 :           0 :           case UDIV:
    3670                 :           0 :           case MOD:
    3671                 :           0 :           case UMOD:
    3672                 :           0 :             return true;
    3673                 :       13814 :           default:
    3674                 :       13814 :             break;
    3675                 :             :           }
    3676                 :             :   return false;
    3677                 :         839 :  }
    3678                 :             : 
    3679                 :             : /* Expand DIVMOD() using:
    3680                 :             :  a) optab handler for udivmod/sdivmod if it is available.
    3681                 :             :  b) If optab_handler doesn't exist, generate call to
    3682                 :             :     target-specific divmod libfunc.  */
    3683                 :             : 
    3684                 :             : static void
    3685                 :       11025 : expand_DIVMOD (internal_fn, gcall *call_stmt)
    3686                 :             : {
    3687                 :       11025 :   tree lhs = gimple_call_lhs (call_stmt);
    3688                 :       11025 :   tree arg0 = gimple_call_arg (call_stmt, 0);
    3689                 :       11025 :   tree arg1 = gimple_call_arg (call_stmt, 1);
    3690                 :             : 
    3691                 :       11025 :   gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
    3692                 :       11025 :   tree type = TREE_TYPE (TREE_TYPE (lhs));
    3693                 :       11025 :   machine_mode mode = TYPE_MODE (type);
    3694                 :       11025 :   bool unsignedp = TYPE_UNSIGNED (type);
    3695                 :       11025 :   optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
    3696                 :             : 
    3697                 :       11025 :   rtx op0 = expand_normal (arg0);
    3698                 :       11025 :   rtx op1 = expand_normal (arg1);
    3699                 :       11025 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3700                 :             : 
    3701                 :       11025 :   rtx quotient = NULL_RTX, remainder = NULL_RTX;
    3702                 :       11025 :   rtx_insn *insns = NULL;
    3703                 :             : 
    3704                 :       11025 :   if (TREE_CODE (arg1) == INTEGER_CST)
    3705                 :             :     {
    3706                 :             :       /* For DIVMOD by integral constants, there could be efficient code
    3707                 :             :          expanded inline e.g. using shifts and plus/minus.  Try to expand
    3708                 :             :          the division and modulo and if it emits any library calls or any
    3709                 :             :          {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
    3710                 :             :          divmod libcall.  */
    3711                 :        1267 :       scalar_int_mode int_mode;
    3712                 :        1267 :       if (remainder == NULL_RTX
    3713                 :        1267 :           && optimize
    3714                 :        1267 :           && CONST_INT_P (op1)
    3715                 :        1265 :           && !pow2p_hwi (INTVAL (op1))
    3716                 :        2530 :           && is_int_mode (TYPE_MODE (type), &int_mode)
    3717                 :        1460 :           && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
    3718                 :        1265 :           && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
    3719                 :        1265 :           && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
    3720                 :        1265 :           && optimize_insn_for_speed_p ())
    3721                 :             :         {
    3722                 :        1260 :           rtx_insn *last = get_last_insn ();
    3723                 :        1260 :           remainder = NULL_RTX;
    3724                 :        3780 :           quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
    3725                 :        1260 :                                                TYPE_UNSIGNED (type));
    3726                 :        1260 :           if (quotient != NULL_RTX)
    3727                 :             :             {
    3728                 :         428 :               if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
    3729                 :             :                 {
    3730                 :         428 :                   rtx_insn *move = emit_move_insn (quotient, quotient);
    3731                 :         856 :                   set_dst_reg_note (move, REG_EQUAL,
    3732                 :         428 :                                     gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
    3733                 :             :                                                     ? UDIV : DIV, int_mode,
    3734                 :             :                                                     copy_rtx (op0), op1),
    3735                 :             :                                     quotient);
    3736                 :         428 :                   move = emit_move_insn (remainder, remainder);
    3737                 :         856 :                   set_dst_reg_note (move, REG_EQUAL,
    3738                 :         428 :                                     gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
    3739                 :             :                                                     ? UMOD : MOD, int_mode,
    3740                 :             :                                                     copy_rtx (op0), op1),
    3741                 :             :                                     quotient);
    3742                 :             :                 }
    3743                 :             :             }
    3744                 :             :           else
    3745                 :         832 :             delete_insns_since (last);
    3746                 :             :         }
    3747                 :             : 
    3748                 :        1267 :       if (remainder == NULL_RTX)
    3749                 :             :         {
    3750                 :         839 :           struct separate_ops ops;
    3751                 :         839 :           ops.code = TRUNC_DIV_EXPR;
    3752                 :         839 :           ops.type = type;
    3753                 :         839 :           ops.op0 = make_tree (ops.type, op0);
    3754                 :         839 :           ops.op1 = arg1;
    3755                 :         839 :           ops.op2 = NULL_TREE;
    3756                 :         839 :           ops.location = gimple_location (call_stmt);
    3757                 :         839 :           start_sequence ();
    3758                 :         839 :           quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
    3759                 :         839 :           if (contains_call_div_mod (get_insns ()))
    3760                 :         839 :             quotient = NULL_RTX;
    3761                 :             :           else
    3762                 :             :             {
    3763                 :           0 :               ops.code = TRUNC_MOD_EXPR;
    3764                 :           0 :               remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
    3765                 :             :                                               EXPAND_NORMAL);
    3766                 :           0 :               if (contains_call_div_mod (get_insns ()))
    3767                 :           0 :                 remainder = NULL_RTX;
    3768                 :             :             }
    3769                 :         839 :           if (remainder)
    3770                 :           0 :             insns = get_insns ();
    3771                 :         839 :           end_sequence ();
    3772                 :             :         }
    3773                 :             :     }
    3774                 :             : 
    3775                 :       11025 :   if (remainder)
    3776                 :         428 :     emit_insn (insns);
    3777                 :             : 
    3778                 :             :   /* Check if optab_handler exists for divmod_optab for given mode.  */
    3779                 :       10597 :   else if (optab_handler (tab, mode) != CODE_FOR_nothing)
    3780                 :             :     {
    3781                 :        9703 :       quotient = gen_reg_rtx (mode);
    3782                 :        9703 :       remainder = gen_reg_rtx (mode);
    3783                 :        9703 :       expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
    3784                 :             :     }
    3785                 :             : 
    3786                 :             :   /* Generate call to divmod libfunc if it exists.  */
    3787                 :         894 :   else if (rtx libfunc = optab_libfunc (tab, mode))
    3788                 :         894 :     targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
    3789                 :             :                                    &quotient, &remainder);
    3790                 :             : 
    3791                 :             :   else
    3792                 :           0 :     gcc_unreachable ();
    3793                 :             : 
    3794                 :             :   /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR.  */
    3795                 :       22050 :   expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
    3796                 :       11025 :                        make_tree (TREE_TYPE (arg0), quotient),
    3797                 :       11025 :                        make_tree (TREE_TYPE (arg1), remainder)),
    3798                 :             :                target, VOIDmode, EXPAND_NORMAL);
    3799                 :       11025 : }
    3800                 :             : 
    3801                 :             : /* Expand a NOP.  */
    3802                 :             : 
    3803                 :             : static void
    3804                 :           1 : expand_NOP (internal_fn, gcall *)
    3805                 :             : {
    3806                 :             :   /* Nothing.  But it shouldn't really prevail.  */
    3807                 :           1 : }
    3808                 :             : 
    3809                 :             : /* Coroutines, all should have been processed at this stage.  */
    3810                 :             : 
    3811                 :             : static void
    3812                 :           0 : expand_CO_FRAME (internal_fn, gcall *)
    3813                 :             : {
    3814                 :           0 :   gcc_unreachable ();
    3815                 :             : }
    3816                 :             : 
    3817                 :             : static void
    3818                 :           0 : expand_CO_YIELD (internal_fn, gcall *)
    3819                 :             : {
    3820                 :           0 :   gcc_unreachable ();
    3821                 :             : }
    3822                 :             : 
    3823                 :             : static void
    3824                 :           0 : expand_CO_SUSPN (internal_fn, gcall *)
    3825                 :             : {
    3826                 :           0 :   gcc_unreachable ();
    3827                 :             : }
    3828                 :             : 
    3829                 :             : static void
    3830                 :           0 : expand_CO_ACTOR (internal_fn, gcall *)
    3831                 :             : {
    3832                 :           0 :   gcc_unreachable ();
    3833                 :             : }
    3834                 :             : 
    3835                 :             : /* Expand a call to FN using the operands in STMT.  FN has a single
    3836                 :             :    output operand and NARGS input operands.  */
    3837                 :             : 
    3838                 :             : static void
    3839                 :       70590 : expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
    3840                 :             :                         unsigned int nargs)
    3841                 :             : {
    3842                 :       70590 :   tree_pair types = direct_internal_fn_types (fn, stmt);
    3843                 :       70590 :   insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
    3844                 :       70590 :   expand_fn_using_insn (stmt, icode, 1, nargs);
    3845                 :       70590 : }
    3846                 :             : 
    3847                 :             : /* Expand WHILE_ULT call STMT using optab OPTAB.  */
    3848                 :             : 
    3849                 :             : static void
    3850                 :           0 : expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
    3851                 :             : {
    3852                 :           0 :   expand_operand ops[4];
    3853                 :           0 :   tree rhs_type[2];
    3854                 :             : 
    3855                 :           0 :   tree lhs = gimple_call_lhs (stmt);
    3856                 :           0 :   tree lhs_type = TREE_TYPE (lhs);
    3857                 :           0 :   rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    3858                 :           0 :   create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
    3859                 :             : 
    3860                 :           0 :   for (unsigned int i = 0; i < 2; ++i)
    3861                 :             :     {
    3862                 :           0 :       tree rhs = gimple_call_arg (stmt, i);
    3863                 :           0 :       rhs_type[i] = TREE_TYPE (rhs);
    3864                 :           0 :       rtx rhs_rtx = expand_normal (rhs);
    3865                 :           0 :       create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
    3866                 :             :     }
    3867                 :             : 
    3868                 :           0 :   int opcnt;
    3869                 :           0 :   if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
    3870                 :             :     {
    3871                 :             :       /* When the mask is an integer mode the exact vector length may not
    3872                 :             :          be clear to the backend, so we pass it in operand[3].
    3873                 :             :          Use the vector in arg2 for the most reliable intended size.  */
    3874                 :           0 :       tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
    3875                 :           0 :       create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
    3876                 :           0 :       opcnt = 4;
    3877                 :             :     }
    3878                 :             :   else
    3879                 :             :     /* The mask has a vector type so the length operand is unnecessary.  */
    3880                 :             :     opcnt = 3;
    3881                 :             : 
    3882                 :           0 :   insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
    3883                 :           0 :                                            TYPE_MODE (lhs_type));
    3884                 :             : 
    3885                 :           0 :   expand_insn (icode, opcnt, ops);
    3886                 :           0 :   if (!rtx_equal_p (lhs_rtx, ops[0].value))
    3887                 :           0 :     emit_move_insn (lhs_rtx, ops[0].value);
    3888                 :           0 : }
    3889                 :             : 
    3890                 :             : /* Expand a call to a convert-like optab using the operands in STMT.
    3891                 :             :    FN has a single output operand and NARGS input operands.  */
    3892                 :             : 
    3893                 :             : static void
    3894                 :         310 : expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
    3895                 :             :                          unsigned int nargs)
    3896                 :             : {
    3897                 :         310 :   tree_pair types = direct_internal_fn_types (fn, stmt);
    3898                 :         310 :   insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
    3899                 :         310 :                                           TYPE_MODE (types.second));
    3900                 :         310 :   expand_fn_using_insn (stmt, icode, 1, nargs);
    3901                 :         310 : }
    3902                 :             : 
    3903                 :             : /* Expanders for optabs that can use expand_direct_optab_fn.  */
    3904                 :             : 
    3905                 :             : #define expand_unary_optab_fn(FN, STMT, OPTAB) \
    3906                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 1)
    3907                 :             : 
    3908                 :             : #define expand_binary_optab_fn(FN, STMT, OPTAB) \
    3909                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 2)
    3910                 :             : 
    3911                 :             : #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
    3912                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
    3913                 :             : 
    3914                 :             : #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
    3915                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
    3916                 :             : 
    3917                 :             : #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
    3918                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 4)
    3919                 :             : 
    3920                 :             : #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
    3921                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 5)
    3922                 :             : 
    3923                 :             : #define expand_cond_len_unary_optab_fn(FN, STMT, OPTAB) \
    3924                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 5)
    3925                 :             : 
    3926                 :             : #define expand_cond_len_binary_optab_fn(FN, STMT, OPTAB) \
    3927                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 6)
    3928                 :             : 
    3929                 :             : #define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
    3930                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 7)
    3931                 :             : 
    3932                 :             : #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
    3933                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
    3934                 :             : 
    3935                 :             : #define expand_fold_len_extract_optab_fn(FN, STMT, OPTAB) \
    3936                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 5)
    3937                 :             : 
    3938                 :             : #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
    3939                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 2)
    3940                 :             : 
    3941                 :             : #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
    3942                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
    3943                 :             : 
    3944                 :             : #define expand_mask_len_fold_left_optab_fn(FN, STMT, OPTAB) \
    3945                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 5)
    3946                 :             : 
    3947                 :             : #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
    3948                 :             :   expand_direct_optab_fn (FN, STMT, OPTAB, 4)
    3949                 :             : 
    3950                 :             : /* Expanders for optabs that can use expand_convert_optab_fn.  */
    3951                 :             : 
    3952                 :             : #define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
    3953                 :             :   expand_convert_optab_fn (FN, STMT, OPTAB, 1)
    3954                 :             : 
    3955                 :             : #define expand_vec_extract_optab_fn(FN, STMT, OPTAB) \
    3956                 :             :   expand_convert_optab_fn (FN, STMT, OPTAB, 2)
    3957                 :             : 
    3958                 :             : /* RETURN_TYPE and ARGS are a return type and argument list that are
    3959                 :             :    in principle compatible with FN (which satisfies direct_internal_fn_p).
    3960                 :             :    Return the types that should be used to determine whether the
    3961                 :             :    target supports FN.  */
    3962                 :             : 
    3963                 :             : tree_pair
    3964                 :        7779 : direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
    3965                 :             : {
    3966                 :        7779 :   const direct_internal_fn_info &info = direct_internal_fn (fn);
    3967                 :        7779 :   tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
    3968                 :        7779 :   tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
    3969                 :        7779 :   return tree_pair (type0, type1);
    3970                 :             : }
    3971                 :             : 
    3972                 :             : /* CALL is a call whose return type and arguments are in principle
    3973                 :             :    compatible with FN (which satisfies direct_internal_fn_p).  Return the
    3974                 :             :    types that should be used to determine whether the target supports FN.  */
    3975                 :             : 
    3976                 :             : tree_pair
    3977                 :      130547 : direct_internal_fn_types (internal_fn fn, gcall *call)
    3978                 :             : {
    3979                 :      130547 :   const direct_internal_fn_info &info = direct_internal_fn (fn);
    3980                 :      130547 :   tree op0 = (info.type0 < 0
    3981                 :      130547 :               ? gimple_call_lhs (call)
    3982                 :      129500 :               : gimple_call_arg (call, info.type0));
    3983                 :      130547 :   tree op1 = (info.type1 < 0
    3984                 :      130547 :               ? gimple_call_lhs (call)
    3985                 :      130547 :               : gimple_call_arg (call, info.type1));
    3986                 :      130547 :   return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
    3987                 :             : }
    3988                 :             : 
    3989                 :             : /* Return true if OPTAB is supported for TYPES (whose modes should be
    3990                 :             :    the same) when the optimization type is OPT_TYPE.  Used for simple
    3991                 :             :    direct optabs.  */
    3992                 :             : 
    3993                 :             : static bool
    3994                 :     4713276 : direct_optab_supported_p (direct_optab optab, tree_pair types,
    3995                 :             :                           optimization_type opt_type)
    3996                 :             : {
    3997                 :     4713276 :   machine_mode mode = TYPE_MODE (types.first);
    3998                 :     4713276 :   gcc_checking_assert (mode == TYPE_MODE (types.second));
    3999                 :     4713276 :   return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
    4000                 :             : }
    4001                 :             : 
    4002                 :             : /* Return true if OPTAB is supported for TYPES, where the first type
    4003                 :             :    is the destination and the second type is the source.  Used for
    4004                 :             :    convert optabs.  */
    4005                 :             : 
    4006                 :             : static bool
    4007                 :         947 : convert_optab_supported_p (convert_optab optab, tree_pair types,
    4008                 :             :                            optimization_type opt_type)
    4009                 :             : {
    4010                 :         947 :   return (convert_optab_handler (optab, TYPE_MODE (types.first),
    4011                 :         947 :                                  TYPE_MODE (types.second), opt_type)
    4012                 :         947 :           != CODE_FOR_nothing);
    4013                 :             : }
    4014                 :             : 
    4015                 :             : /* Return true if load/store lanes optab OPTAB is supported for
    4016                 :             :    array type TYPES.first when the optimization type is OPT_TYPE.  */
    4017                 :             : 
    4018                 :             : static bool
    4019                 :           0 : multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
    4020                 :             :                                 optimization_type opt_type)
    4021                 :             : {
    4022                 :           0 :   gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
    4023                 :           0 :   machine_mode imode = TYPE_MODE (types.first);
    4024                 :           0 :   machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
    4025                 :           0 :   return (convert_optab_handler (optab, imode, vmode, opt_type)
    4026                 :           0 :           != CODE_FOR_nothing);
    4027                 :             : }
    4028                 :             : 
    4029                 :             : #define direct_unary_optab_supported_p direct_optab_supported_p
    4030                 :             : #define direct_unary_convert_optab_supported_p convert_optab_supported_p
    4031                 :             : #define direct_binary_optab_supported_p direct_optab_supported_p
    4032                 :             : #define direct_ternary_optab_supported_p direct_optab_supported_p
    4033                 :             : #define direct_cond_unary_optab_supported_p direct_optab_supported_p
    4034                 :             : #define direct_cond_binary_optab_supported_p direct_optab_supported_p
    4035                 :             : #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
    4036                 :             : #define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
    4037                 :             : #define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
    4038                 :             : #define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
    4039                 :             : #define direct_mask_load_optab_supported_p convert_optab_supported_p
    4040                 :             : #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
    4041                 :             : #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
    4042                 :             : #define direct_gather_load_optab_supported_p convert_optab_supported_p
    4043                 :             : #define direct_len_load_optab_supported_p direct_optab_supported_p
    4044                 :             : #define direct_mask_len_load_optab_supported_p convert_optab_supported_p
    4045                 :             : #define direct_mask_store_optab_supported_p convert_optab_supported_p
    4046                 :             : #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
    4047                 :             : #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
    4048                 :             : #define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
    4049                 :             : #define direct_vec_cond_optab_supported_p convert_optab_supported_p
    4050                 :             : #define direct_scatter_store_optab_supported_p convert_optab_supported_p
    4051                 :             : #define direct_len_store_optab_supported_p direct_optab_supported_p
    4052                 :             : #define direct_mask_len_store_optab_supported_p convert_optab_supported_p
    4053                 :             : #define direct_while_optab_supported_p convert_optab_supported_p
    4054                 :             : #define direct_fold_extract_optab_supported_p direct_optab_supported_p
    4055                 :             : #define direct_fold_len_extract_optab_supported_p direct_optab_supported_p
    4056                 :             : #define direct_fold_left_optab_supported_p direct_optab_supported_p
    4057                 :             : #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
    4058                 :             : #define direct_mask_len_fold_left_optab_supported_p direct_optab_supported_p
    4059                 :             : #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
    4060                 :             : #define direct_vec_set_optab_supported_p direct_optab_supported_p
    4061                 :             : #define direct_vec_extract_optab_supported_p convert_optab_supported_p
    4062                 :             : 
    4063                 :             : /* Return the optab used by internal function FN.  */
    4064                 :             : 
    4065                 :             : optab
    4066                 :      195419 : direct_internal_fn_optab (internal_fn fn, tree_pair types)
    4067                 :             : {
    4068                 :      195419 :   switch (fn)
    4069                 :             :     {
    4070                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
    4071                 :             :     case IFN_##CODE: break;
    4072                 :             : #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
    4073                 :             :     case IFN_##CODE: return OPTAB##_optab;
    4074                 :             : #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
    4075                 :             :                                      UNSIGNED_OPTAB, TYPE)              \
    4076                 :             :     case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR)             \
    4077                 :             :                              ? UNSIGNED_OPTAB ## _optab                 \
    4078                 :             :                              : SIGNED_OPTAB ## _optab);
    4079                 :             : #include "internal-fn.def"
    4080                 :             : 
    4081                 :             :     case IFN_LAST:
    4082                 :             :       break;
    4083                 :             :     }
    4084                 :           0 :   gcc_unreachable ();
    4085                 :             : }
    4086                 :             : 
    4087                 :             : /* Return the optab used by internal function FN.  */
    4088                 :             : 
    4089                 :             : static optab
    4090                 :       84352 : direct_internal_fn_optab (internal_fn fn)
    4091                 :             : {
    4092                 :       84352 :   switch (fn)
    4093                 :             :     {
    4094                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
    4095                 :             :     case IFN_##CODE: break;
    4096                 :             : #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
    4097                 :             :     case IFN_##CODE: return OPTAB##_optab;
    4098                 :             : #include "internal-fn.def"
    4099                 :             : 
    4100                 :             :     case IFN_LAST:
    4101                 :             :       break;
    4102                 :             :     }
    4103                 :           0 :   gcc_unreachable ();
    4104                 :             : }
    4105                 :             : 
    4106                 :             : /* Return true if FN is supported for the types in TYPES when the
    4107                 :             :    optimization type is OPT_TYPE.  The types are those associated with
    4108                 :             :    the "type0" and "type1" fields of FN's direct_internal_fn_info
    4109                 :             :    structure.  */
    4110                 :             : 
    4111                 :             : bool
    4112                 :     4714223 : direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
    4113                 :             :                                 optimization_type opt_type)
    4114                 :             : {
    4115                 :     4714223 :   switch (fn)
    4116                 :             :     {
    4117                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
    4118                 :             :     case IFN_##CODE: break;
    4119                 :             : #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
    4120                 :             :     case IFN_##CODE: \
    4121                 :             :       return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
    4122                 :             :                                                 opt_type);
    4123                 :             : #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
    4124                 :             :                                      UNSIGNED_OPTAB, TYPE)              \
    4125                 :             :     case IFN_##CODE:                                                    \
    4126                 :             :       {                                                                 \
    4127                 :             :         optab which_optab = (TYPE_UNSIGNED (types.SELECTOR)             \
    4128                 :             :                              ? UNSIGNED_OPTAB ## _optab                 \
    4129                 :             :                              : SIGNED_OPTAB ## _optab);                 \
    4130                 :             :         return direct_##TYPE##_optab_supported_p (which_optab, types,   \
    4131                 :             :                                                   opt_type);            \
    4132                 :             :       }
    4133                 :             : #include "internal-fn.def"
    4134                 :             : 
    4135                 :             :     case IFN_LAST:
    4136                 :             :       break;
    4137                 :             :     }
    4138                 :           0 :   gcc_unreachable ();
    4139                 :             : }
    4140                 :             : 
    4141                 :             : /* Return true if FN is supported for type TYPE when the optimization
    4142                 :             :    type is OPT_TYPE.  The caller knows that the "type0" and "type1"
    4143                 :             :    fields of FN's direct_internal_fn_info structure are the same.  */
    4144                 :             : 
    4145                 :             : bool
    4146                 :     4640213 : direct_internal_fn_supported_p (internal_fn fn, tree type,
    4147                 :             :                                 optimization_type opt_type)
    4148                 :             : {
    4149                 :     4640213 :   const direct_internal_fn_info &info = direct_internal_fn (fn);
    4150                 :     4640213 :   gcc_checking_assert (info.type0 == info.type1);
    4151                 :     4640213 :   return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
    4152                 :             : }
    4153                 :             : 
    4154                 :             : /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
    4155                 :             :    given that STMT is a call to a direct internal function.  */
    4156                 :             : 
    4157                 :             : bool
    4158                 :         428 : direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
    4159                 :             : {
    4160                 :         428 :   internal_fn fn = gimple_call_internal_fn (stmt);
    4161                 :         428 :   tree_pair types = direct_internal_fn_types (fn, stmt);
    4162                 :         428 :   return direct_internal_fn_supported_p (fn, types, opt_type);
    4163                 :             : }
    4164                 :             : 
    4165                 :             : /* Return true if FN is a binary operation and if FN is commutative.  */
    4166                 :             : 
    4167                 :             : bool
    4168                 :    30380038 : commutative_binary_fn_p (internal_fn fn)
    4169                 :             : {
    4170                 :    30380038 :   switch (fn)
    4171                 :             :     {
    4172                 :             :     case IFN_AVG_FLOOR:
    4173                 :             :     case IFN_AVG_CEIL:
    4174                 :             :     case IFN_MULH:
    4175                 :             :     case IFN_MULHS:
    4176                 :             :     case IFN_MULHRS:
    4177                 :             :     case IFN_FMIN:
    4178                 :             :     case IFN_FMAX:
    4179                 :             :     case IFN_COMPLEX_MUL:
    4180                 :             :     case IFN_UBSAN_CHECK_ADD:
    4181                 :             :     case IFN_UBSAN_CHECK_MUL:
    4182                 :             :     case IFN_ADD_OVERFLOW:
    4183                 :             :     case IFN_MUL_OVERFLOW:
    4184                 :             :     case IFN_VEC_WIDEN_PLUS:
    4185                 :             :     case IFN_VEC_WIDEN_PLUS_LO:
    4186                 :             :     case IFN_VEC_WIDEN_PLUS_HI:
    4187                 :             :     case IFN_VEC_WIDEN_PLUS_EVEN:
    4188                 :             :     case IFN_VEC_WIDEN_PLUS_ODD:
    4189                 :             :       return true;
    4190                 :             : 
    4191                 :    29504593 :     default:
    4192                 :    29504593 :       return false;
    4193                 :             :     }
    4194                 :             : }
    4195                 :             : 
    4196                 :             : /* Return true if FN is a ternary operation and if its first two arguments
    4197                 :             :    are commutative.  */
    4198                 :             : 
    4199                 :             : bool
    4200                 :    24257784 : commutative_ternary_fn_p (internal_fn fn)
    4201                 :             : {
    4202                 :    24257784 :   switch (fn)
    4203                 :             :     {
    4204                 :             :     case IFN_FMA:
    4205                 :             :     case IFN_FMS:
    4206                 :             :     case IFN_FNMA:
    4207                 :             :     case IFN_FNMS:
    4208                 :             :     case IFN_UADDC:
    4209                 :             :       return true;
    4210                 :             : 
    4211                 :    24136610 :     default:
    4212                 :    24136610 :       return false;
    4213                 :             :     }
    4214                 :             : }
    4215                 :             : 
    4216                 :             : /* Return true if FN is an associative binary operation.  */
    4217                 :             : 
    4218                 :             : bool
    4219                 :          33 : associative_binary_fn_p (internal_fn fn)
    4220                 :             : {
    4221                 :          33 :   switch (fn)
    4222                 :             :     {
    4223                 :             :     case IFN_FMIN:
    4224                 :             :     case IFN_FMAX:
    4225                 :             :       return true;
    4226                 :             : 
    4227                 :           0 :     default:
    4228                 :           0 :       return false;
    4229                 :             :     }
    4230                 :             : }
    4231                 :             : 
    4232                 :             : /* If FN is commutative in two consecutive arguments, return the
    4233                 :             :    index of the first, otherwise return -1.  */
    4234                 :             : 
    4235                 :             : int
    4236                 :    24570430 : first_commutative_argument (internal_fn fn)
    4237                 :             : {
    4238                 :    24570430 :   switch (fn)
    4239                 :             :     {
    4240                 :             :     case IFN_COND_ADD:
    4241                 :             :     case IFN_COND_MUL:
    4242                 :             :     case IFN_COND_MIN:
    4243                 :             :     case IFN_COND_MAX:
    4244                 :             :     case IFN_COND_FMIN:
    4245                 :             :     case IFN_COND_FMAX:
    4246                 :             :     case IFN_COND_AND:
    4247                 :             :     case IFN_COND_IOR:
    4248                 :             :     case IFN_COND_XOR:
    4249                 :             :     case IFN_COND_FMA:
    4250                 :             :     case IFN_COND_FMS:
    4251                 :             :     case IFN_COND_FNMA:
    4252                 :             :     case IFN_COND_FNMS:
    4253                 :             :     case IFN_COND_LEN_ADD:
    4254                 :             :     case IFN_COND_LEN_MUL:
    4255                 :             :     case IFN_COND_LEN_MIN:
    4256                 :             :     case IFN_COND_LEN_MAX:
    4257                 :             :     case IFN_COND_LEN_FMIN:
    4258                 :             :     case IFN_COND_LEN_FMAX:
    4259                 :             :     case IFN_COND_LEN_AND:
    4260                 :             :     case IFN_COND_LEN_IOR:
    4261                 :             :     case IFN_COND_LEN_XOR:
    4262                 :             :     case IFN_COND_LEN_FMA:
    4263                 :             :     case IFN_COND_LEN_FMS:
    4264                 :             :     case IFN_COND_LEN_FNMA:
    4265                 :             :     case IFN_COND_LEN_FNMS:
    4266                 :             :       return 1;
    4267                 :             : 
    4268                 :    24558362 :     default:
    4269                 :    24558362 :       if (commutative_binary_fn_p (fn)
    4270                 :    24558362 :           || commutative_ternary_fn_p (fn))
    4271                 :      421752 :         return 0;
    4272                 :             :       return -1;
    4273                 :             :     }
    4274                 :             : }
    4275                 :             : 
    4276                 :             : /* Return true if this CODE describes an internal_fn that returns a vector with
    4277                 :             :    elements twice as wide as the element size of the input vectors.  */
    4278                 :             : 
    4279                 :             : bool
    4280                 :     1316408 : widening_fn_p (code_helper code)
    4281                 :             : {
    4282                 :     1316408 :   if (!code.is_fn_code ())
    4283                 :             :     return false;
    4284                 :             : 
    4285                 :      149286 :   if (!internal_fn_p ((combined_fn) code))
    4286                 :             :     return false;
    4287                 :             : 
    4288                 :      149286 :   internal_fn fn = as_internal_fn ((combined_fn) code);
    4289                 :      149286 :   switch (fn)
    4290                 :             :     {
    4291                 :             :     #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
    4292                 :             :     case IFN_##NAME:                                              \
    4293                 :             :     case IFN_##NAME##_HI:                                         \
    4294                 :             :     case IFN_##NAME##_LO:                                         \
    4295                 :             :     case IFN_##NAME##_EVEN:                                       \
    4296                 :             :     case IFN_##NAME##_ODD:                                        \
    4297                 :             :       return true;
    4298                 :             :     #include "internal-fn.def"
    4299                 :             : 
    4300                 :             :     default:
    4301                 :             :       return false;
    4302                 :             :     }
    4303                 :             : }
    4304                 :             : 
    4305                 :             : /* Return true if IFN_SET_EDOM is supported.  */
    4306                 :             : 
    4307                 :             : bool
    4308                 :         134 : set_edom_supported_p (void)
    4309                 :             : {
    4310                 :             : #ifdef TARGET_EDOM
    4311                 :             :   return true;
    4312                 :             : #else
    4313                 :         134 :   return false;
    4314                 :             : #endif
    4315                 :             : }
    4316                 :             : 
    4317                 :             : #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
    4318                 :             :   static void                                           \
    4319                 :             :   expand_##CODE (internal_fn fn, gcall *stmt)           \
    4320                 :             :   {                                                     \
    4321                 :             :     expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
    4322                 :             :   }
    4323                 :             : #define DEF_INTERNAL_INT_EXT_FN(CODE, FLAGS, OPTAB, TYPE)
    4324                 :             : #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
    4325                 :             :                                      UNSIGNED_OPTAB, TYPE)              \
    4326                 :             :   static void                                                           \
    4327                 :             :   expand_##CODE (internal_fn fn, gcall *stmt)                           \
    4328                 :             :   {                                                                     \
    4329                 :             :     tree_pair types = direct_internal_fn_types (fn, stmt);              \
    4330                 :             :     optab which_optab = direct_internal_fn_optab (fn, types);           \
    4331                 :             :     expand_##TYPE##_optab_fn (fn, stmt, which_optab);                   \
    4332                 :             :   }
    4333                 :             : #include "internal-fn.def"
    4334                 :             : 
    4335                 :             : /* Routines to expand each internal function, indexed by function number.
    4336                 :             :    Each routine has the prototype:
    4337                 :             : 
    4338                 :             :        expand_<NAME> (gcall *stmt)
    4339                 :             : 
    4340                 :             :    where STMT is the statement that performs the call. */
    4341                 :             : static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
    4342                 :             : 
    4343                 :             : #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
    4344                 :             : #include "internal-fn.def"
    4345                 :             :   0
    4346                 :             : };
    4347                 :             : 
    4348                 :             : /* Invoke T(CODE, SUFFIX) for each conditional function IFN_COND_##SUFFIX
    4349                 :             :    that maps to a tree code CODE.  There is also an IFN_COND_LEN_##SUFFIX
    4350                 :             :    for each such IFN_COND_##SUFFIX.  */
    4351                 :             : #define FOR_EACH_CODE_MAPPING(T) \
    4352                 :             :   T (PLUS_EXPR, ADD) \
    4353                 :             :   T (MINUS_EXPR, SUB) \
    4354                 :             :   T (MULT_EXPR, MUL) \
    4355                 :             :   T (TRUNC_DIV_EXPR, DIV) \
    4356                 :             :   T (TRUNC_MOD_EXPR, MOD) \
    4357                 :             :   T (RDIV_EXPR, RDIV) \
    4358                 :             :   T (MIN_EXPR, MIN) \
    4359                 :             :   T (MAX_EXPR, MAX) \
    4360                 :             :   T (BIT_AND_EXPR, AND) \
    4361                 :             :   T (BIT_IOR_EXPR, IOR) \
    4362                 :             :   T (BIT_XOR_EXPR, XOR) \
    4363                 :             :   T (LSHIFT_EXPR, SHL) \
    4364                 :             :   T (RSHIFT_EXPR, SHR) \
    4365                 :             :   T (NEGATE_EXPR, NEG)
    4366                 :             : 
    4367                 :             : /* Return a function that only performs CODE when a certain condition is met
    4368                 :             :    and that uses a given fallback value otherwise.  For example, if CODE is
    4369                 :             :    a binary operation associated with conditional function FN:
    4370                 :             : 
    4371                 :             :      LHS = FN (COND, A, B, ELSE)
    4372                 :             : 
    4373                 :             :    is equivalent to the C expression:
    4374                 :             : 
    4375                 :             :      LHS = COND ? A CODE B : ELSE;
    4376                 :             : 
    4377                 :             :    operating elementwise if the operands are vectors.
    4378                 :             : 
    4379                 :             :    Return IFN_LAST if no such function exists.  */
    4380                 :             : 
    4381                 :             : internal_fn
    4382                 :      455401 : get_conditional_internal_fn (tree_code code)
    4383                 :             : {
    4384                 :      455401 :   switch (code)
    4385                 :             :     {
    4386                 :             : #define CASE(CODE, IFN) case CODE: return IFN_COND_##IFN;
    4387                 :             :       FOR_EACH_CODE_MAPPING(CASE)
    4388                 :             : #undef CASE
    4389                 :             :     default:
    4390                 :             :       return IFN_LAST;
    4391                 :             :     }
    4392                 :             : }
    4393                 :             : 
    4394                 :             : /* If IFN implements the conditional form of a tree code, return that
    4395                 :             :    tree code, otherwise return ERROR_MARK.  */
    4396                 :             : 
    4397                 :             : tree_code
    4398                 :     2411845 : conditional_internal_fn_code (internal_fn ifn)
    4399                 :             : {
    4400                 :     2411845 :   switch (ifn)
    4401                 :             :     {
    4402                 :             : #define CASE(CODE, IFN)                                                        \
    4403                 :             :   case IFN_COND_##IFN:                                                         \
    4404                 :             :   case IFN_COND_LEN_##IFN:                                                     \
    4405                 :             :     return CODE;
    4406                 :             :       FOR_EACH_CODE_MAPPING (CASE)
    4407                 :             : #undef CASE
    4408                 :             :       default:
    4409                 :             :         return ERROR_MARK;
    4410                 :             :     }
    4411                 :             : }
    4412                 :             : 
    4413                 :             : /* Like get_conditional_internal_fn, but return a function that
    4414                 :             :    additionally restricts the operation to the leading elements
    4415                 :             :    of a vector.  The number of elements to process is given by a length
    4416                 :             :    and bias pair, as for IFN_LOAD_LEN.  The values of the remaining
    4417                 :             :    elements are taken from the fallback ("else") argument.
    4418                 :             : 
    4419                 :             :    For example, if CODE is a binary operation associated with FN:
    4420                 :             : 
    4421                 :             :      LHS = FN (COND, A, B, ELSE, LEN, BIAS)
    4422                 :             : 
    4423                 :             :    is equivalent to the C code:
    4424                 :             : 
    4425                 :             :      for (int i = 0; i < NUNITS; i++)
    4426                 :             :       {
    4427                 :             :         if (i < LEN + BIAS && COND[i])
    4428                 :             :           LHS[i] = A[i] CODE B[i];
    4429                 :             :         else
    4430                 :             :           LHS[i] = ELSE[i];
    4431                 :             :       }
    4432                 :             : */
    4433                 :             : 
    4434                 :             : internal_fn
    4435                 :      438543 : get_conditional_len_internal_fn (tree_code code)
    4436                 :             : {
    4437                 :      438543 :   switch (code)
    4438                 :             :     {
    4439                 :             : #define CASE(CODE, IFN) case CODE: return IFN_COND_LEN_##IFN;
    4440                 :             :       FOR_EACH_CODE_MAPPING(CASE)
    4441                 :             : #undef CASE
    4442                 :             :     default:
    4443                 :             :       return IFN_LAST;
    4444                 :             :     }
    4445                 :             : }
    4446                 :             : 
    4447                 :             : /* Invoke T(IFN) for each internal function IFN that also has an
    4448                 :             :    IFN_COND_* form.  */
    4449                 :             : #define FOR_EACH_COND_FN_PAIR(T) \
    4450                 :             :   T (FMAX) \
    4451                 :             :   T (FMIN) \
    4452                 :             :   T (FMA) \
    4453                 :             :   T (FMS) \
    4454                 :             :   T (FNMA) \
    4455                 :             :   T (FNMS)
    4456                 :             : 
    4457                 :             : /* Return a function that only performs internal function FN when a
    4458                 :             :    certain condition is met and that uses a given fallback value otherwise.
    4459                 :             :    In other words, the returned function FN' is such that:
    4460                 :             : 
    4461                 :             :      LHS = FN' (COND, A1, ... An, ELSE)
    4462                 :             : 
    4463                 :             :    is equivalent to the C expression:
    4464                 :             : 
    4465                 :             :      LHS = COND ? FN (A1, ..., An) : ELSE;
    4466                 :             : 
    4467                 :             :    operating elementwise if the operands are vectors.
    4468                 :             : 
    4469                 :             :    Return IFN_LAST if no such function exists.  */
    4470                 :             : 
    4471                 :             : internal_fn
    4472                 :       10184 : get_conditional_internal_fn (internal_fn fn)
    4473                 :             : {
    4474                 :       10184 :   switch (fn)
    4475                 :             :     {
    4476                 :             : #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
    4477                 :         904 :       FOR_EACH_COND_FN_PAIR(CASE)
    4478                 :             : #undef CASE
    4479                 :        9280 :     default:
    4480                 :        9280 :       return IFN_LAST;
    4481                 :             :     }
    4482                 :             : }
    4483                 :             : 
    4484                 :             : /* If there exists an internal function like IFN that operates on vectors,
    4485                 :             :    but with additional length and bias parameters, return the internal_fn
    4486                 :             :    for that function, otherwise return IFN_LAST.  */
    4487                 :             : internal_fn
    4488                 :        9401 : get_len_internal_fn (internal_fn fn)
    4489                 :             : {
    4490                 :        9401 :   switch (fn)
    4491                 :             :     {
    4492                 :             : #define DEF_INTERNAL_COND_FN(NAME, ...)                                        \
    4493                 :             :   case IFN_COND_##NAME:                                                        \
    4494                 :             :     return IFN_COND_LEN_##NAME;
    4495                 :             : #define DEF_INTERNAL_SIGNED_COND_FN(NAME, ...)                                 \
    4496                 :             :   case IFN_COND_##NAME:                                                        \
    4497                 :             :     return IFN_COND_LEN_##NAME;
    4498                 :             : #include "internal-fn.def"
    4499                 :             :     default:
    4500                 :             :       return IFN_LAST;
    4501                 :             :     }
    4502                 :             : }
    4503                 :             : 
    4504                 :             : /* If IFN implements the conditional form of an unconditional internal
    4505                 :             :    function, return that unconditional function, otherwise return IFN_LAST.  */
    4506                 :             : 
    4507                 :             : internal_fn
    4508                 :     2377326 : get_unconditional_internal_fn (internal_fn ifn)
    4509                 :             : {
    4510                 :     2377326 :   switch (ifn)
    4511                 :             :     {
    4512                 :             : #define CASE(NAME)                                                             \
    4513                 :             :     case IFN_COND_##NAME:                                                      \
    4514                 :             :     case IFN_COND_LEN_##NAME:                                                  \
    4515                 :             :       return IFN_##NAME;
    4516                 :             : FOR_EACH_COND_FN_PAIR (CASE)
    4517                 :             : #undef CASE
    4518                 :             :     default:
    4519                 :             :       return IFN_LAST;
    4520                 :             :     }
    4521                 :             : }
    4522                 :             : 
    4523                 :             : /* Return true if STMT can be interpreted as a conditional tree code
    4524                 :             :    operation of the form:
    4525                 :             : 
    4526                 :             :      LHS = COND ? OP (RHS1, ...) : ELSE;
    4527                 :             : 
    4528                 :             :    operating elementwise if the operands are vectors.  This includes
    4529                 :             :    the case of an all-true COND, so that the operation always happens.
    4530                 :             : 
    4531                 :             :    There is an alternative approach to interpret the STMT when the operands
    4532                 :             :    are vectors which is the operation predicated by both conditional mask
    4533                 :             :    and loop control length, the equivalent C code:
    4534                 :             : 
    4535                 :             :      for (int i = 0; i < NUNTIS; i++)
    4536                 :             :       {
    4537                 :             :         if (i < LEN + BIAS && COND[i])
    4538                 :             :           LHS[i] = A[i] CODE B[i];
    4539                 :             :         else
    4540                 :             :           LHS[i] = ELSE[i];
    4541                 :             :       }
    4542                 :             : 
    4543                 :             :    When returning true, set:
    4544                 :             : 
    4545                 :             :    - *COND_OUT to the condition COND, or to NULL_TREE if the condition
    4546                 :             :      is known to be all-true
    4547                 :             :    - *CODE_OUT to the tree code
    4548                 :             :    - OPS[I] to operand I of *CODE_OUT
    4549                 :             :    - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
    4550                 :             :      condition is known to be all true.
    4551                 :             :    - *LEN to the len argument if it COND_LEN_* operations or to NULL_TREE.
    4552                 :             :    - *BIAS to the bias argument if it COND_LEN_* operations or to NULL_TREE.  */
    4553                 :             : 
    4554                 :             : bool
    4555                 :       34908 : can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
    4556                 :             :                                    tree_code *code_out,
    4557                 :             :                                    tree (&ops)[3], tree *else_out,
    4558                 :             :                                    tree *len, tree *bias)
    4559                 :             : {
    4560                 :       34908 :   *len = NULL_TREE;
    4561                 :       34908 :   *bias = NULL_TREE;
    4562                 :       34908 :   if (gassign *assign = dyn_cast <gassign *> (stmt))
    4563                 :             :     {
    4564                 :       32356 :       *cond_out = NULL_TREE;
    4565                 :       32356 :       *code_out = gimple_assign_rhs_code (assign);
    4566                 :       32356 :       ops[0] = gimple_assign_rhs1 (assign);
    4567                 :       32356 :       ops[1] = gimple_assign_rhs2 (assign);
    4568                 :       32356 :       ops[2] = gimple_assign_rhs3 (assign);
    4569                 :       32356 :       *else_out = NULL_TREE;
    4570                 :       32356 :       return true;
    4571                 :             :     }
    4572                 :        2552 :   if (gcall *call = dyn_cast <gcall *> (stmt))
    4573                 :        1976 :     if (gimple_call_internal_p (call))
    4574                 :             :       {
    4575                 :        1937 :         internal_fn ifn = gimple_call_internal_fn (call);
    4576                 :        1937 :         tree_code code = conditional_internal_fn_code (ifn);
    4577                 :        1937 :         int len_index = internal_fn_len_index (ifn);
    4578                 :        1937 :         int cond_nargs = len_index >= 0 ? 4 : 2;
    4579                 :        1937 :         if (code != ERROR_MARK)
    4580                 :             :           {
    4581                 :         159 :             *cond_out = gimple_call_arg (call, 0);
    4582                 :         159 :             *code_out = code;
    4583                 :         159 :             unsigned int nops = gimple_call_num_args (call) - cond_nargs;
    4584                 :         636 :             for (unsigned int i = 0; i < 3; ++i)
    4585                 :         477 :               ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
    4586                 :         159 :             *else_out = gimple_call_arg (call, nops + 1);
    4587                 :         159 :             if (len_index < 0)
    4588                 :             :               {
    4589                 :         159 :                 if (integer_truep (*cond_out))
    4590                 :             :                   {
    4591                 :           0 :                     *cond_out = NULL_TREE;
    4592                 :           0 :                     *else_out = NULL_TREE;
    4593                 :             :                   }
    4594                 :             :               }
    4595                 :             :             else
    4596                 :             :               {
    4597                 :           0 :                 *len = gimple_call_arg (call, len_index);
    4598                 :           0 :                 *bias = gimple_call_arg (call, len_index + 1);
    4599                 :             :               }
    4600                 :         159 :             return true;
    4601                 :             :           }
    4602                 :             :       }
    4603                 :             :   return false;
    4604                 :             : }
    4605                 :             : 
    4606                 :             : /* Return true if IFN is some form of load from memory.  */
    4607                 :             : 
    4608                 :             : bool
    4609                 :      129067 : internal_load_fn_p (internal_fn fn)
    4610                 :             : {
    4611                 :      129067 :   switch (fn)
    4612                 :             :     {
    4613                 :             :     case IFN_MASK_LOAD:
    4614                 :             :     case IFN_LOAD_LANES:
    4615                 :             :     case IFN_MASK_LOAD_LANES:
    4616                 :             :     case IFN_MASK_LEN_LOAD_LANES:
    4617                 :             :     case IFN_GATHER_LOAD:
    4618                 :             :     case IFN_MASK_GATHER_LOAD:
    4619                 :             :     case IFN_MASK_LEN_GATHER_LOAD:
    4620                 :             :     case IFN_LEN_LOAD:
    4621                 :             :     case IFN_MASK_LEN_LOAD:
    4622                 :             :       return true;
    4623                 :             : 
    4624                 :       92683 :     default:
    4625                 :       92683 :       return false;
    4626                 :             :     }
    4627                 :             : }
    4628                 :             : 
    4629                 :             : /* Return true if IFN is some form of store to memory.  */
    4630                 :             : 
    4631                 :             : bool
    4632                 :      268930 : internal_store_fn_p (internal_fn fn)
    4633                 :             : {
    4634                 :      268930 :   switch (fn)
    4635                 :             :     {
    4636                 :             :     case IFN_MASK_STORE:
    4637                 :             :     case IFN_STORE_LANES:
    4638                 :             :     case IFN_MASK_STORE_LANES:
    4639                 :             :     case IFN_MASK_LEN_STORE_LANES:
    4640                 :             :     case IFN_SCATTER_STORE:
    4641                 :             :     case IFN_MASK_SCATTER_STORE:
    4642                 :             :     case IFN_MASK_LEN_SCATTER_STORE:
    4643                 :             :     case IFN_LEN_STORE:
    4644                 :             :     case IFN_MASK_LEN_STORE:
    4645                 :             :       return true;
    4646                 :             : 
    4647                 :      254392 :     default:
    4648                 :      254392 :       return false;
    4649                 :             :     }
    4650                 :             : }
    4651                 :             : 
    4652                 :             : /* Return true if IFN is some form of gather load or scatter store.  */
    4653                 :             : 
    4654                 :             : bool
    4655                 :       12112 : internal_gather_scatter_fn_p (internal_fn fn)
    4656                 :             : {
    4657                 :       12112 :   switch (fn)
    4658                 :             :     {
    4659                 :             :     case IFN_GATHER_LOAD:
    4660                 :             :     case IFN_MASK_GATHER_LOAD:
    4661                 :             :     case IFN_MASK_LEN_GATHER_LOAD:
    4662                 :             :     case IFN_SCATTER_STORE:
    4663                 :             :     case IFN_MASK_SCATTER_STORE:
    4664                 :             :     case IFN_MASK_LEN_SCATTER_STORE:
    4665                 :             :       return true;
    4666                 :             : 
    4667                 :       12112 :     default:
    4668                 :       12112 :       return false;
    4669                 :             :     }
    4670                 :             : }
    4671                 :             : 
    4672                 :             : /* If FN takes a vector len argument, return the index of that argument,
    4673                 :             :    otherwise return -1.  */
    4674                 :             : 
    4675                 :             : int
    4676                 :     2294824 : internal_fn_len_index (internal_fn fn)
    4677                 :             : {
    4678                 :     2294824 :   switch (fn)
    4679                 :             :     {
    4680                 :             :     case IFN_LEN_LOAD:
    4681                 :             :     case IFN_LEN_STORE:
    4682                 :             :       return 2;
    4683                 :             : 
    4684                 :             :     case IFN_MASK_LEN_GATHER_LOAD:
    4685                 :             :     case IFN_MASK_LEN_SCATTER_STORE:
    4686                 :             :     case IFN_COND_LEN_FMA:
    4687                 :             :     case IFN_COND_LEN_FMS:
    4688                 :             :     case IFN_COND_LEN_FNMA:
    4689                 :             :     case IFN_COND_LEN_FNMS:
    4690                 :             :       return 5;
    4691                 :             : 
    4692                 :             :     case IFN_COND_LEN_ADD:
    4693                 :             :     case IFN_COND_LEN_SUB:
    4694                 :             :     case IFN_COND_LEN_MUL:
    4695                 :             :     case IFN_COND_LEN_DIV:
    4696                 :             :     case IFN_COND_LEN_MOD:
    4697                 :             :     case IFN_COND_LEN_RDIV:
    4698                 :             :     case IFN_COND_LEN_MIN:
    4699                 :             :     case IFN_COND_LEN_MAX:
    4700                 :             :     case IFN_COND_LEN_FMIN:
    4701                 :             :     case IFN_COND_LEN_FMAX:
    4702                 :             :     case IFN_COND_LEN_AND:
    4703                 :             :     case IFN_COND_LEN_IOR:
    4704                 :             :     case IFN_COND_LEN_XOR:
    4705                 :             :     case IFN_COND_LEN_SHL:
    4706                 :             :     case IFN_COND_LEN_SHR:
    4707                 :             :       return 4;
    4708                 :             : 
    4709                 :             :     case IFN_COND_LEN_NEG:
    4710                 :             :     case IFN_MASK_LEN_LOAD:
    4711                 :             :     case IFN_MASK_LEN_STORE:
    4712                 :             :     case IFN_MASK_LEN_LOAD_LANES:
    4713                 :             :     case IFN_MASK_LEN_STORE_LANES:
    4714                 :             :     case IFN_VCOND_MASK_LEN:
    4715                 :             :       return 3;
    4716                 :             : 
    4717                 :             :     default:
    4718                 :             :       return -1;
    4719                 :             :     }
    4720                 :             : }
    4721                 :             : 
    4722                 :             : /* If FN is an IFN_COND_* or IFN_COND_LEN_* function, return the index of the
    4723                 :             :    argument that is used when the condition is false.  Return -1 otherwise.  */
    4724                 :             : 
    4725                 :             : int
    4726                 :        3239 : internal_fn_else_index (internal_fn fn)
    4727                 :             : {
    4728                 :        3239 :   switch (fn)
    4729                 :             :     {
    4730                 :             :     case IFN_COND_NEG:
    4731                 :             :     case IFN_COND_NOT:
    4732                 :             :     case IFN_COND_LEN_NEG:
    4733                 :             :     case IFN_COND_LEN_NOT:
    4734                 :             :       return 2;
    4735                 :             : 
    4736                 :        3239 :     case IFN_COND_ADD:
    4737                 :        3239 :     case IFN_COND_SUB:
    4738                 :        3239 :     case IFN_COND_MUL:
    4739                 :        3239 :     case IFN_COND_DIV:
    4740                 :        3239 :     case IFN_COND_MOD:
    4741                 :        3239 :     case IFN_COND_MIN:
    4742                 :        3239 :     case IFN_COND_MAX:
    4743                 :        3239 :     case IFN_COND_FMIN:
    4744                 :        3239 :     case IFN_COND_FMAX:
    4745                 :        3239 :     case IFN_COND_AND:
    4746                 :        3239 :     case IFN_COND_IOR:
    4747                 :        3239 :     case IFN_COND_XOR:
    4748                 :        3239 :     case IFN_COND_SHL:
    4749                 :        3239 :     case IFN_COND_SHR:
    4750                 :        3239 :     case IFN_COND_LEN_ADD:
    4751                 :        3239 :     case IFN_COND_LEN_SUB:
    4752                 :        3239 :     case IFN_COND_LEN_MUL:
    4753                 :        3239 :     case IFN_COND_LEN_DIV:
    4754                 :        3239 :     case IFN_COND_LEN_MOD:
    4755                 :        3239 :     case IFN_COND_LEN_MIN:
    4756                 :        3239 :     case IFN_COND_LEN_MAX:
    4757                 :        3239 :     case IFN_COND_LEN_FMIN:
    4758                 :        3239 :     case IFN_COND_LEN_FMAX:
    4759                 :        3239 :     case IFN_COND_LEN_AND:
    4760                 :        3239 :     case IFN_COND_LEN_IOR:
    4761                 :        3239 :     case IFN_COND_LEN_XOR:
    4762                 :        3239 :     case IFN_COND_LEN_SHL:
    4763                 :        3239 :     case IFN_COND_LEN_SHR:
    4764                 :        3239 :       return 3;
    4765                 :             : 
    4766                 :           0 :     case IFN_COND_FMA:
    4767                 :           0 :     case IFN_COND_FMS:
    4768                 :           0 :     case IFN_COND_FNMA:
    4769                 :           0 :     case IFN_COND_FNMS:
    4770                 :           0 :     case IFN_COND_LEN_FMA:
    4771                 :           0 :     case IFN_COND_LEN_FMS:
    4772                 :           0 :     case IFN_COND_LEN_FNMA:
    4773                 :           0 :     case IFN_COND_LEN_FNMS:
    4774                 :           0 :       return 4;
    4775                 :             : 
    4776                 :           0 :     default:
    4777                 :           0 :       return -1;
    4778                 :             :     }
    4779                 :             : 
    4780                 :             :   return -1;
    4781                 :             : }
    4782                 :             : 
    4783                 :             : /* If FN takes a vector mask argument, return the index of that argument,
    4784                 :             :    otherwise return -1.  */
    4785                 :             : 
    4786                 :             : int
    4787                 :      151947 : internal_fn_mask_index (internal_fn fn)
    4788                 :             : {
    4789                 :      151947 :   switch (fn)
    4790                 :             :     {
    4791                 :             :     case IFN_MASK_LOAD:
    4792                 :             :     case IFN_MASK_LOAD_LANES:
    4793                 :             :     case IFN_MASK_LEN_LOAD_LANES:
    4794                 :             :     case IFN_MASK_STORE:
    4795                 :             :     case IFN_MASK_STORE_LANES:
    4796                 :             :     case IFN_MASK_LEN_STORE_LANES:
    4797                 :             :     case IFN_MASK_LEN_LOAD:
    4798                 :             :     case IFN_MASK_LEN_STORE:
    4799                 :             :       return 2;
    4800                 :             : 
    4801                 :           0 :     case IFN_MASK_GATHER_LOAD:
    4802                 :           0 :     case IFN_MASK_SCATTER_STORE:
    4803                 :           0 :     case IFN_MASK_LEN_GATHER_LOAD:
    4804                 :           0 :     case IFN_MASK_LEN_SCATTER_STORE:
    4805                 :           0 :       return 4;
    4806                 :             : 
    4807                 :             :     case IFN_VCOND_MASK_LEN:
    4808                 :             :       return 0;
    4809                 :             : 
    4810                 :      119645 :     default:
    4811                 :      119645 :       return (conditional_internal_fn_code (fn) != ERROR_MARK
    4812                 :      119645 :               || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
    4813                 :             :     }
    4814                 :             : }
    4815                 :             : 
    4816                 :             : /* If FN takes a value that should be stored to memory, return the index
    4817                 :             :    of that argument, otherwise return -1.  */
    4818                 :             : 
    4819                 :             : int
    4820                 :       39303 : internal_fn_stored_value_index (internal_fn fn)
    4821                 :             : {
    4822                 :       39303 :   switch (fn)
    4823                 :             :     {
    4824                 :             :     case IFN_MASK_STORE:
    4825                 :             :     case IFN_MASK_STORE_LANES:
    4826                 :             :     case IFN_SCATTER_STORE:
    4827                 :             :     case IFN_MASK_SCATTER_STORE:
    4828                 :             :     case IFN_MASK_LEN_SCATTER_STORE:
    4829                 :             :       return 3;
    4830                 :             : 
    4831                 :           0 :     case IFN_LEN_STORE:
    4832                 :           0 :       return 4;
    4833                 :             : 
    4834                 :           0 :     case IFN_MASK_LEN_STORE:
    4835                 :           0 :     case IFN_MASK_LEN_STORE_LANES:
    4836                 :           0 :       return 5;
    4837                 :             : 
    4838                 :        4130 :     default:
    4839                 :        4130 :       return -1;
    4840                 :             :     }
    4841                 :             : }
    4842                 :             : 
    4843                 :             : /* Return true if the target supports gather load or scatter store function
    4844                 :             :    IFN.  For loads, VECTOR_TYPE is the vector type of the load result,
    4845                 :             :    while for stores it is the vector type of the stored data argument.
    4846                 :             :    MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
    4847                 :             :    or stored.  OFFSET_VECTOR_TYPE is the vector type that holds the
    4848                 :             :    offset from the shared base address of each loaded or stored element.
    4849                 :             :    SCALE is the amount by which these offsets should be multiplied
    4850                 :             :    *after* they have been extended to address width.  */
    4851                 :             : 
    4852                 :             : bool
    4853                 :      327548 : internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
    4854                 :             :                                         tree memory_element_type,
    4855                 :             :                                         tree offset_vector_type, int scale)
    4856                 :             : {
    4857                 :      327548 :   if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
    4858                 :      327548 :                            TYPE_SIZE (memory_element_type)))
    4859                 :             :     return false;
    4860                 :      327548 :   if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
    4861                 :      655096 :                 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
    4862                 :             :     return false;
    4863                 :       79662 :   optab optab = direct_internal_fn_optab (ifn);
    4864                 :       79662 :   insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
    4865                 :       79662 :                                            TYPE_MODE (offset_vector_type));
    4866                 :       79662 :   int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
    4867                 :       79662 :   bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
    4868                 :       79662 :   return (icode != CODE_FOR_nothing
    4869                 :           0 :           && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
    4870                 :       79662 :           && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
    4871                 :             : }
    4872                 :             : 
    4873                 :             : /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
    4874                 :             :    for pointers of type TYPE when the accesses have LENGTH bytes and their
    4875                 :             :    common byte alignment is ALIGN.  */
    4876                 :             : 
    4877                 :             : bool
    4878                 :        4690 : internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
    4879                 :             :                                     poly_uint64 length, unsigned int align)
    4880                 :             : {
    4881                 :        4690 :   machine_mode mode = TYPE_MODE (type);
    4882                 :        4690 :   optab optab = direct_internal_fn_optab (ifn);
    4883                 :        4690 :   insn_code icode = direct_optab_handler (optab, mode);
    4884                 :        4690 :   if (icode == CODE_FOR_nothing)
    4885                 :             :     return false;
    4886                 :           0 :   rtx length_rtx = immed_wide_int_const (length, mode);
    4887                 :           0 :   return (insn_operand_matches (icode, 3, length_rtx)
    4888                 :           0 :           && insn_operand_matches (icode, 4, GEN_INT (align)));
    4889                 :             : }
    4890                 :             : 
    4891                 :             : /* Return the supported bias for IFN which is either IFN_{LEN_,MASK_LEN_,}LOAD
    4892                 :             :    or IFN_{LEN_,MASK_LEN_,}STORE.  For now we only support the biases of 0 and
    4893                 :             :    -1 (in case 0 is not an allowable length for {len_,mask_len_}load or
    4894                 :             :    {len_,mask_len_}store). If none of the biases match what the backend
    4895                 :             :    provides, return VECT_PARTIAL_BIAS_UNSUPPORTED.  */
    4896                 :             : 
    4897                 :             : signed char
    4898                 :           0 : internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
    4899                 :             : {
    4900                 :           0 :   optab optab = direct_internal_fn_optab (ifn);
    4901                 :           0 :   insn_code icode = direct_optab_handler (optab, mode);
    4902                 :           0 :   int bias_no = 3;
    4903                 :             : 
    4904                 :           0 :   if (icode == CODE_FOR_nothing)
    4905                 :             :     {
    4906                 :           0 :       machine_mode mask_mode;
    4907                 :           0 :       if (!targetm.vectorize.get_mask_mode (mode).exists (&mask_mode))
    4908                 :           0 :         return VECT_PARTIAL_BIAS_UNSUPPORTED;
    4909                 :           0 :       if (ifn == IFN_LEN_LOAD)
    4910                 :             :         {
    4911                 :             :           /* Try MASK_LEN_LOAD.  */
    4912                 :           0 :           optab = direct_internal_fn_optab (IFN_MASK_LEN_LOAD);
    4913                 :             :         }
    4914                 :             :       else
    4915                 :             :         {
    4916                 :             :           /* Try MASK_LEN_STORE.  */
    4917                 :           0 :           optab = direct_internal_fn_optab (IFN_MASK_LEN_STORE);
    4918                 :             :         }
    4919                 :           0 :       icode = convert_optab_handler (optab, mode, mask_mode);
    4920                 :           0 :       bias_no = 4;
    4921                 :             :     }
    4922                 :             : 
    4923                 :           0 :   if (icode != CODE_FOR_nothing)
    4924                 :             :     {
    4925                 :             :       /* For now we only support biases of 0 or -1.  Try both of them.  */
    4926                 :           0 :       if (insn_operand_matches (icode, bias_no, GEN_INT (0)))
    4927                 :             :         return 0;
    4928                 :           0 :       if (insn_operand_matches (icode, bias_no, GEN_INT (-1)))
    4929                 :             :         return -1;
    4930                 :             :     }
    4931                 :             : 
    4932                 :             :   return VECT_PARTIAL_BIAS_UNSUPPORTED;
    4933                 :             : }
    4934                 :             : 
    4935                 :             : /* Expand STMT as though it were a call to internal function FN.  */
    4936                 :             : 
    4937                 :             : void
    4938                 :      218691 : expand_internal_call (internal_fn fn, gcall *stmt)
    4939                 :             : {
    4940                 :      218691 :   internal_fn_expanders[fn] (fn, stmt);
    4941                 :      218691 : }
    4942                 :             : 
    4943                 :             : /* Expand STMT, which is a call to internal function FN.  */
    4944                 :             : 
    4945                 :             : void
    4946                 :      184637 : expand_internal_call (gcall *stmt)
    4947                 :             : {
    4948                 :      184637 :   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
    4949                 :      184637 : }
    4950                 :             : 
    4951                 :             : /* If TYPE is a vector type, return true if IFN is a direct internal
    4952                 :             :    function that is supported for that type.  If TYPE is a scalar type,
    4953                 :             :    return true if IFN is a direct internal function that is supported for
    4954                 :             :    the target's preferred vector version of TYPE.  */
    4955                 :             : 
    4956                 :             : bool
    4957                 :       11676 : vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
    4958                 :             : {
    4959                 :       11676 :   if (VECTOR_MODE_P (TYPE_MODE (type)))
    4960                 :        6208 :     return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
    4961                 :             : 
    4962                 :        5468 :   scalar_mode smode;
    4963                 :        5468 :   if (VECTOR_TYPE_P (type)
    4964                 :        5468 :       || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
    4965                 :          11 :     return false;
    4966                 :             : 
    4967                 :        5457 :   machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
    4968                 :        5457 :   if (VECTOR_MODE_P (vmode))
    4969                 :             :     {
    4970                 :        5420 :       tree vectype = build_vector_type_for_mode (type, vmode);
    4971                 :        5420 :       if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
    4972                 :             :         return true;
    4973                 :             :     }
    4974                 :             : 
    4975                 :        3865 :   auto_vector_modes vector_modes;
    4976                 :        3865 :   targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
    4977                 :       24069 :   for (machine_mode base_mode : vector_modes)
    4978                 :       12474 :     if (related_vector_mode (base_mode, smode).exists (&vmode))
    4979                 :             :       {
    4980                 :       10972 :         tree vectype = build_vector_type_for_mode (type, vmode);
    4981                 :       10972 :         if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
    4982                 :             :           return true;
    4983                 :             :       }
    4984                 :             : 
    4985                 :             :   return false;
    4986                 :        3865 : }
    4987                 :             : 
    4988                 :             : void
    4989                 :           0 : expand_SHUFFLEVECTOR (internal_fn, gcall *)
    4990                 :             : {
    4991                 :           0 :   gcc_unreachable ();
    4992                 :             : }
    4993                 :             : 
    4994                 :             : void
    4995                 :           0 : expand_PHI (internal_fn, gcall *)
    4996                 :             : {
    4997                 :           0 :   gcc_unreachable ();
    4998                 :             : }
    4999                 :             : 
    5000                 :             : void
    5001                 :         306 : expand_SPACESHIP (internal_fn, gcall *stmt)
    5002                 :             : {
    5003                 :         306 :   tree lhs = gimple_call_lhs (stmt);
    5004                 :         306 :   tree rhs1 = gimple_call_arg (stmt, 0);
    5005                 :         306 :   tree rhs2 = gimple_call_arg (stmt, 1);
    5006                 :         306 :   tree type = TREE_TYPE (rhs1);
    5007                 :             : 
    5008                 :         306 :   do_pending_stack_adjust ();
    5009                 :             : 
    5010                 :         306 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    5011                 :         306 :   rtx op1 = expand_normal (rhs1);
    5012                 :         306 :   rtx op2 = expand_normal (rhs2);
    5013                 :             : 
    5014                 :         306 :   class expand_operand ops[3];
    5015                 :         306 :   create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
    5016                 :         306 :   create_input_operand (&ops[1], op1, TYPE_MODE (type));
    5017                 :         306 :   create_input_operand (&ops[2], op2, TYPE_MODE (type));
    5018                 :         306 :   insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
    5019                 :         306 :   expand_insn (icode, 3, ops);
    5020                 :         306 :   if (!rtx_equal_p (target, ops[0].value))
    5021                 :           0 :     emit_move_insn (target, ops[0].value);
    5022                 :         306 : }
    5023                 :             : 
    5024                 :             : void
    5025                 :           0 : expand_ASSUME (internal_fn, gcall *)
    5026                 :             : {
    5027                 :           0 : }
    5028                 :             : 
    5029                 :             : void
    5030                 :           0 : expand_MASK_CALL (internal_fn, gcall *)
    5031                 :             : {
    5032                 :             :   /* This IFN should only exist between ifcvt and vect passes.  */
    5033                 :           0 :   gcc_unreachable ();
    5034                 :             : }
    5035                 :             : 
    5036                 :             : void
    5037                 :        1561 : expand_MULBITINT (internal_fn, gcall *stmt)
    5038                 :             : {
    5039                 :        1561 :   rtx_mode_t args[6];
    5040                 :       10927 :   for (int i = 0; i < 6; i++)
    5041                 :        9366 :     args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
    5042                 :       18732 :                           (i & 1) ? SImode : ptr_mode);
    5043                 :        1561 :   rtx fun = init_one_libfunc ("__mulbitint3");
    5044                 :        1561 :   emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 6, args);
    5045                 :        1561 : }
    5046                 :             : 
    5047                 :             : void
    5048                 :         120 : expand_DIVMODBITINT (internal_fn, gcall *stmt)
    5049                 :             : {
    5050                 :         120 :   rtx_mode_t args[8];
    5051                 :        1080 :   for (int i = 0; i < 8; i++)
    5052                 :         960 :     args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
    5053                 :        1920 :                           (i & 1) ? SImode : ptr_mode);
    5054                 :         120 :   rtx fun = init_one_libfunc ("__divmodbitint4");
    5055                 :         120 :   emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 8, args);
    5056                 :         120 : }
    5057                 :             : 
    5058                 :             : void
    5059                 :         163 : expand_FLOATTOBITINT (internal_fn, gcall *stmt)
    5060                 :             : {
    5061                 :         163 :   machine_mode mode = TYPE_MODE (TREE_TYPE (gimple_call_arg (stmt, 2)));
    5062                 :         163 :   rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
    5063                 :         163 :   rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
    5064                 :         163 :   rtx arg2 = expand_normal (gimple_call_arg (stmt, 2));
    5065                 :         163 :   const char *mname = GET_MODE_NAME (mode);
    5066                 :         163 :   unsigned mname_len = strlen (mname);
    5067                 :         163 :   int len = 12 + mname_len;
    5068                 :         163 :   if (DECIMAL_FLOAT_MODE_P (mode))
    5069                 :          53 :     len += 4;
    5070                 :         163 :   char *libfunc_name = XALLOCAVEC (char, len);
    5071                 :         163 :   char *p = libfunc_name;
    5072                 :         163 :   const char *q;
    5073                 :         163 :   if (DECIMAL_FLOAT_MODE_P (mode))
    5074                 :             :     {
    5075                 :             : #if ENABLE_DECIMAL_BID_FORMAT
    5076                 :          53 :       memcpy (p, "__bid_fix", 9);
    5077                 :             : #else
    5078                 :             :       memcpy (p, "__dpd_fix", 9);
    5079                 :             : #endif
    5080                 :          53 :       p += 9;
    5081                 :             :     }
    5082                 :             :   else
    5083                 :             :     {
    5084                 :         110 :       memcpy (p, "__fix", 5);
    5085                 :         110 :       p += 5;
    5086                 :             :     }
    5087                 :         489 :   for (q = mname; *q; q++)
    5088                 :         326 :     *p++ = TOLOWER (*q);
    5089                 :         163 :   memcpy (p, "bitint", 7);
    5090                 :         163 :   rtx fun = init_one_libfunc (libfunc_name);
    5091                 :         163 :   emit_library_call (fun, LCT_NORMAL, VOIDmode, arg0, ptr_mode, arg1,
    5092                 :             :                      SImode, arg2, mode);
    5093                 :         163 : }
    5094                 :             : 
    5095                 :             : void
    5096                 :         126 : expand_BITINTTOFLOAT (internal_fn, gcall *stmt)
    5097                 :             : {
    5098                 :         126 :   tree lhs = gimple_call_lhs (stmt);
    5099                 :         126 :   if (!lhs)
    5100                 :             :     return;
    5101                 :         126 :   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
    5102                 :         126 :   rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
    5103                 :         126 :   rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
    5104                 :         126 :   const char *mname = GET_MODE_NAME (mode);
    5105                 :         126 :   unsigned mname_len = strlen (mname);
    5106                 :         126 :   int len = 14 + mname_len;
    5107                 :         126 :   if (DECIMAL_FLOAT_MODE_P (mode))
    5108                 :          13 :     len += 4;
    5109                 :         126 :   char *libfunc_name = XALLOCAVEC (char, len);
    5110                 :         126 :   char *p = libfunc_name;
    5111                 :         126 :   const char *q;
    5112                 :         126 :   if (DECIMAL_FLOAT_MODE_P (mode))
    5113                 :             :     {
    5114                 :             : #if ENABLE_DECIMAL_BID_FORMAT
    5115                 :          13 :       memcpy (p, "__bid_floatbitint", 17);
    5116                 :             : #else
    5117                 :             :       memcpy (p, "__dpd_floatbitint", 17);
    5118                 :             : #endif
    5119                 :          13 :       p += 17;
    5120                 :             :     }
    5121                 :             :   else
    5122                 :             :     {
    5123                 :         113 :       memcpy (p, "__floatbitint", 13);
    5124                 :         113 :       p += 13;
    5125                 :             :     }
    5126                 :         378 :   for (q = mname; *q; q++)
    5127                 :         252 :     *p++ = TOLOWER (*q);
    5128                 :         126 :   *p = '\0';
    5129                 :         126 :   rtx fun = init_one_libfunc (libfunc_name);
    5130                 :         126 :   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    5131                 :         126 :   rtx val = emit_library_call_value (fun, target, LCT_PURE, mode,
    5132                 :             :                                      arg0, ptr_mode, arg1, SImode);
    5133                 :         126 :   if (val != target)
    5134                 :           0 :     emit_move_insn (target, val);
    5135                 :             : }
    5136                 :             : 
    5137                 :             : static bool
    5138                 :        7245 : expand_bitquery (internal_fn fn, gcall *stmt)
    5139                 :             : {
    5140                 :        7245 :   tree lhs = gimple_call_lhs (stmt);
    5141                 :        7245 :   if (lhs == NULL_TREE)
    5142                 :             :     return false;
    5143                 :        7239 :   tree arg = gimple_call_arg (stmt, 0);
    5144                 :        7239 :   if (TREE_CODE (arg) == INTEGER_CST)
    5145                 :             :     {
    5146                 :           0 :       tree ret = fold_const_call (as_combined_fn (fn), TREE_TYPE (arg), arg);
    5147                 :           0 :       gcc_checking_assert (ret && TREE_CODE (ret) == INTEGER_CST);
    5148                 :           0 :       expand_assignment (lhs, ret, false);
    5149                 :           0 :       return false;
    5150                 :             :     }
    5151                 :             :   return true;
    5152                 :             : }
    5153                 :             : 
    5154                 :             : void
    5155                 :           1 : expand_CLRSB (internal_fn fn, gcall *stmt)
    5156                 :             : {
    5157                 :           1 :   if (expand_bitquery (fn, stmt))
    5158                 :           0 :     expand_unary_optab_fn (fn, stmt, clrsb_optab);
    5159                 :           1 : }
    5160                 :             : 
    5161                 :             : void
    5162                 :        5984 : expand_CLZ (internal_fn fn, gcall *stmt)
    5163                 :             : {
    5164                 :        5984 :   if (expand_bitquery (fn, stmt))
    5165                 :        5983 :     expand_unary_optab_fn (fn, stmt, clz_optab);
    5166                 :        5984 : }
    5167                 :             : 
    5168                 :             : void
    5169                 :         779 : expand_CTZ (internal_fn fn, gcall *stmt)
    5170                 :             : {
    5171                 :         779 :   if (expand_bitquery (fn, stmt))
    5172                 :         778 :     expand_unary_optab_fn (fn, stmt, ctz_optab);
    5173                 :         779 : }
    5174                 :             : 
    5175                 :             : void
    5176                 :         107 : expand_FFS (internal_fn fn, gcall *stmt)
    5177                 :             : {
    5178                 :         107 :   if (expand_bitquery (fn, stmt))
    5179                 :         106 :     expand_unary_optab_fn (fn, stmt, ffs_optab);
    5180                 :         107 : }
    5181                 :             : 
    5182                 :             : void
    5183                 :         171 : expand_PARITY (internal_fn fn, gcall *stmt)
    5184                 :             : {
    5185                 :         171 :   if (expand_bitquery (fn, stmt))
    5186                 :         170 :     expand_unary_optab_fn (fn, stmt, parity_optab);
    5187                 :         171 : }
    5188                 :             : 
    5189                 :             : void
    5190                 :         203 : expand_POPCOUNT (internal_fn fn, gcall *stmt)
    5191                 :             : {
    5192                 :         203 :   if (!expand_bitquery (fn, stmt))
    5193                 :             :     return;
    5194                 :         202 :   if (gimple_call_num_args (stmt) == 1)
    5195                 :             :     {
    5196                 :         202 :       expand_unary_optab_fn (fn, stmt, popcount_optab);
    5197                 :         202 :       return;
    5198                 :             :     }
    5199                 :             :   /* If .POPCOUNT call has 2 arguments, match_single_bit_test marked it
    5200                 :             :      because the result is only used in an equality comparison against 1.
    5201                 :             :      Use rtx costs in that case to determine if .POPCOUNT (arg) == 1
    5202                 :             :      or (arg ^ (arg - 1)) > arg - 1 is cheaper.
    5203                 :             :      If .POPCOUNT second argument is 0, we additionally know that arg
    5204                 :             :      is non-zero, so use arg & (arg - 1) == 0 instead.  */
    5205                 :           0 :   bool speed_p = optimize_insn_for_speed_p ();
    5206                 :           0 :   tree lhs = gimple_call_lhs (stmt);
    5207                 :           0 :   tree arg = gimple_call_arg (stmt, 0);
    5208                 :           0 :   bool nonzero_arg = integer_zerop (gimple_call_arg (stmt, 1));
    5209                 :           0 :   tree type = TREE_TYPE (arg);
    5210                 :           0 :   machine_mode mode = TYPE_MODE (type);
    5211                 :           0 :   do_pending_stack_adjust ();
    5212                 :           0 :   start_sequence ();
    5213                 :           0 :   expand_unary_optab_fn (fn, stmt, popcount_optab);
    5214                 :           0 :   rtx_insn *popcount_insns = get_insns ();
    5215                 :           0 :   end_sequence ();
    5216                 :           0 :   start_sequence ();
    5217                 :           0 :   rtx plhs = expand_normal (lhs);
    5218                 :           0 :   rtx pcmp = emit_store_flag (NULL_RTX, EQ, plhs, const1_rtx, mode, 0, 0);
    5219                 :           0 :   if (pcmp == NULL_RTX)
    5220                 :             :     {
    5221                 :           0 :     fail:
    5222                 :           0 :       end_sequence ();
    5223                 :           0 :       emit_insn (popcount_insns);
    5224                 :           0 :       return;
    5225                 :             :     }
    5226                 :           0 :   rtx_insn *popcount_cmp_insns = get_insns ();
    5227                 :           0 :   end_sequence ();
    5228                 :           0 :   start_sequence ();
    5229                 :           0 :   rtx op0 = expand_normal (arg);
    5230                 :           0 :   rtx argm1 = expand_simple_binop (mode, PLUS, op0, constm1_rtx, NULL_RTX,
    5231                 :             :                                    1, OPTAB_DIRECT);
    5232                 :           0 :   if (argm1 == NULL_RTX)
    5233                 :           0 :     goto fail;
    5234                 :           0 :   rtx argxorargm1 = expand_simple_binop (mode, nonzero_arg ? AND : XOR, op0,
    5235                 :             :                                          argm1, NULL_RTX, 1, OPTAB_DIRECT);
    5236                 :           0 :   if (argxorargm1 == NULL_RTX)
    5237                 :           0 :     goto fail;
    5238                 :           0 :   rtx cmp;
    5239                 :           0 :   if (nonzero_arg)
    5240                 :           0 :     cmp = emit_store_flag (NULL_RTX, EQ, argxorargm1, const0_rtx, mode, 1, 1);
    5241                 :             :   else
    5242                 :           0 :     cmp = emit_store_flag (NULL_RTX, GTU, argxorargm1, argm1, mode, 1, 1);
    5243                 :           0 :   if (cmp == NULL_RTX)
    5244                 :           0 :     goto fail;
    5245                 :           0 :   rtx_insn *cmp_insns = get_insns ();
    5246                 :           0 :   end_sequence ();
    5247                 :           0 :   unsigned popcount_cost = (seq_cost (popcount_insns, speed_p)
    5248                 :           0 :                             + seq_cost (popcount_cmp_insns, speed_p));
    5249                 :           0 :   unsigned cmp_cost = seq_cost (cmp_insns, speed_p);
    5250                 :           0 :   if (popcount_cost <= cmp_cost)
    5251                 :           0 :     emit_insn (popcount_insns);
    5252                 :             :   else
    5253                 :             :     {
    5254                 :           0 :       emit_insn (cmp_insns);
    5255                 :           0 :       plhs = expand_normal (lhs);
    5256                 :           0 :       if (GET_MODE (cmp) != GET_MODE (plhs))
    5257                 :           0 :         cmp = convert_to_mode (GET_MODE (plhs), cmp, 1);
    5258                 :           0 :       emit_move_insn (plhs, cmp);
    5259                 :             :     }
    5260                 :             : }
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.