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

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.