LCOV - code coverage report
Current view: top level - gcc - builtins.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.3 % 5781 4987
Test Date: 2026-07-11 15:47:05 Functions: 93.7 % 221 207
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Expand builtin functions.
       2              :    Copyright (C) 1988-2026 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              : /* Legacy warning!  Please add no further builtin simplifications here
      21              :    (apart from pure constant folding) - builtin simplifications should go
      22              :    to match.pd or gimple-fold.cc instead.  */
      23              : 
      24              : #include "config.h"
      25              : #include "system.h"
      26              : #include "coretypes.h"
      27              : #include "backend.h"
      28              : #include "target.h"
      29              : #include "rtl.h"
      30              : #include "tree.h"
      31              : #include "memmodel.h"
      32              : #include "gimple.h"
      33              : #include "predict.h"
      34              : #include "tm_p.h"
      35              : #include "stringpool.h"
      36              : #include "tree-vrp.h"
      37              : #include "tree-ssanames.h"
      38              : #include "expmed.h"
      39              : #include "optabs.h"
      40              : #include "emit-rtl.h"
      41              : #include "recog.h"
      42              : #include "diagnostic-core.h"
      43              : #include "alias.h"
      44              : #include "fold-const.h"
      45              : #include "fold-const-call.h"
      46              : #include "gimple-ssa-warn-access.h"
      47              : #include "stor-layout.h"
      48              : #include "calls.h"
      49              : #include "varasm.h"
      50              : #include "tree-object-size.h"
      51              : #include "tree-ssa-strlen.h"
      52              : #include "realmpfr.h"
      53              : #include "cfgrtl.h"
      54              : #include "except.h"
      55              : #include "dojump.h"
      56              : #include "explow.h"
      57              : #include "stmt.h"
      58              : #include "expr.h"
      59              : #include "libfuncs.h"
      60              : #include "output.h"
      61              : #include "typeclass.h"
      62              : #include "langhooks.h"
      63              : #include "value-prof.h"
      64              : #include "builtins.h"
      65              : #include "stringpool.h"
      66              : #include "attribs.h"
      67              : #include "asan.h"
      68              : #include "internal-fn.h"
      69              : #include "case-cfn-macros.h"
      70              : #include "gimple-iterator.h"
      71              : #include "gimple-fold.h"
      72              : #include "intl.h"
      73              : #include "file-prefix-map.h" /* remap_macro_filename()  */
      74              : #include "ipa-strub.h" /* strub_watermark_parm()  */
      75              : #include "gomp-constants.h"
      76              : #include "omp-general.h"
      77              : #include "tree-dfa.h"
      78              : #include "gimple-ssa.h"
      79              : #include "tree-ssa-live.h"
      80              : #include "tree-outof-ssa.h"
      81              : #include "attr-fnspec.h"
      82              : #include "demangle.h"
      83              : #include "gimple-range.h"
      84              : #include "pointer-query.h"
      85              : 
      86              : struct target_builtins default_target_builtins;
      87              : #if SWITCHABLE_TARGET
      88              : struct target_builtins *this_target_builtins = &default_target_builtins;
      89              : #endif
      90              : 
      91              : /* Define the names of the builtin function types and codes.  */
      92              : const char *const built_in_class_names[BUILT_IN_LAST]
      93              :   = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
      94              : 
      95              : #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
      96              : const char * built_in_names[(int) END_BUILTINS] =
      97              : {
      98              : #include "builtins.def"
      99              : };
     100              : 
     101              : /* Setup an array of builtin_info_type, make sure each element decl is
     102              :    initialized to NULL_TREE.  */
     103              : builtin_info_type builtin_info[(int)END_BUILTINS];
     104              : 
     105              : /* Non-zero if __builtin_constant_p should be folded right away.  */
     106              : bool force_folding_builtin_constant_p;
     107              : 
     108              : static int target_char_cast (tree, char *);
     109              : static int apply_args_size (void);
     110              : static int apply_result_size (void);
     111              : static rtx result_vector (int, rtx);
     112              : static void expand_builtin_prefetch (tree);
     113              : static rtx expand_builtin_apply_args (void);
     114              : static rtx expand_builtin_apply_args_1 (void);
     115              : static rtx expand_builtin_apply (rtx, rtx, rtx);
     116              : static void expand_builtin_return (rtx);
     117              : static rtx expand_builtin_classify_type (tree);
     118              : static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
     119              : static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
     120              : static rtx expand_builtin_interclass_mathfn (tree, rtx);
     121              : static rtx expand_builtin_sincos (tree);
     122              : static rtx expand_builtin_fegetround (tree, rtx, machine_mode);
     123              : static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode,
     124              :                                                   optab);
     125              : static rtx expand_builtin_cexpi (tree, rtx);
     126              : static rtx expand_builtin_issignaling (tree, rtx);
     127              : static rtx expand_builtin_int_roundingfn (tree, rtx);
     128              : static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
     129              : static rtx expand_builtin_next_arg (void);
     130              : static rtx expand_builtin_va_start (tree);
     131              : static rtx expand_builtin_va_end (tree);
     132              : static rtx expand_builtin_va_copy (tree);
     133              : static rtx inline_expand_builtin_bytecmp (tree, rtx);
     134              : static rtx expand_builtin_strcmp (tree, rtx);
     135              : static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
     136              : static rtx expand_builtin_memcpy (tree, rtx);
     137              : static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
     138              :                                             rtx target, tree exp,
     139              :                                             memop_ret retmode,
     140              :                                             bool might_overlap);
     141              : static rtx expand_builtin_memmove (tree, rtx);
     142              : static rtx expand_builtin_mempcpy (tree, rtx);
     143              : static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
     144              : static rtx expand_builtin_strcpy (tree, rtx);
     145              : static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
     146              : static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
     147              : static rtx expand_builtin_strncpy (tree, rtx);
     148              : static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
     149              : static rtx expand_builtin_bzero (tree);
     150              : static rtx expand_builtin_strlen (tree, rtx, machine_mode);
     151              : static rtx expand_builtin_strnlen (tree, rtx, machine_mode);
     152              : static rtx expand_builtin_alloca (tree);
     153              : static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
     154              : static rtx expand_builtin_frame_address (tree, tree);
     155              : static rtx expand_builtin_stack_address ();
     156              : static tree stabilize_va_list_loc (location_t, tree, int);
     157              : static rtx expand_builtin_expect (tree, rtx);
     158              : static rtx expand_builtin_expect_with_probability (tree, rtx);
     159              : static tree fold_builtin_classify_type (tree);
     160              : static tree fold_builtin_strlen (location_t, tree, tree, tree);
     161              : static tree fold_builtin_inf (location_t, tree, int);
     162              : static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
     163              : static bool validate_arg (const_tree, enum tree_code code);
     164              : static rtx expand_builtin_fabs (tree, rtx, rtx);
     165              : static rtx expand_builtin_signbit (tree, rtx);
     166              : static tree fold_builtin_memcmp (location_t, tree, tree, tree);
     167              : static tree fold_builtin_isascii (location_t, tree);
     168              : static tree fold_builtin_toascii (location_t, tree);
     169              : static tree fold_builtin_isdigit (location_t, tree);
     170              : static tree fold_builtin_fabs (location_t, tree, tree);
     171              : static tree fold_builtin_abs (location_t, tree, tree);
     172              : static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
     173              :                                         enum tree_code);
     174              : static tree fold_builtin_iseqsig (location_t, tree, tree);
     175              : static tree fold_builtin_varargs (location_t, tree, tree*, int);
     176              : 
     177              : static tree fold_builtin_strpbrk (location_t, tree, tree, tree, tree);
     178              : static tree fold_builtin_strspn (location_t, tree, tree, tree, tree);
     179              : static tree fold_builtin_strcspn (location_t, tree, tree, tree, tree);
     180              : 
     181              : static rtx expand_builtin_object_size (tree);
     182              : static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
     183              :                                       enum built_in_function);
     184              : static void maybe_emit_chk_warning (tree, enum built_in_function);
     185              : static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
     186              : static tree fold_builtin_object_size (tree, tree, enum built_in_function);
     187              : 
     188              : unsigned HOST_WIDE_INT target_newline;
     189              : unsigned HOST_WIDE_INT target_percent;
     190              : static unsigned HOST_WIDE_INT target_c;
     191              : static unsigned HOST_WIDE_INT target_s;
     192              : char target_percent_c[3];
     193              : char target_percent_s[3];
     194              : char target_percent_s_newline[4];
     195              : static tree do_mpfr_remquo (tree, tree, tree);
     196              : static tree do_mpfr_lgamma_r (tree, tree, tree);
     197              : static void expand_builtin_sync_synchronize (void);
     198              : 
     199              : /* Return true if NAME starts with __builtin_ or __sync_.  */
     200              : 
     201              : static bool
     202       532291 : is_builtin_name (const char *name)
     203              : {
     204       532291 :   return (startswith (name, "__builtin_")
     205       194648 :           || startswith (name, "__sync_")
     206       726083 :           || startswith (name, "__atomic_"));
     207              : }
     208              : 
     209              : /* Return true if NODE should be considered for inline expansion regardless
     210              :    of the optimization level.  This means whenever a function is invoked with
     211              :    its "internal" name, which normally contains the prefix "__builtin".  */
     212              : 
     213              : bool
     214       532291 : called_as_built_in (tree node)
     215              : {
     216              :   /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
     217              :      we want the name used to call the function, not the name it
     218              :      will have. */
     219       532291 :   const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
     220       532291 :   return is_builtin_name (name);
     221              : }
     222              : 
     223              : /* Compute values M and N such that M divides (address of EXP - N) and such
     224              :    that N < M.  If these numbers can be determined, store M in alignp and N in
     225              :    *BITPOSP and return true.  Otherwise return false and store BITS_PER_UNIT to
     226              :    *alignp and any bit-offset to *bitposp.
     227              : 
     228              :    Note that the address (and thus the alignment) computed here is based
     229              :    on the address to which a symbol resolves, whereas DECL_ALIGN is based
     230              :    on the address at which an object is actually located.  These two
     231              :    addresses are not always the same.  For example, on ARM targets,
     232              :    the address &foo of a Thumb function foo() has the lowest bit set,
     233              :    whereas foo() itself starts on an even address.
     234              : 
     235              :    If ADDR_P is true we are taking the address of the memory reference EXP
     236              :    and thus cannot rely on the access taking place.  */
     237              : 
     238              : bool
     239    111582915 : get_object_alignment_2 (tree exp, unsigned int *alignp,
     240              :                         unsigned HOST_WIDE_INT *bitposp, bool addr_p)
     241              : {
     242    111582915 :   poly_int64 bitsize, bitpos;
     243    111582915 :   tree offset;
     244    111582915 :   machine_mode mode;
     245    111582915 :   int unsignedp, reversep, volatilep;
     246    111582915 :   unsigned int align = BITS_PER_UNIT;
     247    111582915 :   bool known_alignment = false;
     248              : 
     249              :   /* Get the innermost object and the constant (bitpos) and possibly
     250              :      variable (offset) offset of the access.  */
     251    111582915 :   exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
     252              :                              &unsignedp, &reversep, &volatilep);
     253              : 
     254              :   /* Extract alignment information from the innermost object and
     255              :      possibly adjust bitpos and offset.  */
     256    111582915 :   if (TREE_CODE (exp) == FUNCTION_DECL)
     257              :     {
     258              :       /* Function addresses can encode extra information besides their
     259              :          alignment.  However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
     260              :          allows the low bit to be used as a virtual bit, we know
     261              :          that the address itself must be at least 2-byte aligned.  */
     262              :       if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
     263              :         align = 2 * BITS_PER_UNIT;
     264              :     }
     265    111126211 :   else if (TREE_CODE (exp) == LABEL_DECL)
     266              :     ;
     267    111089236 :   else if (TREE_CODE (exp) == CONST_DECL)
     268              :     {
     269              :       /* The alignment of a CONST_DECL is determined by its initializer.  */
     270        59041 :       exp = DECL_INITIAL (exp);
     271        59041 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     272        59041 :       if (CONSTANT_CLASS_P (exp))
     273        59034 :         align = targetm.constant_alignment (exp, align);
     274              : 
     275              :       known_alignment = true;
     276              :     }
     277    111030195 :   else if (DECL_P (exp))
     278              :     {
     279     66804951 :       align = DECL_ALIGN (exp);
     280              :       known_alignment = true;
     281              :     }
     282     44225244 :   else if (TREE_CODE (exp) == INDIRECT_REF
     283     44212829 :            || TREE_CODE (exp) == MEM_REF
     284      5373250 :            || TREE_CODE (exp) == TARGET_MEM_REF)
     285              :     {
     286     42533633 :       tree addr = TREE_OPERAND (exp, 0);
     287     42533633 :       unsigned ptr_align;
     288     42533633 :       unsigned HOST_WIDE_INT ptr_bitpos;
     289     42533633 :       unsigned HOST_WIDE_INT ptr_bitmask = ~0;
     290              : 
     291              :       /* If the address is explicitly aligned, handle that.  */
     292     42533633 :       if (TREE_CODE (addr) == BIT_AND_EXPR
     293     42533633 :           && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
     294              :         {
     295           88 :           ptr_bitmask = TREE_INT_CST_LOW (TREE_OPERAND (addr, 1));
     296           88 :           ptr_bitmask *= BITS_PER_UNIT;
     297           88 :           align = least_bit_hwi (ptr_bitmask);
     298           88 :           addr = TREE_OPERAND (addr, 0);
     299              :         }
     300              : 
     301     42533633 :       known_alignment
     302     42533633 :         = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
     303     42533633 :       align = MAX (ptr_align, align);
     304              : 
     305              :       /* Re-apply explicit alignment to the bitpos.  */
     306     42533633 :       ptr_bitpos &= ptr_bitmask;
     307              : 
     308              :       /* The alignment of the pointer operand in a TARGET_MEM_REF
     309              :          has to take the variable offset parts into account.  */
     310     42533633 :       if (TREE_CODE (exp) == TARGET_MEM_REF)
     311              :         {
     312      3681639 :           if (TMR_INDEX (exp))
     313              :             {
     314      1654570 :               unsigned HOST_WIDE_INT step = 1;
     315      1654570 :               if (TMR_STEP (exp))
     316      1502802 :                 step = TREE_INT_CST_LOW (TMR_STEP (exp));
     317      1654570 :               align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
     318              :             }
     319      3681639 :           if (TMR_INDEX2 (exp))
     320        43313 :             align = BITS_PER_UNIT;
     321              :           known_alignment = false;
     322              :         }
     323              : 
     324              :       /* When EXP is an actual memory reference then we can use
     325              :          TYPE_ALIGN of a pointer indirection to derive alignment.
     326              :          Do so only if get_pointer_alignment_1 did not reveal absolute
     327              :          alignment knowledge and if using that alignment would
     328              :          improve the situation.  */
     329     42533633 :       unsigned int talign;
     330     42533633 :       if (!addr_p && !known_alignment
     331     40115154 :           && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
     332     82648781 :           && talign > align)
     333              :         align = talign;
     334              :       else
     335              :         {
     336              :           /* Else adjust bitpos accordingly.  */
     337     11612933 :           bitpos += ptr_bitpos;
     338     11612933 :           if (TREE_CODE (exp) == MEM_REF
     339     11612933 :               || TREE_CODE (exp) == TARGET_MEM_REF)
     340     11603546 :             bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
     341              :         }
     342     42533633 :     }
     343      1691611 :   else if (TREE_CODE (exp) == STRING_CST)
     344              :     {
     345              :       /* STRING_CST are the only constant objects we allow to be not
     346              :          wrapped inside a CONST_DECL.  */
     347      1691040 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     348      1691040 :       if (CONSTANT_CLASS_P (exp))
     349      1691040 :         align = targetm.constant_alignment (exp, align);
     350              : 
     351              :       known_alignment = true;
     352              :     }
     353              : 
     354              :   /* If there is a non-constant offset part extract the maximum
     355              :      alignment that can prevail.  */
     356    111582915 :   if (offset)
     357              :     {
     358     10085370 :       unsigned int trailing_zeros = tree_ctz (offset);
     359     10085370 :       if (trailing_zeros < HOST_BITS_PER_INT)
     360              :         {
     361     10085292 :           unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     362     10085292 :           if (inner)
     363     10085292 :             align = MIN (align, inner);
     364              :         }
     365              :     }
     366              : 
     367              :   /* Account for the alignment of runtime coefficients, so that the constant
     368              :      bitpos is guaranteed to be accurate.  */
     369    111582915 :   unsigned int alt_align = ::known_alignment (bitpos - bitpos.coeffs[0]);
     370    111582915 :   if (alt_align != 0 && alt_align < align)
     371              :     {
     372              :       align = alt_align;
     373              :       known_alignment = false;
     374              :     }
     375              : 
     376    111582915 :   *alignp = align;
     377    111582915 :   *bitposp = bitpos.coeffs[0] & (align - 1);
     378    111582915 :   return known_alignment;
     379              : }
     380              : 
     381              : /* For a memory reference expression EXP compute values M and N such that M
     382              :    divides (&EXP - N) and such that N < M.  If these numbers can be determined,
     383              :    store M in alignp and N in *BITPOSP and return true.  Otherwise return false
     384              :    and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp.  */
     385              : 
     386              : bool
     387     88472453 : get_object_alignment_1 (tree exp, unsigned int *alignp,
     388              :                         unsigned HOST_WIDE_INT *bitposp)
     389              : {
     390              :   /* Strip a WITH_SIZE_EXPR, get_inner_reference doesn't know how to deal
     391              :      with it.  */
     392     88472453 :   if (TREE_CODE (exp) == WITH_SIZE_EXPR)
     393            0 :     exp = TREE_OPERAND (exp, 0);
     394     88472453 :   return get_object_alignment_2 (exp, alignp, bitposp, false);
     395              : }
     396              : 
     397              : /* Return the alignment in bits of EXP, an object.  */
     398              : 
     399              : unsigned int
     400     36773472 : get_object_alignment (tree exp)
     401              : {
     402     36773472 :   unsigned HOST_WIDE_INT bitpos = 0;
     403     36773472 :   unsigned int align;
     404              : 
     405     36773472 :   get_object_alignment_1 (exp, &align, &bitpos);
     406              : 
     407              :   /* align and bitpos now specify known low bits of the pointer.
     408              :      ptr & (align - 1) == bitpos.  */
     409              : 
     410     36773472 :   if (bitpos != 0)
     411      2767139 :     align = least_bit_hwi (bitpos);
     412     36773472 :   return align;
     413              : }
     414              : 
     415              : /* For a pointer valued expression EXP compute values M and N such that M
     416              :    divides (EXP - N) and such that N < M.  If these numbers can be determined,
     417              :    store M in alignp and N in *BITPOSP and return true.  Return false if
     418              :    the results are just a conservative approximation.
     419              : 
     420              :    If EXP is not a pointer, false is returned too.  */
     421              : 
     422              : bool
     423     84286076 : get_pointer_alignment_1 (tree exp, unsigned int *alignp,
     424              :                          unsigned HOST_WIDE_INT *bitposp)
     425              : {
     426     84286076 :   STRIP_NOPS (exp);
     427              : 
     428     84286076 :   if (TREE_CODE (exp) == ADDR_EXPR)
     429     23108852 :     return get_object_alignment_2 (TREE_OPERAND (exp, 0),
     430     23108852 :                                    alignp, bitposp, true);
     431     61177224 :   else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
     432              :     {
     433      1009869 :       unsigned int align;
     434      1009869 :       unsigned HOST_WIDE_INT bitpos;
     435      1009869 :       bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
     436              :                                           &align, &bitpos);
     437      1009869 :       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
     438         3760 :         bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
     439              :       else
     440              :         {
     441      1006109 :           unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
     442      1006109 :           if (trailing_zeros < HOST_BITS_PER_INT)
     443              :             {
     444      1006101 :               unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     445      1006101 :               if (inner)
     446      1006101 :                 align = MIN (align, inner);
     447              :             }
     448              :         }
     449      1009869 :       *alignp = align;
     450      1009869 :       *bitposp = bitpos & (align - 1);
     451      1009869 :       return res;
     452              :     }
     453     60167355 :   else if (TREE_CODE (exp) == SSA_NAME
     454     60167355 :            && POINTER_TYPE_P (TREE_TYPE (exp)))
     455              :     {
     456     57954618 :       unsigned int ptr_align, ptr_misalign;
     457     57954618 :       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
     458              : 
     459     57954618 :       if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
     460              :         {
     461      6391460 :           *bitposp = ptr_misalign * BITS_PER_UNIT;
     462      6391460 :           *alignp = ptr_align * BITS_PER_UNIT;
     463              :           /* Make sure to return a sensible alignment when the multiplication
     464              :              by BITS_PER_UNIT overflowed.  */
     465      6391460 :           if (*alignp == 0)
     466           30 :             *alignp = 1u << (HOST_BITS_PER_INT - 1);
     467              :           /* We cannot really tell whether this result is an approximation.  */
     468      6391460 :           return false;
     469              :         }
     470              :       else
     471              :         {
     472     51563158 :           *bitposp = 0;
     473     51563158 :           *alignp = BITS_PER_UNIT;
     474     51563158 :           return false;
     475              :         }
     476              :     }
     477      2212737 :   else if (TREE_CODE (exp) == INTEGER_CST)
     478              :     {
     479        17541 :       *alignp = BIGGEST_ALIGNMENT;
     480        17541 :       *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
     481        17541 :                   & (BIGGEST_ALIGNMENT - 1));
     482        17541 :       return true;
     483              :     }
     484              : 
     485      2195196 :   *bitposp = 0;
     486      2195196 :   *alignp = BITS_PER_UNIT;
     487      2195196 :   return false;
     488              : }
     489              : 
     490              : /* Return the alignment in bits of EXP, a pointer valued expression.
     491              :    The alignment returned is, by default, the alignment of the thing that
     492              :    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
     493              : 
     494              :    Otherwise, look at the expression to see if we can do better, i.e., if the
     495              :    expression is actually pointing at an object whose alignment is tighter.  */
     496              : 
     497              : unsigned int
     498     11493711 : get_pointer_alignment (tree exp)
     499              : {
     500     11493711 :   unsigned HOST_WIDE_INT bitpos = 0;
     501     11493711 :   unsigned int align;
     502              : 
     503     11493711 :   get_pointer_alignment_1 (exp, &align, &bitpos);
     504              : 
     505              :   /* align and bitpos now specify known low bits of the pointer.
     506              :      ptr & (align - 1) == bitpos.  */
     507              : 
     508     11493711 :   if (bitpos != 0)
     509        79430 :     align = least_bit_hwi (bitpos);
     510              : 
     511     11493711 :   return align;
     512              : }
     513              : 
     514              : /* Return the number of leading non-zero elements in the sequence
     515              :    [ PTR, PTR + MAXELTS ) where each element's size is ELTSIZE bytes.
     516              :    ELTSIZE must be a power of 2 less than 8.  Used by c_strlen.  */
     517              : 
     518              : unsigned
     519       772490 : string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
     520              : {
     521       772490 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     522              : 
     523       772490 :   unsigned n;
     524              : 
     525       772490 :   if (eltsize == 1)
     526              :     {
     527              :       /* Optimize the common case of plain char.  */
     528    244947041 :       for (n = 0; n < maxelts; n++)
     529              :         {
     530    244858003 :           const char *elt = (const char*) ptr + n;
     531    244858003 :           if (!*elt)
     532              :             break;
     533              :         }
     534              :     }
     535              :   else
     536              :     {
     537          590 :       for (n = 0; n < maxelts; n++)
     538              :         {
     539          566 :           const char *elt = (const char*) ptr + n * eltsize;
     540          566 :           if (!memcmp (elt, "\0\0\0\0", eltsize))
     541              :             break;
     542              :         }
     543              :     }
     544       772490 :   return n;
     545              : }
     546              : 
     547              : /* Compute the length of a null-terminated character string or wide
     548              :    character string handling character sizes of 1, 2, and 4 bytes.
     549              :    TREE_STRING_LENGTH is not the right way because it evaluates to
     550              :    the size of the character array in bytes (as opposed to characters)
     551              :    and because it can contain a zero byte in the middle.
     552              : 
     553              :    ONLY_VALUE should be nonzero if the result is not going to be emitted
     554              :    into the instruction stream and zero if it is going to be expanded.
     555              :    E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
     556              :    is returned, otherwise NULL, since
     557              :    len = c_strlen (ARG, 1); if (len) expand_expr (len, ...); would not
     558              :    evaluate the side-effects.
     559              : 
     560              :    If ONLY_VALUE is two then we do not emit warnings about out-of-bound
     561              :    accesses.  Note that this implies the result is not going to be emitted
     562              :    into the instruction stream.
     563              : 
     564              :    Additional information about the string accessed may be recorded
     565              :    in DATA.  For example, if ARG references an unterminated string,
     566              :    then the declaration will be stored in the DECL field.   If the
     567              :    length of the unterminated string can be determined, it'll be
     568              :    stored in the LEN field.  Note this length could well be different
     569              :    than what a C strlen call would return.
     570              : 
     571              :    ELTSIZE is 1 for normal single byte character strings, and 2 or
     572              :    4 for wide character strings.  ELTSIZE is by default 1.
     573              : 
     574              :    The value returned is of type `ssizetype'.  */
     575              : 
     576              : tree
     577      2581583 : c_strlen (tree arg, int only_value, c_strlen_data *data, unsigned eltsize)
     578              : {
     579              :   /* If we were not passed a DATA pointer, then get one to a local
     580              :      structure.  That avoids having to check DATA for NULL before
     581              :      each time we want to use it.  */
     582      2581583 :   c_strlen_data local_strlen_data = { };
     583      2581583 :   if (!data)
     584       602146 :     data = &local_strlen_data;
     585              : 
     586      2581583 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     587              : 
     588      2581583 :   tree src = STRIP_NOPS (arg);
     589      2581583 :   if (TREE_CODE (src) == COND_EXPR
     590      2581583 :       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     591              :     {
     592          687 :       tree len1, len2;
     593              : 
     594          687 :       len1 = c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
     595          687 :       len2 = c_strlen (TREE_OPERAND (src, 2), only_value, data, eltsize);
     596          687 :       if (tree_int_cst_equal (len1, len2))
     597              :         return len1;
     598              :     }
     599              : 
     600      2581417 :   if (TREE_CODE (src) == COMPOUND_EXPR
     601      2581417 :       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     602           45 :     return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
     603              : 
     604      2581372 :   location_t loc = EXPR_LOC_OR_LOC (src, input_location);
     605              : 
     606              :   /* Offset from the beginning of the string in bytes.  */
     607      2581372 :   tree byteoff;
     608      2581372 :   tree memsize;
     609      2581372 :   tree decl;
     610      2581372 :   src = string_constant (src, &byteoff, &memsize, &decl);
     611      2581372 :   if (src == 0)
     612              :     return NULL_TREE;
     613              : 
     614              :   /* Determine the size of the string element.  */
     615       788722 :   if (eltsize != tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src)))))
     616              :     return NULL_TREE;
     617              : 
     618              :   /* Set MAXELTS to ARRAY_SIZE (SRC) - 1, the maximum possible
     619              :      length of SRC.  Prefer TYPE_SIZE() to TREE_STRING_LENGTH() if possible
     620              :      in case the latter is less than the size of the array, such as when
     621              :      SRC refers to a short string literal used to initialize a large array.
     622              :      In that case, the elements of the array after the terminating NUL are
     623              :      all NUL.  */
     624       776318 :   HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
     625       776318 :   strelts = strelts / eltsize;
     626              : 
     627       776318 :   if (!tree_fits_uhwi_p (memsize))
     628              :     return NULL_TREE;
     629              : 
     630       776318 :   HOST_WIDE_INT maxelts = tree_to_uhwi (memsize) / eltsize;
     631              : 
     632              :   /* PTR can point to the byte representation of any string type, including
     633              :      char* and wchar_t*.  */
     634       776318 :   const char *ptr = TREE_STRING_POINTER (src);
     635              : 
     636       776318 :   if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
     637              :     {
     638              :       /* The code below works only for single byte character types.  */
     639         4714 :       if (eltsize != 1)
     640              :         return NULL_TREE;
     641              : 
     642              :       /* If the string has an internal NUL character followed by any
     643              :          non-NUL characters (e.g., "foo\0bar"), we can't compute
     644              :          the offset to the following NUL if we don't know where to
     645              :          start searching for it.  */
     646         4714 :       unsigned len = string_length (ptr, eltsize, strelts);
     647              : 
     648              :       /* Return when an embedded null character is found or none at all.
     649              :          In the latter case, set the DECL/LEN field in the DATA structure
     650              :          so that callers may examine them.  */
     651         4714 :       if (len + 1 < strelts)
     652              :         return NULL_TREE;
     653         4144 :       else if (len >= maxelts)
     654              :         {
     655         1102 :           data->decl = decl;
     656         1102 :           data->off = byteoff;
     657         1102 :           data->minlen = ssize_int (len);
     658         1102 :           return NULL_TREE;
     659              :         }
     660              : 
     661              :       /* For empty strings the result should be zero.  */
     662         3042 :       if (len == 0)
     663           39 :         return ssize_int (0);
     664              : 
     665              :       /* We don't know the starting offset, but we do know that the string
     666              :          has no internal zero bytes.  If the offset falls within the bounds
     667              :          of the string subtract the offset from the length of the string,
     668              :          and return that.  Otherwise the length is zero.  Take care to
     669              :          use SAVE_EXPR in case the OFFSET has side-effects.  */
     670         3003 :       tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
     671              :                                                  : byteoff;
     672         3003 :       offsave = fold_convert_loc (loc, sizetype, offsave);
     673         3003 :       tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
     674         3003 :                                       size_int (len));
     675         3003 :       tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
     676              :                                      offsave);
     677         3003 :       lenexp = fold_convert_loc (loc, ssizetype, lenexp);
     678         3003 :       return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
     679         3003 :                               build_zero_cst (ssizetype));
     680              :     }
     681              : 
     682              :   /* Offset from the beginning of the string in elements.  */
     683       771604 :   HOST_WIDE_INT eltoff;
     684              : 
     685              :   /* We have a known offset into the string.  Start searching there for
     686              :      a null character if we can represent it as a single HOST_WIDE_INT.  */
     687       771604 :   if (byteoff == 0)
     688              :     eltoff = 0;
     689       771604 :   else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
     690              :     eltoff = -1;
     691              :   else
     692       770416 :     eltoff = tree_to_uhwi (byteoff) / eltsize;
     693              : 
     694              :   /* If the offset is known to be out of bounds, warn, and call strlen at
     695              :      runtime.  */
     696       771604 :   if (eltoff < 0 || eltoff >= maxelts)
     697              :     {
     698              :       /* Suppress multiple warnings for propagated constant strings.  */
     699         3828 :       if (only_value != 2
     700         3828 :           && !warning_suppressed_p (arg, OPT_Warray_bounds_)
     701         7656 :           && warning_at (loc, OPT_Warray_bounds_,
     702              :                          "offset %qwi outside bounds of constant string",
     703              :                          eltoff))
     704              :         {
     705          679 :           if (decl)
     706          678 :             inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
     707          679 :           suppress_warning (arg, OPT_Warray_bounds_);
     708              :         }
     709         3828 :       return NULL_TREE;
     710              :     }
     711              : 
     712              :   /* If eltoff is larger than strelts but less than maxelts the
     713              :      string length is zero, since the excess memory will be zero.  */
     714       767776 :   if (eltoff > strelts)
     715            0 :     return ssize_int (0);
     716              : 
     717              :   /* Use strlen to search for the first zero byte.  Since any strings
     718              :      constructed with build_string will have nulls appended, we win even
     719              :      if we get handed something like (char[4])"abcd".
     720              : 
     721              :      Since ELTOFF is our starting index into the string, no further
     722              :      calculation is needed.  */
     723       767776 :   unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
     724       767776 :                                 strelts - eltoff);
     725              : 
     726              :   /* Don't know what to return if there was no zero termination.
     727              :      Ideally this would turn into a gcc_checking_assert over time.
     728              :      Set DECL/LEN so callers can examine them.  */
     729       767776 :   if (len >= maxelts - eltoff)
     730              :     {
     731        83476 :       data->decl = decl;
     732        83476 :       data->off = byteoff;
     733        83476 :       data->minlen = ssize_int (len);
     734        83476 :       return NULL_TREE;
     735              :     }
     736              : 
     737       684300 :   return ssize_int (len);
     738              : }
     739              : 
     740              : /* Return a constant integer corresponding to target reading
     741              :    GET_MODE_BITSIZE (MODE) bits from string constant STR.  If
     742              :    NULL_TERMINATED_P, reading stops after '\0' character, all further ones
     743              :    are assumed to be zero, otherwise it reads as many characters
     744              :    as needed.  */
     745              : 
     746              : rtx
     747       289482 : c_readstr (const char *str, fixed_size_mode mode,
     748              :            bool null_terminated_p/*=true*/)
     749              : {
     750       289482 :   auto_vec<target_unit, MAX_BITSIZE_MODE_ANY_INT / BITS_PER_UNIT> bytes;
     751              : 
     752       578964 :   bytes.reserve (GET_MODE_SIZE (mode));
     753              : 
     754       289482 :   target_unit ch = 1;
     755      4708120 :   for (unsigned int i = 0; i < GET_MODE_SIZE (mode); ++i)
     756              :     {
     757      2064578 :       if (ch || !null_terminated_p)
     758      1977337 :         ch = (unsigned char) str[i];
     759      2064578 :       bytes.quick_push (ch);
     760              :     }
     761              : 
     762       289482 :   return native_decode_rtx (mode, bytes, 0);
     763       289482 : }
     764              : 
     765              : /* Cast a target constant CST to target CHAR and if that value fits into
     766              :    host char type, return zero and put that value into variable pointed to by
     767              :    P.  */
     768              : 
     769              : static int
     770        60140 : target_char_cast (tree cst, char *p)
     771              : {
     772        60140 :   unsigned HOST_WIDE_INT val, hostval;
     773              : 
     774        60140 :   if (TREE_CODE (cst) != INTEGER_CST
     775              :       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
     776              :     return 1;
     777              : 
     778              :   /* Do not care if it fits or not right here.  */
     779        60140 :   val = TREE_INT_CST_LOW (cst);
     780              : 
     781        60140 :   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
     782        60140 :     val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
     783              : 
     784        60140 :   hostval = val;
     785        60140 :   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
     786        60140 :     hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
     787              : 
     788        60140 :   if (val != hostval)
     789              :     return 1;
     790              : 
     791        60140 :   *p = hostval;
     792        60140 :   return 0;
     793              : }
     794              : 
     795              : /* Similar to save_expr, but assumes that arbitrary code is not executed
     796              :    in between the multiple evaluations.  In particular, we assume that a
     797              :    non-addressable local variable will not be modified.  */
     798              : 
     799              : static tree
     800      1127481 : builtin_save_expr (tree exp)
     801              : {
     802      1127481 :   if (TREE_CODE (exp) == SSA_NAME
     803       963923 :       || (TREE_ADDRESSABLE (exp) == 0
     804       963731 :           && (TREE_CODE (exp) == PARM_DECL
     805       431338 :               || (VAR_P (exp) && !TREE_STATIC (exp)))))
     806              :     return exp;
     807              : 
     808       429529 :   return save_expr (exp);
     809              : }
     810              : 
     811              : /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
     812              :    times to get the address of either a higher stack frame, or a return
     813              :    address located within it (depending on FNDECL_CODE).  */
     814              : 
     815              : static rtx
     816        15922 : expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
     817              : {
     818        15922 :   int i;
     819        15922 :   rtx tem = INITIAL_FRAME_ADDRESS_RTX;
     820        15922 :   if (tem == NULL_RTX)
     821              :     {
     822              :       /* For a zero count with __builtin_return_address, we don't care what
     823              :          frame address we return, because target-specific definitions will
     824              :          override us.  Therefore frame pointer elimination is OK, and using
     825              :          the soft frame pointer is OK.
     826              : 
     827              :          For a nonzero count, or a zero count with __builtin_frame_address,
     828              :          we require a stable offset from the current frame pointer to the
     829              :          previous one, so we must use the hard frame pointer, and
     830              :          we must disable frame pointer elimination.  */
     831        15922 :       if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
     832         4331 :         tem = frame_pointer_rtx;
     833              :       else
     834              :         {
     835        11591 :           tem = hard_frame_pointer_rtx;
     836              : 
     837              :           /* Tell reload not to eliminate the frame pointer.  */
     838        11591 :           crtl->accesses_prior_frames = 1;
     839              :         }
     840              :     }
     841              : 
     842        15922 :   if (count > 0)
     843          932 :     SETUP_FRAME_ADDRESSES ();
     844              : 
     845              :   /* On the SPARC, the return address is not in the frame, it is in a
     846              :      register.  There is no way to access it off of the current frame
     847              :      pointer, but it can be accessed off the previous frame pointer by
     848              :      reading the value from the register window save area.  */
     849              :   if (RETURN_ADDR_IN_PREVIOUS_FRAME && fndecl_code == BUILT_IN_RETURN_ADDRESS)
     850              :     count--;
     851              : 
     852              :   /* Scan back COUNT frames to the specified frame.  */
     853        51798 :   for (i = 0; i < count; i++)
     854              :     {
     855              :       /* Assume the dynamic chain pointer is in the word that the
     856              :          frame address points to, unless otherwise specified.  */
     857        35876 :       tem = DYNAMIC_CHAIN_ADDRESS (tem);
     858        35876 :       tem = memory_address (Pmode, tem);
     859        35876 :       tem = gen_frame_mem (Pmode, tem);
     860        35876 :       tem = copy_to_reg (tem);
     861              :     }
     862              : 
     863              :   /* For __builtin_frame_address, return what we've got.  But, on
     864              :      the SPARC for example, we may have to add a bias.  */
     865        15922 :   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
     866              :     return FRAME_ADDR_RTX (tem);
     867              : 
     868              :   /* For __builtin_return_address, get the return address from that frame.  */
     869              : #ifdef RETURN_ADDR_RTX
     870         7400 :   tem = RETURN_ADDR_RTX (count, tem);
     871              : #else
     872              :   tem = memory_address (Pmode,
     873              :                         plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
     874              :   tem = gen_frame_mem (Pmode, tem);
     875              : #endif
     876         5171 :   return tem;
     877              : }
     878              : 
     879              : /* Alias set used for setjmp buffer.  */
     880              : static alias_set_type setjmp_alias_set = -1;
     881              : 
     882              : /* Construct the leading half of a __builtin_setjmp call.  Control will
     883              :    return to RECEIVER_LABEL.  This is also called directly by the SJLJ
     884              :    exception handling code.  */
     885              : 
     886              : void
     887          841 : expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
     888              : {
     889          841 :   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
     890          841 :   rtx stack_save;
     891          841 :   rtx mem;
     892              : 
     893          841 :   if (setjmp_alias_set == -1)
     894          241 :     setjmp_alias_set = new_alias_set ();
     895              : 
     896          841 :   buf_addr = convert_memory_address (Pmode, buf_addr);
     897              : 
     898          842 :   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
     899              : 
     900              :   /* We store the frame pointer and the address of receiver_label in
     901              :      the buffer and use the rest of it for the stack save area, which
     902              :      is machine-dependent.  */
     903              : 
     904          842 :   mem = gen_rtx_MEM (Pmode, buf_addr);
     905          841 :   set_mem_alias_set (mem, setjmp_alias_set);
     906          841 :   emit_move_insn (mem, hard_frame_pointer_rtx);
     907              : 
     908          842 :   mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
     909         1682 :                                            GET_MODE_SIZE (Pmode))),
     910          841 :   set_mem_alias_set (mem, setjmp_alias_set);
     911              : 
     912         1682 :   emit_move_insn (validize_mem (mem),
     913         1682 :                   force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
     914              : 
     915          841 :   stack_save = gen_rtx_MEM (sa_mode,
     916              :                             plus_constant (Pmode, buf_addr,
     917         1682 :                                            2 * GET_MODE_SIZE (Pmode)));
     918          841 :   set_mem_alias_set (stack_save, setjmp_alias_set);
     919          841 :   emit_stack_save (SAVE_NONLOCAL, &stack_save);
     920              : 
     921              :   /* If there is further processing to do, do it.  */
     922          841 :   if (targetm.have_builtin_setjmp_setup ())
     923            0 :     emit_insn (targetm.gen_builtin_setjmp_setup (buf_addr));
     924              : 
     925              :   /* We have a nonlocal label.   */
     926          841 :   cfun->has_nonlocal_label = 1;
     927          841 : }
     928              : 
     929              : /* Construct the trailing part of a __builtin_setjmp call.  This is
     930              :    also called directly by the SJLJ exception handling code.
     931              :    If RECEIVER_LABEL is NULL, instead construct a nonlocal goto handler.  */
     932              : 
     933              : void
     934         1345 : expand_builtin_setjmp_receiver (rtx receiver_label)
     935              : {
     936         1345 :   rtx chain;
     937              : 
     938              :   /* Mark the FP as used when we get here, so we have to make sure it's
     939              :      marked as used by this function.  */
     940         1345 :   emit_use (hard_frame_pointer_rtx);
     941              : 
     942              :   /* Mark the static chain as clobbered here so life information
     943              :      doesn't get messed up for it.  */
     944         1345 :   chain = rtx_for_static_chain (current_function_decl, true);
     945         1345 :   if (chain && REG_P (chain))
     946            1 :     emit_clobber (chain);
     947              : 
     948         1345 :   if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM])
     949              :     {
     950              :       /* If the argument pointer can be eliminated in favor of the
     951              :          frame pointer, we don't need to restore it.  We assume here
     952              :          that if such an elimination is present, it can always be used.
     953              :          This is the case on all known machines; if we don't make this
     954              :          assumption, we do unnecessary saving on many machines.  */
     955              :       size_t i;
     956              :       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
     957              : 
     958         2690 :       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
     959         2690 :         if (elim_regs[i].from == ARG_POINTER_REGNUM
     960         2690 :             && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
     961              :           break;
     962              : 
     963         1345 :       if (i == ARRAY_SIZE (elim_regs))
     964              :         {
     965              :           /* Now restore our arg pointer from the address at which it
     966              :              was saved in our stack frame.  */
     967            0 :           emit_move_insn (crtl->args.internal_arg_pointer,
     968              :                           copy_to_reg (get_arg_pointer_save_area ()));
     969              :         }
     970              :     }
     971              : 
     972         1345 :   if (receiver_label != NULL && targetm.have_builtin_setjmp_receiver ())
     973            0 :     emit_insn (targetm.gen_builtin_setjmp_receiver (receiver_label));
     974         1345 :   else if (targetm.have_nonlocal_goto_receiver ())
     975            0 :     emit_insn (targetm.gen_nonlocal_goto_receiver ());
     976              :   else
     977              :     { /* Nothing */ }
     978              : 
     979              :   /* We must not allow the code we just generated to be reordered by
     980              :      scheduling.  Specifically, the update of the frame pointer must
     981              :      happen immediately, not later.  */
     982         1345 :   emit_insn (gen_blockage ());
     983         1345 : }
     984              : 
     985              : /* __builtin_longjmp is passed a pointer to an array of five words (not
     986              :    all will be used on all machines).  It operates similarly to the C
     987              :    library function of the same name, but is more efficient.  Much of
     988              :    the code below is copied from the handling of non-local gotos.  */
     989              : 
     990              : static void
     991          391 : expand_builtin_longjmp (rtx buf_addr, rtx value)
     992              : {
     993          391 :   rtx fp, lab, stack;
     994          391 :   rtx_insn *insn, *last;
     995          391 :   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
     996              : 
     997              :   /* DRAP is needed for stack realign if longjmp is expanded to current
     998              :      function  */
     999          391 :   if (SUPPORTS_STACK_ALIGNMENT)
    1000          391 :     crtl->need_drap = true;
    1001              : 
    1002          391 :   if (setjmp_alias_set == -1)
    1003          330 :     setjmp_alias_set = new_alias_set ();
    1004              : 
    1005          391 :   buf_addr = convert_memory_address (Pmode, buf_addr);
    1006              : 
    1007          392 :   buf_addr = force_reg (Pmode, buf_addr);
    1008              : 
    1009              :   /* We require that the user must pass a second argument of 1, because
    1010              :      that is what builtin_setjmp will return.  */
    1011          391 :   gcc_assert (value == const1_rtx);
    1012              : 
    1013          391 :   last = get_last_insn ();
    1014          391 :   if (targetm.have_builtin_longjmp ())
    1015            0 :     emit_insn (targetm.gen_builtin_longjmp (buf_addr));
    1016              :   else
    1017              :     {
    1018          392 :       fp = gen_rtx_MEM (Pmode, buf_addr);
    1019          392 :       lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
    1020          782 :                                                GET_MODE_SIZE (Pmode)));
    1021              : 
    1022          391 :       stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
    1023          782 :                                                    2 * GET_MODE_SIZE (Pmode)));
    1024          391 :       set_mem_alias_set (fp, setjmp_alias_set);
    1025          391 :       set_mem_alias_set (lab, setjmp_alias_set);
    1026          391 :       set_mem_alias_set (stack, setjmp_alias_set);
    1027              : 
    1028              :       /* Pick up FP, label, and SP from the block and jump.  This code is
    1029              :          from expand_goto in stmt.cc; see there for detailed comments.  */
    1030          391 :       if (targetm.have_nonlocal_goto ())
    1031              :         /* We have to pass a value to the nonlocal_goto pattern that will
    1032              :            get copied into the static_chain pointer, but it does not matter
    1033              :            what that value is, because builtin_setjmp does not use it.  */
    1034            0 :         emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
    1035              :       else
    1036              :         {
    1037          391 :           emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
    1038          391 :           emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
    1039              : 
    1040          391 :           lab = copy_to_reg (lab);
    1041              : 
    1042              :           /* Restore the frame pointer and stack pointer.  We must use a
    1043              :              temporary since the setjmp buffer may be a local.  */
    1044          391 :           fp = copy_to_reg (fp);
    1045          391 :           emit_stack_restore (SAVE_NONLOCAL, stack);
    1046              : 
    1047              :           /* Ensure the frame pointer move is not optimized.  */
    1048          391 :           emit_insn (gen_blockage ());
    1049          391 :           emit_clobber (hard_frame_pointer_rtx);
    1050          391 :           emit_clobber (frame_pointer_rtx);
    1051          391 :           emit_move_insn (hard_frame_pointer_rtx, fp);
    1052              : 
    1053          391 :           emit_use (hard_frame_pointer_rtx);
    1054          391 :           emit_use (stack_pointer_rtx);
    1055          391 :           emit_indirect_jump (lab);
    1056              :         }
    1057              :     }
    1058              : 
    1059              :   /* Search backwards and mark the jump insn as a non-local goto.
    1060              :      Note that this precludes the use of __builtin_longjmp to a
    1061              :      __builtin_setjmp target in the same function.  However, we've
    1062              :      already cautioned the user that these functions are for
    1063              :      internal exception handling use only.  */
    1064          782 :   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
    1065              :     {
    1066          782 :       gcc_assert (insn != last);
    1067              : 
    1068          782 :       if (JUMP_P (insn))
    1069              :         {
    1070          391 :           add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
    1071          391 :           break;
    1072              :         }
    1073          391 :       else if (CALL_P (insn))
    1074              :         break;
    1075              :     }
    1076          391 : }
    1077              : 
    1078              : static inline bool
    1079      1930389 : more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
    1080              : {
    1081      1930389 :   return (iter->i < iter->n);
    1082              : }
    1083              : 
    1084              : /* This function validates the types of a function call argument list
    1085              :    against a specified list of tree_codes.  If the last specifier is a 0,
    1086              :    that represents an ellipsis, otherwise the last specifier must be a
    1087              :    VOID_TYPE.  */
    1088              : 
    1089              : static bool
    1090       505121 : validate_arglist (const_tree callexpr, ...)
    1091              : {
    1092       505121 :   enum tree_code code;
    1093       505121 :   bool res = 0;
    1094       505121 :   va_list ap;
    1095       505121 :   const_call_expr_arg_iterator iter;
    1096       505121 :   const_tree arg;
    1097              : 
    1098       505121 :   va_start (ap, callexpr);
    1099       505121 :   init_const_call_expr_arg_iterator (callexpr, &iter);
    1100              : 
    1101              :   /* Get a bitmap of pointer argument numbers declared attribute nonnull.  */
    1102       505121 :   tree fn = CALL_EXPR_FN (callexpr);
    1103       505121 :   bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
    1104              : 
    1105       505121 :   for (unsigned argno = 1; ; ++argno)
    1106              :     {
    1107      1761361 :       code = (enum tree_code) va_arg (ap, int);
    1108              : 
    1109      1761361 :       switch (code)
    1110              :         {
    1111         2046 :         case 0:
    1112              :           /* This signifies an ellipses, any further arguments are all ok.  */
    1113         2046 :           res = true;
    1114         2046 :           goto end;
    1115       502842 :         case VOID_TYPE:
    1116              :           /* This signifies an endlink, if no arguments remain, return
    1117              :              true, otherwise return false.  */
    1118       502842 :           res = !more_const_call_expr_args_p (&iter);
    1119       502842 :           goto end;
    1120       828160 :         case POINTER_TYPE:
    1121              :           /* The actual argument must be nonnull when either the whole
    1122              :              called function has been declared nonnull, or when the formal
    1123              :              argument corresponding to the actual argument has been.  */
    1124       828160 :           if (argmap
    1125       828160 :               && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
    1126              :             {
    1127       281957 :               arg = next_const_call_expr_arg (&iter);
    1128       281957 :               if (!validate_arg (arg, code) || integer_zerop (arg))
    1129           59 :                 goto end;
    1130              :               break;
    1131              :             }
    1132              :           /* FALLTHRU */
    1133       974516 :         default:
    1134              :           /* If no parameters remain or the parameter's code does not
    1135              :              match the specified code, return false.  Otherwise continue
    1136              :              checking any remaining arguments.  */
    1137       974516 :           arg = next_const_call_expr_arg (&iter);
    1138       974516 :           if (!validate_arg (arg, code))
    1139          174 :             goto end;
    1140              :           break;
    1141              :         }
    1142              :     }
    1143              : 
    1144              :   /* We need gotos here since we can only have one VA_CLOSE in a
    1145              :      function.  */
    1146       505121 :  end: ;
    1147       505121 :   va_end (ap);
    1148              : 
    1149       505121 :   BITMAP_FREE (argmap);
    1150              : 
    1151       505121 :   if (res)
    1152       504888 :     for (tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_TYPE (fn)));
    1153       732565 :          (attrs = lookup_attribute ("nonnull_if_nonzero", attrs));
    1154       227677 :          attrs = TREE_CHAIN (attrs))
    1155              :       {
    1156       227699 :         tree args = TREE_VALUE (attrs);
    1157       227699 :         unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
    1158       227699 :         unsigned int idx2
    1159       227699 :           = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
    1160       227699 :         unsigned int idx3 = idx2;
    1161       227699 :         if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args)))
    1162            0 :           idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1;
    1163       227699 :         if (idx < (unsigned) call_expr_nargs (callexpr)
    1164       227699 :             && idx2 < (unsigned) call_expr_nargs (callexpr)
    1165       227699 :             && idx3 < (unsigned) call_expr_nargs (callexpr)
    1166       227699 :             && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx)))
    1167       227699 :             && integer_zerop (CALL_EXPR_ARG (callexpr, idx))
    1168           87 :             && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx2)))
    1169           87 :             && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx2))
    1170           22 :             && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx3)))
    1171       227721 :             && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx3)))
    1172              :           return false;
    1173              :       }
    1174              : 
    1175              :   return res;
    1176              : }
    1177              : 
    1178              : /* Expand a call to __builtin_nonlocal_goto.  We're passed the target label
    1179              :    and the address of the save area.  */
    1180              : 
    1181              : static rtx
    1182          512 : expand_builtin_nonlocal_goto (tree exp)
    1183              : {
    1184          512 :   tree t_label, t_save_area;
    1185          512 :   rtx r_label, r_save_area, r_fp, r_sp;
    1186          512 :   rtx_insn *insn;
    1187              : 
    1188          512 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    1189              :     return NULL_RTX;
    1190              : 
    1191          512 :   t_label = CALL_EXPR_ARG (exp, 0);
    1192          512 :   t_save_area = CALL_EXPR_ARG (exp, 1);
    1193              : 
    1194          512 :   r_label = expand_normal (t_label);
    1195          512 :   r_label = convert_memory_address (Pmode, r_label);
    1196          512 :   r_save_area = expand_normal (t_save_area);
    1197          512 :   r_save_area = convert_memory_address (Pmode, r_save_area);
    1198              :   /* Copy the address of the save location to a register just in case it was
    1199              :      based on the frame pointer.   */
    1200          512 :   r_save_area = copy_to_reg (r_save_area);
    1201          512 :   r_fp = gen_rtx_MEM (Pmode, r_save_area);
    1202          512 :   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
    1203              :                       plus_constant (Pmode, r_save_area,
    1204         1024 :                                      GET_MODE_SIZE (Pmode)));
    1205              : 
    1206          512 :   crtl->has_nonlocal_goto = 1;
    1207              : 
    1208              :   /* ??? We no longer need to pass the static chain value, afaik.  */
    1209          512 :   if (targetm.have_nonlocal_goto ())
    1210            0 :     emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
    1211              :   else
    1212              :     {
    1213          512 :       emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
    1214          512 :       emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
    1215              : 
    1216          512 :       r_label = copy_to_reg (r_label);
    1217              : 
    1218              :       /* Restore the frame pointer and stack pointer.  We must use a
    1219              :          temporary since the setjmp buffer may be a local.  */
    1220          512 :       r_fp = copy_to_reg (r_fp);
    1221          512 :       emit_stack_restore (SAVE_NONLOCAL, r_sp);
    1222              : 
    1223              :       /* Ensure the frame pointer move is not optimized.  */
    1224          512 :       emit_insn (gen_blockage ());
    1225          512 :       emit_clobber (hard_frame_pointer_rtx);
    1226          512 :       emit_clobber (frame_pointer_rtx);
    1227          512 :       emit_move_insn (hard_frame_pointer_rtx, r_fp);
    1228              : 
    1229              :       /* USE of hard_frame_pointer_rtx added for consistency;
    1230              :          not clear if really needed.  */
    1231          512 :       emit_use (hard_frame_pointer_rtx);
    1232          512 :       emit_use (stack_pointer_rtx);
    1233              : 
    1234              :       /* If the architecture is using a GP register, we must
    1235              :          conservatively assume that the target function makes use of it.
    1236              :          The prologue of functions with nonlocal gotos must therefore
    1237              :          initialize the GP register to the appropriate value, and we
    1238              :          must then make sure that this value is live at the point
    1239              :          of the jump.  (Note that this doesn't necessarily apply
    1240              :          to targets with a nonlocal_goto pattern; they are free
    1241              :          to implement it in their own way.  Note also that this is
    1242              :          a no-op if the GP register is a global invariant.)  */
    1243          512 :       unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
    1244            0 :       if (regnum != INVALID_REGNUM && fixed_regs[regnum])
    1245            0 :         emit_use (pic_offset_table_rtx);
    1246              : 
    1247          512 :       emit_indirect_jump (r_label);
    1248              :     }
    1249              : 
    1250              :   /* Search backwards to the jump insn and mark it as a
    1251              :      non-local goto.  */
    1252         1024 :   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
    1253              :     {
    1254         1024 :       if (JUMP_P (insn))
    1255              :         {
    1256          512 :           add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
    1257          512 :           break;
    1258              :         }
    1259          512 :       else if (CALL_P (insn))
    1260              :         break;
    1261              :     }
    1262              : 
    1263          512 :   return const0_rtx;
    1264              : }
    1265              : 
    1266              : /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
    1267              :    (not all will be used on all machines) that was passed to __builtin_setjmp.
    1268              :    It updates the stack pointer in that block to the current value.  This is
    1269              :    also called directly by the SJLJ exception handling code.  */
    1270              : 
    1271              : void
    1272            0 : expand_builtin_update_setjmp_buf (rtx buf_addr)
    1273              : {
    1274            0 :   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
    1275            0 :   buf_addr = convert_memory_address (Pmode, buf_addr);
    1276            0 :   rtx stack_save
    1277            0 :     = gen_rtx_MEM (sa_mode,
    1278            0 :                    memory_address
    1279              :                    (sa_mode,
    1280              :                     plus_constant (Pmode, buf_addr,
    1281            0 :                                    2 * GET_MODE_SIZE (Pmode))));
    1282              : 
    1283            0 :   emit_stack_save (SAVE_NONLOCAL, &stack_save);
    1284            0 : }
    1285              : 
    1286              : /* Expand a call to __builtin_prefetch.  For a target that does not support
    1287              :    data prefetch, evaluate the memory address argument in case it has side
    1288              :    effects.  */
    1289              : 
    1290              : static void
    1291         2046 : expand_builtin_prefetch (tree exp)
    1292              : {
    1293         2046 :   tree arg0, arg1, arg2;
    1294         2046 :   int nargs;
    1295         2046 :   rtx op0, op1, op2;
    1296              : 
    1297         2046 :   if (!validate_arglist (exp, POINTER_TYPE, 0))
    1298              :     return;
    1299              : 
    1300         2046 :   arg0 = CALL_EXPR_ARG (exp, 0);
    1301              : 
    1302              :   /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
    1303              :      zero (read) and argument 2 (locality) defaults to 3 (high degree of
    1304              :      locality).  */
    1305         2046 :   nargs = call_expr_nargs (exp);
    1306         2046 :   arg1 = nargs > 1 ? CALL_EXPR_ARG (exp, 1) : NULL_TREE;
    1307         2006 :   arg2 = nargs > 2 ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
    1308              : 
    1309              :   /* Argument 0 is an address.  */
    1310         2142 :   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
    1311              : 
    1312              :   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
    1313         2046 :   if (arg1 == NULL_TREE)
    1314           40 :     op1 = const0_rtx;
    1315         2006 :   else if (TREE_CODE (arg1) != INTEGER_CST)
    1316              :     {
    1317            0 :       error ("second argument to %<__builtin_prefetch%> must be a constant");
    1318            0 :       op1 = const0_rtx;
    1319              :     }
    1320              :   else
    1321         2006 :     op1 = expand_normal (arg1);
    1322              :   /* Argument 1 must be 0, 1 or 2.  */
    1323         2046 :   if (!IN_RANGE (INTVAL (op1), 0, 2))
    1324              :     {
    1325            3 :       warning (0, "invalid second argument to %<__builtin_prefetch%>;"
    1326              :                " using zero");
    1327            3 :       op1 = const0_rtx;
    1328              :     }
    1329              : 
    1330              :   /* Argument 2 (locality) must be a compile-time constant int.  */
    1331         2046 :   if (arg2 == NULL_TREE)
    1332           65 :     op2 = GEN_INT (3);
    1333         1981 :   else if (TREE_CODE (arg2) != INTEGER_CST)
    1334              :     {
    1335            0 :       error ("third argument to %<__builtin_prefetch%> must be a constant");
    1336            0 :       op2 = const0_rtx;
    1337              :     }
    1338              :   else
    1339         1981 :     op2 = expand_normal (arg2);
    1340              :   /* Argument 2 must be 0, 1, 2, or 3.  */
    1341         2046 :   if (!IN_RANGE (INTVAL (op2), 0, 3))
    1342              :     {
    1343            3 :       warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
    1344            3 :       op2 = const0_rtx;
    1345              :     }
    1346              : 
    1347         2046 :   if (targetm.have_prefetch ())
    1348              :     {
    1349         2046 :       class expand_operand ops[3];
    1350              : 
    1351         2046 :       create_address_operand (&ops[0], op0);
    1352         2046 :       create_integer_operand (&ops[1], INTVAL (op1));
    1353         2046 :       create_integer_operand (&ops[2], INTVAL (op2));
    1354         2046 :       if (maybe_expand_insn (targetm.code_for_prefetch, 3, ops))
    1355         2046 :         return;
    1356              :     }
    1357              : 
    1358              :   /* Don't do anything with direct references to volatile memory, but
    1359              :      generate code to handle other side effects.  */
    1360            0 :   if (!MEM_P (op0) && side_effects_p (op0))
    1361            0 :     emit_insn (op0);
    1362              : }
    1363              : 
    1364              : /* Get a MEM rtx for expression EXP which is the address of an operand
    1365              :    to be used in a string instruction (cmpstrsi, cpymemsi, ..).  LEN is
    1366              :    the maximum length of the block of memory that might be accessed or
    1367              :    NULL if unknown.  */
    1368              : 
    1369              : rtx
    1370       758038 : get_memory_rtx (tree exp, tree len)
    1371              : {
    1372       758038 :   tree orig_exp = exp, base;
    1373       758038 :   rtx addr, mem;
    1374              : 
    1375       758038 :   gcc_checking_assert
    1376              :     (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))));
    1377              : 
    1378              :   /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
    1379              :      from its expression, for expr->a.b only <variable>.a.b is recorded.  */
    1380       758038 :   if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
    1381         1577 :     exp = TREE_OPERAND (exp, 0);
    1382              : 
    1383       758038 :   addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    1384       758038 :   mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
    1385              : 
    1386              :   /* Get an expression we can use to find the attributes to assign to MEM.
    1387              :      First remove any nops.  */
    1388      1516076 :   while (CONVERT_EXPR_P (exp)
    1389       758041 :          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
    1390            3 :     exp = TREE_OPERAND (exp, 0);
    1391              : 
    1392              :   /* Build a MEM_REF representing the whole accessed area as a byte blob,
    1393              :      (as builtin stringops may alias with anything).  */
    1394       758038 :   exp = fold_build2 (MEM_REF,
    1395              :                      build_array_type (char_type_node,
    1396              :                                        build_range_type (sizetype,
    1397              :                                                          size_one_node, len)),
    1398              :                      exp, build_int_cst (ptr_type_node, 0));
    1399              : 
    1400              :   /* If the MEM_REF has no acceptable address, try to get the base object
    1401              :      from the original address we got, and build an all-aliasing
    1402              :      unknown-sized access to that one.  */
    1403       758038 :   if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
    1404       758026 :     set_mem_attributes (mem, exp, 0);
    1405           12 :   else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
    1406           12 :            && (base = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
    1407              :                                                       0))))
    1408              :     {
    1409           12 :       unsigned int align = get_pointer_alignment (TREE_OPERAND (exp, 0));
    1410           12 :       exp = build_fold_addr_expr (base);
    1411           12 :       exp = fold_build2 (MEM_REF,
    1412              :                          build_array_type (char_type_node,
    1413              :                                            build_range_type (sizetype,
    1414              :                                                              size_zero_node,
    1415              :                                                              NULL)),
    1416              :                          exp, build_int_cst (ptr_type_node, 0));
    1417           12 :       set_mem_attributes (mem, exp, 0);
    1418              :       /* Since we stripped parts make sure the offset is unknown and the
    1419              :          alignment is computed from the original address.  */
    1420           12 :       clear_mem_offset (mem);
    1421           12 :       set_mem_align (mem, align);
    1422              :     }
    1423       758038 :   set_mem_alias_set (mem, 0);
    1424       758038 :   return mem;
    1425              : }
    1426              : 
    1427              : /* Built-in functions to perform an untyped call and return.  */
    1428              : 
    1429              : /* Wrapper that implicitly applies a delta when getting or setting the
    1430              :    enclosed value.  */
    1431              : template <typename T>
    1432              : class delta_type
    1433              : {
    1434              :   T &value; T const delta;
    1435              : public:
    1436         2524 :   delta_type (T &val, T dlt) : value (val), delta (dlt) {}
    1437         1809 :   operator T () const { return value + delta; }
    1438          715 :   T operator = (T val) const { value = val - delta; return val; }
    1439              : };
    1440              : 
    1441              : #define saved_apply_args_size \
    1442              :   (delta_type<int> (this_target_builtins->x_apply_args_size_plus_one, -1))
    1443              : #define apply_args_mode \
    1444              :   (this_target_builtins->x_apply_args_mode)
    1445              : #define saved_apply_result_size \
    1446              :   (delta_type<int> (this_target_builtins->x_apply_result_size_plus_one, -1))
    1447              : #define apply_result_mode \
    1448              :   (this_target_builtins->x_apply_result_mode)
    1449              : 
    1450              : /* Return the size required for the block returned by __builtin_apply_args,
    1451              :    and initialize apply_args_mode.  */
    1452              : 
    1453              : static int
    1454          947 : apply_args_size (void)
    1455              : {
    1456          947 :   int size = saved_apply_args_size;
    1457          947 :   int align;
    1458          947 :   unsigned int regno;
    1459              : 
    1460              :   /* The values computed by this function never change.  */
    1461          947 :   if (size < 0)
    1462              :     {
    1463              :       /* The first value is the incoming arg-pointer.  */
    1464          360 :       size = GET_MODE_SIZE (Pmode);
    1465              : 
    1466              :       /* The second value is the structure value address unless this is
    1467              :          passed as an "invisible" first argument.  */
    1468          360 :       if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
    1469            0 :         size += GET_MODE_SIZE (Pmode);
    1470              : 
    1471        33480 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1472        33120 :         if (FUNCTION_ARG_REGNO_P (regno))
    1473              :           {
    1474         5400 :             fixed_size_mode mode = targetm.calls.get_raw_arg_mode (regno);
    1475              : 
    1476         5400 :             if (mode != VOIDmode)
    1477              :               {
    1478         5400 :                 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1479         5400 :                 if (size % align != 0)
    1480            1 :                   size = CEIL (size, align) * align;
    1481         5400 :                 size += GET_MODE_SIZE (mode);
    1482         5400 :                 apply_args_mode[regno] = mode;
    1483              :               }
    1484              :             else
    1485            0 :               apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
    1486              :           }
    1487              :         else
    1488        27720 :           apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
    1489              : 
    1490          360 :       saved_apply_args_size = size;
    1491              :     }
    1492          947 :   return size;
    1493              : }
    1494              : 
    1495              : /* Return the size required for the block returned by __builtin_apply,
    1496              :    and initialize apply_result_mode.  */
    1497              : 
    1498              : static int
    1499          862 : apply_result_size (void)
    1500              : {
    1501          862 :   int size = saved_apply_result_size;
    1502          862 :   int align, regno;
    1503              : 
    1504              :   /* The values computed by this function never change.  */
    1505          862 :   if (size < 0)
    1506              :     {
    1507              :       size = 0;
    1508              : 
    1509        33015 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1510        32660 :         if (targetm.calls.function_value_regno_p (regno))
    1511              :           {
    1512         2130 :             fixed_size_mode mode = targetm.calls.get_raw_result_mode (regno);
    1513              : 
    1514         2130 :             if (mode != VOIDmode)
    1515              :               {
    1516         2130 :                 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1517         2130 :                 if (size % align != 0)
    1518              :                   size = CEIL (size, align) * align;
    1519         2130 :                 size += GET_MODE_SIZE (mode);
    1520         2130 :                 apply_result_mode[regno] = mode;
    1521              :               }
    1522              :             else
    1523            0 :               apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
    1524              :           }
    1525              :         else
    1526        30530 :           apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
    1527              : 
    1528              :       /* Allow targets that use untyped_call and untyped_return to override
    1529              :          the size so that machine-specific information can be stored here.  */
    1530              : #ifdef APPLY_RESULT_SIZE
    1531          355 :       size = APPLY_RESULT_SIZE;
    1532              : #endif
    1533              : 
    1534          355 :       saved_apply_result_size = size;
    1535              :     }
    1536          862 :   return size;
    1537              : }
    1538              : 
    1539              : /* Create a vector describing the result block RESULT.  If SAVEP is true,
    1540              :    the result block is used to save the values; otherwise it is used to
    1541              :    restore the values.  */
    1542              : 
    1543              : static rtx
    1544          483 : result_vector (int savep, rtx result)
    1545              : {
    1546          483 :   int regno, size, align, nelts;
    1547          483 :   fixed_size_mode mode;
    1548          483 :   rtx reg, mem;
    1549          483 :   rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
    1550              : 
    1551          483 :   size = nelts = 0;
    1552        44919 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1553        44436 :     if ((mode = apply_result_mode[regno]) != VOIDmode)
    1554              :       {
    1555         2898 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1556         2898 :         if (size % align != 0)
    1557            0 :           size = CEIL (size, align) * align;
    1558         2898 :         reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
    1559         2898 :         mem = adjust_address (result, mode, size);
    1560         5796 :         savevec[nelts++] = (savep
    1561         5796 :                             ? gen_rtx_SET (mem, reg)
    1562            0 :                             : gen_rtx_SET (reg, mem));
    1563         5796 :         size += GET_MODE_SIZE (mode);
    1564              :       }
    1565          483 :   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
    1566              : }
    1567              : 
    1568              : /* Save the state required to perform an untyped call with the same
    1569              :    arguments as were passed to the current function.  */
    1570              : 
    1571              : static rtx
    1572          464 : expand_builtin_apply_args_1 (void)
    1573              : {
    1574          464 :   rtx registers, tem;
    1575          464 :   int size, align, regno;
    1576          464 :   fixed_size_mode mode;
    1577          464 :   rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
    1578              : 
    1579              :   /* Create a block where the arg-pointer, structure value address,
    1580              :      and argument registers can be saved.  */
    1581          464 :   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
    1582              : 
    1583              :   /* Walk past the arg-pointer and structure value address.  */
    1584          464 :   size = GET_MODE_SIZE (Pmode);
    1585          464 :   if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
    1586            0 :     size += GET_MODE_SIZE (Pmode);
    1587              : 
    1588              :   /* Save each register used in calling a function to the block.  */
    1589        43152 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1590        42688 :     if ((mode = apply_args_mode[regno]) != VOIDmode)
    1591              :       {
    1592         6960 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1593         6960 :         if (size % align != 0)
    1594            1 :           size = CEIL (size, align) * align;
    1595              : 
    1596         6960 :         tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
    1597              : 
    1598         6960 :         emit_move_insn (adjust_address (registers, mode, size), tem);
    1599        13920 :         size += GET_MODE_SIZE (mode);
    1600              :       }
    1601              : 
    1602              :   /* Save the arg pointer to the block.  */
    1603          464 :   tem = copy_to_reg (crtl->args.internal_arg_pointer);
    1604              :   /* We need the pointer as the caller actually passed them to us, not
    1605              :      as we might have pretended they were passed.  Make sure it's a valid
    1606              :      operand, as emit_move_insn isn't expected to handle a PLUS.  */
    1607          464 :   if (STACK_GROWS_DOWNWARD)
    1608          464 :     tem
    1609          464 :       = force_operand (plus_constant (Pmode, tem,
    1610          464 :                                       crtl->args.pretend_args_size),
    1611              :                        NULL_RTX);
    1612          464 :   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
    1613              : 
    1614          464 :   size = GET_MODE_SIZE (Pmode);
    1615              : 
    1616              :   /* Save the structure value address unless this is passed as an
    1617              :      "invisible" first argument.  */
    1618          464 :   if (struct_incoming_value)
    1619            0 :     emit_move_insn (adjust_address (registers, Pmode, size),
    1620              :                     copy_to_reg (struct_incoming_value));
    1621              : 
    1622              :   /* Return the address of the block.  */
    1623          464 :   return copy_addr_to_reg (XEXP (registers, 0));
    1624              : }
    1625              : 
    1626              : /* __builtin_apply_args returns block of memory allocated on
    1627              :    the stack into which is stored the arg pointer, structure
    1628              :    value address, static chain, and all the registers that might
    1629              :    possibly be used in performing a function call.  The code is
    1630              :    moved to the start of the function so the incoming values are
    1631              :    saved.  */
    1632              : 
    1633              : static rtx
    1634          464 : expand_builtin_apply_args (void)
    1635              : {
    1636              :   /* Don't do __builtin_apply_args more than once in a function.
    1637              :      Save the result of the first call and reuse it.  */
    1638          464 :   if (apply_args_value != 0)
    1639              :     return apply_args_value;
    1640          464 :   {
    1641              :     /* When this function is called, it means that registers must be
    1642              :        saved on entry to this function.  So we migrate the
    1643              :        call to the first insn of this function.  */
    1644          464 :     rtx temp;
    1645              : 
    1646          464 :     start_sequence ();
    1647          464 :     temp = expand_builtin_apply_args_1 ();
    1648          464 :     rtx_insn *seq = end_sequence ();
    1649              : 
    1650          464 :     apply_args_value = temp;
    1651              : 
    1652              :     /* Put the insns after the NOTE that starts the function.
    1653              :        If this is inside a start_sequence, make the outer-level insn
    1654              :        chain current, so the code is placed at the start of the
    1655              :        function.  If internal_arg_pointer is a non-virtual pseudo,
    1656              :        it needs to be placed after the function that initializes
    1657              :        that pseudo.  */
    1658          464 :     push_topmost_sequence ();
    1659          464 :     if (REG_P (crtl->args.internal_arg_pointer)
    1660          464 :         && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
    1661            0 :       emit_insn_before (seq, parm_birth_insn);
    1662              :     else
    1663          464 :       emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
    1664          464 :     pop_topmost_sequence ();
    1665          464 :     return temp;
    1666              :   }
    1667              : }
    1668              : 
    1669              : /* Perform an untyped call and save the state required to perform an
    1670              :    untyped return of whatever value was returned by the given function.  */
    1671              : 
    1672              : static rtx
    1673          483 : expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
    1674              : {
    1675          483 :   int size, align, regno;
    1676          483 :   fixed_size_mode mode;
    1677          483 :   rtx incoming_args, result, reg, dest, src;
    1678          483 :   rtx_call_insn *call_insn;
    1679          483 :   rtx old_stack_level = 0;
    1680          483 :   rtx call_fusage = 0;
    1681          483 :   rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
    1682              : 
    1683          483 :   arguments = convert_memory_address (Pmode, arguments);
    1684              : 
    1685              :   /* Create a block where the return registers can be saved.  */
    1686          483 :   result = assign_stack_local (BLKmode, apply_result_size (), -1);
    1687              : 
    1688              :   /* Fetch the arg pointer from the ARGUMENTS block.  */
    1689          483 :   incoming_args = gen_reg_rtx (Pmode);
    1690          483 :   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
    1691          483 :   if (!STACK_GROWS_DOWNWARD)
    1692              :     incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
    1693              :                                          incoming_args, 0, OPTAB_LIB_WIDEN);
    1694              : 
    1695              :   /* Push a new argument block and copy the arguments.  Do not allow
    1696              :      the (potential) memcpy call below to interfere with our stack
    1697              :      manipulations.  */
    1698          483 :   do_pending_stack_adjust ();
    1699          483 :   NO_DEFER_POP;
    1700              : 
    1701              :   /* Save the stack with nonlocal if available.  */
    1702          483 :   if (targetm.have_save_stack_nonlocal ())
    1703          483 :     emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
    1704              :   else
    1705            0 :     emit_stack_save (SAVE_BLOCK, &old_stack_level);
    1706              : 
    1707              :   /* Allocate a block of memory onto the stack and copy the memory
    1708              :      arguments to the outgoing arguments address.  We can pass TRUE
    1709              :      as the 4th argument because we just saved the stack pointer
    1710              :      and will restore it right after the call.  */
    1711          966 :   allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, -1, true);
    1712              : 
    1713              :   /* Set DRAP flag to true, even though allocate_dynamic_stack_space
    1714              :      may have already set current_function_calls_alloca to true.
    1715              :      current_function_calls_alloca won't be set if argsize is zero,
    1716              :      so we have to guarantee need_drap is true here.  */
    1717          483 :   if (SUPPORTS_STACK_ALIGNMENT)
    1718          483 :     crtl->need_drap = true;
    1719              : 
    1720          483 :   dest = virtual_outgoing_args_rtx;
    1721          483 :   if (!STACK_GROWS_DOWNWARD)
    1722              :     {
    1723              :       if (CONST_INT_P (argsize))
    1724              :         dest = plus_constant (Pmode, dest, -INTVAL (argsize));
    1725              :       else
    1726              :         dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
    1727              :     }
    1728          483 :   dest = gen_rtx_MEM (BLKmode, dest);
    1729          483 :   set_mem_align (dest, PARM_BOUNDARY);
    1730          483 :   src = gen_rtx_MEM (BLKmode, incoming_args);
    1731          483 :   set_mem_align (src, PARM_BOUNDARY);
    1732          483 :   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
    1733              : 
    1734              :   /* Refer to the argument block.  */
    1735          483 :   apply_args_size ();
    1736          483 :   arguments = gen_rtx_MEM (BLKmode, arguments);
    1737          483 :   set_mem_align (arguments, PARM_BOUNDARY);
    1738              : 
    1739              :   /* Walk past the arg-pointer and structure value address.  */
    1740          483 :   size = GET_MODE_SIZE (Pmode);
    1741          483 :   if (struct_value)
    1742            0 :     size += GET_MODE_SIZE (Pmode);
    1743              : 
    1744              :   /* Restore each of the registers previously saved.  Make USE insns
    1745              :      for each of these registers for use in making the call.  */
    1746        44919 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1747        44436 :     if ((mode = apply_args_mode[regno]) != VOIDmode)
    1748              :       {
    1749         7245 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1750         7245 :         if (size % align != 0)
    1751            0 :           size = CEIL (size, align) * align;
    1752         7245 :         reg = gen_rtx_REG (mode, regno);
    1753         7245 :         emit_move_insn (reg, adjust_address (arguments, mode, size));
    1754         7245 :         use_reg (&call_fusage, reg);
    1755        14490 :         size += GET_MODE_SIZE (mode);
    1756              :       }
    1757              : 
    1758              :   /* Restore the structure value address unless this is passed as an
    1759              :      "invisible" first argument.  */
    1760          483 :   size = GET_MODE_SIZE (Pmode);
    1761          483 :   if (struct_value)
    1762              :     {
    1763            0 :       rtx value = gen_reg_rtx (Pmode);
    1764            0 :       emit_move_insn (value, adjust_address (arguments, Pmode, size));
    1765            0 :       emit_move_insn (struct_value, value);
    1766            0 :       if (REG_P (struct_value))
    1767            0 :         use_reg (&call_fusage, struct_value);
    1768              :     }
    1769              : 
    1770              :   /* All arguments and registers used for the call are set up by now!  */
    1771          483 :   function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
    1772              : 
    1773              :   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
    1774              :      and we don't want to load it into a register as an optimization,
    1775              :      because prepare_call_address already did it if it should be done.  */
    1776          483 :   if (GET_CODE (function) != SYMBOL_REF)
    1777           29 :     function = memory_address (FUNCTION_MODE, function);
    1778              : 
    1779              :   /* Generate the actual call instruction and save the return value.  */
    1780          483 :   if (targetm.have_untyped_call ())
    1781              :     {
    1782          483 :       rtx mem = gen_rtx_MEM (FUNCTION_MODE, function);
    1783          483 :       rtx_insn *seq = targetm.gen_untyped_call (mem, result,
    1784              :                                                 result_vector (1, result));
    1785         4834 :       for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
    1786         4351 :         if (CALL_P (insn))
    1787          483 :           add_reg_note (insn, REG_UNTYPED_CALL, NULL_RTX);
    1788          483 :       emit_insn (seq);
    1789              :     }
    1790            0 :   else if (targetm.have_call_value ())
    1791              :     {
    1792              :       rtx valreg = 0;
    1793              : 
    1794              :       /* Locate the unique return register.  It is not possible to
    1795              :          express a call that sets more than one return register using
    1796              :          call_value; use untyped_call for that.  In fact, untyped_call
    1797              :          only needs to save the return registers in the given block.  */
    1798            0 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1799            0 :         if ((mode = apply_result_mode[regno]) != VOIDmode)
    1800              :           {
    1801            0 :             gcc_assert (!valreg); /* have_untyped_call required.  */
    1802              : 
    1803            0 :             valreg = gen_rtx_REG (mode, regno);
    1804              :           }
    1805              : 
    1806            0 :       emit_insn (targetm.gen_call_value (valreg,
    1807              :                                          gen_rtx_MEM (FUNCTION_MODE, function),
    1808              :                                          const0_rtx, NULL_RTX, const0_rtx));
    1809              : 
    1810            0 :       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
    1811              :     }
    1812              :   else
    1813            0 :     gcc_unreachable ();
    1814              : 
    1815              :   /* Find the CALL insn we just emitted, and attach the register usage
    1816              :      information.  */
    1817          483 :   call_insn = last_call_insn ();
    1818          483 :   add_function_usage_to (call_insn, call_fusage);
    1819              : 
    1820              :   /* Restore the stack.  */
    1821          483 :   if (targetm.have_save_stack_nonlocal ())
    1822          483 :     emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
    1823              :   else
    1824            0 :     emit_stack_restore (SAVE_BLOCK, old_stack_level);
    1825          483 :   fixup_args_size_notes (call_insn, get_last_insn (), 0);
    1826              : 
    1827          483 :   OK_DEFER_POP;
    1828              : 
    1829              :   /* Return the address of the result block.  */
    1830          483 :   result = copy_addr_to_reg (XEXP (result, 0));
    1831          483 :   return convert_memory_address (ptr_mode, result);
    1832              : }
    1833              : 
    1834              : /* Perform an untyped return.  */
    1835              : 
    1836              : static void
    1837          379 : expand_builtin_return (rtx result)
    1838              : {
    1839          379 :   int size, align, regno;
    1840          379 :   fixed_size_mode mode;
    1841          379 :   rtx reg;
    1842          379 :   rtx_insn *call_fusage = 0;
    1843              : 
    1844          379 :   result = convert_memory_address (Pmode, result);
    1845              : 
    1846          379 :   apply_result_size ();
    1847          379 :   result = gen_rtx_MEM (BLKmode, result);
    1848              : 
    1849          379 :   if (targetm.have_untyped_return ())
    1850              :     {
    1851            0 :       rtx vector = result_vector (0, result);
    1852            0 :       emit_jump_insn (targetm.gen_untyped_return (result, vector));
    1853            0 :       emit_barrier ();
    1854            0 :       return;
    1855              :     }
    1856              : 
    1857              :   /* Restore the return value and note that each value is used.  */
    1858              :   size = 0;
    1859        35247 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1860        34868 :     if ((mode = apply_result_mode[regno]) != VOIDmode)
    1861              :       {
    1862         2274 :         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
    1863         2274 :         if (size % align != 0)
    1864            7 :           size = CEIL (size, align) * align;
    1865         2274 :         reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
    1866         2274 :         emit_move_insn (reg, adjust_address (result, mode, size));
    1867              : 
    1868         2274 :         push_to_sequence (call_fusage);
    1869         2274 :         emit_use (reg);
    1870         2274 :         call_fusage = end_sequence ();
    1871         4548 :         size += GET_MODE_SIZE (mode);
    1872              :       }
    1873              : 
    1874              :   /* Put the USE insns before the return.  */
    1875          379 :   emit_insn (call_fusage);
    1876              : 
    1877              :   /* Return whatever values was restored by jumping directly to the end
    1878              :      of the function.  */
    1879          379 :   expand_naked_return ();
    1880              : }
    1881              : 
    1882              : /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
    1883              : 
    1884              : int
    1885         2369 : type_to_class (tree type)
    1886              : {
    1887         2369 :   switch (TREE_CODE (type))
    1888              :     {
    1889              :     case VOID_TYPE:        return void_type_class;
    1890          898 :     case INTEGER_TYPE:     return integer_type_class;
    1891           39 :     case ENUMERAL_TYPE:    return enumeral_type_class;
    1892           38 :     case BOOLEAN_TYPE:     return boolean_type_class;
    1893          984 :     case POINTER_TYPE:     return pointer_type_class;
    1894           27 :     case REFERENCE_TYPE:   return reference_type_class;
    1895           36 :     case OFFSET_TYPE:      return offset_type_class;
    1896          132 :     case REAL_TYPE:        return real_type_class;
    1897           40 :     case COMPLEX_TYPE:     return complex_type_class;
    1898           20 :     case FUNCTION_TYPE:    return function_type_class;
    1899            0 :     case METHOD_TYPE:      return method_type_class;
    1900           44 :     case RECORD_TYPE:      return record_type_class;
    1901           44 :     case UNION_TYPE:
    1902           44 :     case QUAL_UNION_TYPE:  return union_type_class;
    1903           24 :     case ARRAY_TYPE:       return (TYPE_STRING_FLAG (type)
    1904           24 :                                    ? string_type_class : array_type_class);
    1905            0 :     case LANG_TYPE:        return lang_type_class;
    1906            0 :     case OPAQUE_TYPE:      return opaque_type_class;
    1907            0 :     case BITINT_TYPE:      return bitint_type_class;
    1908           30 :     case VECTOR_TYPE:      return vector_type_class;
    1909            3 :     default:               return no_type_class;
    1910              :     }
    1911              : }
    1912              : 
    1913              : /* Expand a call EXP to __builtin_classify_type.  */
    1914              : 
    1915              : static rtx
    1916            0 : expand_builtin_classify_type (tree exp)
    1917              : {
    1918            0 :   if (call_expr_nargs (exp))
    1919            0 :     return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
    1920            0 :   return GEN_INT (no_type_class);
    1921              : }
    1922              : 
    1923              : /* This helper macro, meant to be used in mathfn_built_in below, determines
    1924              :    which among a set of builtin math functions is appropriate for a given type
    1925              :    mode.  The `F' (float) and `L' (long double) are automatically generated
    1926              :    from the 'double' case.  If a function supports the _Float<N> and _Float<N>X
    1927              :    types, there are additional types that are considered with 'F32', 'F64',
    1928              :    'F128', etc. suffixes.  */
    1929              : #define CASE_MATHFN(MATHFN) \
    1930              :   CASE_CFN_##MATHFN: \
    1931              :   fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
    1932              :   fcodel = BUILT_IN_##MATHFN##L ; break;
    1933              : /* Similar to the above, but also add support for the _Float<N> and _Float<N>X
    1934              :    types.  */
    1935              : #define CASE_MATHFN_FLOATN(MATHFN) \
    1936              :   CASE_CFN_##MATHFN: \
    1937              :   fcode = BUILT_IN_##MATHFN; fcodef = BUILT_IN_##MATHFN##F ; \
    1938              :   fcodel = BUILT_IN_##MATHFN##L ; fcodef16 = BUILT_IN_##MATHFN##F16 ; \
    1939              :   fcodef32 = BUILT_IN_##MATHFN##F32; fcodef64 = BUILT_IN_##MATHFN##F64 ; \
    1940              :   fcodef128 = BUILT_IN_##MATHFN##F128 ; fcodef32x = BUILT_IN_##MATHFN##F32X ; \
    1941              :   fcodef64x = BUILT_IN_##MATHFN##F64X ; fcodef128x = BUILT_IN_##MATHFN##F128X ;\
    1942              :   break;
    1943              : /* Similar to above, but appends _R after any F/L suffix.  */
    1944              : #define CASE_MATHFN_REENT(MATHFN) \
    1945              :   case CFN_BUILT_IN_##MATHFN##_R: \
    1946              :   case CFN_BUILT_IN_##MATHFN##F_R: \
    1947              :   case CFN_BUILT_IN_##MATHFN##L_R: \
    1948              :   fcode = BUILT_IN_##MATHFN##_R; fcodef = BUILT_IN_##MATHFN##F_R ; \
    1949              :   fcodel = BUILT_IN_##MATHFN##L_R ; break;
    1950              : 
    1951              : /* Return a function equivalent to FN but operating on floating-point
    1952              :    values of type TYPE, or END_BUILTINS if no such function exists.
    1953              :    This is purely an operation on function codes; it does not guarantee
    1954              :    that the target actually has an implementation of the function.  */
    1955              : 
    1956              : static built_in_function
    1957       601155 : mathfn_built_in_2 (tree type, combined_fn fn)
    1958              : {
    1959       601155 :   tree mtype;
    1960       601155 :   built_in_function fcode, fcodef, fcodel;
    1961       601155 :   built_in_function fcodef16 = END_BUILTINS;
    1962       601155 :   built_in_function fcodef32 = END_BUILTINS;
    1963       601155 :   built_in_function fcodef64 = END_BUILTINS;
    1964       601155 :   built_in_function fcodef128 = END_BUILTINS;
    1965       601155 :   built_in_function fcodef32x = END_BUILTINS;
    1966       601155 :   built_in_function fcodef64x = END_BUILTINS;
    1967       601155 :   built_in_function fcodef128x = END_BUILTINS;
    1968              : 
    1969              :   /* If <math.h> has been included somehow, HUGE_VAL and NAN definitions
    1970              :      break the uses below.  */
    1971              : #undef HUGE_VAL
    1972              : #undef NAN
    1973              : 
    1974       601155 :   switch (fn)
    1975              :     {
    1976              : #define SEQ_OF_CASE_MATHFN                      \
    1977              :     CASE_MATHFN_FLOATN (ACOS)                   \
    1978              :     CASE_MATHFN_FLOATN (ACOSH)                  \
    1979              :     CASE_MATHFN_FLOATN (ASIN)                   \
    1980              :     CASE_MATHFN_FLOATN (ASINH)                  \
    1981              :     CASE_MATHFN_FLOATN (ATAN)                   \
    1982              :     CASE_MATHFN_FLOATN (ATAN2)                  \
    1983              :     CASE_MATHFN_FLOATN (ATANH)                  \
    1984              :     CASE_MATHFN_FLOATN (CBRT)                   \
    1985              :     CASE_MATHFN_FLOATN (CEIL)                   \
    1986              :     CASE_MATHFN (CEXPI)                         \
    1987              :     CASE_MATHFN_FLOATN (COPYSIGN)               \
    1988              :     CASE_MATHFN_FLOATN (COS)                    \
    1989              :     CASE_MATHFN_FLOATN (COSH)                   \
    1990              :     CASE_MATHFN (DREM)                          \
    1991              :     CASE_MATHFN_FLOATN (ERF)                    \
    1992              :     CASE_MATHFN_FLOATN (ERFC)                   \
    1993              :     CASE_MATHFN_FLOATN (EXP)                    \
    1994              :     CASE_MATHFN (EXP10)                         \
    1995              :     CASE_MATHFN_FLOATN (EXP2)                   \
    1996              :     CASE_MATHFN_FLOATN (EXPM1)                  \
    1997              :     CASE_MATHFN_FLOATN (FABS)                   \
    1998              :     CASE_MATHFN_FLOATN (FDIM)                   \
    1999              :     CASE_MATHFN_FLOATN (FLOOR)                  \
    2000              :     CASE_MATHFN_FLOATN (FMA)                    \
    2001              :     CASE_MATHFN_FLOATN (FMAX)                   \
    2002              :     CASE_MATHFN_FLOATN (FMIN)                   \
    2003              :     CASE_MATHFN_FLOATN (FMOD)                   \
    2004              :     CASE_MATHFN_FLOATN (FREXP)                  \
    2005              :     CASE_MATHFN (GAMMA)                         \
    2006              :     CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */     \
    2007              :     CASE_MATHFN_FLOATN (HUGE_VAL)               \
    2008              :     CASE_MATHFN_FLOATN (HYPOT)                  \
    2009              :     CASE_MATHFN_FLOATN (ILOGB)                  \
    2010              :     CASE_MATHFN (ICEIL)                         \
    2011              :     CASE_MATHFN (IFLOOR)                        \
    2012              :     CASE_MATHFN_FLOATN (INF)                    \
    2013              :     CASE_MATHFN (IRINT)                         \
    2014              :     CASE_MATHFN (IROUND)                        \
    2015              :     CASE_MATHFN (ISINF)                         \
    2016              :     CASE_MATHFN (J0)                            \
    2017              :     CASE_MATHFN (J1)                            \
    2018              :     CASE_MATHFN (JN)                            \
    2019              :     CASE_MATHFN (LCEIL)                         \
    2020              :     CASE_MATHFN_FLOATN (LDEXP)                  \
    2021              :     CASE_MATHFN (LFLOOR)                        \
    2022              :     CASE_MATHFN_FLOATN (LGAMMA)                 \
    2023              :     CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */   \
    2024              :     CASE_MATHFN (LLCEIL)                        \
    2025              :     CASE_MATHFN (LLFLOOR)                       \
    2026              :     CASE_MATHFN_FLOATN (LLRINT)                 \
    2027              :     CASE_MATHFN_FLOATN (LLROUND)                \
    2028              :     CASE_MATHFN_FLOATN (LOG)                    \
    2029              :     CASE_MATHFN_FLOATN (LOG10)                  \
    2030              :     CASE_MATHFN_FLOATN (LOG1P)                  \
    2031              :     CASE_MATHFN_FLOATN (LOG2)                   \
    2032              :     CASE_MATHFN_FLOATN (LOGB)                   \
    2033              :     CASE_MATHFN_FLOATN (LRINT)                  \
    2034              :     CASE_MATHFN_FLOATN (LROUND)                 \
    2035              :     CASE_MATHFN_FLOATN (MODF)                   \
    2036              :     CASE_MATHFN_FLOATN (NAN)                    \
    2037              :     CASE_MATHFN_FLOATN (NANS)                   \
    2038              :     CASE_MATHFN_FLOATN (NEARBYINT)              \
    2039              :     CASE_MATHFN_FLOATN (NEXTAFTER)              \
    2040              :     CASE_MATHFN (NEXTTOWARD)                    \
    2041              :     CASE_MATHFN_FLOATN (POW)                    \
    2042              :     CASE_MATHFN (POWI)                          \
    2043              :     CASE_MATHFN (POW10)                         \
    2044              :     CASE_MATHFN_FLOATN (REMAINDER)              \
    2045              :     CASE_MATHFN_FLOATN (REMQUO)                 \
    2046              :     CASE_MATHFN_FLOATN (RINT)                   \
    2047              :     CASE_MATHFN_FLOATN (ROUND)                  \
    2048              :     CASE_MATHFN_FLOATN (ROUNDEVEN)              \
    2049              :     CASE_MATHFN (SCALB)                         \
    2050              :     CASE_MATHFN_FLOATN (SCALBLN)                \
    2051              :     CASE_MATHFN_FLOATN (SCALBN)                 \
    2052              :     CASE_MATHFN (SIGNBIT)                       \
    2053              :     CASE_MATHFN (SIGNIFICAND)                   \
    2054              :     CASE_MATHFN_FLOATN (SIN)                    \
    2055              :     CASE_MATHFN (SINCOS)                        \
    2056              :     CASE_MATHFN_FLOATN (SINH)                   \
    2057              :     CASE_MATHFN_FLOATN (SQRT)                   \
    2058              :     CASE_MATHFN_FLOATN (TAN)                    \
    2059              :     CASE_MATHFN_FLOATN (TANH)                   \
    2060              :     CASE_MATHFN_FLOATN (TGAMMA)                 \
    2061              :     CASE_MATHFN_FLOATN (TRUNC)                  \
    2062              :     CASE_MATHFN (Y0)                            \
    2063              :     CASE_MATHFN (Y1)                            \
    2064              :     CASE_MATHFN (YN)
    2065              : 
    2066       601091 :     SEQ_OF_CASE_MATHFN
    2067              : 
    2068              :     default:
    2069              :       return END_BUILTINS;
    2070              :     }
    2071              : 
    2072       601155 :   mtype = TYPE_MAIN_VARIANT (type);
    2073       601155 :   if (mtype == double_type_node)
    2074              :     return fcode;
    2075       561892 :   else if (mtype == float_type_node)
    2076              :     return fcodef;
    2077       516739 :   else if (mtype == long_double_type_node)
    2078              :     return fcodel;
    2079       484333 :   else if (mtype == float16_type_node)
    2080              :     return fcodef16;
    2081       484285 :   else if (mtype == float32_type_node)
    2082              :     return fcodef32;
    2083       484285 :   else if (mtype == float64_type_node)
    2084              :     return fcodef64;
    2085       484285 :   else if (mtype == float128_type_node)
    2086              :     return fcodef128;
    2087       477804 :   else if (mtype == float32x_type_node)
    2088              :     return fcodef32x;
    2089       477804 :   else if (mtype == float64x_type_node)
    2090              :     return fcodef64x;
    2091       477804 :   else if (mtype == float128x_type_node)
    2092              :     return fcodef128x;
    2093              :   else
    2094       477804 :     return END_BUILTINS;
    2095              : }
    2096              : 
    2097              : #undef CASE_MATHFN
    2098              : #undef CASE_MATHFN_FLOATN
    2099              : #undef CASE_MATHFN_REENT
    2100              : 
    2101              : /* Return mathematic function equivalent to FN but operating directly on TYPE,
    2102              :    if available.  If IMPLICIT_P is true use the implicit builtin declaration,
    2103              :    otherwise use the explicit declaration.  If we can't do the conversion,
    2104              :    return null.  */
    2105              : 
    2106              : static tree
    2107       601010 : mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
    2108              : {
    2109       601010 :   built_in_function fcode2 = mathfn_built_in_2 (type, fn);
    2110       601010 :   if (fcode2 == END_BUILTINS)
    2111              :     return NULL_TREE;
    2112              : 
    2113       119558 :   if (implicit_p && !builtin_decl_implicit_p (fcode2))
    2114              :     return NULL_TREE;
    2115              : 
    2116       116628 :   return builtin_decl_explicit (fcode2);
    2117              : }
    2118              : 
    2119              : /* Like mathfn_built_in_1, but always use the implicit array.  */
    2120              : 
    2121              : tree
    2122          276 : mathfn_built_in (tree type, combined_fn fn)
    2123              : {
    2124          276 :   return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
    2125              : }
    2126              : 
    2127              : /* Like mathfn_built_in_1, but always use the explicit array.  */
    2128              : 
    2129              : tree
    2130            0 : mathfn_built_in_explicit (tree type, combined_fn fn)
    2131              : {
    2132            0 :   return mathfn_built_in_1 (type, fn, /*implicit=*/ 0);
    2133              : }
    2134              : 
    2135              : /* Like mathfn_built_in_1, but take a built_in_function and
    2136              :    always use the implicit array.  */
    2137              : 
    2138              : tree
    2139       600511 : mathfn_built_in (tree type, enum built_in_function fn)
    2140              : {
    2141       600511 :   return mathfn_built_in_1 (type, as_combined_fn (fn), /*implicit=*/ 1);
    2142              : }
    2143              : 
    2144              : /* Return the type associated with a built in function, i.e., the one
    2145              :    to be passed to mathfn_built_in to get the type-specific
    2146              :    function.  */
    2147              : 
    2148              : tree
    2149         1290 : mathfn_built_in_type (combined_fn fn)
    2150              : {
    2151              : #define CASE_MATHFN(MATHFN)                     \
    2152              :   case CFN_BUILT_IN_##MATHFN:                   \
    2153              :     return double_type_node;                    \
    2154              :   case CFN_BUILT_IN_##MATHFN##F:                \
    2155              :     return float_type_node;                     \
    2156              :   case CFN_BUILT_IN_##MATHFN##L:                \
    2157              :     return long_double_type_node;
    2158              : 
    2159              : #define CASE_MATHFN_FLOATN(MATHFN)              \
    2160              :   CASE_MATHFN(MATHFN)                           \
    2161              :   case CFN_BUILT_IN_##MATHFN##F16:              \
    2162              :     return float16_type_node;                   \
    2163              :   case CFN_BUILT_IN_##MATHFN##F32:              \
    2164              :     return float32_type_node;                   \
    2165              :   case CFN_BUILT_IN_##MATHFN##F64:              \
    2166              :     return float64_type_node;                   \
    2167              :   case CFN_BUILT_IN_##MATHFN##F128:             \
    2168              :     return float128_type_node;                  \
    2169              :   case CFN_BUILT_IN_##MATHFN##F32X:             \
    2170              :     return float32x_type_node;                  \
    2171              :   case CFN_BUILT_IN_##MATHFN##F64X:             \
    2172              :     return float64x_type_node;                  \
    2173              :   case CFN_BUILT_IN_##MATHFN##F128X:            \
    2174              :     return float128x_type_node;
    2175              : 
    2176              : /* Similar to above, but appends _R after any F/L suffix.  */
    2177              : #define CASE_MATHFN_REENT(MATHFN) \
    2178              :   case CFN_BUILT_IN_##MATHFN##_R:               \
    2179              :     return double_type_node;                    \
    2180              :   case CFN_BUILT_IN_##MATHFN##F_R:              \
    2181              :     return float_type_node;                     \
    2182              :   case CFN_BUILT_IN_##MATHFN##L_R:              \
    2183              :     return long_double_type_node;
    2184              : 
    2185         1290 :   switch (fn)
    2186              :     {
    2187         1288 :     SEQ_OF_CASE_MATHFN
    2188              : 
    2189              :     default:
    2190              :       return NULL_TREE;
    2191              :     }
    2192              : 
    2193              : #undef CASE_MATHFN
    2194              : #undef CASE_MATHFN_FLOATN
    2195              : #undef CASE_MATHFN_REENT
    2196              : #undef SEQ_OF_CASE_MATHFN
    2197              : }
    2198              : 
    2199              : /* Check whether there is an internal function associated with function FN
    2200              :    and return type RETURN_TYPE.  Return the function if so, otherwise return
    2201              :    IFN_LAST.
    2202              : 
    2203              :    Note that this function only tests whether the function is defined in
    2204              :    internals.def, not whether it is actually available on the target.  */
    2205              : 
    2206              : static internal_fn
    2207     14042640 : associated_internal_fn (built_in_function fn, tree return_type)
    2208              : {
    2209     14042640 :   switch (fn)
    2210              :     {
    2211              : #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2212              :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2213              : #define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
    2214              :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME; \
    2215              :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_##NAME): return IFN_##NAME;
    2216              : #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2217              :     CASE_INT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2218              : #include "internal-fn.def"
    2219              : 
    2220              :     CASE_FLT_FN (BUILT_IN_POW10):
    2221              :       return IFN_EXP10;
    2222              : 
    2223              :     CASE_FLT_FN (BUILT_IN_DREM):
    2224              :       return IFN_REMAINDER;
    2225              : 
    2226        19543 :     CASE_FLT_FN (BUILT_IN_SCALBN):
    2227        19543 :     CASE_FLT_FN (BUILT_IN_SCALBLN):
    2228        19543 :       if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
    2229              :         return IFN_LDEXP;
    2230              :       return IFN_LAST;
    2231          123 :     case BUILT_IN_CRC8_DATA8:
    2232          123 :     case BUILT_IN_CRC16_DATA8:
    2233          123 :     case BUILT_IN_CRC16_DATA16:
    2234          123 :     case BUILT_IN_CRC32_DATA8:
    2235          123 :     case BUILT_IN_CRC32_DATA16:
    2236          123 :     case BUILT_IN_CRC32_DATA32:
    2237          123 :     case BUILT_IN_CRC64_DATA8:
    2238          123 :     case BUILT_IN_CRC64_DATA16:
    2239          123 :     case BUILT_IN_CRC64_DATA32:
    2240          123 :     case BUILT_IN_CRC64_DATA64:
    2241          123 :       return IFN_CRC;
    2242          176 :     case BUILT_IN_REV_CRC8_DATA8:
    2243          176 :     case BUILT_IN_REV_CRC16_DATA8:
    2244          176 :     case BUILT_IN_REV_CRC16_DATA16:
    2245          176 :     case BUILT_IN_REV_CRC32_DATA8:
    2246          176 :     case BUILT_IN_REV_CRC32_DATA16:
    2247          176 :     case BUILT_IN_REV_CRC32_DATA32:
    2248          176 :     case BUILT_IN_REV_CRC64_DATA8:
    2249          176 :     case BUILT_IN_REV_CRC64_DATA16:
    2250          176 :     case BUILT_IN_REV_CRC64_DATA32:
    2251          176 :     case BUILT_IN_REV_CRC64_DATA64:
    2252          176 :       return IFN_CRC_REV;
    2253              :     default:
    2254              :       return IFN_LAST;
    2255              :     }
    2256              : }
    2257              : 
    2258              : /* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
    2259              :    return its code, otherwise return IFN_LAST.  Note that this function
    2260              :    only tests whether the function is defined in internals.def, not whether
    2261              :    it is actually available on the target.  */
    2262              : 
    2263              : internal_fn
    2264       632125 : associated_internal_fn (tree fndecl)
    2265              : {
    2266       632125 :   gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
    2267       632125 :   return associated_internal_fn (DECL_FUNCTION_CODE (fndecl),
    2268       632125 :                                  TREE_TYPE (TREE_TYPE (fndecl)));
    2269              : }
    2270              : 
    2271              : /* Check whether there is an internal function associated with function CFN
    2272              :    and return type RETURN_TYPE.  Return the function if so, otherwise return
    2273              :    IFN_LAST.
    2274              : 
    2275              :    Note that this function only tests whether the function is defined in
    2276              :    internals.def, not whether it is actually available on the target.  */
    2277              : 
    2278              : internal_fn
    2279     34195911 : associated_internal_fn (combined_fn cfn, tree return_type)
    2280              : {
    2281     34195911 :   if (internal_fn_p (cfn))
    2282     20785396 :     return as_internal_fn (cfn);
    2283     13410515 :   return associated_internal_fn (as_builtin_fn (cfn), return_type);
    2284              : }
    2285              : 
    2286              : /* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
    2287              :    on the current target by a call to an internal function, return the
    2288              :    code of that internal function, otherwise return IFN_LAST.  The caller
    2289              :    is responsible for ensuring that any side-effects of the built-in
    2290              :    call are dealt with correctly.  E.g. if CALL sets errno, the caller
    2291              :    must decide that the errno result isn't needed or make it available
    2292              :    in some other way.  */
    2293              : 
    2294              : internal_fn
    2295       864482 : replacement_internal_fn (gcall *call)
    2296              : {
    2297       864482 :   if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    2298              :     {
    2299       629388 :       internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
    2300       629388 :       if (ifn != IFN_LAST)
    2301              :         {
    2302        58630 :           tree_pair types = direct_internal_fn_types (ifn, call);
    2303        58630 :           optimization_type opt_type = bb_optimization_type (gimple_bb (call));
    2304        58630 :           if (direct_internal_fn_supported_p (ifn, types, opt_type))
    2305        37053 :             return ifn;
    2306              :         }
    2307              :     }
    2308              :   return IFN_LAST;
    2309              : }
    2310              : 
    2311              : /* Expand a call to the builtin trinary math functions (fma).
    2312              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2313              :    function in-line.  EXP is the expression that is a call to the builtin
    2314              :    function; if convenient, the result should be placed in TARGET.
    2315              :    SUBTARGET may be used as the target for computing one of EXP's
    2316              :    operands.  */
    2317              : 
    2318              : static rtx
    2319          368 : expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
    2320              : {
    2321          368 :   optab builtin_optab;
    2322          368 :   rtx op0, op1, op2, result;
    2323          368 :   rtx_insn *insns;
    2324          368 :   tree fndecl = get_callee_fndecl (exp);
    2325          368 :   tree arg0, arg1, arg2;
    2326          368 :   machine_mode mode;
    2327              : 
    2328          368 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    2329              :     return NULL_RTX;
    2330              : 
    2331          368 :   arg0 = CALL_EXPR_ARG (exp, 0);
    2332          368 :   arg1 = CALL_EXPR_ARG (exp, 1);
    2333          368 :   arg2 = CALL_EXPR_ARG (exp, 2);
    2334              : 
    2335          368 :   switch (DECL_FUNCTION_CODE (fndecl))
    2336              :     {
    2337          368 :     CASE_FLT_FN (BUILT_IN_FMA):
    2338          368 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
    2339          368 :       builtin_optab = fma_optab; break;
    2340            0 :     default:
    2341            0 :       gcc_unreachable ();
    2342              :     }
    2343              : 
    2344              :   /* Make a suitable register to place result in.  */
    2345          368 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2346              : 
    2347              :   /* Before working hard, check whether the instruction is available.  */
    2348          368 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2349              :     return NULL_RTX;
    2350              : 
    2351            0 :   result = gen_reg_rtx (mode);
    2352              : 
    2353              :   /* Always stabilize the argument list.  */
    2354            0 :   CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
    2355            0 :   CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
    2356            0 :   CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
    2357              : 
    2358            0 :   op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
    2359            0 :   op1 = expand_normal (arg1);
    2360            0 :   op2 = expand_normal (arg2);
    2361              : 
    2362            0 :   start_sequence ();
    2363              : 
    2364              :   /* Compute into RESULT.
    2365              :      Set RESULT to wherever the result comes back.  */
    2366            0 :   result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
    2367              :                               result, 0);
    2368              : 
    2369              :   /* If we were unable to expand via the builtin, stop the sequence
    2370              :      (without outputting the insns) and call to the library function
    2371              :      with the stabilized argument list.  */
    2372            0 :   if (result == 0)
    2373              :     {
    2374            0 :       end_sequence ();
    2375            0 :       return expand_call (exp, target, target == const0_rtx);
    2376              :     }
    2377              : 
    2378              :   /* Output the entire sequence.  */
    2379            0 :   insns = end_sequence ();
    2380            0 :   emit_insn (insns);
    2381              : 
    2382            0 :   return result;
    2383              : }
    2384              : 
    2385              : /* Expand a call to the builtin sin and cos math functions.
    2386              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2387              :    function in-line.  EXP is the expression that is a call to the builtin
    2388              :    function; if convenient, the result should be placed in TARGET.
    2389              :    SUBTARGET may be used as the target for computing one of EXP's
    2390              :    operands.  */
    2391              : 
    2392              : static rtx
    2393           47 : expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
    2394              : {
    2395           47 :   optab builtin_optab;
    2396           47 :   rtx op0;
    2397           47 :   rtx_insn *insns;
    2398           47 :   tree fndecl = get_callee_fndecl (exp);
    2399           47 :   machine_mode mode;
    2400           47 :   tree arg;
    2401              : 
    2402           47 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2403              :     return NULL_RTX;
    2404              : 
    2405           39 :   arg = CALL_EXPR_ARG (exp, 0);
    2406              : 
    2407           39 :   switch (DECL_FUNCTION_CODE (fndecl))
    2408              :     {
    2409           39 :     CASE_FLT_FN (BUILT_IN_SIN):
    2410           39 :     CASE_FLT_FN (BUILT_IN_COS):
    2411           39 :       builtin_optab = sincos_optab; break;
    2412            0 :     default:
    2413            0 :       gcc_unreachable ();
    2414              :     }
    2415              : 
    2416              :   /* Make a suitable register to place result in.  */
    2417           39 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2418              : 
    2419              :   /* Check if sincos insn is available, otherwise fallback
    2420              :      to sin or cos insn.  */
    2421           39 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2422           39 :     switch (DECL_FUNCTION_CODE (fndecl))
    2423              :       {
    2424              :       CASE_FLT_FN (BUILT_IN_SIN):
    2425              :         builtin_optab = sin_optab; break;
    2426           14 :       CASE_FLT_FN (BUILT_IN_COS):
    2427           14 :         builtin_optab = cos_optab; break;
    2428            0 :       default:
    2429            0 :         gcc_unreachable ();
    2430              :       }
    2431              : 
    2432              :   /* Before working hard, check whether the instruction is available.  */
    2433           39 :   if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
    2434              :     {
    2435            0 :       rtx result = gen_reg_rtx (mode);
    2436              : 
    2437              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2438              :          need to expand the argument again.  This way, we will not perform
    2439              :          side-effects more the once.  */
    2440            0 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2441              : 
    2442            0 :       op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    2443              : 
    2444            0 :       start_sequence ();
    2445              : 
    2446              :       /* Compute into RESULT.
    2447              :          Set RESULT to wherever the result comes back.  */
    2448            0 :       if (builtin_optab == sincos_optab)
    2449              :         {
    2450            0 :           int ok;
    2451              : 
    2452            0 :           switch (DECL_FUNCTION_CODE (fndecl))
    2453              :             {
    2454            0 :             CASE_FLT_FN (BUILT_IN_SIN):
    2455            0 :               ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
    2456            0 :               break;
    2457            0 :             CASE_FLT_FN (BUILT_IN_COS):
    2458            0 :               ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
    2459            0 :               break;
    2460            0 :             default:
    2461            0 :               gcc_unreachable ();
    2462              :             }
    2463            0 :           gcc_assert (ok);
    2464              :         }
    2465              :       else
    2466            0 :         result = expand_unop (mode, builtin_optab, op0, result, 0);
    2467              : 
    2468            0 :       if (result != 0)
    2469              :         {
    2470              :           /* Output the entire sequence.  */
    2471            0 :           insns = end_sequence ();
    2472            0 :           emit_insn (insns);
    2473            0 :           return result;
    2474              :         }
    2475              : 
    2476              :       /* If we were unable to expand via the builtin, stop the sequence
    2477              :          (without outputting the insns) and call to the library function
    2478              :          with the stabilized argument list.  */
    2479            0 :       end_sequence ();
    2480              :     }
    2481              : 
    2482           39 :   return expand_call (exp, target, target == const0_rtx);
    2483              : }
    2484              : 
    2485              : /* Given an interclass math builtin decl FNDECL and it's argument ARG
    2486              :    return an RTL instruction code that implements the functionality.
    2487              :    If that isn't possible or available return CODE_FOR_nothing.  */
    2488              : 
    2489              : static enum insn_code
    2490      1387058 : interclass_mathfn_icode (tree arg, tree fndecl)
    2491              : {
    2492      1387058 :   bool errno_set = false;
    2493      1387058 :   optab builtin_optab = unknown_optab;
    2494      1387058 :   machine_mode mode;
    2495              : 
    2496      1387058 :   switch (DECL_FUNCTION_CODE (fndecl))
    2497              :     {
    2498            4 :     CASE_FLT_FN (BUILT_IN_ILOGB):
    2499            4 :       errno_set = true;
    2500            4 :       builtin_optab = ilogb_optab;
    2501            4 :       break;
    2502       414370 :     CASE_FLT_FN (BUILT_IN_ISINF):
    2503       414370 :       builtin_optab = isinf_optab;
    2504       414370 :       break;
    2505       491603 :     case BUILT_IN_ISFINITE:
    2506       491603 :       builtin_optab = isfinite_optab;
    2507       491603 :       break;
    2508       238188 :     case BUILT_IN_ISNORMAL:
    2509       238188 :       builtin_optab = isnormal_optab;
    2510       238188 :       break;
    2511       240816 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    2512       240816 :       builtin_optab = isnan_optab;
    2513       240816 :       break;
    2514              :     CASE_FLT_FN (BUILT_IN_FINITE):
    2515              :     case BUILT_IN_FINITED32:
    2516              :     case BUILT_IN_FINITED64:
    2517              :     case BUILT_IN_FINITED128:
    2518              :     case BUILT_IN_ISINFD32:
    2519              :     case BUILT_IN_ISINFD64:
    2520              :     case BUILT_IN_ISINFD128:
    2521              :     case BUILT_IN_ISNAND32:
    2522              :     case BUILT_IN_ISNAND64:
    2523              :     case BUILT_IN_ISNAND128:
    2524              :       /* These builtins have no optabs (yet).  */
    2525              :       break;
    2526            0 :     default:
    2527            0 :       gcc_unreachable ();
    2528              :     }
    2529              : 
    2530              :   /* There's no easy way to detect the case we need to set EDOM.  */
    2531      1387058 :   if (flag_errno_math && errno_set)
    2532              :     return CODE_FOR_nothing;
    2533              : 
    2534              :   /* Optab mode depends on the mode of the input argument.  */
    2535      1387058 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2536              : 
    2537      1387058 :   if (builtin_optab)
    2538      1384981 :     return optab_handler (builtin_optab, mode);
    2539              :   return CODE_FOR_nothing;
    2540              : }
    2541              : 
    2542              : /* Expand a call to one of the builtin math functions that operate on
    2543              :    floating point argument and output an integer result (ilogb, isinf,
    2544              :    isnan, etc).
    2545              :    Return 0 if a normal call should be emitted rather than expanding the
    2546              :    function in-line.  EXP is the expression that is a call to the builtin
    2547              :    function; if convenient, the result should be placed in TARGET.  */
    2548              : 
    2549              : static rtx
    2550            4 : expand_builtin_interclass_mathfn (tree exp, rtx target)
    2551              : {
    2552            4 :   enum insn_code icode = CODE_FOR_nothing;
    2553            4 :   rtx op0;
    2554            4 :   tree fndecl = get_callee_fndecl (exp);
    2555            4 :   machine_mode mode;
    2556            4 :   tree arg;
    2557              : 
    2558            4 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2559              :     return NULL_RTX;
    2560              : 
    2561            4 :   arg = CALL_EXPR_ARG (exp, 0);
    2562            4 :   icode = interclass_mathfn_icode (arg, fndecl);
    2563            4 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2564              : 
    2565            4 :   if (icode != CODE_FOR_nothing)
    2566              :     {
    2567            2 :       class expand_operand ops[1];
    2568            2 :       rtx_insn *last = get_last_insn ();
    2569            2 :       tree orig_arg = arg;
    2570              : 
    2571              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2572              :          need to expand the argument again.  This way, we will not perform
    2573              :          side-effects more the once.  */
    2574            2 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2575              : 
    2576            2 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2577              : 
    2578            2 :       if (mode != GET_MODE (op0))
    2579            0 :         op0 = convert_to_mode (mode, op0, 0);
    2580              : 
    2581            2 :       create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
    2582            2 :       if (maybe_legitimize_operands (icode, 0, 1, ops)
    2583            2 :           && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
    2584            1 :         return ops[0].value;
    2585              : 
    2586            1 :       delete_insns_since (last);
    2587            1 :       CALL_EXPR_ARG (exp, 0) = orig_arg;
    2588              :     }
    2589              : 
    2590              :   return NULL_RTX;
    2591              : }
    2592              : 
    2593              : /* Expand a call to the builtin sincos math function.
    2594              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2595              :    function in-line.  EXP is the expression that is a call to the builtin
    2596              :    function.  */
    2597              : 
    2598              : static rtx
    2599            3 : expand_builtin_sincos (tree exp)
    2600              : {
    2601            3 :   rtx op0, op1, op2, target1, target2;
    2602            3 :   machine_mode mode;
    2603            3 :   tree arg, sinp, cosp;
    2604            3 :   int result;
    2605            3 :   location_t loc = EXPR_LOCATION (exp);
    2606            3 :   tree alias_type, alias_off;
    2607              : 
    2608            3 :   if (!validate_arglist (exp, REAL_TYPE,
    2609              :                          POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    2610              :     return NULL_RTX;
    2611              : 
    2612            3 :   arg = CALL_EXPR_ARG (exp, 0);
    2613            3 :   sinp = CALL_EXPR_ARG (exp, 1);
    2614            3 :   cosp = CALL_EXPR_ARG (exp, 2);
    2615              : 
    2616              :   /* Make a suitable register to place result in.  */
    2617            3 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2618              : 
    2619              :   /* Check if sincos insn is available, otherwise emit the call.  */
    2620            3 :   if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
    2621              :     return NULL_RTX;
    2622              : 
    2623            0 :   target1 = gen_reg_rtx (mode);
    2624            0 :   target2 = gen_reg_rtx (mode);
    2625              : 
    2626            0 :   op0 = expand_normal (arg);
    2627            0 :   alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
    2628            0 :   alias_off = build_int_cst (alias_type, 0);
    2629            0 :   op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2630              :                                         sinp, alias_off));
    2631            0 :   op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2632              :                                         cosp, alias_off));
    2633              : 
    2634              :   /* Compute into target1 and target2.
    2635              :      Set TARGET to wherever the result comes back.  */
    2636            0 :   result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
    2637            0 :   gcc_assert (result);
    2638              : 
    2639              :   /* Move target1 and target2 to the memory locations indicated
    2640              :      by op1 and op2.  */
    2641            0 :   emit_move_insn (op1, target1);
    2642            0 :   emit_move_insn (op2, target2);
    2643              : 
    2644            0 :   return const0_rtx;
    2645              : }
    2646              : 
    2647              : /* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the
    2648              :    result and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
    2649              : static rtx
    2650           60 : expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode)
    2651              : {
    2652           60 :   if (!validate_arglist (exp, VOID_TYPE))
    2653              :     return NULL_RTX;
    2654              : 
    2655           60 :   insn_code icode = direct_optab_handler (fegetround_optab, SImode);
    2656           60 :   if (icode == CODE_FOR_nothing)
    2657              :     return NULL_RTX;
    2658              : 
    2659            0 :   if (target == 0
    2660            0 :       || GET_MODE (target) != target_mode
    2661            0 :       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
    2662            0 :     target = gen_reg_rtx (target_mode);
    2663              : 
    2664            0 :   rtx pat = GEN_FCN (icode) (target);
    2665            0 :   if (!pat)
    2666              :     return NULL_RTX;
    2667            0 :   emit_insn (pat);
    2668              : 
    2669            0 :   return target;
    2670              : }
    2671              : 
    2672              : /* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99
    2673              :    fenv.h), returning the result and setting it in TARGET.  Otherwise return
    2674              :    NULL_RTX on failure.  */
    2675              : static rtx
    2676         1894 : expand_builtin_feclear_feraise_except (tree exp, rtx target,
    2677              :                                        machine_mode target_mode, optab op_optab)
    2678              : {
    2679         1894 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    2680              :     return NULL_RTX;
    2681         1894 :   rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
    2682              : 
    2683         1894 :   insn_code icode = direct_optab_handler (op_optab, SImode);
    2684         1894 :   if (icode == CODE_FOR_nothing)
    2685              :     return NULL_RTX;
    2686              : 
    2687            0 :   if (!(*insn_data[icode].operand[1].predicate) (op0, GET_MODE (op0)))
    2688              :     return NULL_RTX;
    2689              : 
    2690            0 :   if (target == 0
    2691            0 :       || GET_MODE (target) != target_mode
    2692            0 :       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
    2693            0 :     target = gen_reg_rtx (target_mode);
    2694              : 
    2695            0 :   rtx pat = GEN_FCN (icode) (target, op0);
    2696            0 :   if (!pat)
    2697              :     return NULL_RTX;
    2698            0 :   emit_insn (pat);
    2699              : 
    2700            0 :   return target;
    2701              : }
    2702              : 
    2703              : /* Expand a call to the internal cexpi builtin to the sincos math function.
    2704              :    EXP is the expression that is a call to the builtin function; if convenient,
    2705              :    the result should be placed in TARGET.  */
    2706              : 
    2707              : static rtx
    2708          170 : expand_builtin_cexpi (tree exp, rtx target)
    2709              : {
    2710          170 :   tree fndecl = get_callee_fndecl (exp);
    2711          170 :   tree arg, type;
    2712          170 :   machine_mode mode;
    2713          170 :   rtx op0, op1, op2;
    2714          170 :   location_t loc = EXPR_LOCATION (exp);
    2715              : 
    2716          170 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2717              :     return NULL_RTX;
    2718              : 
    2719          170 :   arg = CALL_EXPR_ARG (exp, 0);
    2720          170 :   type = TREE_TYPE (arg);
    2721          170 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2722              : 
    2723              :   /* Try expanding via a sincos optab, fall back to emitting a libcall
    2724              :      to sincos or cexp.  We are sure we have sincos or cexp because cexpi
    2725              :      is only generated from sincos, cexp or if we have either of them.  */
    2726          170 :   if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
    2727              :     {
    2728            6 :       op1 = gen_reg_rtx (mode);
    2729            6 :       op2 = gen_reg_rtx (mode);
    2730              : 
    2731            6 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2732              : 
    2733              :       /* Compute into op1 and op2.  */
    2734            6 :       expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
    2735              :     }
    2736          164 :   else if (targetm.libc_has_function (function_sincos, type))
    2737              :     {
    2738          164 :       tree call, fn = NULL_TREE;
    2739          164 :       tree top1, top2;
    2740          164 :       rtx op1a, op2a;
    2741              : 
    2742          164 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2743           54 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
    2744          110 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2745           89 :         fn = builtin_decl_explicit (BUILT_IN_SINCOS);
    2746           21 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2747           21 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
    2748              :       else
    2749            0 :         gcc_unreachable ();
    2750              : 
    2751          164 :       op1 = assign_temp (TREE_TYPE (arg), 1, 1);
    2752          164 :       op2 = assign_temp (TREE_TYPE (arg), 1, 1);
    2753          164 :       op1a = copy_addr_to_reg (XEXP (op1, 0));
    2754          164 :       op2a = copy_addr_to_reg (XEXP (op2, 0));
    2755          164 :       top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
    2756          164 :       top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
    2757              : 
    2758              :       /* Make sure not to fold the sincos call again.  */
    2759          164 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2760          164 :       expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
    2761              :                                       call, 3, arg, top1, top2));
    2762              :     }
    2763              :   else
    2764              :     {
    2765            0 :       tree call, fn = NULL_TREE, narg;
    2766            0 :       tree ctype = build_complex_type (type);
    2767              : 
    2768            0 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2769            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPF);
    2770            0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2771            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXP);
    2772            0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2773            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPL);
    2774              :       else
    2775            0 :         gcc_unreachable ();
    2776              : 
    2777              :       /* If we don't have a decl for cexp create one.  This is the
    2778              :          friendliest fallback if the user calls __builtin_cexpi
    2779              :          without full target C99 function support.  */
    2780            0 :       if (fn == NULL_TREE)
    2781              :         {
    2782            0 :           tree fntype;
    2783            0 :           const char *name = NULL;
    2784              : 
    2785            0 :           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2786              :             name = "cexpf";
    2787            0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2788              :             name = "cexp";
    2789            0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2790            0 :             name = "cexpl";
    2791              : 
    2792            0 :           fntype = build_function_type_list (ctype, ctype, NULL_TREE);
    2793            0 :           fn = build_fn_decl (name, fntype);
    2794              :         }
    2795              : 
    2796            0 :       narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
    2797              :                           build_real (type, dconst0), arg);
    2798              : 
    2799              :       /* Make sure not to fold the cexp call again.  */
    2800            0 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2801            0 :       return expand_expr (build_call_nary (ctype, call, 1, narg),
    2802            0 :                           target, VOIDmode, EXPAND_NORMAL);
    2803              :     }
    2804              : 
    2805              :   /* Now build the proper return type.  */
    2806          340 :   return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
    2807          170 :                               make_tree (TREE_TYPE (arg), op2),
    2808          170 :                               make_tree (TREE_TYPE (arg), op1)),
    2809          170 :                       target, VOIDmode, EXPAND_NORMAL);
    2810              : }
    2811              : 
    2812              : /* Conveniently construct a function call expression.  FNDECL names the
    2813              :    function to be called, N is the number of arguments, and the "..."
    2814              :    parameters are the argument expressions.  Unlike build_call_exr
    2815              :    this doesn't fold the call, hence it will always return a CALL_EXPR.  */
    2816              : 
    2817              : static tree
    2818       135900 : build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
    2819              : {
    2820       135900 :   va_list ap;
    2821       135900 :   tree fntype = TREE_TYPE (fndecl);
    2822       135900 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
    2823              : 
    2824       135900 :   va_start (ap, n);
    2825       135900 :   fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
    2826       135900 :   va_end (ap);
    2827       135900 :   SET_EXPR_LOCATION (fn, loc);
    2828       135900 :   return fn;
    2829              : }
    2830              : 
    2831              : /* Expand the __builtin_issignaling builtin.  This needs to handle
    2832              :    all floating point formats that do support NaNs (for those that
    2833              :    don't it just sets target to 0).  */
    2834              : 
    2835              : static rtx
    2836          784 : expand_builtin_issignaling (tree exp, rtx target)
    2837              : {
    2838          784 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2839              :     return NULL_RTX;
    2840              : 
    2841          784 :   tree arg = CALL_EXPR_ARG (exp, 0);
    2842          784 :   scalar_float_mode fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
    2843          784 :   const struct real_format *fmt = REAL_MODE_FORMAT (fmode);
    2844              : 
    2845              :   /* Expand the argument yielding a RTX expression. */
    2846          784 :   rtx temp = expand_normal (arg);
    2847              : 
    2848              :   /* If mode doesn't support NaN, always return 0.
    2849              :      Don't use !HONOR_SNANS (fmode) here, so there is some possibility of
    2850              :      __builtin_issignaling working without -fsignaling-nans.  Especially
    2851              :      when -fno-signaling-nans is the default.
    2852              :      On the other side, MODE_HAS_NANS (fmode) is unnecessary, with
    2853              :      -ffinite-math-only even __builtin_isnan or __builtin_fpclassify
    2854              :      fold to 0 or non-NaN/Inf classification.  */
    2855          784 :   if (!HONOR_NANS (fmode))
    2856              :     {
    2857            0 :       emit_move_insn (target, const0_rtx);
    2858            0 :       return target;
    2859              :     }
    2860              : 
    2861              :   /* Check if the back end provides an insn that handles issignaling for the
    2862              :      argument's mode. */
    2863          784 :   enum insn_code icode = optab_handler (issignaling_optab, fmode);
    2864          784 :   if (icode != CODE_FOR_nothing)
    2865              :     {
    2866          142 :       rtx_insn *last = get_last_insn ();
    2867          142 :       rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    2868          142 :       if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
    2869              :         return this_target;
    2870            0 :       delete_insns_since (last);
    2871              :     }
    2872              : 
    2873          642 :   if (DECIMAL_FLOAT_MODE_P (fmode))
    2874              :     {
    2875           63 :       scalar_int_mode imode;
    2876           63 :       rtx hi;
    2877           63 :       switch (fmt->ieee_bits)
    2878              :         {
    2879           42 :         case 32:
    2880           42 :         case 64:
    2881           42 :           imode = int_mode_for_mode (fmode).require ();
    2882           42 :           temp = gen_lowpart (imode, temp);
    2883           42 :           break;
    2884           21 :         case 128:
    2885           21 :           imode = int_mode_for_size (64, 1).require ();
    2886           21 :           hi = NULL_RTX;
    2887              :           /* For decimal128, TImode support isn't always there and even when
    2888              :              it is, working on the DImode high part is usually better.  */
    2889           21 :           if (!MEM_P (temp))
    2890              :             {
    2891            6 :               if (rtx t = force_highpart_subreg (imode, temp, fmode))
    2892              :                 hi = t;
    2893              :               else
    2894              :                 {
    2895            0 :                   scalar_int_mode imode2;
    2896            0 :                   if (int_mode_for_mode (fmode).exists (&imode2))
    2897              :                     {
    2898            0 :                       rtx temp2 = gen_lowpart (imode2, temp);
    2899            0 :                       if (rtx t = force_highpart_subreg (imode, temp2, imode2))
    2900              :                         hi = t;
    2901              :                     }
    2902              :                 }
    2903            0 :               if (!hi)
    2904              :                 {
    2905            0 :                   rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    2906            0 :                   emit_move_insn (mem, temp);
    2907            0 :                   temp = mem;
    2908              :                 }
    2909              :             }
    2910            0 :           if (!hi)
    2911              :             {
    2912           15 :               poly_int64 offset
    2913           15 :                 = subreg_highpart_offset (imode, GET_MODE (temp));
    2914           15 :               hi = adjust_address (temp, imode, offset);
    2915              :             }
    2916              :           temp = hi;
    2917              :           break;
    2918            0 :         default:
    2919            0 :           gcc_unreachable ();
    2920              :         }
    2921              :       /* In all of decimal{32,64,128}, there is MSB sign bit and sNaN
    2922              :          have 6 bits below it all set.  */
    2923           63 :       rtx val
    2924           63 :         = GEN_INT (HOST_WIDE_INT_C (0x3f) << (GET_MODE_BITSIZE (imode) - 7));
    2925           63 :       temp = expand_binop (imode, and_optab, temp, val,
    2926              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2927           63 :       temp = emit_store_flag_force (target, EQ, temp, val, imode, 1, 1);
    2928           63 :       return temp;
    2929              :     }
    2930              : 
    2931              :   /* Only PDP11 has these defined differently but doesn't support NaNs.  */
    2932          579 :   gcc_assert (FLOAT_WORDS_BIG_ENDIAN == WORDS_BIG_ENDIAN);
    2933          579 :   gcc_assert (fmt->signbit_ro > 0 && fmt->b == 2);
    2934         4053 :   gcc_assert (MODE_COMPOSITE_P (fmode)
    2935              :               || (fmt->pnan == fmt->p
    2936              :                   && fmt->signbit_ro == fmt->signbit_rw));
    2937              : 
    2938          579 :   switch (fmt->p)
    2939              :     {
    2940            0 :     case 106: /* IBM double double  */
    2941              :       /* For IBM double double, recurse on the most significant double.  */
    2942            0 :       gcc_assert (MODE_COMPOSITE_P (fmode));
    2943            0 :       temp = convert_modes (DFmode, fmode, temp, 0);
    2944            0 :       fmode = DFmode;
    2945            0 :       fmt = REAL_MODE_FORMAT (DFmode);
    2946              :       /* FALLTHRU */
    2947          479 :     case 8: /* bfloat */
    2948          479 :     case 11: /* IEEE half */
    2949          479 :     case 24: /* IEEE single */
    2950          479 :     case 53: /* IEEE double or Intel extended with rounding to double */
    2951          479 :       if (fmt->p == 53 && fmt->signbit_ro == 79)
    2952            0 :         goto extended;
    2953          479 :       {
    2954          479 :         scalar_int_mode imode = int_mode_for_mode (fmode).require ();
    2955          479 :         temp = gen_lowpart (imode, temp);
    2956          479 :         rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2))
    2957              :                            & ~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
    2958          479 :         if (fmt->qnan_msb_set)
    2959              :           {
    2960          479 :             rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
    2961          479 :             rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2));
    2962              :             /* For non-MIPS/PA IEEE single/double/half or bfloat, expand to:
    2963              :                ((temp ^ bit) & mask) > val.  */
    2964          479 :             temp = expand_binop (imode, xor_optab, temp, bit,
    2965              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2966          479 :             temp = expand_binop (imode, and_optab, temp, mask,
    2967              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2968          479 :             temp = emit_store_flag_force (target, GTU, temp, val, imode,
    2969              :                                           1, 1);
    2970              :           }
    2971              :         else
    2972              :           {
    2973              :             /* For MIPS/PA IEEE single/double, expand to:
    2974              :                (temp & val) == val.  */
    2975            0 :             temp = expand_binop (imode, and_optab, temp, val,
    2976              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2977            0 :             temp = emit_store_flag_force (target, EQ, temp, val, imode,
    2978              :                                           1, 1);
    2979              :           }
    2980              :       }
    2981              :       break;
    2982          100 :     case 113: /* IEEE quad */
    2983          100 :       {
    2984          100 :         rtx hi = NULL_RTX, lo = NULL_RTX;
    2985          100 :         scalar_int_mode imode = int_mode_for_size (64, 1).require ();
    2986              :         /* For IEEE quad, TImode support isn't always there and even when
    2987              :            it is, working on DImode parts is usually better.  */
    2988          100 :         if (!MEM_P (temp))
    2989              :           {
    2990           85 :             hi = force_highpart_subreg (imode, temp, fmode);
    2991           85 :             lo = force_lowpart_subreg (imode, temp, fmode);
    2992           85 :             if (!hi || !lo)
    2993              :               {
    2994            0 :                 scalar_int_mode imode2;
    2995            0 :                 if (int_mode_for_mode (fmode).exists (&imode2))
    2996              :                   {
    2997            0 :                     rtx temp2 = gen_lowpart (imode2, temp);
    2998            0 :                     hi = force_highpart_subreg (imode, temp2, imode2);
    2999            0 :                     lo = force_lowpart_subreg (imode, temp2, imode2);
    3000              :                   }
    3001              :               }
    3002           85 :             if (!hi || !lo)
    3003              :               {
    3004            0 :                 rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    3005            0 :                 emit_move_insn (mem, temp);
    3006            0 :                 temp = mem;
    3007              :               }
    3008              :           }
    3009          100 :         if (!hi || !lo)
    3010              :           {
    3011           15 :             poly_int64 offset
    3012           15 :               = subreg_highpart_offset (imode, GET_MODE (temp));
    3013           15 :             hi = adjust_address (temp, imode, offset);
    3014           15 :             offset = subreg_lowpart_offset (imode, GET_MODE (temp));
    3015           15 :             lo = adjust_address (temp, imode, offset);
    3016              :           }
    3017          100 :         rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2 - 64))
    3018              :                            & ~(HOST_WIDE_INT_M1U << (fmt->signbit_ro - 64)));
    3019          100 :         if (fmt->qnan_msb_set)
    3020              :           {
    3021          100 :             rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << (fmt->signbit_ro
    3022              :                                                         - 64)));
    3023          100 :             rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2 - 64));
    3024              :             /* For non-MIPS/PA IEEE quad, expand to:
    3025              :                (((hi ^ bit) | ((lo | -lo) >> 63)) & mask) > val.  */
    3026          100 :             rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
    3027          100 :             lo = expand_binop (imode, ior_optab, lo, nlo,
    3028              :                                NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3029          100 :             lo = expand_shift (RSHIFT_EXPR, imode, lo, 63, NULL_RTX, 1);
    3030          100 :             temp = expand_binop (imode, xor_optab, hi, bit,
    3031              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3032          100 :             temp = expand_binop (imode, ior_optab, temp, lo,
    3033              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3034          100 :             temp = expand_binop (imode, and_optab, temp, mask,
    3035              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3036          100 :             temp = emit_store_flag_force (target, GTU, temp, val, imode,
    3037              :                                           1, 1);
    3038              :           }
    3039              :         else
    3040              :           {
    3041              :             /* For MIPS/PA IEEE quad, expand to:
    3042              :                (hi & val) == val.  */
    3043            0 :             temp = expand_binop (imode, and_optab, hi, val,
    3044              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3045            0 :             temp = emit_store_flag_force (target, EQ, temp, val, imode,
    3046              :                                           1, 1);
    3047              :           }
    3048              :       }
    3049              :       break;
    3050            0 :     case 64: /* Intel or Motorola extended */
    3051            0 :     extended:
    3052            0 :       {
    3053            0 :         rtx ex, hi, lo;
    3054            0 :         scalar_int_mode imode = int_mode_for_size (32, 1).require ();
    3055            0 :         scalar_int_mode iemode = int_mode_for_size (16, 1).require ();
    3056            0 :         if (!MEM_P (temp))
    3057              :           {
    3058            0 :             rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    3059            0 :             emit_move_insn (mem, temp);
    3060            0 :             temp = mem;
    3061              :           }
    3062            0 :         if (fmt->signbit_ro == 95)
    3063              :           {
    3064              :             /* Motorola, always big endian, with 16-bit gap in between
    3065              :                16-bit sign+exponent and 64-bit mantissa.  */
    3066            0 :             ex = adjust_address (temp, iemode, 0);
    3067            0 :             hi = adjust_address (temp, imode, 4);
    3068            0 :             lo = adjust_address (temp, imode, 8);
    3069              :           }
    3070            0 :         else if (!WORDS_BIG_ENDIAN)
    3071              :           {
    3072              :             /* Intel little endian, 64-bit mantissa followed by 16-bit
    3073              :                sign+exponent and then either 16 or 48 bits of gap.  */
    3074            0 :             ex = adjust_address (temp, iemode, 8);
    3075            0 :             hi = adjust_address (temp, imode, 4);
    3076            0 :             lo = adjust_address (temp, imode, 0);
    3077              :           }
    3078              :         else
    3079              :           {
    3080              :             /* Big endian Itanium.  */
    3081              :             ex = adjust_address (temp, iemode, 0);
    3082              :             hi = adjust_address (temp, imode, 2);
    3083              :             lo = adjust_address (temp, imode, 6);
    3084              :           }
    3085            0 :         rtx val = GEN_INT (HOST_WIDE_INT_M1U << 30);
    3086            0 :         gcc_assert (fmt->qnan_msb_set);
    3087            0 :         rtx mask = GEN_INT (0x7fff);
    3088            0 :         rtx bit = GEN_INT (HOST_WIDE_INT_1U << 30);
    3089              :         /* For Intel/Motorola extended format, expand to:
    3090              :            (ex & mask) == mask && ((hi ^ bit) | ((lo | -lo) >> 31)) > val.  */
    3091            0 :         rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
    3092            0 :         lo = expand_binop (imode, ior_optab, lo, nlo,
    3093              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3094            0 :         lo = expand_shift (RSHIFT_EXPR, imode, lo, 31, NULL_RTX, 1);
    3095            0 :         temp = expand_binop (imode, xor_optab, hi, bit,
    3096              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3097            0 :         temp = expand_binop (imode, ior_optab, temp, lo,
    3098              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3099            0 :         temp = emit_store_flag_force (target, GTU, temp, val, imode, 1, 1);
    3100            0 :         ex = expand_binop (iemode, and_optab, ex, mask,
    3101              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3102            0 :         ex = emit_store_flag_force (gen_reg_rtx (GET_MODE (temp)), EQ,
    3103              :                                     ex, mask, iemode, 1, 1);
    3104            0 :         temp = expand_binop (GET_MODE (temp), and_optab, temp, ex,
    3105              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3106              :       }
    3107            0 :       break;
    3108            0 :     default:
    3109            0 :       gcc_unreachable ();
    3110              :     }
    3111              : 
    3112              :   return temp;
    3113              : }
    3114              : 
    3115              : /* Expand a call to one of the builtin rounding functions gcc defines
    3116              :    as an extension (lfloor and lceil).  As these are gcc extensions we
    3117              :    do not need to worry about setting errno to EDOM.
    3118              :    If expanding via optab fails, lower expression to (int)(floor(x)).
    3119              :    EXP is the expression that is a call to the builtin function;
    3120              :    if convenient, the result should be placed in TARGET.  */
    3121              : 
    3122              : static rtx
    3123          223 : expand_builtin_int_roundingfn (tree exp, rtx target)
    3124              : {
    3125          223 :   convert_optab builtin_optab;
    3126          223 :   rtx op0, tmp;
    3127          223 :   rtx_insn *insns;
    3128          223 :   tree fndecl = get_callee_fndecl (exp);
    3129          223 :   enum built_in_function fallback_fn;
    3130          223 :   tree fallback_fndecl;
    3131          223 :   machine_mode mode;
    3132          223 :   tree arg;
    3133              : 
    3134          223 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    3135              :     return NULL_RTX;
    3136              : 
    3137          223 :   arg = CALL_EXPR_ARG (exp, 0);
    3138              : 
    3139          223 :   switch (DECL_FUNCTION_CODE (fndecl))
    3140              :     {
    3141              :     CASE_FLT_FN (BUILT_IN_ICEIL):
    3142              :     CASE_FLT_FN (BUILT_IN_LCEIL):
    3143              :     CASE_FLT_FN (BUILT_IN_LLCEIL):
    3144              :       builtin_optab = lceil_optab;
    3145              :       fallback_fn = BUILT_IN_CEIL;
    3146              :       break;
    3147              : 
    3148          112 :     CASE_FLT_FN (BUILT_IN_IFLOOR):
    3149          112 :     CASE_FLT_FN (BUILT_IN_LFLOOR):
    3150          112 :     CASE_FLT_FN (BUILT_IN_LLFLOOR):
    3151          112 :       builtin_optab = lfloor_optab;
    3152          112 :       fallback_fn = BUILT_IN_FLOOR;
    3153          112 :       break;
    3154              : 
    3155            0 :     default:
    3156            0 :       gcc_unreachable ();
    3157              :     }
    3158              : 
    3159              :   /* Make a suitable register to place result in.  */
    3160          223 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3161              : 
    3162          223 :   target = gen_reg_rtx (mode);
    3163              : 
    3164              :   /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    3165              :      need to expand the argument again.  This way, we will not perform
    3166              :      side-effects more the once.  */
    3167          223 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    3168              : 
    3169          223 :   op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    3170              : 
    3171          223 :   start_sequence ();
    3172              : 
    3173              :   /* Compute into TARGET.  */
    3174          223 :   if (expand_sfix_optab (target, op0, builtin_optab))
    3175              :     {
    3176              :       /* Output the entire sequence.  */
    3177           32 :       insns = end_sequence ();
    3178           32 :       emit_insn (insns);
    3179           32 :       return target;
    3180              :     }
    3181              : 
    3182              :   /* If we were unable to expand via the builtin, stop the sequence
    3183              :      (without outputting the insns).  */
    3184          191 :   end_sequence ();
    3185              : 
    3186              :   /* Fall back to floating point rounding optab.  */
    3187          191 :   fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
    3188              : 
    3189              :   /* For non-C99 targets we may end up without a fallback fndecl here
    3190              :      if the user called __builtin_lfloor directly.  In this case emit
    3191              :      a call to the floor/ceil variants nevertheless.  This should result
    3192              :      in the best user experience for not full C99 targets.  */
    3193          191 :   if (fallback_fndecl == NULL_TREE)
    3194              :     {
    3195            0 :       tree fntype;
    3196            0 :       const char *name = NULL;
    3197              : 
    3198            0 :       switch (DECL_FUNCTION_CODE (fndecl))
    3199              :         {
    3200              :         case BUILT_IN_ICEIL:
    3201              :         case BUILT_IN_LCEIL:
    3202              :         case BUILT_IN_LLCEIL:
    3203              :           name = "ceil";
    3204              :           break;
    3205            0 :         case BUILT_IN_ICEILF:
    3206            0 :         case BUILT_IN_LCEILF:
    3207            0 :         case BUILT_IN_LLCEILF:
    3208            0 :           name = "ceilf";
    3209            0 :           break;
    3210            0 :         case BUILT_IN_ICEILL:
    3211            0 :         case BUILT_IN_LCEILL:
    3212            0 :         case BUILT_IN_LLCEILL:
    3213            0 :           name = "ceill";
    3214            0 :           break;
    3215            0 :         case BUILT_IN_IFLOOR:
    3216            0 :         case BUILT_IN_LFLOOR:
    3217            0 :         case BUILT_IN_LLFLOOR:
    3218            0 :           name = "floor";
    3219            0 :           break;
    3220            0 :         case BUILT_IN_IFLOORF:
    3221            0 :         case BUILT_IN_LFLOORF:
    3222            0 :         case BUILT_IN_LLFLOORF:
    3223            0 :           name = "floorf";
    3224            0 :           break;
    3225            0 :         case BUILT_IN_IFLOORL:
    3226            0 :         case BUILT_IN_LFLOORL:
    3227            0 :         case BUILT_IN_LLFLOORL:
    3228            0 :           name = "floorl";
    3229            0 :           break;
    3230            0 :         default:
    3231            0 :           gcc_unreachable ();
    3232              :         }
    3233              : 
    3234            0 :       fntype = build_function_type_list (TREE_TYPE (arg),
    3235            0 :                                          TREE_TYPE (arg), NULL_TREE);
    3236            0 :       fallback_fndecl = build_fn_decl (name, fntype);
    3237              :     }
    3238              : 
    3239          191 :   exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
    3240              : 
    3241          191 :   tmp = expand_normal (exp);
    3242          191 :   tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
    3243              : 
    3244              :   /* Truncate the result of floating point optab to integer
    3245              :      via expand_fix ().  */
    3246          191 :   target = gen_reg_rtx (mode);
    3247          191 :   expand_fix (target, tmp, 0);
    3248              : 
    3249          191 :   return target;
    3250              : }
    3251              : 
    3252              : /* Expand a call to one of the builtin math functions doing integer
    3253              :    conversion (lrint).
    3254              :    Return 0 if a normal call should be emitted rather than expanding the
    3255              :    function in-line.  EXP is the expression that is a call to the builtin
    3256              :    function; if convenient, the result should be placed in TARGET.  */
    3257              : 
    3258              : static rtx
    3259          588 : expand_builtin_int_roundingfn_2 (tree exp, rtx target)
    3260              : {
    3261          588 :   convert_optab builtin_optab;
    3262          588 :   rtx op0;
    3263          588 :   rtx_insn *insns;
    3264          588 :   tree fndecl = get_callee_fndecl (exp);
    3265          588 :   tree arg;
    3266          588 :   machine_mode mode;
    3267          588 :   enum built_in_function fallback_fn = BUILT_IN_NONE;
    3268              : 
    3269          588 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    3270              :     return NULL_RTX;
    3271              : 
    3272          488 :   arg = CALL_EXPR_ARG (exp, 0);
    3273              : 
    3274          488 :   switch (DECL_FUNCTION_CODE (fndecl))
    3275              :     {
    3276            4 :     CASE_FLT_FN (BUILT_IN_IRINT):
    3277            4 :       fallback_fn = BUILT_IN_LRINT;
    3278              :       gcc_fallthrough ();
    3279              :     CASE_FLT_FN (BUILT_IN_LRINT):
    3280              :     CASE_FLT_FN (BUILT_IN_LLRINT):
    3281              :       builtin_optab = lrint_optab;
    3282              :       break;
    3283              : 
    3284          223 :     CASE_FLT_FN (BUILT_IN_IROUND):
    3285          223 :       fallback_fn = BUILT_IN_LROUND;
    3286              :       gcc_fallthrough ();
    3287              :     CASE_FLT_FN (BUILT_IN_LROUND):
    3288              :     CASE_FLT_FN (BUILT_IN_LLROUND):
    3289              :       builtin_optab = lround_optab;
    3290              :       break;
    3291              : 
    3292            0 :     default:
    3293            0 :       gcc_unreachable ();
    3294              :     }
    3295              : 
    3296              :   /* There's no easy way to detect the case we need to set EDOM.  */
    3297          488 :   if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
    3298              :     return NULL_RTX;
    3299              : 
    3300              :   /* Make a suitable register to place result in.  */
    3301          257 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3302              : 
    3303              :   /* There's no easy way to detect the case we need to set EDOM.  */
    3304          257 :   if (!flag_errno_math)
    3305              :     {
    3306          257 :       rtx result = gen_reg_rtx (mode);
    3307              : 
    3308              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    3309              :          need to expand the argument again.  This way, we will not perform
    3310              :          side-effects more the once.  */
    3311          257 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    3312              : 
    3313          257 :       op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    3314              : 
    3315          257 :       start_sequence ();
    3316              : 
    3317          257 :       if (expand_sfix_optab (result, op0, builtin_optab))
    3318              :         {
    3319              :           /* Output the entire sequence.  */
    3320           20 :           insns = end_sequence ();
    3321           20 :           emit_insn (insns);
    3322           20 :           return result;
    3323              :         }
    3324              : 
    3325              :       /* If we were unable to expand via the builtin, stop the sequence
    3326              :          (without outputting the insns) and call to the library function
    3327              :          with the stabilized argument list.  */
    3328          237 :       end_sequence ();
    3329              :     }
    3330              : 
    3331          237 :   if (fallback_fn != BUILT_IN_NONE)
    3332              :     {
    3333              :       /* Fall back to rounding to long int.  Use implicit_p 0 - for non-C99
    3334              :          targets, (int) round (x) should never be transformed into
    3335              :          BUILT_IN_IROUND and if __builtin_iround is called directly, emit
    3336              :          a call to lround in the hope that the target provides at least some
    3337              :          C99 functions.  This should result in the best user experience for
    3338              :          not full C99 targets.
    3339              :          As scalar float conversions with same mode are useless in GIMPLE,
    3340              :          we can end up e.g. with _Float32 argument passed to float builtin,
    3341              :          try to get the type from the builtin prototype first.  */
    3342          223 :       tree fallback_fndecl = NULL_TREE;
    3343          223 :       if (tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
    3344          223 :         fallback_fndecl
    3345          223 :           = mathfn_built_in_1 (TREE_VALUE (argtypes),
    3346              :                                as_combined_fn (fallback_fn), 0);
    3347          223 :       if (fallback_fndecl == NULL_TREE)
    3348            0 :         fallback_fndecl
    3349            0 :           = mathfn_built_in_1 (TREE_TYPE (arg),
    3350              :                                as_combined_fn (fallback_fn), 0);
    3351            0 :       if (fallback_fndecl)
    3352              :         {
    3353          223 :           exp = build_call_nofold_loc (EXPR_LOCATION (exp),
    3354              :                                        fallback_fndecl, 1, arg);
    3355              : 
    3356          223 :           target = expand_call (exp, NULL_RTX, target == const0_rtx);
    3357          223 :           target = maybe_emit_group_store (target, TREE_TYPE (exp));
    3358          223 :           return convert_to_mode (mode, target, 0);
    3359              :         }
    3360              :     }
    3361              : 
    3362           14 :   return expand_call (exp, target, target == const0_rtx);
    3363              : }
    3364              : 
    3365              : /* Expand a call to the powi built-in mathematical function.  Return NULL_RTX if
    3366              :    a normal call should be emitted rather than expanding the function
    3367              :    in-line.  EXP is the expression that is a call to the builtin
    3368              :    function; if convenient, the result should be placed in TARGET.  */
    3369              : 
    3370              : static rtx
    3371          291 : expand_builtin_powi (tree exp, rtx target)
    3372              : {
    3373          291 :   tree arg0, arg1;
    3374          291 :   rtx op0, op1;
    3375          291 :   machine_mode mode;
    3376          291 :   machine_mode mode2;
    3377              : 
    3378          291 :   if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
    3379              :     return NULL_RTX;
    3380              : 
    3381          291 :   arg0 = CALL_EXPR_ARG (exp, 0);
    3382          291 :   arg1 = CALL_EXPR_ARG (exp, 1);
    3383          291 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3384              : 
    3385              :   /* Emit a libcall to libgcc.  */
    3386              : 
    3387              :   /* Mode of the 2nd argument must match that of an int.  */
    3388          291 :   mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
    3389              : 
    3390          291 :   if (target == NULL_RTX)
    3391            0 :     target = gen_reg_rtx (mode);
    3392              : 
    3393          291 :   op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    3394          291 :   if (GET_MODE (op0) != mode)
    3395            0 :     op0 = convert_to_mode (mode, op0, 0);
    3396          291 :   op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
    3397          291 :   if (GET_MODE (op1) != mode2)
    3398           52 :     op1 = convert_to_mode (mode2, op1, 0);
    3399              : 
    3400          291 :   target = emit_library_call_value (optab_libfunc (powi_optab, mode),
    3401              :                                     target, LCT_CONST, mode,
    3402              :                                     op0, mode, op1, mode2);
    3403              : 
    3404          291 :   return target;
    3405              : }
    3406              : 
    3407              : /* Expand expression EXP which is a call to the strlen builtin.  Return
    3408              :    NULL_RTX if we failed and the caller should emit a normal call, otherwise
    3409              :    try to get the result in TARGET, if convenient.  */
    3410              : 
    3411              : static rtx
    3412        14758 : expand_builtin_strlen (tree exp, rtx target,
    3413              :                        machine_mode target_mode)
    3414              : {
    3415        14758 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    3416              :     return NULL_RTX;
    3417              : 
    3418        14738 :   tree src = CALL_EXPR_ARG (exp, 0);
    3419              : 
    3420              :   /* If the length can be computed at compile-time, return it.  */
    3421        14738 :   if (tree len = c_strlen (src, 0))
    3422          129 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3423              : 
    3424              :   /* If the length can be computed at compile-time and is constant
    3425              :      integer, but there are side-effects in src, evaluate
    3426              :      src for side-effects, then return len.
    3427              :      E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
    3428              :      can be optimized into: i++; x = 3;  */
    3429        14609 :   tree len = c_strlen (src, 1);
    3430        14609 :   if (len && TREE_CODE (len) == INTEGER_CST)
    3431              :     {
    3432            0 :       expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
    3433            0 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3434              :     }
    3435              : 
    3436        14609 :   unsigned int align = get_pointer_alignment (src) / BITS_PER_UNIT;
    3437              : 
    3438              :   /* If SRC is not a pointer type, don't do this operation inline.  */
    3439        14609 :   if (align == 0)
    3440              :     return NULL_RTX;
    3441              : 
    3442              :   /* Bail out if we can't compute strlen in the right mode.  */
    3443              :   machine_mode insn_mode;
    3444              :   enum insn_code icode = CODE_FOR_nothing;
    3445        14609 :   FOR_EACH_MODE_FROM (insn_mode, target_mode)
    3446              :     {
    3447        14609 :       icode = optab_handler (strlen_optab, insn_mode);
    3448        14609 :       if (icode != CODE_FOR_nothing)
    3449              :         break;
    3450              :     }
    3451        14609 :   if (insn_mode == VOIDmode)
    3452              :     return NULL_RTX;
    3453              : 
    3454              :   /* Make a place to hold the source address.  We will not expand
    3455              :      the actual source until we are sure that the expansion will
    3456              :      not fail -- there are trees that cannot be expanded twice.  */
    3457        15224 :   rtx src_reg = gen_reg_rtx (Pmode);
    3458              : 
    3459              :   /* Mark the beginning of the strlen sequence so we can emit the
    3460              :      source operand later.  */
    3461        14609 :   rtx_insn *before_strlen = get_last_insn ();
    3462              : 
    3463        14609 :   class expand_operand ops[4];
    3464        14609 :   create_output_operand (&ops[0], target, insn_mode);
    3465        14609 :   create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
    3466        14609 :   create_integer_operand (&ops[2], 0);
    3467        14609 :   create_integer_operand (&ops[3], align);
    3468        14609 :   if (!maybe_expand_insn (icode, 4, ops))
    3469              :     return NULL_RTX;
    3470              : 
    3471              :   /* Check to see if the argument was declared attribute nonstring
    3472              :      and if so, issue a warning since at this point it's not known
    3473              :      to be nul-terminated.  */
    3474           11 :   maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    3475              : 
    3476              :   /* Now that we are assured of success, expand the source.  */
    3477           11 :   start_sequence ();
    3478           15 :   rtx pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
    3479           11 :   if (pat != src_reg)
    3480              :     {
    3481              : #ifdef POINTERS_EXTEND_UNSIGNED
    3482           15 :       if (GET_MODE (pat) != Pmode)
    3483            0 :         pat = convert_to_mode (Pmode, pat,
    3484              :                                POINTERS_EXTEND_UNSIGNED);
    3485              : #endif
    3486           11 :       emit_move_insn (src_reg, pat);
    3487              :     }
    3488           11 :   pat = end_sequence ();
    3489              : 
    3490           11 :   if (before_strlen)
    3491           11 :     emit_insn_after (pat, before_strlen);
    3492              :   else
    3493            0 :     emit_insn_before (pat, get_insns ());
    3494              : 
    3495              :   /* Return the value in the proper mode for this function.  */
    3496           11 :   if (GET_MODE (ops[0].value) == target_mode)
    3497              :     target = ops[0].value;
    3498            0 :   else if (target != 0)
    3499            0 :     convert_move (target, ops[0].value, 0);
    3500              :   else
    3501            0 :     target = convert_to_mode (target_mode, ops[0].value, 0);
    3502              : 
    3503              :   return target;
    3504              : }
    3505              : 
    3506              : /* Expand call EXP to the strnlen built-in, returning the result
    3507              :    and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
    3508              : 
    3509              : static rtx
    3510          645 : expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
    3511              : {
    3512          645 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3513              :     return NULL_RTX;
    3514              : 
    3515          636 :   tree src = CALL_EXPR_ARG (exp, 0);
    3516          636 :   tree bound = CALL_EXPR_ARG (exp, 1);
    3517              : 
    3518          636 :   if (!bound)
    3519              :     return NULL_RTX;
    3520              : 
    3521          636 :   location_t loc = UNKNOWN_LOCATION;
    3522          636 :   if (EXPR_HAS_LOCATION (exp))
    3523          636 :     loc = EXPR_LOCATION (exp);
    3524              : 
    3525              :   /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
    3526              :      so these conversions aren't necessary.  */
    3527          636 :   c_strlen_data lendata = { };
    3528          636 :   tree len = c_strlen (src, 0, &lendata, 1);
    3529          636 :   if (len)
    3530          102 :     len = fold_convert_loc (loc, TREE_TYPE (bound), len);
    3531              : 
    3532          636 :   if (TREE_CODE (bound) == INTEGER_CST)
    3533              :     {
    3534          369 :       if (!len)
    3535              :         return NULL_RTX;
    3536              : 
    3537           62 :       len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
    3538           62 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3539              :     }
    3540              : 
    3541          267 :   if (TREE_CODE (bound) != SSA_NAME)
    3542              :     return NULL_RTX;
    3543              : 
    3544          267 :   wide_int min, max;
    3545          267 :   int_range_max r;
    3546          534 :   get_range_query (cfun)->range_of_expr (r, bound,
    3547              :                                          currently_expanding_gimple_stmt);
    3548          267 :   if (r.varying_p () || r.undefined_p ())
    3549              :     return NULL_RTX;
    3550          152 :   min = r.lower_bound ();
    3551          152 :   max = r.upper_bound ();
    3552              : 
    3553          152 :   if (!len || TREE_CODE (len) != INTEGER_CST)
    3554              :     {
    3555          115 :       bool exact;
    3556          115 :       lendata.decl = unterminated_array (src, &len, &exact);
    3557          115 :       if (!lendata.decl)
    3558           95 :         return NULL_RTX;
    3559              :     }
    3560              : 
    3561           57 :   if (lendata.decl)
    3562              :     return NULL_RTX;
    3563              : 
    3564           37 :   if (wi::gtu_p (min, wi::to_wide (len)))
    3565            7 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3566              : 
    3567           30 :   len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, bound);
    3568           30 :   return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3569          267 : }
    3570              : 
    3571              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    3572              :    bytes from bytes at DATA + OFFSET and return it reinterpreted as
    3573              :    a target constant.  */
    3574              : 
    3575              : static rtx
    3576       170839 : builtin_memcpy_read_str (void *data, void *, HOST_WIDE_INT offset,
    3577              :                          fixed_size_mode mode)
    3578              : {
    3579              :   /* The REPresentation pointed to by DATA need not be a nul-terminated
    3580              :      string but the caller guarantees it's large enough for MODE.  */
    3581       170839 :   const char *rep = (const char *) data;
    3582              : 
    3583       170839 :   return c_readstr (rep + offset, mode, /*nul_terminated=*/false);
    3584              : }
    3585              : 
    3586              : /* LEN specify length of the block of memcpy/memset operation.
    3587              :    Figure out its range and put it into MIN_SIZE/MAX_SIZE.
    3588              :    In some cases we can make very likely guess on max size, then we
    3589              :    set it into PROBABLE_MAX_SIZE.  */
    3590              : 
    3591              : static void
    3592       188312 : determine_block_size (tree len, rtx &len_rtx,
    3593              :                       unsigned HOST_WIDE_INT *min_size,
    3594              :                       unsigned HOST_WIDE_INT *max_size,
    3595              :                       unsigned HOST_WIDE_INT *probable_max_size)
    3596              : {
    3597       188312 :   if (CONST_INT_P (len_rtx))
    3598              :     {
    3599        95250 :       *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
    3600        95250 :       return;
    3601              :     }
    3602              :   else
    3603              :     {
    3604        93062 :       wide_int min, max;
    3605        93062 :       enum value_range_kind range_type = VR_UNDEFINED;
    3606              : 
    3607              :       /* Determine bounds from the type.  */
    3608        93062 :       if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
    3609        93061 :         *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
    3610              :       else
    3611            1 :         *min_size = 0;
    3612        93062 :       if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
    3613       186124 :         *probable_max_size = *max_size
    3614        93062 :           = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
    3615              :       else
    3616            0 :         *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
    3617              : 
    3618        93062 :       if (TREE_CODE (len) == SSA_NAME)
    3619              :         {
    3620        93062 :           int_range_max r;
    3621        93062 :           tree tmin, tmax;
    3622        93062 :           gimple *cg = currently_expanding_gimple_stmt;
    3623       186124 :           get_range_query (cfun)->range_of_expr (r, len, cg);
    3624        93062 :           range_type = get_legacy_range (r, tmin, tmax);
    3625        93062 :           if (range_type != VR_UNDEFINED)
    3626              :             {
    3627        93061 :               min = wi::to_wide (tmin);
    3628        93061 :               max = wi::to_wide (tmax);
    3629              :             }
    3630        93062 :         }
    3631        93062 :       if (range_type == VR_RANGE)
    3632              :         {
    3633        67157 :           if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
    3634        54650 :             *min_size = min.to_uhwi ();
    3635        67157 :           if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
    3636        60791 :             *probable_max_size = *max_size = max.to_uhwi ();
    3637              :         }
    3638        25905 :       else if (range_type == VR_ANTI_RANGE)
    3639              :         {
    3640              :           /* Code like
    3641              : 
    3642              :              int n;
    3643              :              if (n < 100)
    3644              :                memcpy (a, b, n)
    3645              : 
    3646              :              Produce anti range allowing negative values of N.  We still
    3647              :              can use the information and make a guess that N is not negative.
    3648              :              */
    3649         3109 :           if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
    3650         2982 :             *probable_max_size = min.to_uhwi () - 1;
    3651              :         }
    3652        93062 :     }
    3653              : 
    3654        93062 :   if (*min_size == *max_size)
    3655           10 :     len_rtx = GEN_INT (*min_size);
    3656              :   else
    3657        93052 :     gcc_checking_assert (*max_size <=
    3658              :                          (unsigned HOST_WIDE_INT)
    3659              :                          GET_MODE_MASK (GET_MODE (len_rtx)));
    3660              : }
    3661              : 
    3662              : /* Expand a call EXP to the memcpy builtin.
    3663              :    Return NULL_RTX if we failed, the caller should emit a normal call,
    3664              :    otherwise try to get the result in TARGET, if convenient (and in
    3665              :    mode MODE if that's convenient).  */
    3666              : 
    3667              : static rtx
    3668       107852 : expand_builtin_memcpy (tree exp, rtx target)
    3669              : {
    3670       107852 :   if (!validate_arglist (exp,
    3671              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3672              :     return NULL_RTX;
    3673              : 
    3674       107834 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3675       107834 :   tree src = CALL_EXPR_ARG (exp, 1);
    3676       107834 :   tree len = CALL_EXPR_ARG (exp, 2);
    3677              : 
    3678       107834 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    3679       107834 :                                           /*retmode=*/ RETURN_BEGIN, false);
    3680              : }
    3681              : 
    3682              : /* Check a call EXP to the memmove built-in for validity.
    3683              :    Return NULL_RTX on both success and failure.  */
    3684              : 
    3685              : static rtx
    3686        17198 : expand_builtin_memmove (tree exp, rtx target)
    3687              : {
    3688        17198 :   if (!validate_arglist (exp,
    3689              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3690              :     return NULL_RTX;
    3691              : 
    3692        17183 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3693        17183 :   tree src = CALL_EXPR_ARG (exp, 1);
    3694        17183 :   tree len = CALL_EXPR_ARG (exp, 2);
    3695              : 
    3696        17183 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    3697        17183 :                                           /*retmode=*/ RETURN_BEGIN, true);
    3698              : }
    3699              : 
    3700              : /* Expand a call EXP to the mempcpy builtin.
    3701              :    Return NULL_RTX if we failed; the caller should emit a normal call,
    3702              :    otherwise try to get the result in TARGET, if convenient (and in
    3703              :    mode MODE if that's convenient).  */
    3704              : 
    3705              : static rtx
    3706         1394 : expand_builtin_mempcpy (tree exp, rtx target)
    3707              : {
    3708         1394 :   if (!validate_arglist (exp,
    3709              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3710              :     return NULL_RTX;
    3711              : 
    3712         1389 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3713         1389 :   tree src = CALL_EXPR_ARG (exp, 1);
    3714         1389 :   tree len = CALL_EXPR_ARG (exp, 2);
    3715              : 
    3716              :   /* Policy does not generally allow using compute_objsize (which
    3717              :      is used internally by check_memop_size) to change code generation
    3718              :      or drive optimization decisions.
    3719              : 
    3720              :      In this instance it is safe because the code we generate has
    3721              :      the same semantics regardless of the return value of
    3722              :      check_memop_sizes.   Exactly the same amount of data is copied
    3723              :      and the return value is exactly the same in both cases.
    3724              : 
    3725              :      Furthermore, check_memop_size always uses mode 0 for the call to
    3726              :      compute_objsize, so the imprecise nature of compute_objsize is
    3727              :      avoided.  */
    3728              : 
    3729              :   /* Avoid expanding mempcpy into memcpy when the call is determined
    3730              :      to overflow the buffer.  This also prevents the same overflow
    3731              :      from being diagnosed again when expanding memcpy.  */
    3732              : 
    3733         1389 :   return expand_builtin_mempcpy_args (dest, src, len,
    3734         1389 :                                       target, exp, /*retmode=*/ RETURN_END);
    3735              : }
    3736              : 
    3737              : /* Helper function to do the actual work for expand of memory copy family
    3738              :    functions (memcpy, mempcpy, stpcpy).  Expansing should assign LEN bytes
    3739              :    of memory from SRC to DEST and assign to TARGET if convenient.  Return
    3740              :    value is based on RETMODE argument.  */
    3741              : 
    3742              : static rtx
    3743       126429 : expand_builtin_memory_copy_args (tree dest, tree src, tree len,
    3744              :                                  rtx target, tree exp, memop_ret retmode,
    3745              :                                  bool might_overlap)
    3746              : {
    3747       126429 :   unsigned int src_align = get_pointer_alignment (src);
    3748       126429 :   unsigned int dest_align = get_pointer_alignment (dest);
    3749       126429 :   rtx dest_mem, src_mem, dest_addr, len_rtx;
    3750       126429 :   HOST_WIDE_INT expected_size = -1;
    3751       126429 :   unsigned int expected_align = 0;
    3752       126429 :   unsigned HOST_WIDE_INT min_size;
    3753       126429 :   unsigned HOST_WIDE_INT max_size;
    3754       126429 :   unsigned HOST_WIDE_INT probable_max_size;
    3755              : 
    3756       126429 :   bool is_move_done;
    3757              : 
    3758              :   /* If DEST is not a pointer type, call the normal function.  */
    3759       126429 :   if (dest_align == 0)
    3760              :     return NULL_RTX;
    3761              : 
    3762              :   /* If either SRC is not a pointer type, don't do this
    3763              :      operation in-line.  */
    3764       126429 :   if (src_align == 0)
    3765              :     return NULL_RTX;
    3766              : 
    3767       126429 :   if (currently_expanding_gimple_stmt)
    3768       126429 :     stringop_block_profile (currently_expanding_gimple_stmt,
    3769              :                             &expected_align, &expected_size);
    3770              : 
    3771       126429 :   if (expected_align < dest_align)
    3772       126407 :     expected_align = dest_align;
    3773       126429 :   dest_mem = get_memory_rtx (dest, len);
    3774       126429 :   set_mem_align (dest_mem, dest_align);
    3775       126429 :   len_rtx = expand_normal (len);
    3776       126429 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    3777              :                         &probable_max_size);
    3778              : 
    3779              :   /* Try to get the byte representation of the constant SRC points to,
    3780              :      with its byte size in NBYTES.  */
    3781       126429 :   unsigned HOST_WIDE_INT nbytes;
    3782       126429 :   const char *rep = getbyterep (src, &nbytes);
    3783              : 
    3784              :   /* If the function's constant bound LEN_RTX is less than or equal
    3785              :      to the byte size of the representation of the constant argument,
    3786              :      and if block move would be done by pieces, we can avoid loading
    3787              :      the bytes from memory and only store the computed constant.
    3788              :      This works in the overlap (memmove) case as well because
    3789              :      store_by_pieces just generates a series of stores of constants
    3790              :      from the representation returned by getbyterep().  */
    3791       126429 :   if (rep
    3792        30869 :       && CONST_INT_P (len_rtx)
    3793        29299 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes
    3794       155462 :       && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
    3795              :                               const_cast<char *> (rep),
    3796              :                               dest_align, false))
    3797              :     {
    3798        28550 :       dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
    3799              :                                   builtin_memcpy_read_str,
    3800              :                                   const_cast<char *> (rep),
    3801              :                                   dest_align, false, retmode);
    3802        28550 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    3803        28550 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    3804        28550 :       return dest_mem;
    3805              :     }
    3806              : 
    3807        97879 :   src_mem = get_memory_rtx (src, len);
    3808        97879 :   set_mem_align (src_mem, src_align);
    3809              : 
    3810              :   /* Copy word part most expediently.  */
    3811        97879 :   enum block_op_methods method = BLOCK_OP_NORMAL;
    3812        97879 :   if (CALL_EXPR_TAILCALL (exp)
    3813        97879 :       && (retmode == RETURN_BEGIN || target == const0_rtx))
    3814              :     method = BLOCK_OP_TAILCALL;
    3815        97879 :   bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
    3816        97879 :                            && retmode == RETURN_END
    3817        97879 :                            && !might_overlap
    3818        98953 :                            && target != const0_rtx);
    3819              :   if (use_mempcpy_call)
    3820        97879 :     method = BLOCK_OP_NO_LIBCALL_RET;
    3821        97879 :   dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
    3822              :                                      expected_align, expected_size,
    3823              :                                      min_size, max_size, probable_max_size,
    3824              :                                      use_mempcpy_call, &is_move_done,
    3825              :                                      might_overlap, tree_ctz (len));
    3826              : 
    3827              :   /* Bail out when a mempcpy call would be expanded as libcall and when
    3828              :      we have a target that provides a fast implementation
    3829              :      of mempcpy routine.  */
    3830        97879 :   if (!is_move_done)
    3831              :     return NULL_RTX;
    3832              : 
    3833        85153 :   if (dest_addr == pc_rtx)
    3834              :     return NULL_RTX;
    3835              : 
    3836        85153 :   if (dest_addr == 0)
    3837              :     {
    3838        32897 :       dest_addr = force_operand (XEXP (dest_mem, 0), target);
    3839        32897 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    3840              :     }
    3841              : 
    3842        85153 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    3843              :     {
    3844          815 :       dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
    3845              :       /* stpcpy pointer to last byte.  */
    3846          815 :       if (retmode == RETURN_END_MINUS_ONE)
    3847            0 :         dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
    3848              :     }
    3849              : 
    3850              :   return dest_addr;
    3851              : }
    3852              : 
    3853              : static rtx
    3854         1412 : expand_builtin_mempcpy_args (tree dest, tree src, tree len,
    3855              :                              rtx target, tree orig_exp, memop_ret retmode)
    3856              : {
    3857         1389 :   return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
    3858            0 :                                           retmode, false);
    3859              : }
    3860              : 
    3861              : /* Expand into a movstr instruction, if one is available.  Return NULL_RTX if
    3862              :    we failed, the caller should emit a normal call, otherwise try to
    3863              :    get the result in TARGET, if convenient.
    3864              :    Return value is based on RETMODE argument.  */
    3865              : 
    3866              : static rtx
    3867         2267 : expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
    3868              : {
    3869         2267 :   class expand_operand ops[3];
    3870         2267 :   rtx dest_mem;
    3871         2267 :   rtx src_mem;
    3872              : 
    3873         2267 :   if (!targetm.have_movstr ())
    3874              :     return NULL_RTX;
    3875              : 
    3876            0 :   dest_mem = get_memory_rtx (dest, NULL);
    3877            0 :   src_mem = get_memory_rtx (src, NULL);
    3878            0 :   if (retmode == RETURN_BEGIN)
    3879              :     {
    3880            0 :       target = force_reg (Pmode, XEXP (dest_mem, 0));
    3881            0 :       dest_mem = replace_equiv_address (dest_mem, target);
    3882              :     }
    3883              : 
    3884            0 :   create_output_operand (&ops[0],
    3885            0 :                          retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
    3886            0 :   create_fixed_operand (&ops[1], dest_mem);
    3887            0 :   create_fixed_operand (&ops[2], src_mem);
    3888            0 :   if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
    3889              :     return NULL_RTX;
    3890              : 
    3891            0 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    3892              :     {
    3893            0 :       target = ops[0].value;
    3894              :       /* movstr is supposed to set end to the address of the NUL
    3895              :          terminator.  If the caller requested a mempcpy-like return value,
    3896              :          adjust it.  */
    3897            0 :       if (retmode == RETURN_END)
    3898              :         {
    3899            0 :           rtx tem = plus_constant (GET_MODE (target),
    3900            0 :                                    gen_lowpart (GET_MODE (target), target), 1);
    3901            0 :           emit_move_insn (target, force_operand (tem, NULL_RTX));
    3902              :         }
    3903              :     }
    3904              :   return target;
    3905              : }
    3906              : 
    3907              : /* Expand expression EXP, which is a call to the strcpy builtin.  Return
    3908              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    3909              :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    3910              :    convenient).  */
    3911              : 
    3912              : static rtx
    3913         1860 : expand_builtin_strcpy (tree exp, rtx target)
    3914              : {
    3915         1860 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    3916              :     return NULL_RTX;
    3917              : 
    3918         1845 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3919         1845 :   tree src = CALL_EXPR_ARG (exp, 1);
    3920              : 
    3921         1845 :   return expand_builtin_strcpy_args (exp, dest, src, target);
    3922              : }
    3923              : 
    3924              : /* Helper function to do the actual work for expand_builtin_strcpy.  The
    3925              :    arguments to the builtin_strcpy call DEST and SRC are broken out
    3926              :    so that this can also be called without constructing an actual CALL_EXPR.
    3927              :    The other arguments and return value are the same as for
    3928              :    expand_builtin_strcpy.  */
    3929              : 
    3930              : static rtx
    3931         1845 : expand_builtin_strcpy_args (tree, tree dest, tree src, rtx target)
    3932              : {
    3933         1845 :   return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
    3934              : }
    3935              : 
    3936              : /* Expand a call EXP to the stpcpy builtin.
    3937              :    Return NULL_RTX if we failed the caller should emit a normal call,
    3938              :    otherwise try to get the result in TARGET, if convenient (and in
    3939              :    mode MODE if that's convenient).  */
    3940              : 
    3941              : static rtx
    3942          454 : expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
    3943              : {
    3944          454 :   tree dst, src;
    3945          454 :   location_t loc = EXPR_LOCATION (exp);
    3946              : 
    3947          454 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    3948              :     return NULL_RTX;
    3949              : 
    3950          445 :   dst = CALL_EXPR_ARG (exp, 0);
    3951          445 :   src = CALL_EXPR_ARG (exp, 1);
    3952              : 
    3953              :   /* If return value is ignored, transform stpcpy into strcpy.  */
    3954          445 :   if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
    3955              :     {
    3956            0 :       tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
    3957            0 :       tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
    3958            0 :       return expand_expr (result, target, mode, EXPAND_NORMAL);
    3959              :     }
    3960              :   else
    3961              :     {
    3962          445 :       tree len, lenp1;
    3963          445 :       rtx ret;
    3964              : 
    3965              :       /* Ensure we get an actual string whose length can be evaluated at
    3966              :          compile-time, not an expression containing a string.  This is
    3967              :          because the latter will potentially produce pessimized code
    3968              :          when used to produce the return value.  */
    3969          445 :       c_strlen_data lendata = { };
    3970          445 :       if (!c_getstr (src)
    3971          445 :           || !(len = c_strlen (src, 0, &lendata, 1)))
    3972          422 :         return expand_movstr (dst, src, target,
    3973          422 :                               /*retmode=*/ RETURN_END_MINUS_ONE);
    3974              : 
    3975           23 :       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
    3976           23 :       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
    3977              :                                          target, exp,
    3978              :                                          /*retmode=*/ RETURN_END_MINUS_ONE);
    3979              : 
    3980           23 :       if (ret)
    3981              :         return ret;
    3982              : 
    3983            0 :       if (TREE_CODE (len) == INTEGER_CST)
    3984              :         {
    3985            0 :           rtx len_rtx = expand_normal (len);
    3986              : 
    3987            0 :           if (CONST_INT_P (len_rtx))
    3988              :             {
    3989            0 :               ret = expand_builtin_strcpy_args (exp, dst, src, target);
    3990              : 
    3991            0 :               if (ret)
    3992              :                 {
    3993            0 :                   if (! target)
    3994              :                     {
    3995            0 :                       if (mode != VOIDmode)
    3996            0 :                         target = gen_reg_rtx (mode);
    3997              :                       else
    3998            0 :                         target = gen_reg_rtx (GET_MODE (ret));
    3999              :                     }
    4000            0 :                   if (GET_MODE (target) != GET_MODE (ret))
    4001            0 :                     ret = gen_lowpart (GET_MODE (target), ret);
    4002              : 
    4003            0 :                   ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
    4004            0 :                   ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
    4005            0 :                   gcc_assert (ret);
    4006              : 
    4007              :                   return target;
    4008              :                 }
    4009              :             }
    4010              :         }
    4011              : 
    4012            0 :       return expand_movstr (dst, src, target,
    4013            0 :                             /*retmode=*/ RETURN_END_MINUS_ONE);
    4014              :     }
    4015              : }
    4016              : 
    4017              : /* Expand a call EXP to the stpcpy builtin and diagnose uses of nonstring
    4018              :    arguments while being careful to avoid duplicate warnings (which could
    4019              :    be issued if the expander were to expand the call, resulting in it
    4020              :    being emitted in expand_call().  */
    4021              : 
    4022              : static rtx
    4023          454 : expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
    4024              : {
    4025          454 :   if (rtx ret = expand_builtin_stpcpy_1 (exp, target, mode))
    4026              :     {
    4027              :       /* The call has been successfully expanded.  Check for nonstring
    4028              :          arguments and issue warnings as appropriate.  */
    4029           23 :       maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    4030           23 :       return ret;
    4031              :     }
    4032              : 
    4033              :   return NULL_RTX;
    4034              : }
    4035              : 
    4036              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4037              :    bytes from constant string DATA + OFFSET and return it as target
    4038              :    constant.  */
    4039              : 
    4040              : rtx
    4041         9523 : builtin_strncpy_read_str (void *data, void *, HOST_WIDE_INT offset,
    4042              :                           fixed_size_mode mode)
    4043              : {
    4044         9523 :   const char *str = (const char *) data;
    4045              : 
    4046         9523 :   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
    4047          260 :     return const0_rtx;
    4048              : 
    4049         9263 :   return c_readstr (str + offset, mode);
    4050              : }
    4051              : 
    4052              : /* Helper to check the sizes of sequences and the destination of calls
    4053              :    to __builtin_strncat and __builtin___strncat_chk.  Returns true on
    4054              :    success (no overflow or invalid sizes), false otherwise.  */
    4055              : 
    4056              : static bool
    4057          108 : check_strncat_sizes (tree exp, tree objsize)
    4058              : {
    4059          108 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4060          108 :   tree src = CALL_EXPR_ARG (exp, 1);
    4061          108 :   tree maxread = CALL_EXPR_ARG (exp, 2);
    4062              : 
    4063              :   /* Try to determine the range of lengths that the source expression
    4064              :      refers to.  */
    4065          108 :   c_strlen_data lendata = { };
    4066          108 :   get_range_strlen (src, &lendata, /* eltsize = */ 1);
    4067              : 
    4068              :   /* Try to verify that the destination is big enough for the shortest
    4069              :      string.  */
    4070              : 
    4071          108 :   access_data data (nullptr, exp, access_read_write, maxread, true);
    4072          108 :   if (!objsize && warn_stringop_overflow)
    4073              :     {
    4074              :       /* If it hasn't been provided by __strncat_chk, try to determine
    4075              :          the size of the destination object into which the source is
    4076              :          being copied.  */
    4077            0 :       objsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst);
    4078              :     }
    4079              : 
    4080              :   /* Add one for the terminating nul.  */
    4081          108 :   tree srclen = (lendata.minlen
    4082          108 :                  ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
    4083              :                                 size_one_node)
    4084              :                  : NULL_TREE);
    4085              : 
    4086              :   /* The strncat function copies at most MAXREAD bytes and always appends
    4087              :      the terminating nul so the specified upper bound should never be equal
    4088              :      to (or greater than) the size of the destination.  */
    4089           55 :   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
    4090          155 :       && tree_int_cst_equal (objsize, maxread))
    4091              :     {
    4092           23 :       location_t loc = EXPR_LOCATION (exp);
    4093           23 :       warning_at (loc, OPT_Wstringop_overflow_,
    4094              :                   "%qD specified bound %E equals destination size",
    4095              :                   get_callee_fndecl (exp), maxread);
    4096              : 
    4097           23 :       return false;
    4098              :     }
    4099              : 
    4100           85 :   if (!srclen
    4101           85 :       || (maxread && tree_fits_uhwi_p (maxread)
    4102           32 :           && tree_fits_uhwi_p (srclen)
    4103           32 :           && tree_int_cst_lt (maxread, srclen)))
    4104              :     srclen = maxread;
    4105              : 
    4106              :   /* The number of bytes to write is LEN but check_access will alsoa
    4107              :      check SRCLEN if LEN's value isn't known.  */
    4108           85 :   return check_access (exp, /*dstwrite=*/NULL_TREE, maxread, srclen,
    4109           85 :                        objsize, data.mode, &data);
    4110              : }
    4111              : 
    4112              : /* Expand expression EXP, which is a call to the strncpy builtin.  Return
    4113              :    NULL_RTX if we failed the caller should emit a normal call.  */
    4114              : 
    4115              : static rtx
    4116         2177 : expand_builtin_strncpy (tree exp, rtx target)
    4117              : {
    4118         2177 :   location_t loc = EXPR_LOCATION (exp);
    4119              : 
    4120         2177 :   if (!validate_arglist (exp,
    4121              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4122              :     return NULL_RTX;
    4123         2165 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4124         2165 :   tree src = CALL_EXPR_ARG (exp, 1);
    4125              :   /* The number of bytes to write (not the maximum).  */
    4126         2165 :   tree len = CALL_EXPR_ARG (exp, 2);
    4127              : 
    4128              :   /* The length of the source sequence.  */
    4129         2165 :   tree slen = c_strlen (src, 1);
    4130              : 
    4131              :   /* We must be passed a constant len and src parameter.  */
    4132         2165 :   if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
    4133              :     return NULL_RTX;
    4134              : 
    4135          237 :   slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
    4136              : 
    4137              :   /* We're required to pad with trailing zeros if the requested
    4138              :      len is greater than strlen(s2)+1.  In that case try to
    4139              :      use store_by_pieces, if it fails, punt.  */
    4140          237 :   if (tree_int_cst_lt (slen, len))
    4141              :     {
    4142          142 :       unsigned int dest_align = get_pointer_alignment (dest);
    4143          142 :       const char *p = c_getstr (src);
    4144          142 :       rtx dest_mem;
    4145              : 
    4146          136 :       if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
    4147          278 :           || !can_store_by_pieces (tree_to_uhwi (len),
    4148              :                                    builtin_strncpy_read_str,
    4149              :                                    const_cast<char *> (p),
    4150              :                                    dest_align, false))
    4151           14 :         return NULL_RTX;
    4152              : 
    4153          128 :       dest_mem = get_memory_rtx (dest, len);
    4154          128 :       store_by_pieces (dest_mem, tree_to_uhwi (len),
    4155              :                        builtin_strncpy_read_str,
    4156              :                        const_cast<char *> (p), dest_align, false,
    4157              :                        RETURN_BEGIN);
    4158          128 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    4159          128 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4160          128 :       return dest_mem;
    4161              :     }
    4162              : 
    4163              :   return NULL_RTX;
    4164              : }
    4165              : 
    4166              : /* Return the RTL of a register in MODE generated from PREV in the
    4167              :    previous iteration.  */
    4168              : 
    4169              : static rtx
    4170       249012 : gen_memset_value_from_prev (by_pieces_prev *prev, fixed_size_mode mode)
    4171              : {
    4172       249012 :   rtx target = nullptr;
    4173       249012 :   if (prev != nullptr && prev->data != nullptr)
    4174              :     {
    4175              :       /* Use the previous data in the same mode.  */
    4176       137249 :       if (prev->mode == mode)
    4177       249012 :         return prev->data;
    4178              : 
    4179        32121 :       fixed_size_mode prev_mode = prev->mode;
    4180              : 
    4181              :       /* Don't use the previous data to write QImode if it is in a
    4182              :          vector mode.  */
    4183        32121 :       if (VECTOR_MODE_P (prev_mode) && mode == QImode)
    4184              :         return target;
    4185              : 
    4186        31727 :       rtx prev_rtx = prev->data;
    4187              : 
    4188        31727 :       if (REG_P (prev_rtx)
    4189        23395 :           && HARD_REGISTER_P (prev_rtx)
    4190        31727 :           && lowpart_subreg_regno (REGNO (prev_rtx), prev_mode, mode) < 0)
    4191              :         {
    4192              :           /* This case occurs when PREV_MODE is a vector and when
    4193              :              MODE is too small to store using vector operations.
    4194              :              After register allocation, the code will need to move the
    4195              :              lowpart of the vector register into a non-vector register.
    4196              : 
    4197              :              Also, the target has chosen to use a hard register
    4198              :              instead of going with the default choice of using a
    4199              :              pseudo register.  We should respect that choice and try to
    4200              :              avoid creating a pseudo register with the same mode as the
    4201              :              current hard register.
    4202              : 
    4203              :              In principle, we could just use a lowpart MODE subreg of
    4204              :              the vector register.  However, the vector register mode might
    4205              :              be too wide for non-vector registers, and we already know
    4206              :              that the non-vector mode is too small for vector registers.
    4207              :              It's therefore likely that we'd need to spill to memory in
    4208              :              the vector mode and reload the non-vector value from there.
    4209              : 
    4210              :              Try to avoid that by reducing the vector register to the
    4211              :              smallest size that it can hold.  This should increase the
    4212              :              chances that non-vector registers can hold both the inner
    4213              :              and outer modes of the subreg that we generate later.  */
    4214            0 :           machine_mode m;
    4215            0 :           fixed_size_mode candidate;
    4216            0 :           FOR_EACH_MODE_IN_CLASS (m, GET_MODE_CLASS (mode))
    4217            0 :             if (is_a<fixed_size_mode> (m, &candidate))
    4218              :               {
    4219            0 :                 if (GET_MODE_SIZE (candidate)
    4220            0 :                     >= GET_MODE_SIZE (prev_mode))
    4221              :                   break;
    4222            0 :                 if (GET_MODE_SIZE (candidate) >= GET_MODE_SIZE (mode)
    4223            0 :                     && lowpart_subreg_regno (REGNO (prev_rtx),
    4224              :                                              prev_mode, candidate) >= 0)
    4225              :                   {
    4226            0 :                     target = lowpart_subreg (candidate, prev_rtx,
    4227              :                                              prev_mode);
    4228            0 :                     prev_rtx = target;
    4229            0 :                     prev_mode = candidate;
    4230            0 :                     break;
    4231              :                   }
    4232              :               }
    4233            0 :           if (target == nullptr)
    4234            0 :             prev_rtx = copy_to_reg (prev_rtx);
    4235              :         }
    4236              : 
    4237        31727 :       target = lowpart_subreg (mode, prev_rtx, prev_mode);
    4238              :     }
    4239              :   return target;
    4240              : }
    4241              : 
    4242              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4243              :    bytes from constant string DATA + OFFSET and return it as target
    4244              :    constant.  If PREV isn't nullptr, it has the RTL info from the
    4245              :    previous iteration.  */
    4246              : 
    4247              : rtx
    4248       247753 : builtin_memset_read_str (void *data, void *prev,
    4249              :                          HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4250              :                          fixed_size_mode mode)
    4251              : {
    4252       247753 :   const char *c = (const char *) data;
    4253       247753 :   unsigned int size = GET_MODE_SIZE (mode);
    4254              : 
    4255       247753 :   rtx target = gen_memset_value_from_prev ((by_pieces_prev *) prev,
    4256              :                                            mode);
    4257       247753 :   if (target != nullptr)
    4258              :     return target;
    4259       111442 :   rtx src = gen_int_mode (*c, QImode);
    4260              : 
    4261       111442 :   if (VECTOR_MODE_P (mode))
    4262              :     {
    4263       160786 :       gcc_assert (GET_MODE_INNER (mode) == QImode);
    4264              : 
    4265        80393 :       rtx const_vec = gen_const_vec_duplicate (mode, src);
    4266        80393 :       if (prev == NULL)
    4267              :         /* Return CONST_VECTOR when called by a query function.  */
    4268              :         return const_vec;
    4269              : 
    4270              :       /* Use the move expander with CONST_VECTOR.  */
    4271        59761 :       target = gen_reg_rtx (mode);
    4272        59761 :       emit_move_insn (target, const_vec);
    4273        59761 :       return target;
    4274              :     }
    4275              : 
    4276        31049 :   char *p = XALLOCAVEC (char, size);
    4277              : 
    4278        31049 :   memset (p, *c, size);
    4279              : 
    4280        31049 :   return c_readstr (p, mode);
    4281              : }
    4282              : 
    4283              : /* Callback routine for store_by_pieces.  Return the RTL of a register
    4284              :    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
    4285              :    char value given in the RTL register data.  For example, if mode is
    4286              :    4 bytes wide, return the RTL for 0x01010101*data.  If PREV isn't
    4287              :    nullptr, it has the RTL info from the previous iteration.  */
    4288              : 
    4289              : static rtx
    4290         1440 : builtin_memset_gen_str (void *data, void *prev,
    4291              :                         HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4292              :                         fixed_size_mode mode)
    4293              : {
    4294         1440 :   rtx target, coeff;
    4295         1440 :   size_t size;
    4296         1440 :   char *p;
    4297              : 
    4298         1440 :   size = GET_MODE_SIZE (mode);
    4299         1440 :   if (size == 1)
    4300              :     return (rtx) data;
    4301              : 
    4302         1259 :   target = gen_memset_value_from_prev ((by_pieces_prev *) prev, mode);
    4303         1259 :   if (target != nullptr)
    4304              :     return target;
    4305              : 
    4306          715 :   if (VECTOR_MODE_P (mode))
    4307              :     {
    4308          362 :       gcc_assert (GET_MODE_INNER (mode) == QImode);
    4309              : 
    4310              :       /* vec_duplicate_optab is a precondition to pick a vector mode for
    4311              :          the memset expander.  */
    4312          181 :       insn_code icode = optab_handler (vec_duplicate_optab, mode);
    4313              : 
    4314          181 :       target = gen_reg_rtx (mode);
    4315          181 :       class expand_operand ops[2];
    4316          181 :       create_output_operand (&ops[0], target, mode);
    4317          181 :       create_input_operand (&ops[1], (rtx) data, QImode);
    4318          181 :       expand_insn (icode, 2, ops);
    4319          181 :       if (!rtx_equal_p (target, ops[0].value))
    4320            0 :         emit_move_insn (target, ops[0].value);
    4321              : 
    4322          181 :       return target;
    4323              :     }
    4324              : 
    4325          534 :   p = XALLOCAVEC (char, size);
    4326          534 :   memset (p, 1, size);
    4327          534 :   coeff = c_readstr (p, mode);
    4328              : 
    4329          534 :   target = convert_to_mode (mode, (rtx) data, 1);
    4330          534 :   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
    4331          534 :   return force_reg (mode, target);
    4332              : }
    4333              : 
    4334              : /* Expand expression EXP, which is a call to the memset builtin.  Return
    4335              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    4336              :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    4337              :    convenient).  */
    4338              : 
    4339              : rtx
    4340        61892 : expand_builtin_memset (tree exp, rtx target, machine_mode mode)
    4341              : {
    4342        61892 :   if (!validate_arglist (exp,
    4343              :                          POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4344              :     return NULL_RTX;
    4345              : 
    4346        61883 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4347        61883 :   tree val = CALL_EXPR_ARG (exp, 1);
    4348        61883 :   tree len = CALL_EXPR_ARG (exp, 2);
    4349              : 
    4350        61883 :   return expand_builtin_memset_args (dest, val, len, target, mode, exp);
    4351              : }
    4352              : 
    4353              : /* Check that store_by_pieces allows BITS + LEN (so that we don't
    4354              :    expand something too unreasonably long), and every power of 2 in
    4355              :    BITS.  It is assumed that LEN has already been tested by
    4356              :    itself.  */
    4357              : static bool
    4358        24409 : can_store_by_multiple_pieces (unsigned HOST_WIDE_INT bits,
    4359              :                               by_pieces_constfn constfun,
    4360              :                               void *constfundata, unsigned int align,
    4361              :                               bool memsetp,
    4362              :                               unsigned HOST_WIDE_INT len)
    4363              : {
    4364        24409 :   if (bits
    4365        24409 :       && !can_store_by_pieces (bits + len, constfun, constfundata,
    4366              :                                align, memsetp))
    4367              :     return false;
    4368              : 
    4369              :   /* BITS set are expected to be generally in the low range and
    4370              :      contiguous.  We do NOT want to repeat the test above in case BITS
    4371              :      has a single bit set, so we terminate the loop when BITS == BIT.
    4372              :      In the unlikely case that BITS has the MSB set, also terminate in
    4373              :      case BIT gets shifted out.  */
    4374         1122 :   for (unsigned HOST_WIDE_INT bit = 1; bit < bits && bit; bit <<= 1)
    4375              :     {
    4376          840 :       if ((bits & bit) == 0)
    4377          504 :         continue;
    4378              : 
    4379          336 :       if (!can_store_by_pieces (bit, constfun, constfundata,
    4380              :                                 align, memsetp))
    4381              :         return false;
    4382              :     }
    4383              : 
    4384              :   return true;
    4385              : }
    4386              : 
    4387              : /* Try to store VAL (or, if NULL_RTX, VALC) in LEN bytes starting at TO.
    4388              :    Return TRUE if successful, FALSE otherwise.  TO is assumed to be
    4389              :    aligned at an ALIGN-bits boundary.  LEN must be a multiple of
    4390              :    1<<CTZ_LEN between MIN_LEN and MAX_LEN.
    4391              : 
    4392              :    The strategy is to issue one store_by_pieces for each power of two,
    4393              :    from most to least significant, guarded by a test on whether there
    4394              :    are at least that many bytes left to copy in LEN.
    4395              : 
    4396              :    ??? Should we skip some powers of two in favor of loops?  Maybe start
    4397              :    at the max of TO/LEN/word alignment, at least when optimizing for
    4398              :    size, instead of ensuring O(log len) dynamic compares?  */
    4399              : 
    4400              : bool
    4401        22268 : try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len,
    4402              :                               unsigned HOST_WIDE_INT min_len,
    4403              :                               unsigned HOST_WIDE_INT max_len,
    4404              :                               rtx val, char valc, unsigned int align)
    4405              : {
    4406        22268 :   int max_bits = floor_log2 (max_len);
    4407        22268 :   int min_bits = floor_log2 (min_len);
    4408        22268 :   int sctz_len = ctz_len;
    4409              : 
    4410        22268 :   gcc_checking_assert (sctz_len >= 0);
    4411              : 
    4412        22268 :   if (val)
    4413          624 :     valc = 1;
    4414              : 
    4415              :   /* Bits more significant than TST_BITS are part of the shared prefix
    4416              :      in the binary representation of both min_len and max_len.  Since
    4417              :      they're identical, we don't need to test them in the loop.  */
    4418        22268 :   int tst_bits = (max_bits != min_bits ? max_bits
    4419         9989 :                   : floor_log2 (max_len ^ min_len));
    4420              : 
    4421              :   /* Save the pre-blksize values.  */
    4422        22268 :   int orig_max_bits = max_bits;
    4423        22268 :   int orig_tst_bits = tst_bits;
    4424              : 
    4425              :   /* Check whether it's profitable to start by storing a fixed BLKSIZE
    4426              :      bytes, to lower max_bits.  In the unlikely case of a constant LEN
    4427              :      (implied by identical MAX_LEN and MIN_LEN), we want to issue a
    4428              :      single store_by_pieces, but otherwise, select the minimum multiple
    4429              :      of the ALIGN (in bytes) and of the MCD of the possible LENs, that
    4430              :      brings MAX_LEN below TST_BITS, if that's lower than min_len.  */
    4431        22268 :   unsigned HOST_WIDE_INT blksize;
    4432        22268 :   if (max_len > min_len)
    4433              :     {
    4434        12292 :       unsigned HOST_WIDE_INT alrng = MAX (HOST_WIDE_INT_1U << ctz_len,
    4435              :                                           align / BITS_PER_UNIT);
    4436        12292 :       blksize = max_len - (HOST_WIDE_INT_1U << tst_bits) + alrng;
    4437        12292 :       blksize &= ~(alrng - 1);
    4438              :     }
    4439         9976 :   else if (max_len == min_len)
    4440              :     blksize = max_len;
    4441              :   else
    4442              :     /* Huh, max_len < min_len?  Punt.  See pr100843.c.  */
    4443              :     return false;
    4444        22267 :   if (min_len >= blksize
    4445              :       /* ??? Maybe try smaller fixed-prefix blksizes before
    4446              :          punting?  */
    4447        22267 :       && can_store_by_pieces (blksize, builtin_memset_read_str,
    4448              :                               &valc, align, true))
    4449              :     {
    4450          277 :       min_len -= blksize;
    4451          277 :       min_bits = floor_log2 (min_len);
    4452          277 :       max_len -= blksize;
    4453          277 :       max_bits = floor_log2 (max_len);
    4454              : 
    4455          277 :       tst_bits = (max_bits != min_bits ? max_bits
    4456          175 :                  : floor_log2 (max_len ^ min_len));
    4457              :     }
    4458              :   else
    4459              :     blksize = 0;
    4460              : 
    4461              :   /* Check that we can use store by pieces for the maximum store count
    4462              :      we may issue (initial fixed-size block, plus conditional
    4463              :      power-of-two-sized from max_bits to ctz_len.  */
    4464        22267 :   unsigned HOST_WIDE_INT xlenest = blksize;
    4465        22267 :   if (max_bits >= 0)
    4466        22092 :     xlenest += ((HOST_WIDE_INT_1U << max_bits) * 2
    4467        22092 :                 - (HOST_WIDE_INT_1U << ctz_len));
    4468        22267 :   bool max_loop = false;
    4469        22267 :   bool use_store_by_pieces = true;
    4470              :   /* Skip the test in case of overflow in xlenest.  It shouldn't
    4471              :      happen because of the way max_bits and blksize are related, but
    4472              :      it doesn't hurt to test.  */
    4473        22267 :   if (blksize > xlenest
    4474        22267 :       || !can_store_by_multiple_pieces (xlenest - blksize,
    4475              :                                         builtin_memset_read_str,
    4476              :                                         &valc, align, true, blksize))
    4477              :     {
    4478        22092 :       if (!(flag_inline_stringops & ILSOP_MEMSET))
    4479              :         return false;
    4480              : 
    4481         2067 :       for (max_bits = orig_max_bits;
    4482         2174 :            max_bits >= sctz_len;
    4483              :            --max_bits)
    4484              :         {
    4485         2174 :           xlenest = ((HOST_WIDE_INT_1U << max_bits) * 2
    4486         2174 :                      - (HOST_WIDE_INT_1U << ctz_len));
    4487              :           /* Check that blksize plus the bits to be stored as blocks
    4488              :              sized at powers of two can be stored by pieces.  This is
    4489              :              like the test above, but with smaller max_bits.  Skip
    4490              :              orig_max_bits (it would be redundant).  Also skip in case
    4491              :              of overflow.  */
    4492         2174 :           if (max_bits < orig_max_bits
    4493         2067 :               && xlenest + blksize >= xlenest
    4494         4241 :               && can_store_by_multiple_pieces (xlenest,
    4495              :                                                builtin_memset_read_str,
    4496              :                                                &valc, align, true, blksize))
    4497              :             {
    4498              :               max_loop = true;
    4499              :               break;
    4500              :             }
    4501         2067 :           if (blksize
    4502         2067 :               && can_store_by_multiple_pieces (xlenest,
    4503              :                                                builtin_memset_read_str,
    4504              :                                                &valc, align, true, 0))
    4505              :             {
    4506            0 :               max_len += blksize;
    4507            0 :               min_len += blksize;
    4508            0 :               tst_bits = orig_tst_bits;
    4509            0 :               blksize = 0;
    4510            0 :               max_loop = true;
    4511            0 :               break;
    4512              :             }
    4513         2067 :           if (max_bits == sctz_len)
    4514              :             {
    4515              :               /* We'll get here if can_store_by_pieces refuses to
    4516              :                  store even a single QImode.  We'll fall back to
    4517              :                  QImode stores then.  */
    4518           98 :               if (!sctz_len)
    4519              :                 {
    4520              :                   blksize = 0;
    4521              :                   max_loop = true;
    4522              :                   use_store_by_pieces = false;
    4523              :                   break;
    4524              :                 }
    4525           98 :               --sctz_len;
    4526           98 :               --ctz_len;
    4527              :             }
    4528              :         }
    4529          107 :       if (!max_loop)
    4530              :         return false;
    4531              :       /* If the boundaries are such that min and max may run a
    4532              :          different number of trips in the initial loop, the remainder
    4533              :          needs not be between the moduli, so set tst_bits to cover all
    4534              :          bits.  Otherwise, if the trip counts are the same, max_len
    4535              :          has the common prefix, and the previously-computed tst_bits
    4536              :          is usable.  */
    4537          107 :       if (max_len >> max_bits > min_len >> max_bits)
    4538           64 :         tst_bits = max_bits;
    4539              :     }
    4540              : 
    4541          282 :   by_pieces_constfn constfun;
    4542          282 :   void *constfundata;
    4543          282 :   if (val)
    4544              :     {
    4545            1 :       constfun = builtin_memset_gen_str;
    4546            1 :       constfundata = val = force_reg (TYPE_MODE (unsigned_char_type_node),
    4547              :                                       val);
    4548              :     }
    4549              :   else
    4550              :     {
    4551              :       constfun = builtin_memset_read_str;
    4552              :       constfundata = &valc;
    4553              :     }
    4554              : 
    4555          282 :   rtx ptr = copy_addr_to_reg (XEXP (to, 0));
    4556          282 :   rtx rem = copy_to_mode_reg (ptr_mode, convert_to_mode (ptr_mode, len, 0));
    4557          282 :   to = replace_equiv_address (to, ptr);
    4558          282 :   set_mem_align (to, align);
    4559              : 
    4560          282 :   if (blksize)
    4561              :     {
    4562          363 :       to = store_by_pieces (to, blksize,
    4563              :                             constfun, constfundata,
    4564              :                             align, true,
    4565              :                             max_len != 0 ? RETURN_END : RETURN_BEGIN);
    4566          189 :       if (max_len == 0)
    4567              :         return true;
    4568              : 
    4569              :       /* Adjust PTR, TO and REM.  Since TO's address is likely
    4570              :          PTR+offset, we have to replace it.  */
    4571           15 :       emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
    4572           15 :       to = replace_equiv_address (to, ptr);
    4573           15 :       rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
    4574           15 :       emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
    4575              :     }
    4576              : 
    4577              :   /* Iterate over power-of-two block sizes from the maximum length to
    4578              :      the least significant bit possibly set in the length.  */
    4579          493 :   for (int i = max_bits; i >= sctz_len; i--)
    4580              :     {
    4581          385 :       rtx_code_label *loop_label = NULL;
    4582          385 :       rtx_code_label *label = NULL;
    4583              : 
    4584          385 :       blksize = HOST_WIDE_INT_1U << i;
    4585              : 
    4586              :       /* If we're past the bits shared between min_ and max_len, expand
    4587              :          a test on the dynamic length, comparing it with the
    4588              :          BLKSIZE.  */
    4589          385 :       if (i <= tst_bits)
    4590              :         {
    4591          275 :           label = gen_label_rtx ();
    4592          275 :           emit_cmp_and_jump_insns (rem, GEN_INT (blksize), LT, NULL,
    4593              :                                    ptr_mode, 1, label,
    4594              :                                    profile_probability::even ());
    4595              :         }
    4596              :       /* If we are at a bit that is in the prefix shared by min_ and
    4597              :          max_len, skip the current BLKSIZE if the bit is clear, but do
    4598              :          not skip the loop, even if it doesn't require
    4599              :          prechecking.  */
    4600          110 :       else if ((max_len & blksize) == 0
    4601           69 :                && !(max_loop && i == max_bits))
    4602           39 :         continue;
    4603              : 
    4604          346 :       if (max_loop && i == max_bits)
    4605              :         {
    4606          107 :           loop_label = gen_label_rtx ();
    4607          107 :           emit_label (loop_label);
    4608              :           /* Since we may run this multiple times, don't assume we
    4609              :              know anything about the offset.  */
    4610          107 :           clear_mem_offset (to);
    4611              :         }
    4612              : 
    4613          346 :       bool update_needed = i != sctz_len || loop_label;
    4614          346 :       rtx next_ptr = NULL_RTX;
    4615          346 :       if (!use_store_by_pieces)
    4616              :         {
    4617            0 :           gcc_checking_assert (blksize == 1);
    4618            0 :           if (!val)
    4619            0 :             val = gen_int_mode (valc, QImode);
    4620            0 :           to = change_address (to, QImode, 0);
    4621            0 :           emit_move_insn (to, val);
    4622            0 :           if (update_needed)
    4623            0 :             next_ptr = plus_constant (GET_MODE (ptr), ptr, blksize);
    4624              :         }
    4625              :       else
    4626              :         {
    4627              :           /* Issue a store of BLKSIZE bytes.  */
    4628          404 :           to = store_by_pieces (to, blksize,
    4629              :                                 constfun, constfundata,
    4630              :                                 align, true,
    4631              :                                 update_needed ? RETURN_END : RETURN_BEGIN);
    4632          346 :           next_ptr = XEXP (to, 0);
    4633              :         }
    4634              :       /* Adjust REM and PTR, unless this is the last iteration.  */
    4635          346 :       if (update_needed)
    4636              :         {
    4637          288 :           emit_move_insn (ptr, force_operand (next_ptr, NULL_RTX));
    4638          288 :           to = replace_equiv_address (to, ptr);
    4639          288 :           rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
    4640          288 :           emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
    4641              :         }
    4642              : 
    4643          288 :       if (loop_label)
    4644          107 :         emit_cmp_and_jump_insns (rem, GEN_INT (blksize), GE, NULL,
    4645              :                                  ptr_mode, 1, loop_label,
    4646              :                                  profile_probability::likely ());
    4647              : 
    4648          346 :       if (label)
    4649              :         {
    4650          275 :           emit_label (label);
    4651              : 
    4652              :           /* Given conditional stores, the offset can no longer be
    4653              :              known, so clear it.  */
    4654          275 :           clear_mem_offset (to);
    4655              :         }
    4656              :     }
    4657              : 
    4658              :   return true;
    4659              : }
    4660              : 
    4661              : /* Helper function to do the actual work for expand_builtin_memset.  The
    4662              :    arguments to the builtin_memset call DEST, VAL, and LEN are broken out
    4663              :    so that this can also be called without constructing an actual CALL_EXPR.
    4664              :    The other arguments and return value are the same as for
    4665              :    expand_builtin_memset.  */
    4666              : 
    4667              : static rtx
    4668        61883 : expand_builtin_memset_args (tree dest, tree val, tree len,
    4669              :                             rtx target, machine_mode mode, tree orig_exp)
    4670              : {
    4671        61883 :   tree fndecl, fn;
    4672        61883 :   enum built_in_function fcode;
    4673        61883 :   machine_mode val_mode;
    4674        61883 :   char c;
    4675        61883 :   unsigned int dest_align;
    4676        61883 :   rtx dest_mem, dest_addr, len_rtx;
    4677        61883 :   HOST_WIDE_INT expected_size = -1;
    4678        61883 :   unsigned int expected_align = 0;
    4679        61883 :   unsigned HOST_WIDE_INT min_size;
    4680        61883 :   unsigned HOST_WIDE_INT max_size;
    4681        61883 :   unsigned HOST_WIDE_INT probable_max_size;
    4682              : 
    4683        61883 :   dest_align = get_pointer_alignment (dest);
    4684              : 
    4685              :   /* If DEST is not a pointer type, don't do this operation in-line.  */
    4686        61883 :   if (dest_align == 0)
    4687              :     return NULL_RTX;
    4688              : 
    4689        61883 :   if (currently_expanding_gimple_stmt)
    4690        61883 :     stringop_block_profile (currently_expanding_gimple_stmt,
    4691              :                             &expected_align, &expected_size);
    4692              : 
    4693        61883 :   if (expected_align < dest_align)
    4694        61875 :     expected_align = dest_align;
    4695              : 
    4696              :   /* If the LEN parameter is zero, return DEST.  */
    4697        61883 :   if (integer_zerop (len))
    4698              :     {
    4699              :       /* Evaluate and ignore VAL in case it has side-effects.  */
    4700            0 :       expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
    4701            0 :       return expand_expr (dest, target, mode, EXPAND_NORMAL);
    4702              :     }
    4703              : 
    4704              :   /* Stabilize the arguments in case we fail.  */
    4705        61883 :   dest = builtin_save_expr (dest);
    4706        61883 :   val = builtin_save_expr (val);
    4707        61883 :   len = builtin_save_expr (len);
    4708              : 
    4709        61883 :   len_rtx = expand_normal (len);
    4710        61883 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    4711              :                         &probable_max_size);
    4712        61883 :   dest_mem = get_memory_rtx (dest, len);
    4713        61883 :   val_mode = TYPE_MODE (unsigned_char_type_node);
    4714              : 
    4715        61883 :   if (TREE_CODE (val) != INTEGER_CST
    4716        61883 :       || target_char_cast (val, &c))
    4717              :     {
    4718         1743 :       rtx val_rtx;
    4719              : 
    4720         1743 :       val_rtx = expand_normal (val);
    4721         1743 :       val_rtx = convert_to_mode (val_mode, val_rtx, 0);
    4722              : 
    4723              :       /* Assume that we can memset by pieces if we can store
    4724              :        * the coefficients by pieces (in the required modes).
    4725              :        * We can't pass builtin_memset_gen_str as that emits RTL.  */
    4726         1743 :       c = 1;
    4727         1743 :       if (tree_fits_uhwi_p (len)
    4728         1743 :           && can_store_by_pieces (tree_to_uhwi (len),
    4729              :                                   builtin_memset_read_str, &c, dest_align,
    4730              :                                   true))
    4731              :         {
    4732          760 :           val_rtx = force_reg (val_mode, val_rtx);
    4733          760 :           store_by_pieces (dest_mem, tree_to_uhwi (len),
    4734              :                            builtin_memset_gen_str, val_rtx, dest_align,
    4735              :                            true, RETURN_BEGIN);
    4736              :         }
    4737          983 :       else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
    4738              :                                         dest_align, expected_align,
    4739              :                                         expected_size, min_size, max_size,
    4740              :                                         probable_max_size)
    4741          983 :                && !try_store_by_multiple_pieces (dest_mem, len_rtx,
    4742              :                                                  tree_ctz (len),
    4743              :                                                  min_size, max_size,
    4744              :                                                  val_rtx, 0,
    4745              :                                                  dest_align))
    4746          623 :         goto do_libcall;
    4747              : 
    4748         1120 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4749         1120 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4750         1120 :       return dest_mem;
    4751              :     }
    4752              : 
    4753        60140 :   if (c)
    4754              :     {
    4755        13299 :       if (tree_fits_uhwi_p (len)
    4756        13299 :           && can_store_by_pieces (tree_to_uhwi (len),
    4757              :                                   builtin_memset_read_str, &c, dest_align,
    4758              :                                   true))
    4759         5856 :         store_by_pieces (dest_mem, tree_to_uhwi (len),
    4760              :                          builtin_memset_read_str, &c, dest_align, true,
    4761              :                          RETURN_BEGIN);
    4762         9328 :       else if (!set_storage_via_setmem (dest_mem, len_rtx,
    4763         7443 :                                         gen_int_mode (c, val_mode),
    4764              :                                         dest_align, expected_align,
    4765              :                                         expected_size, min_size, max_size,
    4766              :                                         probable_max_size)
    4767         7443 :                && !try_store_by_multiple_pieces (dest_mem, len_rtx,
    4768              :                                                  tree_ctz (len),
    4769              :                                                  min_size, max_size,
    4770              :                                                  NULL_RTX, c,
    4771              :                                                  dest_align))
    4772         5558 :         goto do_libcall;
    4773              : 
    4774         7741 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4775         7741 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4776         7741 :       return dest_mem;
    4777              :     }
    4778              : 
    4779        46841 :   set_mem_align (dest_mem, dest_align);
    4780        93682 :   dest_addr = clear_storage_hints (dest_mem, len_rtx,
    4781        46841 :                                    CALL_EXPR_TAILCALL (orig_exp)
    4782              :                                    ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
    4783              :                                    expected_align, expected_size,
    4784              :                                    min_size, max_size,
    4785              :                                    probable_max_size, tree_ctz (len));
    4786              : 
    4787        46841 :   if (dest_addr == 0)
    4788              :     {
    4789        36870 :       dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4790        36870 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    4791              :     }
    4792              : 
    4793              :   return dest_addr;
    4794              : 
    4795         6181 :  do_libcall:
    4796         6181 :   fndecl = get_callee_fndecl (orig_exp);
    4797         6181 :   fcode = DECL_FUNCTION_CODE (fndecl);
    4798         6181 :   if (fcode == BUILT_IN_MEMSET)
    4799         6181 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
    4800              :                                 dest, val, len);
    4801            0 :   else if (fcode == BUILT_IN_BZERO)
    4802            0 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
    4803              :                                 dest, len);
    4804              :   else
    4805            0 :     gcc_unreachable ();
    4806         6181 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    4807         6181 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
    4808         6181 :   return expand_call (fn, target, target == const0_rtx);
    4809              : }
    4810              : 
    4811              : /* Expand expression EXP, which is a call to the bzero builtin.  Return
    4812              :    NULL_RTX if we failed the caller should emit a normal call.  */
    4813              : 
    4814              : static rtx
    4815            0 : expand_builtin_bzero (tree exp)
    4816              : {
    4817            0 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4818              :     return NULL_RTX;
    4819              : 
    4820            0 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4821            0 :   tree size = CALL_EXPR_ARG (exp, 1);
    4822              : 
    4823              :   /* New argument list transforming bzero(ptr x, int y) to
    4824              :      memset(ptr x, int 0, size_t y).   This is done this way
    4825              :      so that if it isn't expanded inline, we fallback to
    4826              :      calling bzero instead of memset.  */
    4827              : 
    4828            0 :   location_t loc = EXPR_LOCATION (exp);
    4829              : 
    4830            0 :   return expand_builtin_memset_args (dest, integer_zero_node,
    4831              :                                      fold_convert_loc (loc,
    4832              :                                                        size_type_node, size),
    4833            0 :                                      const0_rtx, VOIDmode, exp);
    4834              : }
    4835              : 
    4836              : /* Try to expand cmpstr operation ICODE with the given operands.
    4837              :    Return the result rtx on success, otherwise return null.  */
    4838              : 
    4839              : static rtx
    4840            0 : expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
    4841              :                HOST_WIDE_INT align)
    4842              : {
    4843            0 :   machine_mode insn_mode = insn_data[icode].operand[0].mode;
    4844              : 
    4845            0 :   if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
    4846              :     target = NULL_RTX;
    4847              : 
    4848            0 :   class expand_operand ops[4];
    4849            0 :   create_output_operand (&ops[0], target, insn_mode);
    4850            0 :   create_fixed_operand (&ops[1], arg1_rtx);
    4851            0 :   create_fixed_operand (&ops[2], arg2_rtx);
    4852            0 :   create_integer_operand (&ops[3], align);
    4853            0 :   if (maybe_expand_insn (icode, 4, ops))
    4854            0 :     return ops[0].value;
    4855              :   return NULL_RTX;
    4856              : }
    4857              : 
    4858              : /* Expand expression EXP, which is a call to the memcmp built-in function.
    4859              :    Return NULL_RTX if we failed and the caller should emit a normal call,
    4860              :    otherwise try to get the result in TARGET, if convenient.
    4861              :    RESULT_EQ is true if we can relax the returned value to be either zero
    4862              :    or nonzero, without caring about the sign.  */
    4863              : 
    4864              : static rtx
    4865       106205 : expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
    4866              : {
    4867       106205 :   if (!validate_arglist (exp,
    4868              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4869              :     return NULL_RTX;
    4870              : 
    4871       106201 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    4872       106201 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    4873       106201 :   tree len = CALL_EXPR_ARG (exp, 2);
    4874              : 
    4875              :   /* Due to the performance benefit, always inline the calls first
    4876              :      when result_eq is false.  */
    4877       106201 :   rtx result = NULL_RTX;
    4878       106201 :   enum built_in_function fcode = DECL_FUNCTION_CODE (get_callee_fndecl (exp));
    4879       106201 :   if (!result_eq && fcode != BUILT_IN_BCMP)
    4880              :     {
    4881        14875 :       result = inline_expand_builtin_bytecmp (exp, target);
    4882        14875 :       if (result)
    4883              :         return result;
    4884              :     }
    4885              : 
    4886       106183 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    4887       106183 :   location_t loc = EXPR_LOCATION (exp);
    4888              : 
    4889       106183 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    4890       106183 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    4891              : 
    4892              :   /* If we don't have POINTER_TYPE, call the function.  */
    4893       106183 :   if (arg1_align == 0 || arg2_align == 0)
    4894              :     return NULL_RTX;
    4895              : 
    4896       106183 :   rtx arg1_rtx = get_memory_rtx (arg1, len);
    4897       106183 :   rtx arg2_rtx = get_memory_rtx (arg2, len);
    4898       106183 :   rtx len_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
    4899              : 
    4900              :   /* Set MEM_SIZE as appropriate.  */
    4901       106183 :   if (CONST_INT_P (len_rtx))
    4902              :     {
    4903        81196 :       set_mem_size (arg1_rtx, INTVAL (len_rtx));
    4904        81196 :       set_mem_size (arg2_rtx, INTVAL (len_rtx));
    4905              :     }
    4906              : 
    4907       106183 :   by_pieces_constfn constfn = NULL;
    4908              : 
    4909              :   /* Try to get the byte representation of the constant ARG2 (or, only
    4910              :      when the function's result is used for equality to zero, ARG1)
    4911              :      points to, with its byte size in NBYTES.  */
    4912       106183 :   unsigned HOST_WIDE_INT nbytes;
    4913       106183 :   const char *rep = getbyterep (arg2, &nbytes);
    4914       106183 :   if (result_eq && rep == NULL)
    4915              :     {
    4916              :       /* For equality to zero the arguments are interchangeable.  */
    4917        63465 :       rep = getbyterep (arg1, &nbytes);
    4918        63465 :       if (rep != NULL)
    4919              :         std::swap (arg1_rtx, arg2_rtx);
    4920              :     }
    4921              : 
    4922              :   /* If the function's constant bound LEN_RTX is less than or equal
    4923              :      to the byte size of the representation of the constant argument,
    4924              :      and if block move would be done by pieces, we can avoid loading
    4925              :      the bytes from memory and only store the computed constant result.  */
    4926        42718 :   if (rep
    4927        29969 :       && CONST_INT_P (len_rtx)
    4928        29816 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes)
    4929       106183 :     constfn = builtin_memcpy_read_str;
    4930              : 
    4931       212366 :   result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
    4932       106183 :                                  TREE_TYPE (len), target,
    4933              :                                  result_eq, constfn,
    4934              :                                  const_cast<char *> (rep),
    4935              :                                  tree_ctz (len));
    4936              : 
    4937       106183 :   if (result)
    4938              :     {
    4939              :       /* Return the value in the proper mode for this function.  */
    4940        68787 :       if (GET_MODE (result) == mode)
    4941              :         return result;
    4942              : 
    4943            0 :       if (target != 0)
    4944              :         {
    4945            0 :           convert_move (target, result, 0);
    4946            0 :           return target;
    4947              :         }
    4948              : 
    4949            0 :       return convert_to_mode (mode, result, 0);
    4950              :     }
    4951              : 
    4952              :   return NULL_RTX;
    4953              : }
    4954              : 
    4955              : /* Expand expression EXP, which is a call to the strcmp builtin.  Return NULL_RTX
    4956              :    if we failed the caller should emit a normal call, otherwise try to get
    4957              :    the result in TARGET, if convenient.  */
    4958              : 
    4959              : static rtx
    4960       127966 : expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
    4961              : {
    4962       127966 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    4963              :     return NULL_RTX;
    4964              : 
    4965       127951 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    4966       127951 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    4967              : 
    4968              :   /* Due to the performance benefit, always inline the calls first.  */
    4969       127951 :   rtx result = NULL_RTX;
    4970       127951 :   result = inline_expand_builtin_bytecmp (exp, target);
    4971       127951 :   if (result)
    4972              :     return result;
    4973              : 
    4974       127552 :   insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
    4975       127552 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    4976       127552 :   if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
    4977              :     return NULL_RTX;
    4978              : 
    4979       127552 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    4980       127552 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    4981              : 
    4982              :   /* If we don't have POINTER_TYPE, call the function.  */
    4983       127552 :   if (arg1_align == 0 || arg2_align == 0)
    4984              :     return NULL_RTX;
    4985              : 
    4986              :   /* Stabilize the arguments in case gen_cmpstr(n)si fail.  */
    4987       127552 :   arg1 = builtin_save_expr (arg1);
    4988       127552 :   arg2 = builtin_save_expr (arg2);
    4989              : 
    4990       127552 :   rtx arg1_rtx = get_memory_rtx (arg1, NULL);
    4991       127552 :   rtx arg2_rtx = get_memory_rtx (arg2, NULL);
    4992              : 
    4993              :   /* Try to call cmpstrsi.  */
    4994       127552 :   if (cmpstr_icode != CODE_FOR_nothing)
    4995            0 :     result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
    4996            0 :                             MIN (arg1_align, arg2_align));
    4997              : 
    4998              :   /* Try to determine at least one length and call cmpstrnsi.  */
    4999       127552 :   if (!result && cmpstrn_icode != CODE_FOR_nothing)
    5000              :     {
    5001       127552 :       tree len;
    5002       127552 :       rtx arg3_rtx;
    5003              : 
    5004       127552 :       tree len1 = c_strlen (arg1, 1);
    5005       127552 :       tree len2 = c_strlen (arg2, 1);
    5006              : 
    5007       127552 :       if (len1)
    5008          224 :         len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
    5009       127552 :       if (len2)
    5010       125927 :         len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
    5011              : 
    5012              :       /* If we don't have a constant length for the first, use the length
    5013              :          of the second, if we know it.  We don't require a constant for
    5014              :          this case; some cost analysis could be done if both are available
    5015              :          but neither is constant.  For now, assume they're equally cheap,
    5016              :          unless one has side effects.  If both strings have constant lengths,
    5017              :          use the smaller.  */
    5018              : 
    5019       127552 :       if (!len1)
    5020              :         len = len2;
    5021          224 :       else if (!len2)
    5022              :         len = len1;
    5023           17 :       else if (TREE_SIDE_EFFECTS (len1))
    5024              :         len = len2;
    5025           17 :       else if (TREE_SIDE_EFFECTS (len2))
    5026              :         len = len1;
    5027           17 :       else if (TREE_CODE (len1) != INTEGER_CST)
    5028              :         len = len2;
    5029           17 :       else if (TREE_CODE (len2) != INTEGER_CST)
    5030              :         len = len1;
    5031           10 :       else if (tree_int_cst_lt (len1, len2))
    5032              :         len = len1;
    5033              :       else
    5034       127334 :         len = len2;
    5035              : 
    5036              :       /* If both arguments have side effects, we cannot optimize.  */
    5037       127552 :       if (len && !TREE_SIDE_EFFECTS (len))
    5038              :         {
    5039       126134 :           arg3_rtx = expand_normal (len);
    5040       126134 :           result = expand_cmpstrn_or_cmpmem
    5041       126134 :             (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
    5042       126134 :              arg3_rtx, MIN (arg1_align, arg2_align));
    5043              :         }
    5044              :     }
    5045              : 
    5046       127552 :   tree fndecl = get_callee_fndecl (exp);
    5047       127552 :   if (result)
    5048              :     {
    5049              :       /* Return the value in the proper mode for this function.  */
    5050           52 :       machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    5051           52 :       if (GET_MODE (result) == mode)
    5052              :         return result;
    5053            0 :       if (target == 0)
    5054            0 :         return convert_to_mode (mode, result, 0);
    5055            0 :       convert_move (target, result, 0);
    5056            0 :       return target;
    5057              :     }
    5058              : 
    5059              :   /* Expand the library call ourselves using a stabilized argument
    5060              :      list to avoid re-evaluating the function's arguments twice.  */
    5061       127500 :   tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
    5062       127500 :   copy_warning (fn, exp);
    5063       127500 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    5064       127500 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    5065       127500 :   return expand_call (fn, target, target == const0_rtx);
    5066              : }
    5067              : 
    5068              : /* Expand expression EXP, which is a call to the strncmp builtin. Return
    5069              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    5070              :    try to get the result in TARGET, if convenient.  */
    5071              : 
    5072              : static rtx
    5073         2031 : expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
    5074              :                         ATTRIBUTE_UNUSED machine_mode mode)
    5075              : {
    5076         2031 :   if (!validate_arglist (exp,
    5077              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    5078              :     return NULL_RTX;
    5079              : 
    5080         2025 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    5081         2025 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    5082         2025 :   tree arg3 = CALL_EXPR_ARG (exp, 2);
    5083              : 
    5084         2025 :   location_t loc = EXPR_LOCATION (exp);
    5085         2025 :   tree len1 = c_strlen (arg1, 1);
    5086         2025 :   tree len2 = c_strlen (arg2, 1);
    5087              : 
    5088              :   /* Due to the performance benefit, always inline the calls first.  */
    5089         2025 :   rtx result = NULL_RTX;
    5090         2025 :   result = inline_expand_builtin_bytecmp (exp, target);
    5091         2025 :   if (result)
    5092              :     return result;
    5093              : 
    5094              :   /* If c_strlen can determine an expression for one of the string
    5095              :      lengths, and it doesn't have side effects, then emit cmpstrnsi
    5096              :      using length MIN(strlen(string)+1, arg3).  */
    5097         1807 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    5098         1807 :   if (cmpstrn_icode == CODE_FOR_nothing)
    5099              :     return NULL_RTX;
    5100              : 
    5101         1807 :   tree len;
    5102              : 
    5103         1807 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    5104         1807 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    5105              : 
    5106         1807 :   if (len1)
    5107          164 :     len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
    5108         1807 :   if (len2)
    5109          674 :     len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
    5110              : 
    5111         1807 :   tree len3 = fold_convert_loc (loc, sizetype, arg3);
    5112              : 
    5113              :   /* If we don't have a constant length for the first, use the length
    5114              :      of the second, if we know it.  If neither string is constant length,
    5115              :      use the given length argument.  We don't require a constant for
    5116              :      this case; some cost analysis could be done if both are available
    5117              :      but neither is constant.  For now, assume they're equally cheap,
    5118              :      unless one has side effects.  If both strings have constant lengths,
    5119              :      use the smaller.  */
    5120              : 
    5121         1807 :   if (!len1 && !len2)
    5122              :     len = len3;
    5123          721 :   else if (!len1)
    5124              :     len = len2;
    5125          164 :   else if (!len2)
    5126              :     len = len1;
    5127          117 :   else if (TREE_SIDE_EFFECTS (len1))
    5128              :     len = len2;
    5129          117 :   else if (TREE_SIDE_EFFECTS (len2))
    5130              :     len = len1;
    5131          117 :   else if (TREE_CODE (len1) != INTEGER_CST)
    5132              :     len = len2;
    5133          117 :   else if (TREE_CODE (len2) != INTEGER_CST)
    5134              :     len = len1;
    5135          117 :   else if (tree_int_cst_lt (len1, len2))
    5136              :     len = len1;
    5137              :   else
    5138          558 :     len = len2;
    5139              : 
    5140              :   /* If we are not using the given length, we must incorporate it here.
    5141              :      The actual new length parameter will be MIN(len,arg3) in this case.  */
    5142         1807 :   if (len != len3)
    5143              :     {
    5144          721 :       len = fold_convert_loc (loc, sizetype, len);
    5145          721 :       len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
    5146              :     }
    5147         1807 :   rtx arg1_rtx = get_memory_rtx (arg1, len);
    5148         1807 :   rtx arg2_rtx = get_memory_rtx (arg2, len);
    5149         1807 :   rtx arg3_rtx = expand_normal (len);
    5150         1807 :   result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
    5151         1807 :                                      arg2_rtx, TREE_TYPE (len), arg3_rtx,
    5152         1807 :                                      MIN (arg1_align, arg2_align));
    5153              : 
    5154         1807 :   tree fndecl = get_callee_fndecl (exp);
    5155         1807 :   if (result)
    5156              :     {
    5157              :       /* Return the value in the proper mode for this function.  */
    5158           17 :       mode = TYPE_MODE (TREE_TYPE (exp));
    5159           17 :       if (GET_MODE (result) == mode)
    5160              :         return result;
    5161            0 :       if (target == 0)
    5162            0 :         return convert_to_mode (mode, result, 0);
    5163            0 :       convert_move (target, result, 0);
    5164            0 :       return target;
    5165              :     }
    5166              : 
    5167              :   /* Expand the library call ourselves using a stabilized argument
    5168              :      list to avoid re-evaluating the function's arguments twice.  */
    5169         1790 :   tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
    5170         1790 :   copy_warning (call, exp);
    5171         1790 :   gcc_assert (TREE_CODE (call) == CALL_EXPR);
    5172         1790 :   CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
    5173         1790 :   return expand_call (call, target, target == const0_rtx);
    5174              : }
    5175              : 
    5176              : /* Expand a call to __builtin_saveregs, generating the result in TARGET,
    5177              :    if that's convenient.  */
    5178              : 
    5179              : rtx
    5180            0 : expand_builtin_saveregs (void)
    5181              : {
    5182            0 :   rtx val;
    5183            0 :   rtx_insn *seq;
    5184              : 
    5185              :   /* Don't do __builtin_saveregs more than once in a function.
    5186              :      Save the result of the first call and reuse it.  */
    5187            0 :   if (saveregs_value != 0)
    5188              :     return saveregs_value;
    5189              : 
    5190              :   /* When this function is called, it means that registers must be
    5191              :      saved on entry to this function.  So we migrate the call to the
    5192              :      first insn of this function.  */
    5193              : 
    5194            0 :   start_sequence ();
    5195              : 
    5196              :   /* Do whatever the machine needs done in this case.  */
    5197            0 :   val = targetm.calls.expand_builtin_saveregs ();
    5198              : 
    5199            0 :   seq = end_sequence ();
    5200              : 
    5201            0 :   saveregs_value = val;
    5202              : 
    5203              :   /* Put the insns after the NOTE that starts the function.  If this
    5204              :      is inside a start_sequence, make the outer-level insn chain current, so
    5205              :      the code is placed at the start of the function.  */
    5206            0 :   push_topmost_sequence ();
    5207            0 :   emit_insn_after (seq, entry_of_function ());
    5208            0 :   pop_topmost_sequence ();
    5209              : 
    5210            0 :   return val;
    5211              : }
    5212              : 
    5213              : /* Expand a call to __builtin_next_arg.  */
    5214              : 
    5215              : static rtx
    5216        21237 : expand_builtin_next_arg (void)
    5217              : {
    5218              :   /* Checking arguments is already done in fold_builtin_next_arg
    5219              :      that must be called before this function.  */
    5220        21237 :   return expand_binop (ptr_mode, add_optab,
    5221              :                        crtl->args.internal_arg_pointer,
    5222              :                        crtl->args.arg_offset_rtx,
    5223        21237 :                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
    5224              : }
    5225              : 
    5226              : /* Make it easier for the backends by protecting the valist argument
    5227              :    from multiple evaluations.  */
    5228              : 
    5229              : static tree
    5230        21559 : stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
    5231              : {
    5232        21559 :   tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
    5233              : 
    5234              :   /* The current way of determining the type of valist is completely
    5235              :      bogus.  We should have the information on the va builtin instead.  */
    5236        21559 :   if (!vatype)
    5237        21435 :     vatype = targetm.fn_abi_va_list (cfun->decl);
    5238              : 
    5239        21559 :   if (TREE_CODE (vatype) == ARRAY_TYPE)
    5240              :     {
    5241        15897 :       if (TREE_SIDE_EFFECTS (valist))
    5242            0 :         valist = save_expr (valist);
    5243              : 
    5244              :       /* For this case, the backends will be expecting a pointer to
    5245              :          vatype, but it's possible we've actually been given an array
    5246              :          (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
    5247              :          So fix it.  */
    5248        15897 :       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
    5249              :         {
    5250            0 :           tree p1 = build_pointer_type (TREE_TYPE (vatype));
    5251            0 :           valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
    5252              :         }
    5253              :     }
    5254              :   else
    5255              :     {
    5256         5662 :       tree pt = build_pointer_type (vatype);
    5257              : 
    5258         5662 :       if (! needs_lvalue)
    5259              :         {
    5260            6 :           if (! TREE_SIDE_EFFECTS (valist))
    5261              :             return valist;
    5262              : 
    5263            0 :           valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
    5264            0 :           TREE_SIDE_EFFECTS (valist) = 1;
    5265              :         }
    5266              : 
    5267         5656 :       if (TREE_SIDE_EFFECTS (valist))
    5268            0 :         valist = save_expr (valist);
    5269         5656 :       valist = fold_build2_loc (loc, MEM_REF,
    5270              :                                 vatype, valist, build_int_cst (pt, 0));
    5271              :     }
    5272              : 
    5273              :   return valist;
    5274              : }
    5275              : 
    5276              : /* The "standard" definition of va_list is void*.  */
    5277              : 
    5278              : tree
    5279            0 : std_build_builtin_va_list (void)
    5280              : {
    5281            0 :   return ptr_type_node;
    5282              : }
    5283              : 
    5284              : /* The "standard" abi va_list is va_list_type_node.  */
    5285              : 
    5286              : tree
    5287            0 : std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
    5288              : {
    5289            0 :   return va_list_type_node;
    5290              : }
    5291              : 
    5292              : /* The "standard" type of va_list is va_list_type_node.  */
    5293              : 
    5294              : tree
    5295          502 : std_canonical_va_list_type (tree type)
    5296              : {
    5297          502 :   tree wtype, htype;
    5298              : 
    5299          502 :   wtype = va_list_type_node;
    5300          502 :   htype = type;
    5301              : 
    5302          502 :   if (TREE_CODE (wtype) == ARRAY_TYPE)
    5303              :     {
    5304              :       /* If va_list is an array type, the argument may have decayed
    5305              :          to a pointer type, e.g. by being passed to another function.
    5306              :          In that case, unwrap both types so that we can compare the
    5307              :          underlying records.  */
    5308            0 :       if (TREE_CODE (htype) == ARRAY_TYPE
    5309            0 :           || POINTER_TYPE_P (htype))
    5310              :         {
    5311            0 :           wtype = TREE_TYPE (wtype);
    5312            0 :           htype = TREE_TYPE (htype);
    5313              :         }
    5314              :     }
    5315          502 :   if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
    5316          332 :     return va_list_type_node;
    5317              : 
    5318              :   return NULL_TREE;
    5319              : }
    5320              : 
    5321              : /* The "standard" implementation of va_start: just assign `nextarg' to
    5322              :    the variable.  */
    5323              : 
    5324              : void
    5325         5652 : std_expand_builtin_va_start (tree valist, rtx nextarg)
    5326              : {
    5327         5652 :   rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
    5328         5652 :   convert_move (va_r, nextarg, 0);
    5329         5652 : }
    5330              : 
    5331              : /* Expand EXP, a call to __builtin_va_start.  */
    5332              : 
    5333              : static rtx
    5334        21079 : expand_builtin_va_start (tree exp)
    5335              : {
    5336        21079 :   rtx nextarg;
    5337        21079 :   tree valist;
    5338        21079 :   location_t loc = EXPR_LOCATION (exp);
    5339              : 
    5340        21079 :   if (call_expr_nargs (exp) < 2)
    5341              :     {
    5342            0 :       error_at (loc, "too few arguments to function %<va_start%>");
    5343            0 :       return const0_rtx;
    5344              :     }
    5345              : 
    5346        21079 :   if (fold_builtin_next_arg (exp, true))
    5347            0 :     return const0_rtx;
    5348              : 
    5349        21079 :   nextarg = expand_builtin_next_arg ();
    5350        21079 :   valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
    5351              : 
    5352        21079 :   if (targetm.expand_builtin_va_start)
    5353        21079 :     targetm.expand_builtin_va_start (valist, nextarg);
    5354              :   else
    5355            0 :     std_expand_builtin_va_start (valist, nextarg);
    5356              : 
    5357        21079 :   return const0_rtx;
    5358              : }
    5359              : 
    5360              : /* Expand EXP, a call to __builtin_va_end.  */
    5361              : 
    5362              : static rtx
    5363        12172 : expand_builtin_va_end (tree exp)
    5364              : {
    5365        12172 :   tree valist = CALL_EXPR_ARG (exp, 0);
    5366              : 
    5367              :   /* Evaluate for side effects, if needed.  I hate macros that don't
    5368              :      do that.  */
    5369        12172 :   if (TREE_SIDE_EFFECTS (valist))
    5370            0 :     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5371              : 
    5372        12172 :   return const0_rtx;
    5373              : }
    5374              : 
    5375              : /* Expand EXP, a call to __builtin_va_copy.  We do this as a
    5376              :    builtin rather than just as an assignment in stdarg.h because of the
    5377              :    nastiness of array-type va_list types.  */
    5378              : 
    5379              : static rtx
    5380          240 : expand_builtin_va_copy (tree exp)
    5381              : {
    5382          240 :   tree dst, src, t;
    5383          240 :   location_t loc = EXPR_LOCATION (exp);
    5384              : 
    5385          240 :   dst = CALL_EXPR_ARG (exp, 0);
    5386          240 :   src = CALL_EXPR_ARG (exp, 1);
    5387              : 
    5388          240 :   dst = stabilize_va_list_loc (loc, dst, 1);
    5389          240 :   src = stabilize_va_list_loc (loc, src, 0);
    5390              : 
    5391          240 :   gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
    5392              : 
    5393          240 :   if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
    5394              :     {
    5395            0 :       t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
    5396            0 :       TREE_SIDE_EFFECTS (t) = 1;
    5397            0 :       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5398              :     }
    5399              :   else
    5400              :     {
    5401          240 :       rtx dstb, srcb, size;
    5402              : 
    5403              :       /* Evaluate to pointers.  */
    5404          240 :       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
    5405          240 :       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
    5406          240 :       size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
    5407              :                   NULL_RTX, VOIDmode, EXPAND_NORMAL);
    5408              : 
    5409          240 :       dstb = convert_memory_address (Pmode, dstb);
    5410          240 :       srcb = convert_memory_address (Pmode, srcb);
    5411              : 
    5412              :       /* "Dereference" to BLKmode memories.  */
    5413          240 :       dstb = gen_rtx_MEM (BLKmode, dstb);
    5414          240 :       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
    5415          240 :       set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5416          240 :       srcb = gen_rtx_MEM (BLKmode, srcb);
    5417          240 :       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
    5418          240 :       set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5419              : 
    5420              :       /* Copy.  */
    5421          240 :       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
    5422              :     }
    5423              : 
    5424          240 :   return const0_rtx;
    5425              : }
    5426              : 
    5427              : /* Expand a call to one of the builtin functions __builtin_frame_address or
    5428              :    __builtin_return_address.  */
    5429              : 
    5430              : static rtx
    5431        15922 : expand_builtin_frame_address (tree fndecl, tree exp)
    5432              : {
    5433              :   /* The argument must be a nonnegative integer constant.
    5434              :      It counts the number of frames to scan up the stack.
    5435              :      The value is either the frame pointer value or the return
    5436              :      address saved in that frame.  */
    5437        15922 :   if (call_expr_nargs (exp) == 0)
    5438              :     /* Warning about missing arg was already issued.  */
    5439            0 :     return const0_rtx;
    5440        15922 :   else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
    5441              :     {
    5442            0 :       error ("invalid argument to %qD", fndecl);
    5443            0 :       return const0_rtx;
    5444              :     }
    5445              :   else
    5446              :     {
    5447              :       /* Number of frames to scan up the stack.  */
    5448        15922 :       unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
    5449              : 
    5450        15922 :       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
    5451              : 
    5452              :       /* Some ports cannot access arbitrary stack frames.  */
    5453        15922 :       if (tem == NULL)
    5454              :         {
    5455            0 :           warning (0, "unsupported argument to %qD", fndecl);
    5456            0 :           return const0_rtx;
    5457              :         }
    5458              : 
    5459        15922 :       if (count)
    5460              :         {
    5461              :           /* Warn since no effort is made to ensure that any frame
    5462              :              beyond the current one exists or can be safely reached.  */
    5463          932 :           warning (OPT_Wframe_address, "calling %qD with "
    5464              :                    "a nonzero argument is unsafe", fndecl);
    5465              :         }
    5466              : 
    5467              :       /* For __builtin_frame_address, return what we've got.  */
    5468        15922 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
    5469              :         return tem;
    5470              : 
    5471         5171 :       if (!REG_P (tem)
    5472         5171 :           && ! CONSTANT_P (tem))
    5473         5171 :         tem = copy_addr_to_reg (tem);
    5474         5171 :       return tem;
    5475              :     }
    5476              : }
    5477              : 
    5478              : #if ! STACK_GROWS_DOWNWARD
    5479              : # define STACK_TOPS GT
    5480              : #else
    5481              : # define STACK_TOPS LT
    5482              : #endif
    5483              : 
    5484              : #ifdef POINTERS_EXTEND_UNSIGNED
    5485              : # define STACK_UNSIGNED POINTERS_EXTEND_UNSIGNED
    5486              : #else
    5487              : # define STACK_UNSIGNED true
    5488              : #endif
    5489              : 
    5490              : /* Expand a call to builtin function __builtin_stack_address.  */
    5491              : 
    5492              : static rtx
    5493         3429 : expand_builtin_stack_address ()
    5494              : {
    5495         3429 :   rtx ret = convert_to_mode (ptr_mode, copy_to_reg (stack_pointer_rtx),
    5496              :                              STACK_UNSIGNED);
    5497              : 
    5498              : #ifdef STACK_ADDRESS_OFFSET
    5499              :   /* Unbias the stack pointer, bringing it to the boundary between the
    5500              :      stack area claimed by the active function calling this builtin,
    5501              :      and stack ranges that could get clobbered if it called another
    5502              :      function.  It should NOT encompass any stack red zone, that is
    5503              :      used in leaf functions.
    5504              : 
    5505              :      On SPARC, the register save area is *not* considered active or
    5506              :      used by the active function, but rather as akin to the area in
    5507              :      which call-preserved registers are saved by callees.  This
    5508              :      enables __strub_leave to clear what would otherwise overlap with
    5509              :      its own register save area.
    5510              : 
    5511              :      If the address is computed too high or too low, parts of a stack
    5512              :      range that should be scrubbed may be left unscrubbed, scrubbing
    5513              :      may corrupt active portions of the stack frame, and stack ranges
    5514              :      may be doubly-scrubbed by caller and callee.
    5515              : 
    5516              :      In order for it to be just right, the area delimited by
    5517              :      @code{__builtin_stack_address} and @code{__builtin_frame_address
    5518              :      (0)} should encompass caller's registers saved by the function,
    5519              :      local on-stack variables and @code{alloca} stack areas.
    5520              :      Accumulated outgoing on-stack arguments, preallocated as part of
    5521              :      a function's own prologue, are to be regarded as part of the
    5522              :      (caller) function's active area as well, whereas those pushed or
    5523              :      allocated temporarily for a call are regarded as part of the
    5524              :      callee's stack range, rather than the caller's.  */
    5525              :   ret = plus_constant (ptr_mode, ret, STACK_ADDRESS_OFFSET);
    5526              : #endif
    5527              : 
    5528         3429 :   return force_reg (ptr_mode, ret);
    5529              : }
    5530              : 
    5531              : /* Expand a call to builtin function __builtin_strub_enter.  */
    5532              : 
    5533              : static rtx
    5534         2160 : expand_builtin_strub_enter (tree exp)
    5535              : {
    5536         2160 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5537              :     return NULL_RTX;
    5538              : 
    5539         2160 :   if (optimize < 1 || flag_no_inline)
    5540              :     return NULL_RTX;
    5541              : 
    5542         1516 :   rtx stktop = expand_builtin_stack_address ();
    5543              : 
    5544         1516 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5545         1516 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5546         1516 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5547              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5548         1516 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5549              : 
    5550         1516 :   emit_move_insn (wmark, stktop);
    5551              : 
    5552         1516 :   return const0_rtx;
    5553              : }
    5554              : 
    5555              : /* Expand a call to builtin function __builtin_strub_update.  */
    5556              : 
    5557              : static rtx
    5558         1073 : expand_builtin_strub_update (tree exp)
    5559              : {
    5560         1073 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5561              :     return NULL_RTX;
    5562              : 
    5563         1073 :   if (optimize < 2 || flag_no_inline)
    5564              :     return NULL_RTX;
    5565              : 
    5566          653 :   rtx stktop = expand_builtin_stack_address ();
    5567              : 
    5568              : #ifdef RED_ZONE_SIZE
    5569              :   /* Here's how the strub enter, update and leave functions deal with red zones.
    5570              : 
    5571              :      If it weren't for red zones, update, called from within a strub context,
    5572              :      would bump the watermark to the top of the stack.  Enter and leave, running
    5573              :      in the caller, would use the caller's top of stack address both to
    5574              :      initialize the watermark passed to the callee, and to start strubbing the
    5575              :      stack afterwards.
    5576              : 
    5577              :      Ideally, we'd update the watermark so as to cover the used amount of red
    5578              :      zone, and strub starting at the caller's other end of the (presumably
    5579              :      unused) red zone.  Normally, only leaf functions use the red zone, but at
    5580              :      this point we can't tell whether a function is a leaf, nor can we tell how
    5581              :      much of the red zone it uses.  Furthermore, some strub contexts may have
    5582              :      been inlined so that update and leave are called from the same stack frame,
    5583              :      and the strub builtins may all have been inlined, turning a strub function
    5584              :      into a leaf.
    5585              : 
    5586              :      So cleaning the range from the caller's stack pointer (one end of the red
    5587              :      zone) to the (potentially inlined) callee's (other end of the) red zone
    5588              :      could scribble over the caller's own red zone.
    5589              : 
    5590              :      We avoid this possibility by arranging for callers that are strub contexts
    5591              :      to use their own watermark as the strub starting point.  So, if A calls B,
    5592              :      and B calls C, B will tell A to strub up to the end of B's red zone, and
    5593              :      will strub itself only the part of C's stack frame and red zone that
    5594              :      doesn't overlap with B's.  With that, we don't need to know who's leaf and
    5595              :      who isn't: inlined calls will shrink their strub window to zero, each
    5596              :      remaining call will strub some portion of the stack, and eventually the
    5597              :      strub context will return to a caller that isn't a strub context itself,
    5598              :      that will therefore use its own stack pointer as the strub starting point.
    5599              :      It's not a leaf, because strub contexts can't be inlined into non-strub
    5600              :      contexts, so it doesn't use the red zone, and it will therefore correctly
    5601              :      strub up the callee's stack frame up to the end of the callee's red zone.
    5602              :      Neat!  */
    5603          653 :   if (true /* (flags_from_decl_or_type (current_function_decl) & ECF_LEAF) */)
    5604              :     {
    5605          653 :       poly_int64 red_zone_size = RED_ZONE_SIZE;
    5606              : #if STACK_GROWS_DOWNWARD
    5607          653 :       red_zone_size = -red_zone_size;
    5608              : #endif
    5609          653 :       stktop = plus_constant (ptr_mode, stktop, red_zone_size);
    5610          653 :       stktop = force_reg (ptr_mode, stktop);
    5611              :     }
    5612              : #endif
    5613              : 
    5614          653 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5615          653 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5616          653 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5617              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5618          653 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5619              : 
    5620          653 :   rtx wmarkr = force_reg (ptr_mode, wmark);
    5621              : 
    5622          653 :   rtx_code_label *lab = gen_label_rtx ();
    5623          653 :   do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
    5624              :                            ptr_mode, NULL_RTX, lab, NULL,
    5625              :                            profile_probability::very_likely ());
    5626          653 :   emit_move_insn (wmark, stktop);
    5627              : 
    5628              :   /* If this is an inlined strub function, also bump the watermark for the
    5629              :      enclosing function.  This avoids a problem with the following scenario: A
    5630              :      calls B and B calls C, and both B and C get inlined into A.  B allocates
    5631              :      temporary stack space before calling C.  If we don't update A's watermark,
    5632              :      we may use an outdated baseline for the post-C strub_leave, erasing B's
    5633              :      temporary stack allocation.  We only need this if we're fully expanding
    5634              :      strub_leave inline.  */
    5635          653 :   tree xwmptr = (optimize > 2
    5636          653 :                  ? strub_watermark_parm (current_function_decl)
    5637              :                  : wmptr);
    5638          653 :   if (wmptr != xwmptr)
    5639              :     {
    5640          156 :       wmptr = xwmptr;
    5641          156 :       wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5642          156 :       wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5643              :                             build_int_cst (TREE_TYPE (wmptr), 0));
    5644          156 :       wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5645          156 :       wmarkr = force_reg (ptr_mode, wmark);
    5646              : 
    5647          156 :       do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
    5648              :                                ptr_mode, NULL_RTX, lab, NULL,
    5649              :                                profile_probability::very_likely ());
    5650          156 :       emit_move_insn (wmark, stktop);
    5651              :     }
    5652              : 
    5653          653 :   emit_label (lab);
    5654              : 
    5655          653 :   return const0_rtx;
    5656              : }
    5657              : 
    5658              : 
    5659              : /* Expand a call to builtin function __builtin_strub_leave.  */
    5660              : 
    5661              : static rtx
    5662         2730 : expand_builtin_strub_leave (tree exp)
    5663              : {
    5664         2730 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5665              :     return NULL_RTX;
    5666              : 
    5667         2730 :   if (optimize < 2 || optimize_size || flag_no_inline)
    5668              :     return NULL_RTX;
    5669              : 
    5670         1229 :   rtx stktop = NULL_RTX;
    5671              : 
    5672         1229 :   if (tree wmptr = (optimize
    5673         1229 :                     ? strub_watermark_parm (current_function_decl)
    5674              :                     : NULL_TREE))
    5675              :     {
    5676          509 :       tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5677          509 :       tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5678              :                                  build_int_cst (TREE_TYPE (wmptr), 0));
    5679          509 :       rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5680          509 :       stktop = force_reg (ptr_mode, wmark);
    5681              :     }
    5682              : 
    5683          509 :   if (!stktop)
    5684          720 :     stktop = expand_builtin_stack_address ();
    5685              : 
    5686         1229 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5687         1229 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5688         1229 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5689              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5690         1229 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5691              : 
    5692         1229 :   rtx wmarkr = force_reg (ptr_mode, wmark);
    5693              : 
    5694              : #if ! STACK_GROWS_DOWNWARD
    5695              :   rtx base = stktop;
    5696              :   rtx end = wmarkr;
    5697              : #else
    5698         1229 :   rtx base = wmarkr;
    5699         1229 :   rtx end = stktop;
    5700              : #endif
    5701              : 
    5702              :   /* We're going to modify it, so make sure it's not e.g. the stack pointer.  */
    5703         1229 :   base = copy_to_reg (base);
    5704              : 
    5705         1229 :   rtx_code_label *done = gen_label_rtx ();
    5706         1229 :   do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
    5707              :                            ptr_mode, NULL_RTX, done, NULL,
    5708              :                            profile_probability::very_likely ());
    5709              : 
    5710         1229 :   if (optimize < 3)
    5711          909 :     expand_call (exp, NULL_RTX, true);
    5712              :   else
    5713              :     {
    5714              :       /* Ok, now we've determined we want to copy the block, so convert the
    5715              :          addresses to Pmode, as needed to dereference them to access ptr_mode
    5716              :          memory locations, so that we don't have to convert anything within the
    5717              :          loop.  */
    5718          320 :       base = memory_address (ptr_mode, base);
    5719          320 :       end = memory_address (ptr_mode, end);
    5720              : 
    5721          320 :       rtx zero = force_operand (const0_rtx, NULL_RTX);
    5722          320 :       int ulen = GET_MODE_SIZE (ptr_mode);
    5723              : 
    5724              :       /* ??? It would be nice to use setmem or similar patterns here,
    5725              :          but they do not necessarily obey the stack growth direction,
    5726              :          which has security implications.  We also have to avoid calls
    5727              :          (memset, bzero or any machine-specific ones), which are
    5728              :          likely unsafe here (see TARGET_STRUB_MAY_USE_MEMSET).  */
    5729              : #if ! STACK_GROWS_DOWNWARD
    5730              :       rtx incr = plus_constant (Pmode, base, ulen);
    5731              :       rtx dstm = gen_rtx_MEM (ptr_mode, base);
    5732              : 
    5733              :       rtx_code_label *loop = gen_label_rtx ();
    5734              :       emit_label (loop);
    5735              :       emit_move_insn (dstm, zero);
    5736              :       emit_move_insn (base, force_operand (incr, NULL_RTX));
    5737              : #else
    5738          320 :       rtx decr = plus_constant (Pmode, end, -ulen);
    5739          320 :       rtx dstm = gen_rtx_MEM (ptr_mode, end);
    5740              : 
    5741          320 :       rtx_code_label *loop = gen_label_rtx ();
    5742          320 :       emit_label (loop);
    5743          320 :       emit_move_insn (end, force_operand (decr, NULL_RTX));
    5744          320 :       emit_move_insn (dstm, zero);
    5745              : #endif
    5746          640 :       do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
    5747          320 :                                Pmode, NULL_RTX, NULL, loop,
    5748              :                                profile_probability::very_likely ());
    5749              :     }
    5750              : 
    5751         1229 :   emit_label (done);
    5752              : 
    5753         1229 :   return const0_rtx;
    5754              : }
    5755              : 
    5756              : /* Expand EXP, a call to the alloca builtin.  Return NULL_RTX if we
    5757              :    failed and the caller should emit a normal call.  */
    5758              : 
    5759              : static rtx
    5760        27779 : expand_builtin_alloca (tree exp)
    5761              : {
    5762        27779 :   rtx op0;
    5763        27779 :   rtx result;
    5764        27779 :   unsigned int align;
    5765        27779 :   tree fndecl = get_callee_fndecl (exp);
    5766        27779 :   HOST_WIDE_INT max_size;
    5767        27779 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    5768        27779 :   bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
    5769        27779 :   bool valid_arglist
    5770              :     = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5771        27779 :        ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
    5772              :                            VOID_TYPE)
    5773              :        : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
    5774        27777 :          ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
    5775        27779 :          : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
    5776              : 
    5777        27779 :   if (!valid_arglist)
    5778              :     return NULL_RTX;
    5779              : 
    5780              :   /* Compute the argument.  */
    5781        27774 :   op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
    5782              : 
    5783              :   /* Compute the alignment.  */
    5784        51631 :   align = (fcode == BUILT_IN_ALLOCA
    5785        23858 :            ? BIGGEST_ALIGNMENT
    5786         3916 :            : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
    5787              : 
    5788              :   /* Compute the maximum size.  */
    5789            2 :   max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5790        27776 :               ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
    5791              :               : -1);
    5792              : 
    5793              :   /* Allocate the desired space.  If the allocation stems from the declaration
    5794              :      of a variable-sized object, it cannot accumulate.  */
    5795        27774 :   result
    5796        27774 :     = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
    5797        27774 :   result = convert_memory_address (ptr_mode, result);
    5798              : 
    5799              :   /* Dynamic allocations for variables are recorded during gimplification.  */
    5800        27774 :   if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
    5801            0 :     record_dynamic_alloc (exp);
    5802              : 
    5803              :   return result;
    5804              : }
    5805              : 
    5806              : /* Emit a call to __asan_allocas_unpoison call in EXP.  Add to second argument
    5807              :    of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
    5808              :    STACK_DYNAMIC_OFFSET value.  See motivation for this in comment to
    5809              :    handle_builtin_stack_restore function.  */
    5810              : 
    5811              : static rtx
    5812          204 : expand_asan_emit_allocas_unpoison (tree exp)
    5813              : {
    5814          204 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    5815          204 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    5816          204 :   rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5817          204 :   rtx bot = expand_expr (arg1, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5818          204 :   rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
    5819              :                                  stack_pointer_rtx, NULL_RTX, 0,
    5820              :                                  OPTAB_LIB_WIDEN);
    5821          204 :   off = convert_modes (ptr_mode, Pmode, off, 0);
    5822          204 :   bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
    5823              :                              OPTAB_LIB_WIDEN);
    5824          204 :   rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
    5825          204 :   ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
    5826              :                                  top, ptr_mode, bot, ptr_mode);
    5827          204 :   return ret;
    5828              : }
    5829              : 
    5830              : /* Expand a call to bswap builtin in EXP.
    5831              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5832              :    function in-line.  If convenient, the result should be placed in TARGET.
    5833              :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5834              : 
    5835              : static rtx
    5836         1278 : expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
    5837              :                       rtx subtarget)
    5838              : {
    5839         1278 :   tree arg;
    5840         1278 :   rtx op0;
    5841              : 
    5842         1278 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5843              :     return NULL_RTX;
    5844              : 
    5845         1278 :   arg = CALL_EXPR_ARG (exp, 0);
    5846         1278 :   op0 = expand_expr (arg,
    5847           55 :                      subtarget && GET_MODE (subtarget) == target_mode
    5848              :                      ? subtarget : NULL_RTX,
    5849              :                      target_mode, EXPAND_NORMAL);
    5850         1278 :   if (GET_MODE (op0) != target_mode)
    5851            0 :     op0 = convert_to_mode (target_mode, op0, 1);
    5852              : 
    5853         1278 :   target = expand_unop (target_mode, bswap_optab, op0, target, 1);
    5854              : 
    5855         1278 :   gcc_assert (target);
    5856              : 
    5857         1278 :   return convert_to_mode (target_mode, target, 1);
    5858              : }
    5859              : 
    5860              : /* Expand a call to a unary builtin in EXP.
    5861              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5862              :    function in-line.  If convenient, the result should be placed in TARGET.
    5863              :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5864              : 
    5865              : static rtx
    5866          834 : expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
    5867              :                      rtx subtarget, optab op_optab)
    5868              : {
    5869          834 :   rtx op0;
    5870              : 
    5871          834 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5872              :     return NULL_RTX;
    5873              : 
    5874              :   /* Compute the argument.  */
    5875         1668 :   op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
    5876              :                      (subtarget
    5877          101 :                       && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
    5878          101 :                           == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
    5879              :                      VOIDmode, EXPAND_NORMAL);
    5880              :   /* Compute op, into TARGET if possible.
    5881              :      Set TARGET to wherever the result comes back.  */
    5882          834 :   target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
    5883              :                         op_optab, op0, target, op_optab != clrsb_optab);
    5884          834 :   gcc_assert (target);
    5885              : 
    5886          834 :   return convert_to_mode (target_mode, target, 0);
    5887              : }
    5888              : 
    5889              : /* Expand a call to __builtin_expect.  We just return our argument
    5890              :    as the builtin_expect semantic should've been already executed by
    5891              :    tree branch prediction pass. */
    5892              : 
    5893              : static rtx
    5894         1353 : expand_builtin_expect (tree exp, rtx target)
    5895              : {
    5896         1353 :   tree arg;
    5897              : 
    5898         1353 :   if (call_expr_nargs (exp) < 2)
    5899            0 :     return const0_rtx;
    5900         1353 :   arg = CALL_EXPR_ARG (exp, 0);
    5901              : 
    5902         1353 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5903              :   /* When guessing was done, the hints should be already stripped away.  */
    5904         1353 :   gcc_assert (!flag_guess_branch_prob
    5905              :               || optimize == 0 || seen_error ());
    5906              :   return target;
    5907              : }
    5908              : 
    5909              : /* Expand a call to __builtin_expect_with_probability.  We just return our
    5910              :    argument as the builtin_expect semantic should've been already executed by
    5911              :    tree branch prediction pass.  */
    5912              : 
    5913              : static rtx
    5914            5 : expand_builtin_expect_with_probability (tree exp, rtx target)
    5915              : {
    5916            5 :   tree arg;
    5917              : 
    5918            5 :   if (call_expr_nargs (exp) < 3)
    5919            0 :     return const0_rtx;
    5920            5 :   arg = CALL_EXPR_ARG (exp, 0);
    5921              : 
    5922            5 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5923              :   /* When guessing was done, the hints should be already stripped away.  */
    5924            5 :   gcc_assert (!flag_guess_branch_prob
    5925              :               || optimize == 0 || seen_error ());
    5926              :   return target;
    5927              : }
    5928              : 
    5929              : 
    5930              : /* Expand a call to __builtin_assume_aligned.  We just return our first
    5931              :    argument as the builtin_assume_aligned semantic should've been already
    5932              :    executed by CCP.  */
    5933              : 
    5934              : static rtx
    5935          665 : expand_builtin_assume_aligned (tree exp, rtx target)
    5936              : {
    5937          665 :   if (call_expr_nargs (exp) < 2)
    5938            0 :     return const0_rtx;
    5939          665 :   target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
    5940              :                         EXPAND_NORMAL);
    5941          665 :   gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
    5942              :               && (call_expr_nargs (exp) < 3
    5943              :                   || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
    5944              :   return target;
    5945              : }
    5946              : 
    5947              : void
    5948        38632 : expand_builtin_trap (void)
    5949              : {
    5950        38632 :   if (targetm.have_trap ())
    5951              :     {
    5952        38632 :       rtx_insn *insn = emit_insn (targetm.gen_trap ());
    5953              :       /* For trap insns when not accumulating outgoing args force
    5954              :          REG_ARGS_SIZE note to prevent crossjumping of calls with
    5955              :          different args sizes.  */
    5956        38632 :       if (!ACCUMULATE_OUTGOING_ARGS)
    5957        38630 :         add_args_size_note (insn, stack_pointer_delta);
    5958              :     }
    5959              :   else
    5960              :     {
    5961            0 :       tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
    5962            0 :       tree call_expr = build_call_expr (fn, 0);
    5963            0 :       expand_call (call_expr, NULL_RTX, false);
    5964              :     }
    5965              : 
    5966        38632 :   emit_barrier ();
    5967        38632 : }
    5968              : 
    5969              : /* Expand a call to __builtin_unreachable.  We do nothing except emit
    5970              :    a barrier saying that control flow will not pass here.
    5971              : 
    5972              :    It is the responsibility of the program being compiled to ensure
    5973              :    that control flow does never reach __builtin_unreachable.  */
    5974              : static void
    5975         2522 : expand_builtin_unreachable (void)
    5976              : {
    5977              :   /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable
    5978              :      to avoid this.  */
    5979         2522 :   gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE));
    5980         2522 :   emit_barrier ();
    5981         2522 : }
    5982              : 
    5983              : /* Expand EXP, a call to fabs, fabsf or fabsl.
    5984              :    Return NULL_RTX if a normal call should be emitted rather than expanding
    5985              :    the function inline.  If convenient, the result should be placed
    5986              :    in TARGET.  SUBTARGET may be used as the target for computing
    5987              :    the operand.  */
    5988              : 
    5989              : static rtx
    5990            4 : expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
    5991              : {
    5992            4 :   machine_mode mode;
    5993            4 :   tree arg;
    5994            4 :   rtx op0;
    5995              : 
    5996            4 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    5997              :     return NULL_RTX;
    5998              : 
    5999            0 :   arg = CALL_EXPR_ARG (exp, 0);
    6000            0 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    6001            0 :   mode = TYPE_MODE (TREE_TYPE (arg));
    6002            0 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6003            0 :   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
    6004              : }
    6005              : 
    6006              : /* Expand EXP, a call to copysign, copysignf, or copysignl.
    6007              :    Return NULL is a normal call should be emitted rather than expanding the
    6008              :    function inline.  If convenient, the result should be placed in TARGET.
    6009              :    SUBTARGET may be used as the target for computing the operand.  */
    6010              : 
    6011              : static rtx
    6012        11677 : expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
    6013              : {
    6014        11677 :   rtx op0, op1;
    6015        11677 :   tree arg;
    6016              : 
    6017        11677 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    6018              :     return NULL_RTX;
    6019              : 
    6020        11676 :   arg = CALL_EXPR_ARG (exp, 0);
    6021        11676 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6022              : 
    6023        11676 :   arg = CALL_EXPR_ARG (exp, 1);
    6024        11676 :   op1 = expand_normal (arg);
    6025              : 
    6026        11676 :   return expand_copysign (op0, op1, target);
    6027              : }
    6028              : 
    6029              : /* Emit a call to __builtin___clear_cache.  */
    6030              : 
    6031              : void
    6032            0 : default_emit_call_builtin___clear_cache (rtx begin, rtx end)
    6033              : {
    6034            0 :   rtx callee = gen_rtx_SYMBOL_REF (Pmode,
    6035              :                                    BUILTIN_ASM_NAME_PTR
    6036              :                                    (BUILT_IN_CLEAR_CACHE));
    6037              : 
    6038            0 :   emit_library_call (callee,
    6039              :                      LCT_NORMAL, VOIDmode,
    6040              :                      convert_memory_address (ptr_mode, begin), ptr_mode,
    6041              :                      convert_memory_address (ptr_mode, end), ptr_mode);
    6042            0 : }
    6043              : 
    6044              : /* Emit a call to __builtin___clear_cache, unless the target specifies
    6045              :    it as do-nothing.  This function can be used by trampoline
    6046              :    finalizers to duplicate the effects of expanding a call to the
    6047              :    clear_cache builtin.  */
    6048              : 
    6049              : void
    6050           28 : maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
    6051              : {
    6052           28 :   gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
    6053              :                || CONST_INT_P (begin))
    6054              :               && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
    6055              :                   || CONST_INT_P (end)));
    6056              : 
    6057           28 :   if (targetm.have_clear_cache ())
    6058              :     {
    6059              :       /* We have a "clear_cache" insn, and it will handle everything.  */
    6060            0 :       class expand_operand ops[2];
    6061              : 
    6062            0 :       create_address_operand (&ops[0], begin);
    6063            0 :       create_address_operand (&ops[1], end);
    6064              : 
    6065            0 :       if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
    6066            0 :         return;
    6067              :     }
    6068              :   else
    6069              :     {
    6070              : #ifndef CLEAR_INSN_CACHE
    6071              :       /* There is no "clear_cache" insn, and __clear_cache() in libgcc
    6072              :          does nothing.  There is no need to call it.  Do nothing.  */
    6073              :       return;
    6074              : #endif /* CLEAR_INSN_CACHE */
    6075              :     }
    6076              : 
    6077            0 :   targetm.calls.emit_call_builtin___clear_cache (begin, end);
    6078              : }
    6079              : 
    6080              : /* Expand a call to __builtin___clear_cache.  */
    6081              : 
    6082              : static void
    6083           28 : expand_builtin___clear_cache (tree exp)
    6084              : {
    6085           28 :   tree begin, end;
    6086           28 :   rtx begin_rtx, end_rtx;
    6087              : 
    6088              :   /* We must not expand to a library call.  If we did, any
    6089              :      fallback library function in libgcc that might contain a call to
    6090              :      __builtin___clear_cache() would recurse infinitely.  */
    6091           28 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    6092              :     {
    6093            0 :       error ("both arguments to %<__builtin___clear_cache%> must be pointers");
    6094            0 :       return;
    6095              :     }
    6096              : 
    6097           28 :   begin = CALL_EXPR_ARG (exp, 0);
    6098           30 :   begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
    6099              : 
    6100           28 :   end = CALL_EXPR_ARG (exp, 1);
    6101           30 :   end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
    6102              : 
    6103           28 :   maybe_emit_call_builtin___clear_cache (begin_rtx, end_rtx);
    6104              : }
    6105              : 
    6106              : /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
    6107              : 
    6108              : static rtx
    6109          657 : round_trampoline_addr (rtx tramp)
    6110              : {
    6111          657 :   rtx temp, addend, mask;
    6112              : 
    6113              :   /* If we don't need too much alignment, we'll have been guaranteed
    6114              :      proper alignment by get_trampoline_type.  */
    6115          657 :   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
    6116              :     return tramp;
    6117              : 
    6118              :   /* Round address up to desired boundary.  */
    6119            0 :   temp = gen_reg_rtx (Pmode);
    6120            0 :   addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
    6121            0 :   mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
    6122              : 
    6123            0 :   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
    6124              :                                temp, 0, OPTAB_LIB_WIDEN);
    6125            0 :   tramp = expand_simple_binop (Pmode, AND, temp, mask,
    6126              :                                temp, 0, OPTAB_LIB_WIDEN);
    6127              : 
    6128            0 :   return tramp;
    6129              : }
    6130              : 
    6131              : static rtx
    6132          305 : expand_builtin_init_trampoline (tree exp, bool onstack)
    6133              : {
    6134          305 :   tree t_tramp, t_func, t_chain;
    6135          305 :   rtx m_tramp, r_tramp, r_chain, tmp;
    6136              : 
    6137          305 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
    6138              :                          POINTER_TYPE, VOID_TYPE))
    6139              :     return NULL_RTX;
    6140              : 
    6141          305 :   t_tramp = CALL_EXPR_ARG (exp, 0);
    6142          305 :   t_func = CALL_EXPR_ARG (exp, 1);
    6143          305 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6144              : 
    6145          305 :   r_tramp = expand_normal (t_tramp);
    6146          305 :   m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
    6147          305 :   MEM_NOTRAP_P (m_tramp) = 1;
    6148              : 
    6149              :   /* If ONSTACK, the TRAMP argument should be the address of a field
    6150              :      within the local function's FRAME decl.  Either way, let's see if
    6151              :      we can fill in the MEM_ATTRs for this memory.  */
    6152          305 :   if (TREE_CODE (t_tramp) == ADDR_EXPR)
    6153          305 :     set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
    6154              : 
    6155              :   /* Creator of a heap trampoline is responsible for making sure the
    6156              :      address is aligned to at least STACK_BOUNDARY.  Normally malloc
    6157              :      will ensure this anyhow.  */
    6158          305 :   tmp = round_trampoline_addr (r_tramp);
    6159          305 :   if (tmp != r_tramp)
    6160              :     {
    6161            0 :       m_tramp = change_address (m_tramp, BLKmode, tmp);
    6162            0 :       set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
    6163            0 :       set_mem_size (m_tramp, TRAMPOLINE_SIZE);
    6164              :     }
    6165              : 
    6166              :   /* The FUNC argument should be the address of the nested function.
    6167              :      Extract the actual function decl to pass to the hook.  */
    6168          305 :   gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
    6169          305 :   t_func = TREE_OPERAND (t_func, 0);
    6170          305 :   gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
    6171              : 
    6172          305 :   r_chain = expand_normal (t_chain);
    6173              : 
    6174              :   /* Generate insns to initialize the trampoline.  */
    6175          305 :   targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
    6176              : 
    6177          305 :   if (onstack)
    6178              :     {
    6179          305 :       trampolines_created = 1;
    6180              : 
    6181          305 :       if (targetm.calls.custom_function_descriptors != 0)
    6182          305 :         warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
    6183              :                     "trampoline generated for nested function %qD", t_func);
    6184              :     }
    6185              : 
    6186          305 :   return const0_rtx;
    6187              : }
    6188              : 
    6189              : static rtx
    6190          352 : expand_builtin_adjust_trampoline (tree exp)
    6191              : {
    6192          352 :   rtx tramp;
    6193              : 
    6194          352 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6195              :     return NULL_RTX;
    6196              : 
    6197          352 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6198          352 :   tramp = round_trampoline_addr (tramp);
    6199          352 :   if (targetm.calls.trampoline_adjust_address)
    6200            0 :     tramp = targetm.calls.trampoline_adjust_address (tramp);
    6201              : 
    6202              :   return tramp;
    6203              : }
    6204              : 
    6205              : /* Expand a call to the builtin descriptor initialization routine.
    6206              :    A descriptor is made up of a couple of pointers to the static
    6207              :    chain and the code entry in this order.  */
    6208              : 
    6209              : static rtx
    6210            0 : expand_builtin_init_descriptor (tree exp)
    6211              : {
    6212            0 :   tree t_descr, t_func, t_chain;
    6213            0 :   rtx m_descr, r_descr, r_func, r_chain;
    6214              : 
    6215            0 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
    6216              :                          VOID_TYPE))
    6217              :     return NULL_RTX;
    6218              : 
    6219            0 :   t_descr = CALL_EXPR_ARG (exp, 0);
    6220            0 :   t_func = CALL_EXPR_ARG (exp, 1);
    6221            0 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6222              : 
    6223            0 :   r_descr = expand_normal (t_descr);
    6224            0 :   m_descr = gen_rtx_MEM (BLKmode, r_descr);
    6225            0 :   MEM_NOTRAP_P (m_descr) = 1;
    6226            0 :   set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
    6227              : 
    6228            0 :   r_func = expand_normal (t_func);
    6229            0 :   r_chain = expand_normal (t_chain);
    6230              : 
    6231              :   /* Generate insns to initialize the descriptor.  */
    6232            0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
    6233            0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
    6234              :                                      POINTER_SIZE / BITS_PER_UNIT), r_func);
    6235              : 
    6236            0 :   return const0_rtx;
    6237              : }
    6238              : 
    6239              : /* Expand a call to the builtin descriptor adjustment routine.  */
    6240              : 
    6241              : static rtx
    6242            0 : expand_builtin_adjust_descriptor (tree exp)
    6243              : {
    6244            0 :   rtx tramp;
    6245              : 
    6246            0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6247              :     return NULL_RTX;
    6248              : 
    6249            0 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6250              : 
    6251              :   /* Unalign the descriptor to allow runtime identification.  */
    6252            0 :   tramp = plus_constant (ptr_mode, tramp,
    6253            0 :                          targetm.calls.custom_function_descriptors);
    6254              : 
    6255            0 :   return force_operand (tramp, NULL_RTX);
    6256              : }
    6257              : 
    6258              : /* Expand the call EXP to the built-in signbit, signbitf or signbitl
    6259              :    function.  The function first checks whether the back end provides
    6260              :    an insn to implement signbit for the respective mode.  If not, it
    6261              :    checks whether the floating point format of the value is such that
    6262              :    the sign bit can be extracted.  If that is not the case, error out.
    6263              :    EXP is the expression that is a call to the builtin function; if
    6264              :    convenient, the result should be placed in TARGET.  */
    6265              : static rtx
    6266         1086 : expand_builtin_signbit (tree exp, rtx target)
    6267              : {
    6268         1086 :   const struct real_format *fmt;
    6269         1086 :   scalar_float_mode fmode;
    6270         1086 :   scalar_int_mode rmode, imode;
    6271         1086 :   tree arg;
    6272         1086 :   int word, bitpos;
    6273         1086 :   enum insn_code icode;
    6274         1086 :   rtx temp;
    6275         1086 :   location_t loc = EXPR_LOCATION (exp);
    6276              : 
    6277         1086 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    6278              :     return NULL_RTX;
    6279              : 
    6280         1086 :   arg = CALL_EXPR_ARG (exp, 0);
    6281         1086 :   fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
    6282         1086 :   rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
    6283         1086 :   fmt = REAL_MODE_FORMAT (fmode);
    6284              : 
    6285         1086 :   arg = builtin_save_expr (arg);
    6286              : 
    6287              :   /* Expand the argument yielding a RTX expression. */
    6288         1086 :   temp = expand_normal (arg);
    6289              : 
    6290              :   /* Check if the back end provides an insn that handles signbit for the
    6291              :      argument's mode. */
    6292         1086 :   icode = optab_handler (signbit_optab, fmode);
    6293         1086 :   if (icode != CODE_FOR_nothing)
    6294              :     {
    6295           10 :       rtx_insn *last = get_last_insn ();
    6296           10 :       rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    6297           10 :       if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
    6298              :         return this_target;
    6299            0 :       delete_insns_since (last);
    6300              :     }
    6301              : 
    6302              :   /* For floating point formats without a sign bit, implement signbit
    6303              :      as "ARG < 0.0".  */
    6304         1076 :   bitpos = fmt->signbit_ro;
    6305         1076 :   if (bitpos < 0)
    6306              :   {
    6307              :     /* But we can't do this if the format supports signed zero.  */
    6308            0 :     gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
    6309              : 
    6310            0 :     arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
    6311            0 :                        build_real (TREE_TYPE (arg), dconst0));
    6312            0 :     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    6313              :   }
    6314              : 
    6315         2152 :   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
    6316              :     {
    6317          972 :       imode = int_mode_for_mode (fmode).require ();
    6318          972 :       temp = gen_lowpart (imode, temp);
    6319              :     }
    6320              :   else
    6321              :     {
    6322          104 :       imode = word_mode;
    6323              :       /* Handle targets with different FP word orders.  */
    6324          104 :       if (FLOAT_WORDS_BIG_ENDIAN)
    6325              :         word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
    6326              :       else
    6327          104 :         word = bitpos / BITS_PER_WORD;
    6328          104 :       temp = operand_subword_force (temp, word, fmode);
    6329          104 :       bitpos = bitpos % BITS_PER_WORD;
    6330              :     }
    6331              : 
    6332              :   /* Force the intermediate word_mode (or narrower) result into a
    6333              :      register.  This avoids attempting to create paradoxical SUBREGs
    6334              :      of floating point modes below.  */
    6335         1076 :   temp = force_reg (imode, temp);
    6336              : 
    6337              :   /* If the bitpos is within the "result mode" lowpart, the operation
    6338              :      can be implement with a single bitwise AND.  Otherwise, we need
    6339              :      a right shift and an AND.  */
    6340              : 
    6341         2152 :   if (bitpos < GET_MODE_BITSIZE (rmode))
    6342              :     {
    6343          868 :       wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
    6344              : 
    6345         2604 :       if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
    6346            0 :         temp = gen_lowpart (rmode, temp);
    6347         1736 :       temp = expand_binop (rmode, and_optab, temp,
    6348         1736 :                            immed_wide_int_const (mask, rmode),
    6349              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6350          868 :     }
    6351              :   else
    6352              :     {
    6353              :       /* Perform a logical right shift to place the signbit in the least
    6354              :          significant bit, then truncate the result to the desired mode
    6355              :          and mask just this bit.  */
    6356          208 :       temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
    6357          208 :       temp = gen_lowpart (rmode, temp);
    6358          208 :       temp = expand_binop (rmode, and_optab, temp, const1_rtx,
    6359              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6360              :     }
    6361              : 
    6362              :   return temp;
    6363              : }
    6364              : 
    6365              : /* Expand fork or exec calls.  TARGET is the desired target of the
    6366              :    call.  EXP is the call. FN is the
    6367              :    identificator of the actual function.  IGNORE is nonzero if the
    6368              :    value is to be ignored.  */
    6369              : 
    6370              : static rtx
    6371          109 : expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
    6372              : {
    6373          109 :   tree id, decl;
    6374          109 :   tree call;
    6375              : 
    6376              :   /* If we are not profiling, just call the function.  */
    6377          109 :   if (!coverage_instrumentation_p ())
    6378              :     return NULL_RTX;
    6379              : 
    6380              :   /* Otherwise call the wrapper.  This should be equivalent for the rest of
    6381              :      compiler, so the code does not diverge, and the wrapper may run the
    6382              :      code necessary for keeping the profiling sane.  */
    6383              : 
    6384            4 :   switch (DECL_FUNCTION_CODE (fn))
    6385              :     {
    6386            4 :     case BUILT_IN_FORK:
    6387            4 :       id = get_identifier ("__gcov_fork");
    6388            4 :       break;
    6389              : 
    6390            0 :     case BUILT_IN_EXECL:
    6391            0 :       id = get_identifier ("__gcov_execl");
    6392            0 :       break;
    6393              : 
    6394            0 :     case BUILT_IN_EXECV:
    6395            0 :       id = get_identifier ("__gcov_execv");
    6396            0 :       break;
    6397              : 
    6398            0 :     case BUILT_IN_EXECLP:
    6399            0 :       id = get_identifier ("__gcov_execlp");
    6400            0 :       break;
    6401              : 
    6402            0 :     case BUILT_IN_EXECLE:
    6403            0 :       id = get_identifier ("__gcov_execle");
    6404            0 :       break;
    6405              : 
    6406            0 :     case BUILT_IN_EXECVP:
    6407            0 :       id = get_identifier ("__gcov_execvp");
    6408            0 :       break;
    6409              : 
    6410            0 :     case BUILT_IN_EXECVE:
    6411            0 :       id = get_identifier ("__gcov_execve");
    6412            0 :       break;
    6413              : 
    6414            0 :     default:
    6415            0 :       gcc_unreachable ();
    6416              :     }
    6417              : 
    6418            4 :   decl = build_decl (DECL_SOURCE_LOCATION (fn),
    6419            4 :                      FUNCTION_DECL, id, TREE_TYPE (fn));
    6420            4 :   DECL_EXTERNAL (decl) = 1;
    6421            4 :   TREE_PUBLIC (decl) = 1;
    6422            4 :   DECL_ARTIFICIAL (decl) = 1;
    6423            4 :   TREE_NOTHROW (decl) = 1;
    6424            4 :   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
    6425            4 :   DECL_VISIBILITY_SPECIFIED (decl) = 1;
    6426            4 :   call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
    6427            4 :   return expand_call (call, target, ignore);
    6428              :  }
    6429              : 
    6430              : 
    6431              : 
    6432              : /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
    6433              :    the pointer in these functions is void*, the tree optimizers may remove
    6434              :    casts.  The mode computed in expand_builtin isn't reliable either, due
    6435              :    to __sync_bool_compare_and_swap.
    6436              : 
    6437              :    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
    6438              :    group of builtins.  This gives us log2 of the mode size.  */
    6439              : 
    6440              : static inline machine_mode
    6441       133853 : get_builtin_sync_mode (int fcode_diff)
    6442              : {
    6443              :   /* The size is not negotiable, so ask not to get BLKmode in return
    6444              :      if the target indicates that a smaller size would be better.  */
    6445       133853 :   return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
    6446              : }
    6447              : 
    6448              : /* Expand the memory expression LOC and return the appropriate memory operand
    6449              :    for the builtin_sync operations.  */
    6450              : 
    6451              : static rtx
    6452       150439 : get_builtin_sync_mem (tree loc, machine_mode mode)
    6453              : {
    6454       150439 :   rtx addr, mem;
    6455       150439 :   int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
    6456              :                                     ? TREE_TYPE (TREE_TYPE (loc))
    6457              :                                     : TREE_TYPE (loc));
    6458       150439 :   scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
    6459              : 
    6460       150439 :   addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
    6461       150439 :   addr = convert_memory_address (addr_mode, addr);
    6462              : 
    6463              :   /* Note that we explicitly do not want any alias information for this
    6464              :      memory, so that we kill all other live memories.  Otherwise we don't
    6465              :      satisfy the full barrier semantics of the intrinsic.  */
    6466       150439 :   mem = gen_rtx_MEM (mode, addr);
    6467              : 
    6468       150439 :   set_mem_addr_space (mem, addr_space);
    6469              : 
    6470       150439 :   mem = validize_mem (mem);
    6471              : 
    6472              :   /* The alignment needs to be at least according to that of the mode.  */
    6473       150439 :   set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
    6474              :                            get_pointer_alignment (loc)));
    6475       150439 :   set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
    6476       150439 :   MEM_VOLATILE_P (mem) = 1;
    6477              : 
    6478       150439 :   return mem;
    6479              : }
    6480              : 
    6481              : /* Make sure an argument is in the right mode.
    6482              :    EXP is the tree argument.
    6483              :    MODE is the mode it should be in.  */
    6484              : 
    6485              : static rtx
    6486        93796 : expand_expr_force_mode (tree exp, machine_mode mode)
    6487              : {
    6488        93796 :   rtx val;
    6489        93796 :   machine_mode old_mode;
    6490              : 
    6491        93796 :   if (TREE_CODE (exp) == SSA_NAME
    6492        93796 :       && TYPE_MODE (TREE_TYPE (exp)) != mode)
    6493              :     {
    6494              :       /* Undo argument promotion if possible, as combine might not
    6495              :          be able to do it later due to MEM_VOLATILE_P uses in the
    6496              :          patterns.  */
    6497           25 :       gimple *g = get_gimple_for_ssa_name (exp);
    6498           25 :       if (g && gimple_assign_cast_p (g))
    6499              :         {
    6500            0 :           tree rhs = gimple_assign_rhs1 (g);
    6501            0 :           tree_code code = gimple_assign_rhs_code (g);
    6502            0 :           if (CONVERT_EXPR_CODE_P (code)
    6503            0 :               && TYPE_MODE (TREE_TYPE (rhs)) == mode
    6504            0 :               && INTEGRAL_TYPE_P (TREE_TYPE (exp))
    6505            0 :               && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
    6506            0 :               && (TYPE_PRECISION (TREE_TYPE (exp))
    6507            0 :                   > TYPE_PRECISION (TREE_TYPE (rhs))))
    6508              :             exp = rhs;
    6509              :         }
    6510              :     }
    6511              : 
    6512        93796 :   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
    6513              :   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
    6514              :      of CONST_INTs, where we know the old_mode only from the call argument.  */
    6515              : 
    6516        93796 :   old_mode = GET_MODE (val);
    6517        93796 :   if (old_mode == VOIDmode)
    6518        44069 :     old_mode = TYPE_MODE (TREE_TYPE (exp));
    6519        93796 :   val = convert_modes (mode, old_mode, val, 1);
    6520        93796 :   return val;
    6521              : }
    6522              : 
    6523              : 
    6524              : /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
    6525              :    EXP is the CALL_EXPR.  CODE is the rtx code
    6526              :    that corresponds to the arithmetic or logical operation from the name;
    6527              :    an exception here is that NOT actually means NAND.  TARGET is an optional
    6528              :    place for us to store the results; AFTER is true if this is the
    6529              :    fetch_and_xxx form.  */
    6530              : 
    6531              : static rtx
    6532         4011 : expand_builtin_sync_operation (machine_mode mode, tree exp,
    6533              :                                enum rtx_code code, bool after,
    6534              :                                rtx target)
    6535              : {
    6536         4011 :   rtx val, mem;
    6537         4011 :   location_t loc = EXPR_LOCATION (exp);
    6538              : 
    6539         4011 :   if (code == NOT && warn_sync_nand)
    6540              :     {
    6541          523 :       tree fndecl = get_callee_fndecl (exp);
    6542          523 :       enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    6543              : 
    6544          523 :       static bool warned_f_a_n, warned_n_a_f;
    6545              : 
    6546          523 :       switch (fcode)
    6547              :         {
    6548          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    6549          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    6550          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    6551          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    6552          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    6553          434 :           if (warned_f_a_n)
    6554              :             break;
    6555              : 
    6556           30 :           fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
    6557           30 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6558           30 :           warned_f_a_n = true;
    6559           30 :           break;
    6560              : 
    6561           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    6562           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    6563           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    6564           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    6565           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    6566           89 :           if (warned_n_a_f)
    6567              :             break;
    6568              : 
    6569           22 :          fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
    6570           22 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6571           22 :           warned_n_a_f = true;
    6572           22 :           break;
    6573              : 
    6574            0 :         default:
    6575            0 :           gcc_unreachable ();
    6576              :         }
    6577              :     }
    6578              : 
    6579              :   /* Expand the operands.  */
    6580         4011 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6581         4011 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6582              : 
    6583         4011 :   return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
    6584         4011 :                                  after);
    6585              : }
    6586              : 
    6587              : /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
    6588              :    intrinsics. EXP is the CALL_EXPR.  IS_BOOL is
    6589              :    true if this is the boolean form.  TARGET is a place for us to store the
    6590              :    results; this is NOT optional if IS_BOOL is true.  */
    6591              : 
    6592              : static rtx
    6593          460 : expand_builtin_compare_and_swap (machine_mode mode, tree exp,
    6594              :                                  bool is_bool, rtx target)
    6595              : {
    6596          460 :   rtx old_val, new_val, mem;
    6597          460 :   rtx *pbool, *poval;
    6598              : 
    6599              :   /* Expand the operands.  */
    6600          460 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6601          460 :   old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6602          460 :   new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6603              : 
    6604          460 :   pbool = poval = NULL;
    6605          460 :   if (target != const0_rtx)
    6606              :     {
    6607          434 :       if (is_bool)
    6608              :         pbool = &target;
    6609              :       else
    6610          230 :         poval = &target;
    6611              :     }
    6612          460 :   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
    6613              :                                        false, MEMMODEL_SYNC_SEQ_CST,
    6614              :                                        MEMMODEL_SYNC_SEQ_CST))
    6615              :     return NULL_RTX;
    6616              : 
    6617          458 :   return target;
    6618              : }
    6619              : 
    6620              : /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
    6621              :    general form is actually an atomic exchange, and some targets only
    6622              :    support a reduced form with the second argument being a constant 1.
    6623              :    EXP is the CALL_EXPR; TARGET is an optional place for us to store
    6624              :    the results.  */
    6625              : 
    6626              : static rtx
    6627          326 : expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
    6628              :                                        rtx target)
    6629              : {
    6630          326 :   rtx val, mem;
    6631              : 
    6632              :   /* Expand the operands.  */
    6633          326 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6634          326 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6635              : 
    6636          326 :   return expand_sync_lock_test_and_set (target, mem, val);
    6637              : }
    6638              : 
    6639              : /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
    6640              : 
    6641              : static rtx
    6642          146 : expand_builtin_sync_lock_release (machine_mode mode, tree exp)
    6643              : {
    6644          146 :   rtx mem;
    6645              : 
    6646              :   /* Expand the operands.  */
    6647          146 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6648              : 
    6649          146 :   return expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
    6650              : }
    6651              : 
    6652              : /* Given an integer representing an ``enum memmodel'', verify its
    6653              :    correctness and return the memory model enum.  */
    6654              : 
    6655              : static enum memmodel
    6656       168908 : get_memmodel (tree exp)
    6657              : {
    6658              :   /* If the parameter is not a constant, it's a run time value so we'll just
    6659              :      convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking.  */
    6660       168908 :   if (TREE_CODE (exp) != INTEGER_CST)
    6661              :     return MEMMODEL_SEQ_CST;
    6662              : 
    6663       168081 :   rtx op = expand_normal (exp);
    6664              : 
    6665       168081 :   unsigned HOST_WIDE_INT val = INTVAL (op);
    6666       168081 :   if (targetm.memmodel_check)
    6667       168081 :     val = targetm.memmodel_check (val);
    6668            0 :   else if (val & ~MEMMODEL_MASK)
    6669              :     return MEMMODEL_SEQ_CST;
    6670              : 
    6671              :   /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
    6672       168081 :   if (memmodel_base (val) >= MEMMODEL_LAST)
    6673              :     return MEMMODEL_SEQ_CST;
    6674              : 
    6675              :   /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
    6676              :      be conservative and promote consume to acquire.  */
    6677       168078 :   if (val == MEMMODEL_CONSUME)
    6678          755 :     val = MEMMODEL_ACQUIRE;
    6679              : 
    6680       168078 :   return (enum memmodel) val;
    6681              : }
    6682              : 
    6683              : /* Expand the __atomic_exchange intrinsic:
    6684              :         TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
    6685              :    EXP is the CALL_EXPR.
    6686              :    TARGET is an optional place for us to store the results.  */
    6687              : 
    6688              : static rtx
    6689         2881 : expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
    6690              : {
    6691         2881 :   rtx val, mem;
    6692         2881 :   enum memmodel model;
    6693              : 
    6694         2881 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6695              : 
    6696         2881 :   if (!flag_inline_atomics)
    6697              :     return NULL_RTX;
    6698              : 
    6699              :   /* Expand the operands.  */
    6700         2830 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6701         2830 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6702              : 
    6703         2830 :   return expand_atomic_exchange (target, mem, val, model);
    6704              : }
    6705              : 
    6706              : /* Expand the __atomic_compare_exchange intrinsic:
    6707              :         bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
    6708              :                                         TYPE desired, BOOL weak,
    6709              :                                         enum memmodel success,
    6710              :                                         enum memmodel failure)
    6711              :    EXP is the CALL_EXPR.
    6712              :    TARGET is an optional place for us to store the results.  */
    6713              : 
    6714              : static rtx
    6715         9126 : expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
    6716              :                                         rtx target)
    6717              : {
    6718         9126 :   rtx expect, desired, mem, oldval;
    6719         9126 :   rtx_code_label *label;
    6720         9126 :   tree weak;
    6721         9126 :   bool is_weak;
    6722              : 
    6723         9126 :   memmodel success = get_memmodel (CALL_EXPR_ARG (exp, 4));
    6724         9126 :   memmodel failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
    6725              : 
    6726         9126 :   if (failure > success)
    6727           22 :     success = MEMMODEL_SEQ_CST;
    6728              : 
    6729         9126 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6730              :     {
    6731              :       failure = MEMMODEL_SEQ_CST;
    6732              :       success = MEMMODEL_SEQ_CST;
    6733              :     }
    6734              : 
    6735              : 
    6736         9126 :   if (!flag_inline_atomics)
    6737              :     return NULL_RTX;
    6738              : 
    6739              :   /* Expand the operands.  */
    6740         9075 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6741              : 
    6742         9075 :   expect = expand_normal (CALL_EXPR_ARG (exp, 1));
    6743         9075 :   expect = convert_memory_address (Pmode, expect);
    6744         9075 :   expect = gen_rtx_MEM (mode, expect);
    6745         9075 :   desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6746              : 
    6747         9075 :   weak = CALL_EXPR_ARG (exp, 3);
    6748         9075 :   is_weak = false;
    6749         9075 :   if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
    6750         9075 :     is_weak = true;
    6751              : 
    6752         9075 :   if (target == const0_rtx)
    6753          287 :     target = NULL;
    6754              : 
    6755              :   /* Lest the rtl backend create a race condition with an imporoper store
    6756              :      to memory, always create a new pseudo for OLDVAL.  */
    6757         9075 :   oldval = NULL;
    6758              : 
    6759         9075 :   if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
    6760              :                                        is_weak, success, failure))
    6761              :     return NULL_RTX;
    6762              : 
    6763              :   /* Conditionally store back to EXPECT, lest we create a race condition
    6764              :      with an improper store to memory.  */
    6765              :   /* ??? With a rearrangement of atomics at the gimple level, we can handle
    6766              :      the normal case where EXPECT is totally private, i.e. a register.  At
    6767              :      which point the store can be unconditional.  */
    6768         7326 :   label = gen_label_rtx ();
    6769         7326 :   emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
    6770         7326 :                            GET_MODE (target), 1, label);
    6771         7326 :   emit_move_insn (expect, oldval);
    6772         7326 :   emit_label (label);
    6773              : 
    6774         7326 :   return target;
    6775              : }
    6776              : 
    6777              : /* Helper function for expand_ifn_atomic_compare_exchange - expand
    6778              :    internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
    6779              :    call.  The weak parameter must be dropped to match the expected parameter
    6780              :    list and the expected argument changed from value to pointer to memory
    6781              :    slot.  */
    6782              : 
    6783              : static void
    6784            0 : expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
    6785              : {
    6786            0 :   unsigned int z;
    6787            0 :   vec<tree, va_gc> *vec;
    6788              : 
    6789            0 :   vec_alloc (vec, 5);
    6790            0 :   vec->quick_push (gimple_call_arg (call, 0));
    6791            0 :   tree expected = gimple_call_arg (call, 1);
    6792            0 :   rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
    6793            0 :                                       TREE_TYPE (expected));
    6794            0 :   rtx expd = expand_expr (expected, x, mode, EXPAND_NORMAL);
    6795            0 :   if (expd != x)
    6796            0 :     emit_move_insn (x, expd);
    6797            0 :   tree v = make_tree (TREE_TYPE (expected), x);
    6798            0 :   vec->quick_push (build1 (ADDR_EXPR,
    6799            0 :                            build_pointer_type (TREE_TYPE (expected)), v));
    6800            0 :   vec->quick_push (gimple_call_arg (call, 2));
    6801              :   /* Skip the boolean weak parameter.  */
    6802            0 :   for (z = 4; z < 6; z++)
    6803            0 :     vec->quick_push (gimple_call_arg (call, z));
    6804              :   /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}.  */
    6805            0 :   unsigned int bytes_log2 = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
    6806            0 :   gcc_assert (bytes_log2 < 5);
    6807            0 :   built_in_function fncode
    6808              :     = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
    6809              :                            + bytes_log2);
    6810            0 :   tree fndecl = builtin_decl_explicit (fncode);
    6811            0 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
    6812              :                     fndecl);
    6813            0 :   tree exp = build_call_vec (boolean_type_node, fn, vec);
    6814            0 :   tree lhs = gimple_call_lhs (call);
    6815            0 :   rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
    6816            0 :   if (lhs)
    6817              :     {
    6818            0 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6819            0 :       if (GET_MODE (boolret) != mode)
    6820            0 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6821            0 :       x = force_reg (mode, x);
    6822            0 :       write_complex_part (target, boolret, true, true);
    6823            0 :       write_complex_part (target, x, false, false);
    6824              :     }
    6825            0 : }
    6826              : 
    6827              : /* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function.  */
    6828              : 
    6829              : void
    6830        13898 : expand_ifn_atomic_compare_exchange (gcall *call)
    6831              : {
    6832        13898 :   int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
    6833        13898 :   gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
    6834        13898 :   machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
    6835              : 
    6836        13898 :   memmodel success = get_memmodel (gimple_call_arg (call, 4));
    6837        13898 :   memmodel failure = get_memmodel (gimple_call_arg (call, 5));
    6838              : 
    6839        13898 :   if (failure > success)
    6840            0 :     success = MEMMODEL_SEQ_CST;
    6841              : 
    6842        13898 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6843              :     {
    6844              :       failure = MEMMODEL_SEQ_CST;
    6845              :       success = MEMMODEL_SEQ_CST;
    6846              :     }
    6847              : 
    6848        13898 :   if (!flag_inline_atomics)
    6849              :     {
    6850            0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6851            0 :       return;
    6852              :     }
    6853              : 
    6854              :   /* Expand the operands.  */
    6855        13898 :   rtx mem = get_builtin_sync_mem (gimple_call_arg (call, 0), mode);
    6856              : 
    6857        13898 :   rtx expect = expand_expr_force_mode (gimple_call_arg (call, 1), mode);
    6858        13898 :   rtx desired = expand_expr_force_mode (gimple_call_arg (call, 2), mode);
    6859              : 
    6860        13898 :   bool is_weak = (tree_to_shwi (gimple_call_arg (call, 3)) & 256) != 0;
    6861              : 
    6862        13898 :   rtx boolret = NULL;
    6863        13898 :   rtx oldval = NULL;
    6864              : 
    6865        13898 :   if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
    6866              :                                        is_weak, success, failure))
    6867              :     {
    6868            0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6869            0 :       return;
    6870              :     }
    6871              : 
    6872        13898 :   tree lhs = gimple_call_lhs (call);
    6873        13898 :   if (lhs)
    6874              :     {
    6875        13690 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6876        13690 :       if (GET_MODE (boolret) != mode)
    6877        12242 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6878        13690 :       write_complex_part (target, boolret, true, true);
    6879        13690 :       write_complex_part (target, oldval, false, false);
    6880              :     }
    6881              : }
    6882              : 
    6883              : /* Expand the __atomic_load intrinsic:
    6884              :         TYPE __atomic_load (TYPE *object, enum memmodel)
    6885              :    EXP is the CALL_EXPR.
    6886              :    TARGET is an optional place for us to store the results.  */
    6887              : 
    6888              : static rtx
    6889        70577 : expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
    6890              : {
    6891        70577 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    6892        70577 :   if (is_mm_release (model) || is_mm_acq_rel (model))
    6893              :     model = MEMMODEL_SEQ_CST;
    6894              : 
    6895        70577 :   if (!flag_inline_atomics)
    6896              :     return NULL_RTX;
    6897              : 
    6898              :   /* Expand the operand.  */
    6899        70536 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6900              : 
    6901        70536 :   return expand_atomic_load (target, mem, model);
    6902              : }
    6903              : 
    6904              : 
    6905              : /* Expand the __atomic_store intrinsic:
    6906              :         void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
    6907              :    EXP is the CALL_EXPR.
    6908              :    TARGET is an optional place for us to store the results.  */
    6909              : 
    6910              : static rtx
    6911        17428 : expand_builtin_atomic_store (machine_mode mode, tree exp)
    6912              : {
    6913        17428 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6914        17428 :   if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
    6915         1592 :         || is_mm_release (model)))
    6916              :     model = MEMMODEL_SEQ_CST;
    6917              : 
    6918        17428 :   if (!flag_inline_atomics)
    6919              :     return NULL_RTX;
    6920              : 
    6921              :   /* Expand the operands.  */
    6922        17397 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6923        17397 :   rtx val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6924              : 
    6925        17397 :   return expand_atomic_store (mem, val, model, false);
    6926              : }
    6927              : 
    6928              : /* Expand the __atomic_fetch_XXX intrinsic:
    6929              :         TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
    6930              :    EXP is the CALL_EXPR.
    6931              :    TARGET is an optional place for us to store the results.
    6932              :    CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
    6933              :    FETCH_AFTER is true if returning the result of the operation.
    6934              :    FETCH_AFTER is false if returning the value before the operation.
    6935              :    IGNORE is true if the result is not used.
    6936              :    EXT_CALL is the correct builtin for an external call if this cannot be
    6937              :    resolved to an instruction sequence.  */
    6938              : 
    6939              : static rtx
    6940        28867 : expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
    6941              :                                 enum rtx_code code, bool fetch_after,
    6942              :                                 bool ignore, enum built_in_function ext_call)
    6943              : {
    6944        28867 :   rtx val, mem, ret;
    6945        28867 :   enum memmodel model;
    6946        28867 :   tree fndecl;
    6947        28867 :   tree addr;
    6948              : 
    6949        28867 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6950              : 
    6951              :   /* Expand the operands.  */
    6952        28867 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6953        28867 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6954              : 
    6955              :   /* Only try generating instructions if inlining is turned on.  */
    6956        28867 :   if (flag_inline_atomics)
    6957              :     {
    6958        28324 :       ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
    6959        28324 :       if (ret)
    6960              :         return ret;
    6961              :     }
    6962              : 
    6963              :   /* Return if a different routine isn't needed for the library call.  */
    6964         1142 :   if (ext_call == BUILT_IN_NONE)
    6965              :     return NULL_RTX;
    6966              : 
    6967              :   /* Change the call to the specified function.  */
    6968          279 :   fndecl = get_callee_fndecl (exp);
    6969          279 :   addr = CALL_EXPR_FN (exp);
    6970          279 :   STRIP_NOPS (addr);
    6971              : 
    6972          279 :   gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
    6973          279 :   TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
    6974              : 
    6975              :   /* If we will emit code after the call, the call cannot be a tail call.
    6976              :      If it is emitted as a tail call, a barrier is emitted after it, and
    6977              :      then all trailing code is removed.  */
    6978          279 :   if (!ignore)
    6979          182 :     CALL_EXPR_TAILCALL (exp) = 0;
    6980              : 
    6981              :   /* Expand the call here so we can emit trailing code.  */
    6982          279 :   ret = expand_call (exp, target, ignore);
    6983              : 
    6984              :   /* Replace the original function just in case it matters.  */
    6985          279 :   TREE_OPERAND (addr, 0) = fndecl;
    6986              : 
    6987              :   /* Then issue the arithmetic correction to return the right result.  */
    6988          279 :   if (!ignore)
    6989              :     {
    6990          182 :       if (code == NOT)
    6991              :         {
    6992           31 :           ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
    6993              :                                      OPTAB_LIB_WIDEN);
    6994           31 :           ret = expand_simple_unop (mode, NOT, ret, target, true);
    6995              :         }
    6996              :       else
    6997          151 :         ret = expand_simple_binop (mode, code, ret, val, target, true,
    6998              :                                    OPTAB_LIB_WIDEN);
    6999              :     }
    7000              :   return ret;
    7001              : }
    7002              : 
    7003              : /* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function.  */
    7004              : 
    7005              : void
    7006          427 : expand_ifn_atomic_bit_test_and (gcall *call)
    7007              : {
    7008          427 :   tree ptr = gimple_call_arg (call, 0);
    7009          427 :   tree bit = gimple_call_arg (call, 1);
    7010          427 :   tree flag = gimple_call_arg (call, 2);
    7011          427 :   tree lhs = gimple_call_lhs (call);
    7012          427 :   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
    7013          427 :   machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
    7014          427 :   enum rtx_code code;
    7015          427 :   optab optab;
    7016          427 :   class expand_operand ops[5];
    7017              : 
    7018          427 :   gcc_assert (flag_inline_atomics);
    7019              : 
    7020          427 :   if (gimple_call_num_args (call) == 5)
    7021          296 :     model = get_memmodel (gimple_call_arg (call, 3));
    7022              : 
    7023          427 :   rtx mem = get_builtin_sync_mem (ptr, mode);
    7024          427 :   rtx val = expand_expr_force_mode (bit, mode);
    7025              : 
    7026          427 :   switch (gimple_call_internal_fn (call))
    7027              :     {
    7028              :     case IFN_ATOMIC_BIT_TEST_AND_SET:
    7029              :       code = IOR;
    7030              :       optab = atomic_bit_test_and_set_optab;
    7031              :       break;
    7032              :     case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
    7033              :       code = XOR;
    7034              :       optab = atomic_bit_test_and_complement_optab;
    7035              :       break;
    7036              :     case IFN_ATOMIC_BIT_TEST_AND_RESET:
    7037              :       code = AND;
    7038              :       optab = atomic_bit_test_and_reset_optab;
    7039              :       break;
    7040            0 :     default:
    7041            0 :       gcc_unreachable ();
    7042              :     }
    7043              : 
    7044          427 :   if (lhs == NULL_TREE)
    7045              :     {
    7046            0 :       rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7047              :                                       val, NULL_RTX, true, OPTAB_DIRECT);
    7048            0 :       if (code == AND)
    7049            0 :         val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
    7050            0 :       if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
    7051          427 :         return;
    7052              :     }
    7053              : 
    7054          427 :   rtx target;
    7055          427 :   if (lhs)
    7056          427 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    7057              :   else
    7058            0 :     target = gen_reg_rtx (mode);
    7059          427 :   enum insn_code icode = direct_optab_handler (optab, mode);
    7060          427 :   gcc_assert (icode != CODE_FOR_nothing);
    7061          427 :   create_output_operand (&ops[0], target, mode);
    7062          427 :   create_fixed_operand (&ops[1], mem);
    7063          427 :   create_convert_operand_to (&ops[2], val, mode, true);
    7064          427 :   create_integer_operand (&ops[3], model);
    7065          427 :   create_integer_operand (&ops[4], integer_onep (flag));
    7066          427 :   if (maybe_expand_insn (icode, 5, ops))
    7067              :     return;
    7068              : 
    7069            0 :   rtx bitval = val;
    7070            0 :   val = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7071              :                              val, NULL_RTX, true, OPTAB_DIRECT);
    7072            0 :   rtx maskval = val;
    7073            0 :   if (code == AND)
    7074            0 :     val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
    7075            0 :   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
    7076              :                                        code, model, false);
    7077            0 :   if (!result)
    7078              :     {
    7079            0 :       bool is_atomic = gimple_call_num_args (call) == 5;
    7080            0 :       tree tcall = gimple_call_arg (call, 3 + is_atomic);
    7081            0 :       tree fndecl = gimple_call_addr_fndecl (tcall);
    7082            0 :       tree type = TREE_TYPE (TREE_TYPE (fndecl));
    7083            0 :       tree exp;
    7084            0 :       if (is_atomic)
    7085            0 :         exp = build_call_nary (type, tcall, 3,
    7086              :                                ptr, make_tree (type, val),
    7087              :                                gimple_call_arg (call, 3));
    7088              :       else
    7089            0 :         exp = build_call_nary (type, tcall, 2, ptr, make_tree (type, val));
    7090            0 :       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
    7091              :                                mode, !lhs);
    7092              :     }
    7093            0 :   if (!lhs)
    7094              :     return;
    7095            0 :   if (integer_onep (flag))
    7096              :     {
    7097            0 :       result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
    7098              :                                     NULL_RTX, true, OPTAB_DIRECT);
    7099            0 :       result = expand_simple_binop (mode, AND, result, const1_rtx, target,
    7100              :                                     true, OPTAB_DIRECT);
    7101              :     }
    7102              :   else
    7103            0 :     result = expand_simple_binop (mode, AND, result, maskval, target, true,
    7104              :                                   OPTAB_DIRECT);
    7105            0 :   if (result != target)
    7106            0 :     emit_move_insn (target, result);
    7107              : }
    7108              : 
    7109              : /* Expand IFN_ATOMIC_*_FETCH_CMP_0 internal function.  */
    7110              : 
    7111              : void
    7112         2147 : expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
    7113              : {
    7114         2147 :   tree cmp = gimple_call_arg (call, 0);
    7115         2147 :   tree ptr = gimple_call_arg (call, 1);
    7116         2147 :   tree arg = gimple_call_arg (call, 2);
    7117         2147 :   tree lhs = gimple_call_lhs (call);
    7118         2147 :   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
    7119         2147 :   machine_mode mode = TYPE_MODE (TREE_TYPE (cmp));
    7120         2147 :   optab optab;
    7121         2147 :   rtx_code code;
    7122         2147 :   class expand_operand ops[5];
    7123              : 
    7124         2147 :   gcc_assert (flag_inline_atomics);
    7125              : 
    7126         2147 :   if (gimple_call_num_args (call) == 5)
    7127         1739 :     model = get_memmodel (gimple_call_arg (call, 3));
    7128              : 
    7129         2147 :   rtx mem = get_builtin_sync_mem (ptr, mode);
    7130         2147 :   rtx op = expand_expr_force_mode (arg, mode);
    7131              : 
    7132         2147 :   switch (gimple_call_internal_fn (call))
    7133              :     {
    7134              :     case IFN_ATOMIC_ADD_FETCH_CMP_0:
    7135              :       code = PLUS;
    7136              :       optab = atomic_add_fetch_cmp_0_optab;
    7137              :       break;
    7138              :     case IFN_ATOMIC_SUB_FETCH_CMP_0:
    7139              :       code = MINUS;
    7140              :       optab = atomic_sub_fetch_cmp_0_optab;
    7141              :       break;
    7142              :     case IFN_ATOMIC_AND_FETCH_CMP_0:
    7143              :       code = AND;
    7144              :       optab = atomic_and_fetch_cmp_0_optab;
    7145              :       break;
    7146              :     case IFN_ATOMIC_OR_FETCH_CMP_0:
    7147              :       code = IOR;
    7148              :       optab = atomic_or_fetch_cmp_0_optab;
    7149              :       break;
    7150              :     case IFN_ATOMIC_XOR_FETCH_CMP_0:
    7151              :       code = XOR;
    7152              :       optab = atomic_xor_fetch_cmp_0_optab;
    7153              :       break;
    7154            0 :     default:
    7155            0 :       gcc_unreachable ();
    7156              :     }
    7157              : 
    7158         2147 :   enum rtx_code comp = UNKNOWN;
    7159         2147 :   switch (tree_to_uhwi (cmp))
    7160              :     {
    7161              :     case ATOMIC_OP_FETCH_CMP_0_EQ: comp = EQ; break;
    7162              :     case ATOMIC_OP_FETCH_CMP_0_NE: comp = NE; break;
    7163              :     case ATOMIC_OP_FETCH_CMP_0_GT: comp = GT; break;
    7164              :     case ATOMIC_OP_FETCH_CMP_0_GE: comp = GE; break;
    7165              :     case ATOMIC_OP_FETCH_CMP_0_LT: comp = LT; break;
    7166              :     case ATOMIC_OP_FETCH_CMP_0_LE: comp = LE; break;
    7167            0 :     default: gcc_unreachable ();
    7168              :     }
    7169              : 
    7170         2147 :   rtx target;
    7171         2147 :   if (lhs == NULL_TREE)
    7172            0 :     target = gen_reg_rtx (TYPE_MODE (boolean_type_node));
    7173              :   else
    7174         2147 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    7175         2147 :   enum insn_code icode = direct_optab_handler (optab, mode);
    7176         2147 :   gcc_assert (icode != CODE_FOR_nothing);
    7177         2147 :   create_output_operand (&ops[0], target, TYPE_MODE (boolean_type_node));
    7178         2147 :   create_fixed_operand (&ops[1], mem);
    7179         2147 :   create_convert_operand_to (&ops[2], op, mode, true);
    7180         2147 :   create_integer_operand (&ops[3], model);
    7181         2147 :   create_integer_operand (&ops[4], comp);
    7182         2147 :   if (maybe_expand_insn (icode, 5, ops))
    7183         2115 :     return;
    7184              : 
    7185           32 :   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
    7186              :                                        code, model, true);
    7187           32 :   if (!result)
    7188              :     {
    7189            0 :       bool is_atomic = gimple_call_num_args (call) == 5;
    7190            0 :       tree tcall = gimple_call_arg (call, 3 + is_atomic);
    7191            0 :       tree fndecl = gimple_call_addr_fndecl (tcall);
    7192            0 :       tree type = TREE_TYPE (TREE_TYPE (fndecl));
    7193            0 :       tree exp;
    7194            0 :       if (is_atomic)
    7195            0 :         exp = build_call_nary (type, tcall, 3,
    7196              :                                ptr, arg,
    7197              :                                gimple_call_arg (call, 3));
    7198              :       else
    7199            0 :         exp = build_call_nary (type, tcall, 2, ptr, arg);
    7200            0 :       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
    7201              :                                mode, !lhs);
    7202              :     }
    7203              : 
    7204           32 :   if (lhs)
    7205              :     {
    7206           32 :       result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
    7207              :                                       0, 1);
    7208           32 :       if (result != target)
    7209           32 :         emit_move_insn (target, result);
    7210              :     }
    7211              : }
    7212              : 
    7213              : /* Expand an atomic clear operation.
    7214              :         void _atomic_clear (BOOL *obj, enum memmodel)
    7215              :    EXP is the call expression.  */
    7216              : 
    7217              : static rtx
    7218           53 : expand_builtin_atomic_clear (tree exp)
    7219              : {
    7220           53 :   machine_mode mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7221           53 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7222           53 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7223              : 
    7224           53 :   if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
    7225              :     model = MEMMODEL_SEQ_CST;
    7226              : 
    7227              :   /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
    7228              :      Failing that, a store is issued by __atomic_store.  The only way this can
    7229              :      fail is if the bool type is larger than a word size.  Unlikely, but
    7230              :      handle it anyway for completeness.  Assume a single threaded model since
    7231              :      there is no atomic support in this case, and no barriers are required.  */
    7232           53 :   rtx ret = expand_atomic_store (mem, const0_rtx, model, true);
    7233           53 :   if (!ret)
    7234            0 :     emit_move_insn (mem, const0_rtx);
    7235           53 :   return const0_rtx;
    7236              : }
    7237              : 
    7238              : /* Expand an atomic test_and_set operation.
    7239              :         bool _atomic_test_and_set (BOOL *obj, enum memmodel)
    7240              :    EXP is the call expression.  */
    7241              : 
    7242              : static rtx
    7243          266 : expand_builtin_atomic_test_and_set (tree exp, rtx target)
    7244              : {
    7245          266 :   rtx mem;
    7246          266 :   enum memmodel model;
    7247          266 :   machine_mode mode;
    7248              : 
    7249          266 :   mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7250          266 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7251          266 :   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7252              : 
    7253          266 :   return expand_atomic_test_and_set (target, mem, model);
    7254              : }
    7255              : 
    7256              : 
    7257              : /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
    7258              :    this architecture.  If ARG1 is NULL, use typical alignment for size ARG0.  */
    7259              : 
    7260              : static tree
    7261       143459 : fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
    7262              : {
    7263       143459 :   int size;
    7264       143459 :   machine_mode mode;
    7265       143459 :   unsigned int mode_align, type_align;
    7266              : 
    7267       143459 :   if (TREE_CODE (arg0) != INTEGER_CST)
    7268              :     return NULL_TREE;
    7269              : 
    7270              :   /* We need a corresponding integer mode for the access to be lock-free.  */
    7271       143365 :   size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
    7272       143365 :   if (!int_mode_for_size (size, 0).exists (&mode))
    7273            9 :     return boolean_false_node;
    7274              : 
    7275       143356 :   mode_align = GET_MODE_ALIGNMENT (mode);
    7276              : 
    7277       143356 :   if (TREE_CODE (arg1) == INTEGER_CST)
    7278              :     {
    7279       123858 :       unsigned HOST_WIDE_INT val = UINTVAL (expand_normal (arg1));
    7280              : 
    7281              :       /* Either this argument is null, or it's a fake pointer encoding
    7282              :          the alignment of the object.  */
    7283       123858 :       val = least_bit_hwi (val);
    7284       123858 :       val *= BITS_PER_UNIT;
    7285              : 
    7286       123858 :       if (val == 0 || mode_align < val)
    7287              :         type_align = mode_align;
    7288              :       else
    7289        18900 :         type_align = val;
    7290              :     }
    7291              :   else
    7292              :     {
    7293        19498 :       tree ttype = TREE_TYPE (arg1);
    7294              : 
    7295              :       /* This function is usually invoked and folded immediately by the front
    7296              :          end before anything else has a chance to look at it.  The pointer
    7297              :          parameter at this point is usually cast to a void *, so check for that
    7298              :          and look past the cast.  */
    7299           63 :       if (CONVERT_EXPR_P (arg1)
    7300        19466 :           && POINTER_TYPE_P (ttype)
    7301        19466 :           && VOID_TYPE_P (TREE_TYPE (ttype))
    7302        38964 :           && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
    7303        19435 :         arg1 = TREE_OPERAND (arg1, 0);
    7304              : 
    7305        19498 :       ttype = TREE_TYPE (arg1);
    7306        19498 :       gcc_assert (POINTER_TYPE_P (ttype));
    7307              : 
    7308              :       /* Get the underlying type of the object.  */
    7309        19498 :       ttype = TREE_TYPE (ttype);
    7310        19498 :       type_align = TYPE_ALIGN (ttype);
    7311              :     }
    7312              : 
    7313              :   /* If the object has smaller alignment, the lock free routines cannot
    7314              :      be used.  */
    7315       143356 :   if (type_align < mode_align)
    7316           87 :     return boolean_false_node;
    7317              : 
    7318              :   /* Check if a compare_and_swap pattern exists for the mode which represents
    7319              :      the required size.  The pattern is not allowed to fail, so the existence
    7320              :      of the pattern indicates support is present.  Also require that an
    7321              :      atomic load exists for the required size.  */
    7322       143269 :   if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
    7323       143228 :     return boolean_true_node;
    7324              :   else
    7325           41 :     return boolean_false_node;
    7326              : }
    7327              : 
    7328              : /* Return true if the parameters to call EXP represent an object which will
    7329              :    always generate lock free instructions.  The first argument represents the
    7330              :    size of the object, and the second parameter is a pointer to the object
    7331              :    itself.  If NULL is passed for the object, then the result is based on
    7332              :    typical alignment for an object of the specified size.  Otherwise return
    7333              :    false.  */
    7334              : 
    7335              : static rtx
    7336            1 : expand_builtin_atomic_always_lock_free (tree exp)
    7337              : {
    7338            1 :   tree size;
    7339            1 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7340            1 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7341              : 
    7342            1 :   if (TREE_CODE (arg0) != INTEGER_CST)
    7343              :     {
    7344            1 :       error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
    7345            1 :       return const0_rtx;
    7346              :     }
    7347              : 
    7348            0 :   size = fold_builtin_atomic_always_lock_free (arg0, arg1);
    7349            0 :   if (size == boolean_true_node)
    7350            0 :     return const1_rtx;
    7351            0 :   return const0_rtx;
    7352              : }
    7353              : 
    7354              : /* Return a one or zero if it can be determined that object ARG1 of size ARG
    7355              :    is lock free on this architecture.  */
    7356              : 
    7357              : static tree
    7358        38441 : fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
    7359              : {
    7360        38441 :   if (!flag_inline_atomics)
    7361              :     return NULL_TREE;
    7362              : 
    7363              :   /* If it isn't always lock free, don't generate a result.  */
    7364        38432 :   if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
    7365              :     return boolean_true_node;
    7366              : 
    7367              :   return NULL_TREE;
    7368              : }
    7369              : 
    7370              : /* Return true if the parameters to call EXP represent an object which will
    7371              :    always generate lock free instructions.  The first argument represents the
    7372              :    size of the object, and the second parameter is a pointer to the object
    7373              :    itself.  If NULL is passed for the object, then the result is based on
    7374              :    typical alignment for an object of the specified size.  Otherwise return
    7375              :    NULL*/
    7376              : 
    7377              : static rtx
    7378            3 : expand_builtin_atomic_is_lock_free (tree exp)
    7379              : {
    7380            3 :   tree size;
    7381            3 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7382            3 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7383              : 
    7384            3 :   if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
    7385              :     {
    7386            0 :       error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
    7387            0 :       return NULL_RTX;
    7388              :     }
    7389              : 
    7390            3 :   if (!flag_inline_atomics)
    7391              :     return NULL_RTX;
    7392              : 
    7393              :   /* If the value is known at compile time, return the RTX for it.  */
    7394            2 :   size = fold_builtin_atomic_is_lock_free (arg0, arg1);
    7395            2 :   if (size == boolean_true_node)
    7396            0 :     return const1_rtx;
    7397              : 
    7398              :   return NULL_RTX;
    7399              : }
    7400              : 
    7401              : /* Expand the __atomic_thread_fence intrinsic:
    7402              :         void __atomic_thread_fence (enum memmodel)
    7403              :    EXP is the CALL_EXPR.  */
    7404              : 
    7405              : static void
    7406          693 : expand_builtin_atomic_thread_fence (tree exp)
    7407              : {
    7408          693 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7409          693 :   expand_mem_thread_fence (model);
    7410          693 : }
    7411              : 
    7412              : /* Expand the __atomic_signal_fence intrinsic:
    7413              :         void __atomic_signal_fence (enum memmodel)
    7414              :    EXP is the CALL_EXPR.  */
    7415              : 
    7416              : static void
    7417           60 : expand_builtin_atomic_signal_fence (tree exp)
    7418              : {
    7419           60 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7420           60 :   expand_mem_signal_fence (model);
    7421           60 : }
    7422              : 
    7423              : /* Expand the __sync_synchronize intrinsic.  */
    7424              : 
    7425              : static void
    7426          273 : expand_builtin_sync_synchronize (void)
    7427              : {
    7428            0 :   expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
    7429            0 : }
    7430              : 
    7431              : static rtx
    7432            3 : expand_builtin_thread_pointer (tree exp, rtx target)
    7433              : {
    7434            3 :   enum insn_code icode;
    7435            3 :   if (!validate_arglist (exp, VOID_TYPE))
    7436            0 :     return const0_rtx;
    7437            3 :   icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
    7438            3 :   if (icode != CODE_FOR_nothing)
    7439              :     {
    7440            3 :       class expand_operand op;
    7441              :       /* If the target is not sutitable then create a new target. */
    7442            3 :       if (target == NULL_RTX
    7443            3 :           || !REG_P (target)
    7444            6 :           || GET_MODE (target) != Pmode)
    7445            0 :         target = gen_reg_rtx (Pmode);
    7446            3 :       create_output_operand (&op, target, Pmode);
    7447            3 :       expand_insn (icode, 1, &op);
    7448            3 :       return target;
    7449              :     }
    7450            0 :   error ("%<__builtin_thread_pointer%> is not supported on this target");
    7451            0 :   return const0_rtx;
    7452              : }
    7453              : 
    7454              : static void
    7455            0 : expand_builtin_set_thread_pointer (tree exp)
    7456              : {
    7457            0 :   enum insn_code icode;
    7458            0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    7459              :     return;
    7460            0 :   icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
    7461            0 :   if (icode != CODE_FOR_nothing)
    7462              :     {
    7463            0 :       class expand_operand op;
    7464            0 :       rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
    7465            0 :                              Pmode, EXPAND_NORMAL);
    7466            0 :       create_input_operand (&op, val, Pmode);
    7467            0 :       expand_insn (icode, 1, &op);
    7468            0 :       return;
    7469              :     }
    7470            0 :   error ("%<__builtin_set_thread_pointer%> is not supported on this target");
    7471              : }
    7472              : 
    7473              : 
    7474              : /* Emit code to restore the current value of stack.  */
    7475              : 
    7476              : static void
    7477         1722 : expand_stack_restore (tree var)
    7478              : {
    7479         1722 :   rtx_insn *prev;
    7480         1722 :   rtx sa = expand_normal (var);
    7481              : 
    7482         1722 :   sa = convert_memory_address (Pmode, sa);
    7483              : 
    7484         1722 :   prev = get_last_insn ();
    7485         1722 :   emit_stack_restore (SAVE_BLOCK, sa);
    7486              : 
    7487         1722 :   record_new_stack_level ();
    7488              : 
    7489         1722 :   fixup_args_size_notes (prev, get_last_insn (), 0);
    7490         1722 : }
    7491              : 
    7492              : /* Emit code to save the current value of stack.  */
    7493              : 
    7494              : static rtx
    7495         1823 : expand_stack_save (void)
    7496              : {
    7497         1823 :   rtx ret = NULL_RTX;
    7498              : 
    7499            0 :   emit_stack_save (SAVE_BLOCK, &ret);
    7500         1823 :   return ret;
    7501              : }
    7502              : 
    7503              : /* Emit code to get the openacc gang, worker or vector id or size.  */
    7504              : 
    7505              : static rtx
    7506          356 : expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
    7507              : {
    7508          356 :   const char *name;
    7509          356 :   rtx fallback_retval;
    7510          356 :   rtx_insn *(*gen_fn) (rtx, rtx);
    7511          356 :   switch (DECL_FUNCTION_CODE (get_callee_fndecl (exp)))
    7512              :     {
    7513          244 :     case BUILT_IN_GOACC_PARLEVEL_ID:
    7514          244 :       name = "__builtin_goacc_parlevel_id";
    7515          244 :       fallback_retval = const0_rtx;
    7516          244 :       gen_fn = targetm.gen_oacc_dim_pos;
    7517          244 :       break;
    7518          112 :     case BUILT_IN_GOACC_PARLEVEL_SIZE:
    7519          112 :       name = "__builtin_goacc_parlevel_size";
    7520          112 :       fallback_retval = const1_rtx;
    7521          112 :       gen_fn = targetm.gen_oacc_dim_size;
    7522          112 :       break;
    7523            0 :     default:
    7524            0 :       gcc_unreachable ();
    7525              :     }
    7526              : 
    7527          356 :   if (oacc_get_fn_attrib (current_function_decl) == NULL_TREE)
    7528              :     {
    7529            8 :       error ("%qs only supported in OpenACC code", name);
    7530            8 :       return const0_rtx;
    7531              :     }
    7532              : 
    7533          348 :   tree arg = CALL_EXPR_ARG (exp, 0);
    7534          348 :   if (TREE_CODE (arg) != INTEGER_CST)
    7535              :     {
    7536            8 :       error ("non-constant argument 0 to %qs", name);
    7537            8 :       return const0_rtx;
    7538              :     }
    7539              : 
    7540          340 :   int dim = TREE_INT_CST_LOW (arg);
    7541          340 :   switch (dim)
    7542              :     {
    7543          324 :     case GOMP_DIM_GANG:
    7544          324 :     case GOMP_DIM_WORKER:
    7545          324 :     case GOMP_DIM_VECTOR:
    7546          324 :       break;
    7547           16 :     default:
    7548           16 :       error ("illegal argument 0 to %qs", name);
    7549           16 :       return const0_rtx;
    7550              :     }
    7551              : 
    7552          324 :   if (ignore)
    7553              :     return target;
    7554              : 
    7555          180 :   if (target == NULL_RTX)
    7556            0 :     target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    7557              : 
    7558          180 :   if (!targetm.have_oacc_dim_size ())
    7559              :     {
    7560          180 :       emit_move_insn (target, fallback_retval);
    7561          180 :       return target;
    7562              :     }
    7563              : 
    7564            0 :   rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
    7565            0 :   emit_insn (gen_fn (reg, GEN_INT (dim)));
    7566            0 :   if (reg != target)
    7567            0 :     emit_move_insn (target, reg);
    7568              : 
    7569              :   return target;
    7570              : }
    7571              : 
    7572              : /* Expand a string compare operation using a sequence of char comparison
    7573              :    to get rid of the calling overhead, with result going to TARGET if
    7574              :    that's convenient.
    7575              : 
    7576              :    VAR_STR is the variable string source;
    7577              :    CONST_STR is the constant string source;
    7578              :    LENGTH is the number of chars to compare;
    7579              :    CONST_STR_N indicates which source string is the constant string;
    7580              :    IS_MEMCMP indicates whether it's a memcmp or strcmp.
    7581              : 
    7582              :    to: (assume const_str_n is 2, i.e., arg2 is a constant string)
    7583              : 
    7584              :    target = (int) (unsigned char) var_str[0]
    7585              :             - (int) (unsigned char) const_str[0];
    7586              :    if (target != 0)
    7587              :      goto ne_label;
    7588              :      ...
    7589              :    target = (int) (unsigned char) var_str[length - 2]
    7590              :             - (int) (unsigned char) const_str[length - 2];
    7591              :    if (target != 0)
    7592              :      goto ne_label;
    7593              :    target = (int) (unsigned char) var_str[length - 1]
    7594              :             - (int) (unsigned char) const_str[length - 1];
    7595              :    ne_label:
    7596              :   */
    7597              : 
    7598              : static rtx
    7599          635 : inline_string_cmp (rtx target, tree var_str, const char *const_str,
    7600              :                    unsigned HOST_WIDE_INT length,
    7601              :                    int const_str_n, machine_mode mode)
    7602              : {
    7603          635 :   HOST_WIDE_INT offset = 0;
    7604          635 :   rtx var_rtx_array
    7605          635 :     = get_memory_rtx (var_str, build_int_cst (unsigned_type_node,length));
    7606          635 :   rtx var_rtx = NULL_RTX;
    7607          635 :   rtx const_rtx = NULL_RTX;
    7608          635 :   rtx result = target ? target : gen_reg_rtx (mode);
    7609          635 :   rtx_code_label *ne_label = gen_label_rtx ();
    7610          635 :   tree unit_type_node = unsigned_char_type_node;
    7611          635 :   scalar_int_mode unit_mode
    7612          635 :     = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
    7613              : 
    7614          635 :   start_sequence ();
    7615              : 
    7616         2329 :   for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
    7617              :     {
    7618         1694 :       var_rtx
    7619         1694 :         = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
    7620         1694 :       const_rtx = c_readstr (const_str + offset, unit_mode);
    7621         1694 :       rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
    7622         1544 :       rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
    7623              : 
    7624         1694 :       op0 = convert_modes (mode, unit_mode, op0, 1);
    7625         1694 :       op1 = convert_modes (mode, unit_mode, op1, 1);
    7626         1694 :       rtx diff = expand_simple_binop (mode, MINUS, op0, op1,
    7627              :                                       result, 1, OPTAB_WIDEN);
    7628              : 
    7629              :       /* Force the difference into result register.  We cannot reassign
    7630              :          result here ("result = diff") or we may end up returning
    7631              :          uninitialized result when expand_simple_binop allocates a new
    7632              :          pseudo-register for returning.  */
    7633         1694 :       if (diff != result)
    7634            0 :         emit_move_insn (result, diff);
    7635              : 
    7636         1694 :       if (i < length - 1)
    7637         1059 :         emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
    7638              :                                  mode, true, ne_label);
    7639         3388 :       offset += GET_MODE_SIZE (unit_mode);
    7640              :     }
    7641              : 
    7642          635 :   emit_label (ne_label);
    7643          635 :   rtx_insn *insns = end_sequence ();
    7644          635 :   emit_insn (insns);
    7645              : 
    7646          635 :   return result;
    7647              : }
    7648              : 
    7649              : /* Inline expansion of a call to str(n)cmp and memcmp, with result going
    7650              :    to TARGET if that's convenient.
    7651              :    If the call is not been inlined, return NULL_RTX.  */
    7652              : 
    7653              : static rtx
    7654       144851 : inline_expand_builtin_bytecmp (tree exp, rtx target)
    7655              : {
    7656       144851 :   tree fndecl = get_callee_fndecl (exp);
    7657       144851 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7658       144851 :   bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
    7659              : 
    7660              :   /* Do NOT apply this inlining expansion when optimizing for size or
    7661              :      optimization level below 2 or if unused *cmp hasn't been DCEd.  */
    7662       144851 :   if (optimize < 2 || optimize_insn_for_size_p () || target == const0_rtx)
    7663       122120 :     return NULL_RTX;
    7664              : 
    7665        22731 :   gcc_checking_assert (fcode == BUILT_IN_STRCMP
    7666              :                        || fcode == BUILT_IN_STRNCMP
    7667              :                        || fcode == BUILT_IN_MEMCMP);
    7668              : 
    7669              :   /* On a target where the type of the call (int) has same or narrower precision
    7670              :      than unsigned char, give up the inlining expansion.  */
    7671        22731 :   if (TYPE_PRECISION (unsigned_char_type_node)
    7672        22731 :       >= TYPE_PRECISION (TREE_TYPE (exp)))
    7673              :     return NULL_RTX;
    7674              : 
    7675        22731 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    7676        22731 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    7677        22731 :   tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
    7678              : 
    7679        22731 :   unsigned HOST_WIDE_INT len1 = 0;
    7680        22731 :   unsigned HOST_WIDE_INT len2 = 0;
    7681        22731 :   unsigned HOST_WIDE_INT len3 = 0;
    7682              : 
    7683              :   /* Get the object representation of the initializers of ARG1 and ARG2
    7684              :      as strings, provided they refer to constant objects, with their byte
    7685              :      sizes in LEN1 and LEN2, respectively.  */
    7686        22731 :   const char *bytes1 = getbyterep (arg1, &len1);
    7687        22731 :   const char *bytes2 = getbyterep (arg2, &len2);
    7688              : 
    7689              :   /* Fail if neither argument refers to an initialized constant.  */
    7690        22731 :   if (!bytes1 && !bytes2)
    7691              :     return NULL_RTX;
    7692              : 
    7693        18500 :   if (is_ncmp)
    7694              :     {
    7695              :       /* Fail if the memcmp/strncmp bound is not a constant.  */
    7696         1386 :       if (!tree_fits_uhwi_p (len3_tree))
    7697              :         return NULL_RTX;
    7698              : 
    7699          966 :       len3 = tree_to_uhwi (len3_tree);
    7700              : 
    7701          966 :       if (fcode == BUILT_IN_MEMCMP)
    7702              :         {
    7703              :           /* Fail if the memcmp bound is greater than the size of either
    7704              :              of the two constant objects.  */
    7705          462 :           if ((bytes1 && len1 < len3)
    7706          462 :               || (bytes2 && len2 < len3))
    7707              :             return NULL_RTX;
    7708              :         }
    7709              :     }
    7710              : 
    7711              :   if (fcode != BUILT_IN_MEMCMP)
    7712              :     {
    7713              :       /* For string functions (i.e., strcmp and strncmp) reduce LEN1
    7714              :          and LEN2 to the length of the nul-terminated string stored
    7715              :          in each.  */
    7716        17618 :       if (bytes1 != NULL)
    7717          240 :         len1 = strnlen (bytes1, len1) + 1;
    7718        17618 :       if (bytes2 != NULL)
    7719        17381 :         len2 = strnlen (bytes2, len2) + 1;
    7720              :     }
    7721              : 
    7722              :   /* See inline_string_cmp.  */
    7723        18076 :   int const_str_n;
    7724        18076 :   if (!len1)
    7725              :     const_str_n = 2;
    7726          245 :   else if (!len2)
    7727              :     const_str_n = 1;
    7728            3 :   else if (len2 > len1)
    7729              :     const_str_n = 1;
    7730              :   else
    7731              :     const_str_n = 2;
    7732              : 
    7733              :   /* For strncmp only, compute the new bound as the smallest of
    7734              :      the lengths of the two strings (plus 1) and the bound provided
    7735              :      to the function.  */
    7736        17833 :   unsigned HOST_WIDE_INT bound = (const_str_n == 1) ? len1 : len2;
    7737        18076 :   if (is_ncmp && len3 < bound)
    7738          538 :     bound = len3;
    7739              : 
    7740              :   /* If the bound of the comparison is larger than the threshold,
    7741              :      do nothing.  */
    7742        18076 :   if (bound > (unsigned HOST_WIDE_INT) param_builtin_string_cmp_inline_length)
    7743              :     return NULL_RTX;
    7744              : 
    7745          635 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    7746              : 
    7747              :   /* Now, start inline expansion the call.  */
    7748         1213 :   return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
    7749              :                             (const_str_n == 1) ? bytes1 : bytes2, bound,
    7750          635 :                             const_str_n, mode);
    7751              : }
    7752              : 
    7753              : /* Expand a call to __builtin_speculation_safe_value_<N>.  MODE
    7754              :    represents the size of the first argument to that call, or VOIDmode
    7755              :    if the argument is a pointer.  IGNORE will be true if the result
    7756              :    isn't used.  */
    7757              : static rtx
    7758           35 : expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
    7759              :                                bool ignore)
    7760              : {
    7761           35 :   rtx val, failsafe;
    7762           35 :   unsigned nargs = call_expr_nargs (exp);
    7763              : 
    7764           35 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7765              : 
    7766           35 :   if (mode == VOIDmode)
    7767              :     {
    7768            4 :       mode = TYPE_MODE (TREE_TYPE (arg0));
    7769            4 :       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
    7770              :     }
    7771              : 
    7772           35 :   val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    7773              : 
    7774              :   /* An optional second argument can be used as a failsafe value on
    7775              :      some machines.  If it isn't present, then the failsafe value is
    7776              :      assumed to be 0.  */
    7777           35 :   if (nargs > 1)
    7778              :     {
    7779            4 :       tree arg1 = CALL_EXPR_ARG (exp, 1);
    7780            4 :       failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
    7781              :     }
    7782              :   else
    7783           31 :     failsafe = const0_rtx;
    7784              : 
    7785              :   /* If the result isn't used, the behavior is undefined.  It would be
    7786              :      nice to emit a warning here, but path splitting means this might
    7787              :      happen with legitimate code.  So simply drop the builtin
    7788              :      expansion in that case; we've handled any side-effects above.  */
    7789           35 :   if (ignore)
    7790            0 :     return const0_rtx;
    7791              : 
    7792              :   /* If we don't have a suitable target, create one to hold the result.  */
    7793           35 :   if (target == NULL || GET_MODE (target) != mode)
    7794            0 :     target = gen_reg_rtx (mode);
    7795              : 
    7796           35 :   if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
    7797            0 :     val = convert_modes (mode, VOIDmode, val, false);
    7798              : 
    7799           35 :   return targetm.speculation_safe_value (mode, target, val, failsafe);
    7800              : }
    7801              : 
    7802              : /* Expand CRC* or REV_CRC* built-ins.  */
    7803              : 
    7804              : rtx
    7805           36 : expand_builtin_crc_table_based (internal_fn fn, scalar_mode crc_mode,
    7806              :                                 scalar_mode data_mode, machine_mode mode,
    7807              :                                 tree exp, rtx target)
    7808              : {
    7809           36 :   tree rhs1 = CALL_EXPR_ARG (exp, 0); // crc
    7810           36 :   tree rhs2 = CALL_EXPR_ARG (exp, 1); // data
    7811           36 :   tree rhs3 = CALL_EXPR_ARG (exp, 2); // polynomial
    7812              : 
    7813           36 :   if (!target || mode == VOIDmode)
    7814            0 :     target = gen_reg_rtx (crc_mode);
    7815              : 
    7816           36 :   rtx op1 = expand_normal (rhs1);
    7817           36 :   rtx op2 = expand_normal (rhs2);
    7818           36 :   rtx op3;
    7819           36 :   if (TREE_CODE (rhs3) != INTEGER_CST)
    7820              :     {
    7821            1 :       error ("third argument to %<crc%> builtins must be a constant");
    7822            1 :       op3 = const0_rtx;
    7823              :     }
    7824              :   else
    7825           35 :     op3 = convert_to_mode (crc_mode, expand_normal (rhs3), 0);
    7826              : 
    7827           36 :   if (CONST_INT_P (op2))
    7828           35 :     op2 = convert_to_mode (crc_mode, op2, 0);
    7829              : 
    7830           36 :   if (fn == IFN_CRC)
    7831           19 :     expand_crc_table_based (target, op1, op2, op3, data_mode);
    7832              :   else
    7833              :     /* If it's IFN_CRC_REV generate bit-reversed CRC.  */
    7834           17 :     expand_reversed_crc_table_based (target, op1, op2, op3,
    7835              :                                      data_mode);
    7836           36 :   return target;
    7837              : }
    7838              : 
    7839              : /* Expand an expression EXP that calls a built-in function,
    7840              :    with result going to TARGET if that's convenient
    7841              :    (and in mode MODE if that's convenient).
    7842              :    SUBTARGET may be used as the target for computing one of EXP's operands.
    7843              :    IGNORE is nonzero if the value is to be ignored.  */
    7844              : 
    7845              : rtx
    7846      2003033 : expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
    7847              :                 int ignore)
    7848              : {
    7849      2003033 :   tree fndecl = get_callee_fndecl (exp);
    7850      2003033 :   machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
    7851      2003033 :   int flags;
    7852              : 
    7853      2003033 :   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
    7854       175629 :     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
    7855              : 
    7856              :   /* When ASan is enabled, we don't want to expand some memory/string
    7857              :      builtins and rely on libsanitizer's hooks.  This allows us to avoid
    7858              :      redundant checks and be sure, that possible overflow will be detected
    7859              :      by ASan.  */
    7860              : 
    7861      1827404 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7862      1827404 :   if (param_asan_kernel_mem_intrinsic_prefix
    7863      1827404 :       && sanitize_flags_p (SANITIZE_KERNEL_ADDRESS
    7864              :                            | SANITIZE_KERNEL_HWADDRESS))
    7865           42 :     switch (fcode)
    7866              :       {
    7867           42 :         rtx save_decl_rtl, ret;
    7868           42 :       case BUILT_IN_MEMCPY:
    7869           42 :       case BUILT_IN_MEMMOVE:
    7870           42 :       case BUILT_IN_MEMSET:
    7871           42 :         save_decl_rtl = DECL_RTL (fndecl);
    7872           42 :         DECL_RTL (fndecl) = asan_memfn_rtl (fndecl);
    7873           42 :         ret = expand_call (exp, target, ignore);
    7874           42 :         DECL_RTL (fndecl) = save_decl_rtl;
    7875           42 :         return ret;
    7876              :       default:
    7877              :         break;
    7878              :       }
    7879      1827362 :   if (sanitize_flags_p (SANITIZE_ADDRESS | SANITIZE_HWADDRESS)
    7880      1827362 :                   && asan_intercepted_p (fcode))
    7881          938 :     return expand_call (exp, target, ignore);
    7882              : 
    7883              :   /* When not optimizing, generate calls to library functions for a certain
    7884              :      set of builtins.  */
    7885      1826424 :   if (!optimize
    7886       427781 :       && !called_as_built_in (fndecl)
    7887       145895 :       && fcode != BUILT_IN_FORK
    7888       145895 :       && fcode != BUILT_IN_EXECL
    7889       145882 :       && fcode != BUILT_IN_EXECV
    7890       145882 :       && fcode != BUILT_IN_EXECLP
    7891       145880 :       && fcode != BUILT_IN_EXECLE
    7892       145880 :       && fcode != BUILT_IN_EXECVP
    7893       145879 :       && fcode != BUILT_IN_EXECVE
    7894       145879 :       && fcode != BUILT_IN_CLEAR_CACHE
    7895       145876 :       && !ALLOCA_FUNCTION_CODE_P (fcode)
    7896       145822 :       && fcode != BUILT_IN_FREE
    7897       143682 :       && (fcode != BUILT_IN_MEMSET
    7898        55896 :           || !(flag_inline_stringops & ILSOP_MEMSET))
    7899       143679 :       && (fcode != BUILT_IN_MEMCPY
    7900          918 :           || !(flag_inline_stringops & ILSOP_MEMCPY))
    7901       143543 :       && (fcode != BUILT_IN_MEMMOVE
    7902          348 :           || !(flag_inline_stringops & ILSOP_MEMMOVE))
    7903      1969967 :       && (fcode != BUILT_IN_MEMCMP
    7904         2529 :           || !(flag_inline_stringops & ILSOP_MEMCMP)))
    7905       143495 :     return expand_call (exp, target, ignore);
    7906              : 
    7907              :   /* The built-in function expanders test for target == const0_rtx
    7908              :      to determine whether the function's result will be ignored.  */
    7909      1682929 :   if (ignore)
    7910       995561 :     target = const0_rtx;
    7911              : 
    7912              :   /* If the result of a pure or const built-in function is ignored, and
    7913              :      none of its arguments are volatile, we can avoid expanding the
    7914              :      built-in call and just evaluate the arguments for side-effects.  */
    7915      1682929 :   if (target == const0_rtx
    7916       995561 :       && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
    7917      1686557 :       && !(flags & ECF_LOOPING_CONST_OR_PURE))
    7918              :     {
    7919            6 :       bool volatilep = false;
    7920            6 :       tree arg;
    7921            6 :       call_expr_arg_iterator iter;
    7922              : 
    7923           20 :       FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
    7924            8 :         if (TREE_THIS_VOLATILE (arg))
    7925              :           {
    7926              :             volatilep = true;
    7927              :             break;
    7928              :           }
    7929              : 
    7930            6 :       if (! volatilep)
    7931              :         {
    7932           20 :           FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
    7933            8 :             expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
    7934            6 :           return const0_rtx;
    7935              :         }
    7936              :     }
    7937              : 
    7938      1682923 :   switch (fcode)
    7939              :     {
    7940            4 :     CASE_FLT_FN (BUILT_IN_FABS):
    7941            4 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
    7942            4 :     case BUILT_IN_FABSD32:
    7943            4 :     case BUILT_IN_FABSD64:
    7944            4 :     case BUILT_IN_FABSD128:
    7945            4 :     case BUILT_IN_FABSD64X:
    7946            4 :       target = expand_builtin_fabs (exp, target, subtarget);
    7947            4 :       if (target)
    7948       838144 :         return target;
    7949       844779 :       break;
    7950              : 
    7951        11677 :     CASE_FLT_FN (BUILT_IN_COPYSIGN):
    7952        11677 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
    7953        11677 :       target = expand_builtin_copysign (exp, target, subtarget);
    7954        11677 :       if (target)
    7955              :         return target;
    7956              :       break;
    7957              : 
    7958              :       /* Just do a normal library call if we were unable to fold
    7959              :          the values.  */
    7960              :     CASE_FLT_FN (BUILT_IN_CABS):
    7961              :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_CABS):
    7962              :       break;
    7963              : 
    7964          368 :     CASE_FLT_FN (BUILT_IN_FMA):
    7965          368 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
    7966          368 :       target = expand_builtin_mathfn_ternary (exp, target, subtarget);
    7967          368 :       if (target)
    7968              :         return target;
    7969              :       break;
    7970              : 
    7971          232 :     CASE_FLT_FN (BUILT_IN_ILOGB):
    7972          232 :       if (! flag_unsafe_math_optimizations)
    7973              :         break;
    7974            4 :       gcc_fallthrough ();
    7975            4 :     CASE_FLT_FN (BUILT_IN_ISINF):
    7976            4 :     CASE_FLT_FN (BUILT_IN_FINITE):
    7977            4 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    7978            4 :     case BUILT_IN_ISFINITE:
    7979            4 :     case BUILT_IN_ISNORMAL:
    7980            4 :       target = expand_builtin_interclass_mathfn (exp, target);
    7981            4 :       if (target)
    7982              :         return target;
    7983              :       break;
    7984              : 
    7985          784 :     case BUILT_IN_ISSIGNALING:
    7986          784 :       target = expand_builtin_issignaling (exp, target);
    7987          784 :       if (target)
    7988              :         return target;
    7989              :       break;
    7990              : 
    7991          223 :     CASE_FLT_FN (BUILT_IN_ICEIL):
    7992          223 :     CASE_FLT_FN (BUILT_IN_LCEIL):
    7993          223 :     CASE_FLT_FN (BUILT_IN_LLCEIL):
    7994          223 :     CASE_FLT_FN (BUILT_IN_LFLOOR):
    7995          223 :     CASE_FLT_FN (BUILT_IN_IFLOOR):
    7996          223 :     CASE_FLT_FN (BUILT_IN_LLFLOOR):
    7997          223 :       target = expand_builtin_int_roundingfn (exp, target);
    7998          223 :       if (target)
    7999              :         return target;
    8000              :       break;
    8001              : 
    8002          588 :     CASE_FLT_FN (BUILT_IN_IRINT):
    8003          588 :     CASE_FLT_FN (BUILT_IN_LRINT):
    8004          588 :     CASE_FLT_FN (BUILT_IN_LLRINT):
    8005          588 :     CASE_FLT_FN (BUILT_IN_IROUND):
    8006          588 :     CASE_FLT_FN (BUILT_IN_LROUND):
    8007          588 :     CASE_FLT_FN (BUILT_IN_LLROUND):
    8008          588 :       target = expand_builtin_int_roundingfn_2 (exp, target);
    8009          588 :       if (target)
    8010              :         return target;
    8011              :       break;
    8012              : 
    8013          291 :     CASE_FLT_FN (BUILT_IN_POWI):
    8014          291 :       target = expand_builtin_powi (exp, target);
    8015          291 :       if (target)
    8016              :         return target;
    8017              :       break;
    8018              : 
    8019          170 :     CASE_FLT_FN (BUILT_IN_CEXPI):
    8020          170 :       target = expand_builtin_cexpi (exp, target);
    8021          170 :       gcc_assert (target);
    8022              :       return target;
    8023              : 
    8024         1017 :     CASE_FLT_FN (BUILT_IN_SIN):
    8025         1017 :     CASE_FLT_FN (BUILT_IN_COS):
    8026         1017 :       if (! flag_unsafe_math_optimizations)
    8027              :         break;
    8028           47 :       target = expand_builtin_mathfn_3 (exp, target, subtarget);
    8029           47 :       if (target)
    8030              :         return target;
    8031              :       break;
    8032              : 
    8033          164 :     CASE_FLT_FN (BUILT_IN_SINCOS):
    8034          164 :       if (! flag_unsafe_math_optimizations)
    8035              :         break;
    8036            3 :       target = expand_builtin_sincos (exp);
    8037            3 :       if (target)
    8038              :         return target;
    8039              :       break;
    8040              : 
    8041           60 :     case BUILT_IN_FEGETROUND:
    8042           60 :       target = expand_builtin_fegetround (exp, target, target_mode);
    8043           60 :       if (target)
    8044              :         return target;
    8045              :       break;
    8046              : 
    8047         1063 :     case BUILT_IN_FECLEAREXCEPT:
    8048         1063 :       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
    8049              :                                                       feclearexcept_optab);
    8050         1063 :       if (target)
    8051              :         return target;
    8052              :       break;
    8053              : 
    8054          831 :     case BUILT_IN_FERAISEEXCEPT:
    8055          831 :       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
    8056              :                                                       feraiseexcept_optab);
    8057          831 :       if (target)
    8058              :         return target;
    8059              :       break;
    8060              : 
    8061          464 :     case BUILT_IN_APPLY_ARGS:
    8062          464 :       return expand_builtin_apply_args ();
    8063              : 
    8064              :       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
    8065              :          FUNCTION with a copy of the parameters described by
    8066              :          ARGUMENTS, and ARGSIZE.  It returns a block of memory
    8067              :          allocated on the stack into which is stored all the registers
    8068              :          that might possibly be used for returning the result of a
    8069              :          function.  ARGUMENTS is the value returned by
    8070              :          __builtin_apply_args.  ARGSIZE is the number of bytes of
    8071              :          arguments that must be copied.  ??? How should this value be
    8072              :          computed?  We'll also need a safe worst case value for varargs
    8073              :          functions.  */
    8074          483 :     case BUILT_IN_APPLY:
    8075          483 :       if (!validate_arglist (exp, POINTER_TYPE,
    8076              :                              POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
    8077          483 :           && !validate_arglist (exp, REFERENCE_TYPE,
    8078              :                                 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    8079            0 :         return const0_rtx;
    8080              :       else
    8081              :         {
    8082          483 :           rtx ops[3];
    8083              : 
    8084          483 :           ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
    8085          483 :           ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
    8086          483 :           ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
    8087              : 
    8088          483 :           return expand_builtin_apply (ops[0], ops[1], ops[2]);
    8089              :         }
    8090              : 
    8091              :       /* __builtin_return (RESULT) causes the function to return the
    8092              :          value described by RESULT.  RESULT is address of the block of
    8093              :          memory returned by __builtin_apply.  */
    8094          379 :     case BUILT_IN_RETURN:
    8095          379 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8096          379 :         expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
    8097          379 :       return const0_rtx;
    8098              : 
    8099            0 :     case BUILT_IN_CALL_CODE_ADDRESS:
    8100              :       /* All valid uses of __builtin_call_code_address () are removed in
    8101              :          in tree-nested.cc or gimple-fold.cc.  */
    8102            0 :       error ("argument to %<__builtin_call_code_address%> must be a function");
    8103            0 :       return const0_rtx;
    8104              : 
    8105            0 :     case BUILT_IN_CALL_STATIC_CHAIN:
    8106              :        /* All valid uses of __builtin_call_static_chain () are removed in
    8107              :           in tree-nested.cc or gimple-fold.cc.  */
    8108            0 :       error ("argument to %<__builtin_call_static_chain%> must be a function");
    8109            0 :       return const0_rtx;
    8110              : 
    8111            0 :     case BUILT_IN_SAVEREGS:
    8112            0 :       return expand_builtin_saveregs ();
    8113              : 
    8114           16 :     case BUILT_IN_VA_ARG_PACK:
    8115              :       /* All valid uses of __builtin_va_arg_pack () are removed during
    8116              :          inlining.  */
    8117           16 :       error ("invalid use of %<__builtin_va_arg_pack ()%>");
    8118           16 :       return const0_rtx;
    8119              : 
    8120            0 :     case BUILT_IN_VA_ARG_PACK_LEN:
    8121              :       /* All valid uses of __builtin_va_arg_pack_len () are removed during
    8122              :          inlining.  */
    8123            0 :       error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
    8124            0 :       return const0_rtx;
    8125              : 
    8126              :       /* Return the address of the first anonymous stack arg.  */
    8127          158 :     case BUILT_IN_NEXT_ARG:
    8128          158 :       if (fold_builtin_next_arg (exp, false))
    8129            0 :         return const0_rtx;
    8130          158 :       return expand_builtin_next_arg ();
    8131              : 
    8132           28 :     case BUILT_IN_CLEAR_CACHE:
    8133           28 :       expand_builtin___clear_cache (exp);
    8134           28 :       return const0_rtx;
    8135              : 
    8136            0 :     case BUILT_IN_CLASSIFY_TYPE:
    8137            0 :       return expand_builtin_classify_type (exp);
    8138              : 
    8139            0 :     case BUILT_IN_CONSTANT_P:
    8140            0 :       return const0_rtx;
    8141              : 
    8142        15922 :     case BUILT_IN_FRAME_ADDRESS:
    8143        15922 :     case BUILT_IN_RETURN_ADDRESS:
    8144        15922 :       return expand_builtin_frame_address (fndecl, exp);
    8145              : 
    8146          540 :     case BUILT_IN_STACK_ADDRESS:
    8147          540 :       return expand_builtin_stack_address ();
    8148              : 
    8149         2160 :     case BUILT_IN___STRUB_ENTER:
    8150         2160 :       target = expand_builtin_strub_enter (exp);
    8151         2160 :       if (target)
    8152              :         return target;
    8153              :       break;
    8154              : 
    8155         1073 :     case BUILT_IN___STRUB_UPDATE:
    8156         1073 :       target = expand_builtin_strub_update (exp);
    8157         1073 :       if (target)
    8158              :         return target;
    8159              :       break;
    8160              : 
    8161         2730 :     case BUILT_IN___STRUB_LEAVE:
    8162         2730 :       target = expand_builtin_strub_leave (exp);
    8163         2730 :       if (target)
    8164              :         return target;
    8165              :       break;
    8166              : 
    8167              :     /* Returns the address of the area where the structure is returned.
    8168              :        0 otherwise.  */
    8169            0 :     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
    8170            0 :       if (call_expr_nargs (exp) != 0
    8171            0 :           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
    8172            0 :           || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
    8173            0 :         return const0_rtx;
    8174              :       else
    8175            0 :         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
    8176              : 
    8177        27779 :     CASE_BUILT_IN_ALLOCA:
    8178        27779 :       target = expand_builtin_alloca (exp);
    8179        27779 :       if (target)
    8180              :         return target;
    8181              :       break;
    8182              : 
    8183          204 :     case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
    8184          204 :       return expand_asan_emit_allocas_unpoison (exp);
    8185              : 
    8186         1823 :     case BUILT_IN_STACK_SAVE:
    8187         1823 :       return expand_stack_save ();
    8188              : 
    8189         1722 :     case BUILT_IN_STACK_RESTORE:
    8190         1722 :       expand_stack_restore (CALL_EXPR_ARG (exp, 0));
    8191         1722 :       return const0_rtx;
    8192              : 
    8193         1278 :     case BUILT_IN_BSWAP16:
    8194         1278 :     case BUILT_IN_BSWAP32:
    8195         1278 :     case BUILT_IN_BSWAP64:
    8196         1278 :     case BUILT_IN_BSWAP128:
    8197         1278 :       target = expand_builtin_bswap (target_mode, exp, target, subtarget);
    8198         1278 :       if (target)
    8199              :         return target;
    8200              :       break;
    8201              : 
    8202           49 :     case BUILT_IN_BITREVERSE8:
    8203           49 :     case BUILT_IN_BITREVERSE16:
    8204           49 :     case BUILT_IN_BITREVERSE32:
    8205           49 :     case BUILT_IN_BITREVERSE64:
    8206           49 :     case BUILT_IN_BITREVERSE128:
    8207           49 :       target = expand_builtin_unop (target_mode, exp, target, subtarget,
    8208              :                                     bitreverse_optab);
    8209           49 :       if (target)
    8210              :         return target;
    8211              :       break;
    8212              : 
    8213            0 :     CASE_INT_FN (BUILT_IN_FFS):
    8214            0 :       target = expand_builtin_unop (target_mode, exp, target,
    8215              :                                     subtarget, ffs_optab);
    8216            0 :       if (target)
    8217              :         return target;
    8218              :       break;
    8219              : 
    8220          201 :     CASE_INT_FN (BUILT_IN_CLZ):
    8221          201 :       target = expand_builtin_unop (target_mode, exp, target,
    8222              :                                     subtarget, clz_optab);
    8223          201 :       if (target)
    8224              :         return target;
    8225              :       break;
    8226              : 
    8227           50 :     CASE_INT_FN (BUILT_IN_CTZ):
    8228           50 :       target = expand_builtin_unop (target_mode, exp, target,
    8229              :                                     subtarget, ctz_optab);
    8230           50 :       if (target)
    8231              :         return target;
    8232              :       break;
    8233              : 
    8234           91 :     CASE_INT_FN (BUILT_IN_CLRSB):
    8235           91 :       target = expand_builtin_unop (target_mode, exp, target,
    8236              :                                     subtarget, clrsb_optab);
    8237           91 :       if (target)
    8238              :         return target;
    8239              :       break;
    8240              : 
    8241          432 :     CASE_INT_FN (BUILT_IN_POPCOUNT):
    8242          432 :       target = expand_builtin_unop (target_mode, exp, target,
    8243              :                                     subtarget, popcount_optab);
    8244          432 :       if (target)
    8245              :         return target;
    8246              :       break;
    8247              : 
    8248           11 :     CASE_INT_FN (BUILT_IN_PARITY):
    8249           11 :       target = expand_builtin_unop (target_mode, exp, target,
    8250              :                                     subtarget, parity_optab);
    8251           11 :       if (target)
    8252              :         return target;
    8253              :       break;
    8254              : 
    8255        14758 :     case BUILT_IN_STRLEN:
    8256        14758 :       target = expand_builtin_strlen (exp, target, target_mode);
    8257        14758 :       if (target)
    8258              :         return target;
    8259              :       break;
    8260              : 
    8261          645 :     case BUILT_IN_STRNLEN:
    8262          645 :       target = expand_builtin_strnlen (exp, target, target_mode);
    8263          645 :       if (target)
    8264              :         return target;
    8265              :       break;
    8266              : 
    8267         1860 :     case BUILT_IN_STRCPY:
    8268         1860 :       target = expand_builtin_strcpy (exp, target);
    8269         1860 :       if (target)
    8270              :         return target;
    8271              :       break;
    8272              : 
    8273         2177 :     case BUILT_IN_STRNCPY:
    8274         2177 :       target = expand_builtin_strncpy (exp, target);
    8275         2177 :       if (target)
    8276              :         return target;
    8277              :       break;
    8278              : 
    8279          454 :     case BUILT_IN_STPCPY:
    8280          454 :       target = expand_builtin_stpcpy (exp, target, mode);
    8281          454 :       if (target)
    8282              :         return target;
    8283              :       break;
    8284              : 
    8285       107852 :     case BUILT_IN_MEMCPY:
    8286       107852 :       target = expand_builtin_memcpy (exp, target);
    8287       107852 :       if (target)
    8288              :         return target;
    8289              :       break;
    8290              : 
    8291        17198 :     case BUILT_IN_MEMMOVE:
    8292        17198 :       target = expand_builtin_memmove (exp, target);
    8293        17198 :       if (target)
    8294              :         return target;
    8295              :       break;
    8296              : 
    8297         1394 :     case BUILT_IN_MEMPCPY:
    8298         1394 :       target = expand_builtin_mempcpy (exp, target);
    8299         1394 :       if (target)
    8300              :         return target;
    8301              :       break;
    8302              : 
    8303        36696 :     case BUILT_IN_MEMSET:
    8304        36696 :       target = expand_builtin_memset (exp, target, mode);
    8305        36696 :       if (target)
    8306              :         return target;
    8307              :       break;
    8308              : 
    8309            0 :     case BUILT_IN_BZERO:
    8310            0 :       target = expand_builtin_bzero (exp);
    8311            0 :       if (target)
    8312              :         return target;
    8313              :       break;
    8314              : 
    8315              :     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
    8316              :        back to a BUILT_IN_STRCMP. Remember to delete the 3rd parameter
    8317              :        when changing it to a strcmp call.  */
    8318          368 :     case BUILT_IN_STRCMP_EQ:
    8319          368 :       target = expand_builtin_memcmp (exp, target, true);
    8320          368 :       if (target)
    8321              :         return target;
    8322              : 
    8323              :       /* Change this call back to a BUILT_IN_STRCMP.  */
    8324           25 :       TREE_OPERAND (exp, 1)
    8325           25 :         = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
    8326              : 
    8327              :       /* Delete the last parameter.  */
    8328           25 :       unsigned int i;
    8329           25 :       vec<tree, va_gc> *arg_vec;
    8330           25 :       vec_alloc (arg_vec, 2);
    8331          100 :       for (i = 0; i < 2; i++)
    8332           50 :         arg_vec->quick_push (CALL_EXPR_ARG (exp, i));
    8333           25 :       exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), arg_vec);
    8334              :       /* FALLTHROUGH */
    8335              : 
    8336       127966 :     case BUILT_IN_STRCMP:
    8337       127966 :       target = expand_builtin_strcmp (exp, target);
    8338       127966 :       if (target)
    8339              :         return target;
    8340              :       break;
    8341              : 
    8342              :     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
    8343              :        back to a BUILT_IN_STRNCMP.  */
    8344           38 :     case BUILT_IN_STRNCMP_EQ:
    8345           38 :       target = expand_builtin_memcmp (exp, target, true);
    8346           38 :       if (target)
    8347              :         return target;
    8348              : 
    8349              :       /* Change it back to a BUILT_IN_STRNCMP.  */
    8350            0 :       TREE_OPERAND (exp, 1)
    8351            0 :         = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
    8352              :       /* FALLTHROUGH */
    8353              : 
    8354         2031 :     case BUILT_IN_STRNCMP:
    8355         2031 :       target = expand_builtin_strncmp (exp, target, mode);
    8356         2031 :       if (target)
    8357              :         return target;
    8358              :       break;
    8359              : 
    8360       105799 :     case BUILT_IN_BCMP:
    8361       105799 :     case BUILT_IN_MEMCMP:
    8362       105799 :     case BUILT_IN_MEMCMP_EQ:
    8363       105799 :       target = expand_builtin_memcmp (exp, target, fcode == BUILT_IN_MEMCMP_EQ);
    8364       105799 :       if (target)
    8365              :         return target;
    8366        37375 :       if (fcode == BUILT_IN_MEMCMP_EQ)
    8367              :         {
    8368        22884 :           tree newdecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
    8369        22884 :           TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
    8370              :         }
    8371              :       break;
    8372              : 
    8373            0 :     case BUILT_IN_SETJMP:
    8374              :       /* This should have been lowered to the builtins below.  */
    8375            0 :       gcc_unreachable ();
    8376              : 
    8377          841 :     case BUILT_IN_SETJMP_SETUP:
    8378              :       /* __builtin_setjmp_setup is passed a pointer to an array of five words
    8379              :           and the receiver label.  */
    8380          841 :       if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    8381              :         {
    8382          841 :           rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
    8383              :                                       VOIDmode, EXPAND_NORMAL);
    8384          841 :           tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
    8385          841 :           rtx_insn *label_r = label_rtx (label);
    8386              : 
    8387          841 :           expand_builtin_setjmp_setup (buf_addr, label_r);
    8388          841 :           return const0_rtx;
    8389              :         }
    8390              :       break;
    8391              : 
    8392          841 :     case BUILT_IN_SETJMP_RECEIVER:
    8393              :        /* __builtin_setjmp_receiver is passed the receiver label.  */
    8394          841 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8395              :         {
    8396          841 :           tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
    8397          841 :           rtx_insn *label_r = label_rtx (label);
    8398              : 
    8399          841 :           expand_builtin_setjmp_receiver (label_r);
    8400          841 :           nonlocal_goto_handler_labels
    8401         1682 :             = gen_rtx_INSN_LIST (VOIDmode, label_r,
    8402          841 :                                  nonlocal_goto_handler_labels);
    8403              :           /* ??? Do not let expand_label treat us as such since we would
    8404              :              not want to be both on the list of non-local labels and on
    8405              :              the list of forced labels.  */
    8406          841 :           FORCED_LABEL (label) = 0;
    8407          841 :           return const0_rtx;
    8408              :         }
    8409              :       break;
    8410              : 
    8411              :       /* __builtin_longjmp is passed a pointer to an array of five words.
    8412              :          It's similar to the C library longjmp function but works with
    8413              :          __builtin_setjmp above.  */
    8414          391 :     case BUILT_IN_LONGJMP:
    8415          391 :       if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    8416              :         {
    8417          391 :           rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
    8418              :                                       VOIDmode, EXPAND_NORMAL);
    8419          391 :           rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
    8420              : 
    8421          391 :           if (value != const1_rtx)
    8422              :             {
    8423            0 :               error ("%<__builtin_longjmp%> second argument must be 1");
    8424            0 :               return const0_rtx;
    8425              :             }
    8426              : 
    8427          391 :           expand_builtin_longjmp (buf_addr, value);
    8428          391 :           return const0_rtx;
    8429              :         }
    8430              :       break;
    8431              : 
    8432          512 :     case BUILT_IN_NONLOCAL_GOTO:
    8433          512 :       target = expand_builtin_nonlocal_goto (exp);
    8434          512 :       if (target)
    8435              :         return target;
    8436              :       break;
    8437              : 
    8438              :       /* This updates the setjmp buffer that is its argument with the value
    8439              :          of the current stack pointer.  */
    8440            0 :     case BUILT_IN_UPDATE_SETJMP_BUF:
    8441            0 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8442              :         {
    8443            0 :           rtx buf_addr
    8444            0 :             = expand_normal (CALL_EXPR_ARG (exp, 0));
    8445              : 
    8446            0 :           expand_builtin_update_setjmp_buf (buf_addr);
    8447            0 :           return const0_rtx;
    8448              :         }
    8449              :       break;
    8450              : 
    8451        38631 :     case BUILT_IN_TRAP:
    8452        38631 :     case BUILT_IN_UNREACHABLE_TRAP:
    8453        38631 :       expand_builtin_trap ();
    8454        38631 :       return const0_rtx;
    8455              : 
    8456         2522 :     case BUILT_IN_UNREACHABLE:
    8457         2522 :       expand_builtin_unreachable ();
    8458         2522 :       return const0_rtx;
    8459              : 
    8460          364 :     case BUILT_IN_OBSERVABLE_CHKPT:
    8461              :       /* Generate no code.  */
    8462          364 :       return const0_rtx;
    8463              : 
    8464         1086 :     CASE_FLT_FN (BUILT_IN_SIGNBIT):
    8465         1086 :     case BUILT_IN_SIGNBITD32:
    8466         1086 :     case BUILT_IN_SIGNBITD64:
    8467         1086 :     case BUILT_IN_SIGNBITD128:
    8468         1086 :       target = expand_builtin_signbit (exp, target);
    8469         1086 :       if (target)
    8470              :         return target;
    8471              :       break;
    8472              : 
    8473              :       /* Various hooks for the DWARF 2 __throw routine.  */
    8474           34 :     case BUILT_IN_UNWIND_INIT:
    8475           34 :       expand_builtin_unwind_init ();
    8476           34 :       return const0_rtx;
    8477         1224 :     case BUILT_IN_DWARF_CFA:
    8478         1224 :       return virtual_cfa_rtx;
    8479              : #ifdef DWARF2_UNWIND_INFO
    8480           48 :     case BUILT_IN_DWARF_SP_COLUMN:
    8481           48 :       return expand_builtin_dwarf_sp_column ();
    8482            8 :     case BUILT_IN_INIT_DWARF_REG_SIZES:
    8483            8 :       expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
    8484            8 :       return const0_rtx;
    8485              : #endif
    8486           19 :     case BUILT_IN_FROB_RETURN_ADDR:
    8487           19 :       return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
    8488         2352 :     case BUILT_IN_EXTRACT_RETURN_ADDR:
    8489         2352 :       return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
    8490           29 :     case BUILT_IN_EH_RETURN:
    8491           58 :       expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
    8492           29 :                                 CALL_EXPR_ARG (exp, 1));
    8493           29 :       return const0_rtx;
    8494           21 :     case BUILT_IN_EH_RETURN_DATA_REGNO:
    8495           21 :       return expand_builtin_eh_return_data_regno (exp);
    8496            2 :     case BUILT_IN_EXTEND_POINTER:
    8497            2 :       return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
    8498       100261 :     case BUILT_IN_EH_POINTER:
    8499       100261 :       return expand_builtin_eh_pointer (exp);
    8500         5640 :     case BUILT_IN_EH_FILTER:
    8501         5640 :       return expand_builtin_eh_filter (exp);
    8502        99113 :     case BUILT_IN_EH_COPY_VALUES:
    8503        99113 :       return expand_builtin_eh_copy_values (exp);
    8504              : 
    8505        21079 :     case BUILT_IN_VA_START:
    8506        21079 :       return expand_builtin_va_start (exp);
    8507        12172 :     case BUILT_IN_VA_END:
    8508        12172 :       return expand_builtin_va_end (exp);
    8509          240 :     case BUILT_IN_VA_COPY:
    8510          240 :       return expand_builtin_va_copy (exp);
    8511         1353 :     case BUILT_IN_EXPECT:
    8512         1353 :       return expand_builtin_expect (exp, target);
    8513            5 :     case BUILT_IN_EXPECT_WITH_PROBABILITY:
    8514            5 :       return expand_builtin_expect_with_probability (exp, target);
    8515          665 :     case BUILT_IN_ASSUME_ALIGNED:
    8516          665 :       return expand_builtin_assume_aligned (exp, target);
    8517         2046 :     case BUILT_IN_PREFETCH:
    8518         2046 :       expand_builtin_prefetch (exp);
    8519         2046 :       return const0_rtx;
    8520              : 
    8521          305 :     case BUILT_IN_INIT_TRAMPOLINE:
    8522          305 :       return expand_builtin_init_trampoline (exp, true);
    8523            0 :     case BUILT_IN_INIT_HEAP_TRAMPOLINE:
    8524            0 :       return expand_builtin_init_trampoline (exp, false);
    8525          352 :     case BUILT_IN_ADJUST_TRAMPOLINE:
    8526          352 :       return expand_builtin_adjust_trampoline (exp);
    8527              : 
    8528            0 :     case BUILT_IN_INIT_DESCRIPTOR:
    8529            0 :       return expand_builtin_init_descriptor (exp);
    8530            0 :     case BUILT_IN_ADJUST_DESCRIPTOR:
    8531            0 :       return expand_builtin_adjust_descriptor (exp);
    8532              : 
    8533              :     case BUILT_IN_GCC_NESTED_PTR_CREATED:
    8534              :     case BUILT_IN_GCC_NESTED_PTR_DELETED:
    8535              :       break; /* At present, no expansion, just call the function.  */
    8536              : 
    8537          109 :     case BUILT_IN_FORK:
    8538          109 :     case BUILT_IN_EXECL:
    8539          109 :     case BUILT_IN_EXECV:
    8540          109 :     case BUILT_IN_EXECLP:
    8541          109 :     case BUILT_IN_EXECLE:
    8542          109 :     case BUILT_IN_EXECVP:
    8543          109 :     case BUILT_IN_EXECVE:
    8544          109 :       target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
    8545          109 :       if (target)
    8546              :         return target;
    8547              :       break;
    8548              : 
    8549          708 :     case BUILT_IN_SYNC_FETCH_AND_ADD_1:
    8550          708 :     case BUILT_IN_SYNC_FETCH_AND_ADD_2:
    8551          708 :     case BUILT_IN_SYNC_FETCH_AND_ADD_4:
    8552          708 :     case BUILT_IN_SYNC_FETCH_AND_ADD_8:
    8553          708 :     case BUILT_IN_SYNC_FETCH_AND_ADD_16:
    8554          708 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
    8555          708 :       target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
    8556          708 :       if (target)
    8557              :         return target;
    8558              :       break;
    8559              : 
    8560          581 :     case BUILT_IN_SYNC_FETCH_AND_SUB_1:
    8561          581 :     case BUILT_IN_SYNC_FETCH_AND_SUB_2:
    8562          581 :     case BUILT_IN_SYNC_FETCH_AND_SUB_4:
    8563          581 :     case BUILT_IN_SYNC_FETCH_AND_SUB_8:
    8564          581 :     case BUILT_IN_SYNC_FETCH_AND_SUB_16:
    8565          581 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
    8566          581 :       target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
    8567          581 :       if (target)
    8568              :         return target;
    8569              :       break;
    8570              : 
    8571          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_1:
    8572          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_2:
    8573          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_4:
    8574          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_8:
    8575          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_16:
    8576          512 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
    8577          512 :       target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
    8578          512 :       if (target)
    8579              :         return target;
    8580              :       break;
    8581              : 
    8582          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_1:
    8583          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_2:
    8584          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_4:
    8585          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_8:
    8586          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_16:
    8587          488 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
    8588          488 :       target = expand_builtin_sync_operation (mode, exp, AND, false, target);
    8589          488 :       if (target)
    8590              :         return target;
    8591              :       break;
    8592              : 
    8593          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_1:
    8594          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_2:
    8595          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_4:
    8596          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_8:
    8597          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_16:
    8598          581 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
    8599          581 :       target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
    8600          581 :       if (target)
    8601              :         return target;
    8602              :       break;
    8603              : 
    8604          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    8605          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    8606          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    8607          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    8608          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    8609          434 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
    8610          434 :       target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
    8611          434 :       if (target)
    8612              :         return target;
    8613              :       break;
    8614              : 
    8615          156 :     case BUILT_IN_SYNC_ADD_AND_FETCH_1:
    8616          156 :     case BUILT_IN_SYNC_ADD_AND_FETCH_2:
    8617          156 :     case BUILT_IN_SYNC_ADD_AND_FETCH_4:
    8618          156 :     case BUILT_IN_SYNC_ADD_AND_FETCH_8:
    8619          156 :     case BUILT_IN_SYNC_ADD_AND_FETCH_16:
    8620          156 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
    8621          156 :       target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
    8622          156 :       if (target)
    8623              :         return target;
    8624              :       break;
    8625              : 
    8626          117 :     case BUILT_IN_SYNC_SUB_AND_FETCH_1:
    8627          117 :     case BUILT_IN_SYNC_SUB_AND_FETCH_2:
    8628          117 :     case BUILT_IN_SYNC_SUB_AND_FETCH_4:
    8629          117 :     case BUILT_IN_SYNC_SUB_AND_FETCH_8:
    8630          117 :     case BUILT_IN_SYNC_SUB_AND_FETCH_16:
    8631          117 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
    8632          117 :       target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
    8633          117 :       if (target)
    8634              :         return target;
    8635              :       break;
    8636              : 
    8637          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_1:
    8638          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_2:
    8639          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_4:
    8640          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_8:
    8641          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_16:
    8642          115 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
    8643          115 :       target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
    8644          115 :       if (target)
    8645              :         return target;
    8646              :       break;
    8647              : 
    8648          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_1:
    8649          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_2:
    8650          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_4:
    8651          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_8:
    8652          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_16:
    8653          116 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
    8654          116 :       target = expand_builtin_sync_operation (mode, exp, AND, true, target);
    8655          116 :       if (target)
    8656              :         return target;
    8657              :       break;
    8658              : 
    8659          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_1:
    8660          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_2:
    8661          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_4:
    8662          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_8:
    8663          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_16:
    8664          114 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
    8665          114 :       target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
    8666          114 :       if (target)
    8667              :         return target;
    8668              :       break;
    8669              : 
    8670           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    8671           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    8672           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    8673           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    8674           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    8675           89 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
    8676           89 :       target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
    8677           89 :       if (target)
    8678              :         return target;
    8679              :       break;
    8680              : 
    8681          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
    8682          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
    8683          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
    8684          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
    8685          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
    8686          204 :       if (mode == VOIDmode)
    8687           40 :         mode = TYPE_MODE (boolean_type_node);
    8688          204 :       if (!target || !register_operand (target, mode))
    8689           40 :         target = gen_reg_rtx (mode);
    8690              : 
    8691          204 :       mode = get_builtin_sync_mode
    8692          204 :                                 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
    8693          204 :       target = expand_builtin_compare_and_swap (mode, exp, true, target);
    8694          204 :       if (target)
    8695              :         return target;
    8696              :       break;
    8697              : 
    8698          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
    8699          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
    8700          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
    8701          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
    8702          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
    8703          256 :       mode = get_builtin_sync_mode
    8704          256 :                                 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
    8705          256 :       target = expand_builtin_compare_and_swap (mode, exp, false, target);
    8706          256 :       if (target)
    8707              :         return target;
    8708              :       break;
    8709              : 
    8710          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
    8711          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
    8712          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
    8713          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
    8714          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
    8715          326 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
    8716          326 :       target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
    8717          326 :       if (target)
    8718              :         return target;
    8719              :       break;
    8720              : 
    8721          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_1:
    8722          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_2:
    8723          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_4:
    8724          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_8:
    8725          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_16:
    8726          146 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
    8727          146 :       if (expand_builtin_sync_lock_release (mode, exp))
    8728          144 :         return const0_rtx;
    8729              :       break;
    8730              : 
    8731          273 :     case BUILT_IN_SYNC_SYNCHRONIZE:
    8732          273 :       expand_builtin_sync_synchronize ();
    8733          273 :       return const0_rtx;
    8734              : 
    8735         2881 :     case BUILT_IN_ATOMIC_EXCHANGE_1:
    8736         2881 :     case BUILT_IN_ATOMIC_EXCHANGE_2:
    8737         2881 :     case BUILT_IN_ATOMIC_EXCHANGE_4:
    8738         2881 :     case BUILT_IN_ATOMIC_EXCHANGE_8:
    8739         2881 :     case BUILT_IN_ATOMIC_EXCHANGE_16:
    8740         2881 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
    8741         2881 :       target = expand_builtin_atomic_exchange (mode, exp, target);
    8742         2881 :       if (target)
    8743              :         return target;
    8744              :       break;
    8745              : 
    8746         9126 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
    8747         9126 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
    8748         9126 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
    8749         9126 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
    8750         9126 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
    8751         9126 :       {
    8752         9126 :         unsigned int nargs, z;
    8753         9126 :         vec<tree, va_gc> *vec;
    8754              : 
    8755         9126 :         mode =
    8756         9126 :             get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
    8757         9126 :         target = expand_builtin_atomic_compare_exchange (mode, exp, target);
    8758         9126 :         if (target)
    8759         7326 :           return target;
    8760              : 
    8761              :         /* If this is turned into an external library call, the weak parameter
    8762              :            must be dropped to match the expected parameter list.  */
    8763         1800 :         nargs = call_expr_nargs (exp);
    8764         1800 :         vec_alloc (vec, nargs - 1);
    8765         9000 :         for (z = 0; z < 3; z++)
    8766         5400 :           vec->quick_push (CALL_EXPR_ARG (exp, z));
    8767              :         /* Skip the boolean weak parameter.  */
    8768         5400 :         for (z = 4; z < 6; z++)
    8769         3600 :           vec->quick_push (CALL_EXPR_ARG (exp, z));
    8770         1800 :         exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
    8771         1800 :         break;
    8772              :       }
    8773              : 
    8774        70577 :     case BUILT_IN_ATOMIC_LOAD_1:
    8775        70577 :     case BUILT_IN_ATOMIC_LOAD_2:
    8776        70577 :     case BUILT_IN_ATOMIC_LOAD_4:
    8777        70577 :     case BUILT_IN_ATOMIC_LOAD_8:
    8778        70577 :     case BUILT_IN_ATOMIC_LOAD_16:
    8779        70577 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
    8780        70577 :       target = expand_builtin_atomic_load (mode, exp, target);
    8781        70577 :       if (target)
    8782              :         return target;
    8783              :       break;
    8784              : 
    8785        17428 :     case BUILT_IN_ATOMIC_STORE_1:
    8786        17428 :     case BUILT_IN_ATOMIC_STORE_2:
    8787        17428 :     case BUILT_IN_ATOMIC_STORE_4:
    8788        17428 :     case BUILT_IN_ATOMIC_STORE_8:
    8789        17428 :     case BUILT_IN_ATOMIC_STORE_16:
    8790        17428 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
    8791        17428 :       target = expand_builtin_atomic_store (mode, exp);
    8792        17428 :       if (target)
    8793        15801 :         return const0_rtx;
    8794              :       break;
    8795              : 
    8796         4385 :     case BUILT_IN_ATOMIC_ADD_FETCH_1:
    8797         4385 :     case BUILT_IN_ATOMIC_ADD_FETCH_2:
    8798         4385 :     case BUILT_IN_ATOMIC_ADD_FETCH_4:
    8799         4385 :     case BUILT_IN_ATOMIC_ADD_FETCH_8:
    8800         4385 :     case BUILT_IN_ATOMIC_ADD_FETCH_16:
    8801         4385 :       {
    8802         4385 :         enum built_in_function lib;
    8803         4385 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
    8804         4385 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
    8805              :                                        (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
    8806         4385 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
    8807              :                                                  ignore, lib);
    8808         4385 :         if (target)
    8809              :           return target;
    8810              :         break;
    8811              :       }
    8812         2168 :     case BUILT_IN_ATOMIC_SUB_FETCH_1:
    8813         2168 :     case BUILT_IN_ATOMIC_SUB_FETCH_2:
    8814         2168 :     case BUILT_IN_ATOMIC_SUB_FETCH_4:
    8815         2168 :     case BUILT_IN_ATOMIC_SUB_FETCH_8:
    8816         2168 :     case BUILT_IN_ATOMIC_SUB_FETCH_16:
    8817         2168 :       {
    8818         2168 :         enum built_in_function lib;
    8819         2168 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
    8820         2168 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
    8821              :                                        (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
    8822         2168 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
    8823              :                                                  ignore, lib);
    8824         2168 :         if (target)
    8825              :           return target;
    8826              :         break;
    8827              :       }
    8828          895 :     case BUILT_IN_ATOMIC_AND_FETCH_1:
    8829          895 :     case BUILT_IN_ATOMIC_AND_FETCH_2:
    8830          895 :     case BUILT_IN_ATOMIC_AND_FETCH_4:
    8831          895 :     case BUILT_IN_ATOMIC_AND_FETCH_8:
    8832          895 :     case BUILT_IN_ATOMIC_AND_FETCH_16:
    8833          895 :       {
    8834          895 :         enum built_in_function lib;
    8835          895 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
    8836          895 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
    8837              :                                        (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
    8838          895 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
    8839              :                                                  ignore, lib);
    8840          895 :         if (target)
    8841              :           return target;
    8842              :         break;
    8843              :       }
    8844          155 :     case BUILT_IN_ATOMIC_NAND_FETCH_1:
    8845          155 :     case BUILT_IN_ATOMIC_NAND_FETCH_2:
    8846          155 :     case BUILT_IN_ATOMIC_NAND_FETCH_4:
    8847          155 :     case BUILT_IN_ATOMIC_NAND_FETCH_8:
    8848          155 :     case BUILT_IN_ATOMIC_NAND_FETCH_16:
    8849          155 :       {
    8850          155 :         enum built_in_function lib;
    8851          155 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
    8852          155 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
    8853              :                                        (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
    8854          155 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
    8855              :                                                  ignore, lib);
    8856          155 :         if (target)
    8857              :           return target;
    8858              :         break;
    8859              :       }
    8860          840 :     case BUILT_IN_ATOMIC_XOR_FETCH_1:
    8861          840 :     case BUILT_IN_ATOMIC_XOR_FETCH_2:
    8862          840 :     case BUILT_IN_ATOMIC_XOR_FETCH_4:
    8863          840 :     case BUILT_IN_ATOMIC_XOR_FETCH_8:
    8864          840 :     case BUILT_IN_ATOMIC_XOR_FETCH_16:
    8865          840 :       {
    8866          840 :         enum built_in_function lib;
    8867          840 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
    8868          840 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
    8869              :                                        (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
    8870          840 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
    8871              :                                                  ignore, lib);
    8872          840 :         if (target)
    8873              :           return target;
    8874              :         break;
    8875              :       }
    8876          956 :     case BUILT_IN_ATOMIC_OR_FETCH_1:
    8877          956 :     case BUILT_IN_ATOMIC_OR_FETCH_2:
    8878          956 :     case BUILT_IN_ATOMIC_OR_FETCH_4:
    8879          956 :     case BUILT_IN_ATOMIC_OR_FETCH_8:
    8880          956 :     case BUILT_IN_ATOMIC_OR_FETCH_16:
    8881          956 :       {
    8882          956 :         enum built_in_function lib;
    8883          956 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
    8884          956 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
    8885              :                                        (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
    8886          956 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
    8887              :                                                  ignore, lib);
    8888          956 :         if (target)
    8889              :           return target;
    8890              :         break;
    8891              :       }
    8892        14479 :     case BUILT_IN_ATOMIC_FETCH_ADD_1:
    8893        14479 :     case BUILT_IN_ATOMIC_FETCH_ADD_2:
    8894        14479 :     case BUILT_IN_ATOMIC_FETCH_ADD_4:
    8895        14479 :     case BUILT_IN_ATOMIC_FETCH_ADD_8:
    8896        14479 :     case BUILT_IN_ATOMIC_FETCH_ADD_16:
    8897        14479 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
    8898        14479 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
    8899              :                                                ignore, BUILT_IN_NONE);
    8900        14479 :       if (target)
    8901              :         return target;
    8902              :       break;
    8903              : 
    8904         2103 :     case BUILT_IN_ATOMIC_FETCH_SUB_1:
    8905         2103 :     case BUILT_IN_ATOMIC_FETCH_SUB_2:
    8906         2103 :     case BUILT_IN_ATOMIC_FETCH_SUB_4:
    8907         2103 :     case BUILT_IN_ATOMIC_FETCH_SUB_8:
    8908         2103 :     case BUILT_IN_ATOMIC_FETCH_SUB_16:
    8909         2103 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
    8910         2103 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
    8911              :                                                ignore, BUILT_IN_NONE);
    8912         2103 :       if (target)
    8913              :         return target;
    8914              :       break;
    8915              : 
    8916          778 :     case BUILT_IN_ATOMIC_FETCH_AND_1:
    8917          778 :     case BUILT_IN_ATOMIC_FETCH_AND_2:
    8918          778 :     case BUILT_IN_ATOMIC_FETCH_AND_4:
    8919          778 :     case BUILT_IN_ATOMIC_FETCH_AND_8:
    8920          778 :     case BUILT_IN_ATOMIC_FETCH_AND_16:
    8921          778 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
    8922          778 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
    8923              :                                                ignore, BUILT_IN_NONE);
    8924          778 :       if (target)
    8925              :         return target;
    8926              :       break;
    8927              : 
    8928          118 :     case BUILT_IN_ATOMIC_FETCH_NAND_1:
    8929          118 :     case BUILT_IN_ATOMIC_FETCH_NAND_2:
    8930          118 :     case BUILT_IN_ATOMIC_FETCH_NAND_4:
    8931          118 :     case BUILT_IN_ATOMIC_FETCH_NAND_8:
    8932          118 :     case BUILT_IN_ATOMIC_FETCH_NAND_16:
    8933          118 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
    8934          118 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
    8935              :                                                ignore, BUILT_IN_NONE);
    8936          118 :       if (target)
    8937              :         return target;
    8938              :       break;
    8939              : 
    8940          868 :     case BUILT_IN_ATOMIC_FETCH_XOR_1:
    8941          868 :     case BUILT_IN_ATOMIC_FETCH_XOR_2:
    8942          868 :     case BUILT_IN_ATOMIC_FETCH_XOR_4:
    8943          868 :     case BUILT_IN_ATOMIC_FETCH_XOR_8:
    8944          868 :     case BUILT_IN_ATOMIC_FETCH_XOR_16:
    8945          868 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
    8946          868 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
    8947              :                                                ignore, BUILT_IN_NONE);
    8948          868 :       if (target)
    8949              :         return target;
    8950              :       break;
    8951              : 
    8952         1122 :     case BUILT_IN_ATOMIC_FETCH_OR_1:
    8953         1122 :     case BUILT_IN_ATOMIC_FETCH_OR_2:
    8954         1122 :     case BUILT_IN_ATOMIC_FETCH_OR_4:
    8955         1122 :     case BUILT_IN_ATOMIC_FETCH_OR_8:
    8956         1122 :     case BUILT_IN_ATOMIC_FETCH_OR_16:
    8957         1122 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
    8958         1122 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
    8959              :                                                ignore, BUILT_IN_NONE);
    8960         1122 :       if (target)
    8961              :         return target;
    8962              :       break;
    8963              : 
    8964          266 :     case BUILT_IN_ATOMIC_TEST_AND_SET:
    8965          266 :       target = expand_builtin_atomic_test_and_set (exp, target);
    8966          266 :       if (target)
    8967              :         return target;
    8968              :       break;
    8969              : 
    8970           53 :     case BUILT_IN_ATOMIC_CLEAR:
    8971           53 :       return expand_builtin_atomic_clear (exp);
    8972              : 
    8973            1 :     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
    8974            1 :       return expand_builtin_atomic_always_lock_free (exp);
    8975              : 
    8976            3 :     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
    8977            3 :       target = expand_builtin_atomic_is_lock_free (exp);
    8978            3 :       if (target)
    8979              :         return target;
    8980              :       break;
    8981              : 
    8982          693 :     case BUILT_IN_ATOMIC_THREAD_FENCE:
    8983          693 :       expand_builtin_atomic_thread_fence (exp);
    8984          693 :       return const0_rtx;
    8985              : 
    8986           60 :     case BUILT_IN_ATOMIC_SIGNAL_FENCE:
    8987           60 :       expand_builtin_atomic_signal_fence (exp);
    8988           60 :       return const0_rtx;
    8989              : 
    8990          618 :     case BUILT_IN_OBJECT_SIZE:
    8991          618 :     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
    8992          618 :       return expand_builtin_object_size (exp);
    8993              : 
    8994          837 :     case BUILT_IN_MEMCPY_CHK:
    8995          837 :     case BUILT_IN_MEMPCPY_CHK:
    8996          837 :     case BUILT_IN_MEMMOVE_CHK:
    8997          837 :     case BUILT_IN_MEMSET_CHK:
    8998          837 :       target = expand_builtin_memory_chk (exp, target, mode, fcode);
    8999          837 :       if (target)
    9000              :         return target;
    9001              :       break;
    9002              : 
    9003         1086 :     case BUILT_IN_STRCPY_CHK:
    9004         1086 :     case BUILT_IN_STPCPY_CHK:
    9005         1086 :     case BUILT_IN_STRNCPY_CHK:
    9006         1086 :     case BUILT_IN_STPNCPY_CHK:
    9007         1086 :     case BUILT_IN_STRCAT_CHK:
    9008         1086 :     case BUILT_IN_STRNCAT_CHK:
    9009         1086 :     case BUILT_IN_SNPRINTF_CHK:
    9010         1086 :     case BUILT_IN_VSNPRINTF_CHK:
    9011         1086 :       maybe_emit_chk_warning (exp, fcode);
    9012         1086 :       break;
    9013              : 
    9014         1327 :     case BUILT_IN_SPRINTF_CHK:
    9015         1327 :     case BUILT_IN_VSPRINTF_CHK:
    9016         1327 :       maybe_emit_sprintf_chk_warning (exp, fcode);
    9017         1327 :       break;
    9018              : 
    9019            3 :     case BUILT_IN_THREAD_POINTER:
    9020            3 :       return expand_builtin_thread_pointer (exp, target);
    9021              : 
    9022            0 :     case BUILT_IN_SET_THREAD_POINTER:
    9023            0 :       expand_builtin_set_thread_pointer (exp);
    9024            0 :       return const0_rtx;
    9025              : 
    9026              :     case BUILT_IN_ACC_ON_DEVICE:
    9027              :       /* Do library call, if we failed to expand the builtin when
    9028              :          folding.  */
    9029              :       break;
    9030              : 
    9031          356 :     case BUILT_IN_GOACC_PARLEVEL_ID:
    9032          356 :     case BUILT_IN_GOACC_PARLEVEL_SIZE:
    9033          356 :       return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
    9034              : 
    9035            4 :     case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
    9036            4 :       return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
    9037              : 
    9038           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_1:
    9039           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_2:
    9040           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_4:
    9041           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_8:
    9042           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_16:
    9043           31 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
    9044           31 :       return expand_speculation_safe_value (mode, exp, target, ignore);
    9045              : 
    9046            3 :     case BUILT_IN_CRC8_DATA8:
    9047            3 :       return expand_builtin_crc_table_based (IFN_CRC, QImode, QImode, mode,
    9048              :                                                exp, target);
    9049            2 :     case BUILT_IN_CRC16_DATA8:
    9050            2 :       return expand_builtin_crc_table_based (IFN_CRC, HImode, QImode, mode,
    9051              :                                                exp, target);
    9052            2 :     case BUILT_IN_CRC16_DATA16:
    9053            2 :       return expand_builtin_crc_table_based (IFN_CRC, HImode, HImode, mode,
    9054              :                                                exp, target);
    9055            2 :     case BUILT_IN_CRC32_DATA8:
    9056            2 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, QImode, mode,
    9057              :                                                exp, target);
    9058            2 :     case BUILT_IN_CRC32_DATA16:
    9059            2 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, HImode, mode,
    9060              :                                                exp, target);
    9061            4 :     case BUILT_IN_CRC32_DATA32:
    9062            4 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, SImode, mode,
    9063              :                                                exp, target);
    9064            1 :     case BUILT_IN_CRC64_DATA8:
    9065            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, QImode, mode,
    9066              :                                                exp, target);
    9067            1 :     case BUILT_IN_CRC64_DATA16:
    9068            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, HImode, mode,
    9069              :                                                exp, target);
    9070            1 :     case BUILT_IN_CRC64_DATA32:
    9071            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, SImode, mode,
    9072              :                                                exp, target);
    9073            1 :     case BUILT_IN_CRC64_DATA64:
    9074            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, DImode, mode,
    9075              :                                                exp, target);
    9076            2 :     case BUILT_IN_REV_CRC8_DATA8:
    9077            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, QImode, QImode,
    9078              :                                                mode, exp, target);
    9079            2 :     case BUILT_IN_REV_CRC16_DATA8:
    9080            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, QImode,
    9081              :                                                mode, exp, target);
    9082            2 :     case BUILT_IN_REV_CRC16_DATA16:
    9083            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, HImode,
    9084              :                                                mode, exp, target);
    9085            3 :     case BUILT_IN_REV_CRC32_DATA8:
    9086            3 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, QImode,
    9087              :                                                mode, exp, target);
    9088            2 :     case BUILT_IN_REV_CRC32_DATA16:
    9089            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, HImode,
    9090              :                                                mode, exp, target);
    9091            2 :     case BUILT_IN_REV_CRC32_DATA32:
    9092            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, SImode,
    9093              :                                                mode, exp, target);
    9094            1 :     case BUILT_IN_REV_CRC64_DATA8:
    9095            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, QImode,
    9096              :                                                mode, exp, target);
    9097            1 :     case BUILT_IN_REV_CRC64_DATA16:
    9098            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, HImode,
    9099              :                                                mode, exp, target);
    9100            1 :     case BUILT_IN_REV_CRC64_DATA32:
    9101            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, SImode,
    9102              :                                                mode, exp, target);
    9103            1 :     case BUILT_IN_REV_CRC64_DATA64:
    9104            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, DImode,
    9105              :                                                mode, exp, target);
    9106              :     default:    /* just do library call, if unknown builtin */
    9107              :       break;
    9108              :     }
    9109              : 
    9110              :   /* The switch statement above can drop through to cause the function
    9111              :      to be called normally.  */
    9112       844779 :   return expand_call (exp, target, ignore);
    9113              : }
    9114              : 
    9115              : /* Determine whether a tree node represents a call to a built-in
    9116              :    function.  If the tree T is a call to a built-in function with
    9117              :    the right number of arguments of the appropriate types, return
    9118              :    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
    9119              :    Otherwise the return value is END_BUILTINS.  */
    9120              : 
    9121              : enum built_in_function
    9122    108066643 : builtin_mathfn_code (const_tree t)
    9123              : {
    9124    108066643 :   const_tree fndecl, arg, parmlist;
    9125    108066643 :   const_tree argtype, parmtype;
    9126    108066643 :   const_call_expr_arg_iterator iter;
    9127              : 
    9128    108066643 :   if (TREE_CODE (t) != CALL_EXPR)
    9129              :     return END_BUILTINS;
    9130              : 
    9131      1439143 :   fndecl = get_callee_fndecl (t);
    9132      1439143 :   if (fndecl == NULL_TREE || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
    9133              :       return END_BUILTINS;
    9134              : 
    9135       650046 :   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
    9136       650046 :   init_const_call_expr_arg_iterator (t, &iter);
    9137      2097147 :   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
    9138              :     {
    9139              :       /* If a function doesn't take a variable number of arguments,
    9140              :          the last element in the list will have type `void'.  */
    9141      1427547 :       parmtype = TREE_VALUE (parmlist);
    9142      1427547 :       if (VOID_TYPE_P (parmtype))
    9143              :         {
    9144       630478 :           if (more_const_call_expr_args_p (&iter))
    9145              :             return END_BUILTINS;
    9146       630478 :           return DECL_FUNCTION_CODE (fndecl);
    9147              :         }
    9148              : 
    9149       797069 :       if (! more_const_call_expr_args_p (&iter))
    9150              :         return END_BUILTINS;
    9151              : 
    9152       797069 :       arg = next_const_call_expr_arg (&iter);
    9153       797069 :       argtype = TREE_TYPE (arg);
    9154              : 
    9155       797069 :       if (SCALAR_FLOAT_TYPE_P (parmtype))
    9156              :         {
    9157       537596 :           if (! SCALAR_FLOAT_TYPE_P (argtype))
    9158              :             return END_BUILTINS;
    9159              :         }
    9160       259473 :       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
    9161              :         {
    9162         7545 :           if (! COMPLEX_FLOAT_TYPE_P (argtype))
    9163              :             return END_BUILTINS;
    9164              :         }
    9165       251928 :       else if (POINTER_TYPE_P (parmtype))
    9166              :         {
    9167        75151 :           if (! POINTER_TYPE_P (argtype))
    9168              :             return END_BUILTINS;
    9169              :         }
    9170       176777 :       else if (INTEGRAL_TYPE_P (parmtype))
    9171              :         {
    9172       176777 :           if (! INTEGRAL_TYPE_P (argtype))
    9173              :             return END_BUILTINS;
    9174              :         }
    9175              :       else
    9176              :         return END_BUILTINS;
    9177              :     }
    9178              : 
    9179              :   /* Variable-length argument list.  */
    9180        19554 :   return DECL_FUNCTION_CODE (fndecl);
    9181              : }
    9182              : 
    9183              : /* Fold a call to __builtin_constant_p, if we know its argument ARG will
    9184              :    evaluate to a constant.  */
    9185              : 
    9186              : tree
    9187      3240415 : fold_builtin_constant_p (tree arg)
    9188              : {
    9189              :   /* We return 1 for a numeric type that's known to be a constant
    9190              :      value at compile-time or for an aggregate type that's a
    9191              :      literal constant.  */
    9192      3240415 :   STRIP_NOPS (arg);
    9193              : 
    9194              :   /* If we know this is a constant, emit the constant of one.  */
    9195      3240415 :   if (CONSTANT_CLASS_P (arg)
    9196      3240415 :       || (TREE_CODE (arg) == CONSTRUCTOR
    9197            6 :           && TREE_CONSTANT (arg)))
    9198      1832496 :     return integer_one_node;
    9199      1407919 :   if (TREE_CODE (arg) == ADDR_EXPR)
    9200              :     {
    9201          110 :        tree op = TREE_OPERAND (arg, 0);
    9202          110 :        if (TREE_CODE (op) == STRING_CST
    9203          110 :            || (TREE_CODE (op) == ARRAY_REF
    9204           57 :                && integer_zerop (TREE_OPERAND (op, 1))
    9205           57 :                && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
    9206           87 :          return integer_one_node;
    9207              :     }
    9208              : 
    9209              :   /* If this expression has side effects, show we don't know it to be a
    9210              :      constant.  Likewise if it's a pointer or aggregate type since in
    9211              :      those case we only want literals, since those are only optimized
    9212              :      when generating RTL, not later.
    9213              :      And finally, if we are compiling an initializer, not code, we
    9214              :      need to return a definite result now; there's not going to be any
    9215              :      more optimization done.  */
    9216      1407832 :   if (TREE_SIDE_EFFECTS (arg)
    9217      1407707 :       || AGGREGATE_TYPE_P (TREE_TYPE (arg))
    9218      1407701 :       || POINTER_TYPE_P (TREE_TYPE (arg))
    9219      1407530 :       || cfun == 0
    9220      1407487 :       || folding_initializer
    9221      2815312 :       || force_folding_builtin_constant_p)
    9222          402 :     return integer_zero_node;
    9223              : 
    9224              :   return NULL_TREE;
    9225              : }
    9226              : 
    9227              : /* Create builtin_expect or builtin_expect_with_probability
    9228              :    with PRED and EXPECTED as its arguments and return it as a truthvalue.
    9229              :    Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
    9230              :    builtin_expect_with_probability instead uses third argument as PROBABILITY
    9231              :    value.  */
    9232              : 
    9233              : static tree
    9234       218920 : build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
    9235              :                                 tree predictor, tree probability)
    9236              : {
    9237       218920 :   tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
    9238              : 
    9239       218920 :   fn = builtin_decl_explicit (probability == NULL_TREE ? BUILT_IN_EXPECT
    9240              :                               : BUILT_IN_EXPECT_WITH_PROBABILITY);
    9241       218920 :   arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
    9242       218920 :   ret_type = TREE_TYPE (TREE_TYPE (fn));
    9243       218920 :   pred_type = TREE_VALUE (arg_types);
    9244       218920 :   expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
    9245              : 
    9246       218920 :   pred = fold_convert_loc (loc, pred_type, pred);
    9247       218920 :   expected = fold_convert_loc (loc, expected_type, expected);
    9248              : 
    9249       218920 :   if (probability)
    9250            0 :     call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
    9251              :   else
    9252       437840 :     call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
    9253              :                                      predictor);
    9254              : 
    9255       218920 :   return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
    9256       218920 :                  build_int_cst (ret_type, 0));
    9257              : }
    9258              : 
    9259              : /* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3.  Return
    9260              :    NULL_TREE if no simplification is possible.  */
    9261              : 
    9262              : tree
    9263      7215860 : fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
    9264              :                      tree arg3)
    9265              : {
    9266      7215860 :   tree inner, fndecl, inner_arg0;
    9267      7215860 :   enum tree_code code;
    9268              : 
    9269              :   /* Distribute the expected value over short-circuiting operators.
    9270              :      See through the cast from truthvalue_type_node to long.  */
    9271      7215860 :   inner_arg0 = arg0;
    9272     14739432 :   while (CONVERT_EXPR_P (inner_arg0)
    9273      1047955 :          && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
    9274      9311769 :          && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
    9275      1047954 :     inner_arg0 = TREE_OPERAND (inner_arg0, 0);
    9276              : 
    9277              :   /* If this is a builtin_expect within a builtin_expect keep the
    9278              :      inner one.  See through a comparison against a constant.  It
    9279              :      might have been added to create a thruthvalue.  */
    9280      7215860 :   inner = inner_arg0;
    9281              : 
    9282      7215860 :   if (COMPARISON_CLASS_P (inner)
    9283      7215860 :       && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
    9284      1370581 :     inner = TREE_OPERAND (inner, 0);
    9285              : 
    9286      7215860 :   if (TREE_CODE (inner) == CALL_EXPR
    9287       174735 :       && (fndecl = get_callee_fndecl (inner))
    9288      7390595 :       && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT,
    9289              :                             BUILT_IN_EXPECT_WITH_PROBABILITY))
    9290              :     return arg0;
    9291              : 
    9292      7215852 :   inner = inner_arg0;
    9293      7215852 :   code = TREE_CODE (inner);
    9294      7215852 :   if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
    9295              :     {
    9296       109460 :       tree op0 = TREE_OPERAND (inner, 0);
    9297       109460 :       tree op1 = TREE_OPERAND (inner, 1);
    9298       109460 :       arg1 = save_expr (arg1);
    9299              : 
    9300       109460 :       op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2, arg3);
    9301       109460 :       op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2, arg3);
    9302       109460 :       inner = build2 (code, TREE_TYPE (inner), op0, op1);
    9303              : 
    9304       109460 :       return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
    9305              :     }
    9306              : 
    9307              :   /* If the argument isn't invariant then there's nothing else we can do.  */
    9308      7106392 :   if (!TREE_CONSTANT (inner_arg0))
    9309              :     return NULL_TREE;
    9310              : 
    9311              :   /* If we expect that a comparison against the argument will fold to
    9312              :      a constant return the constant.  In practice, this means a true
    9313              :      constant or the address of a non-weak symbol.  */
    9314       247483 :   inner = inner_arg0;
    9315       247483 :   STRIP_NOPS (inner);
    9316       247483 :   if (TREE_CODE (inner) == ADDR_EXPR)
    9317              :     {
    9318            1 :       do
    9319              :         {
    9320            1 :           inner = TREE_OPERAND (inner, 0);
    9321              :         }
    9322            1 :       while (TREE_CODE (inner) == COMPONENT_REF
    9323            1 :              || TREE_CODE (inner) == ARRAY_REF);
    9324            1 :       if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner))
    9325              :         return NULL_TREE;
    9326              :     }
    9327              : 
    9328              :   /* Otherwise, ARG0 already has the proper type for the return value.  */
    9329              :   return arg0;
    9330              : }
    9331              : 
    9332              : /* Fold a call to __builtin_classify_type with argument ARG.  */
    9333              : 
    9334              : static tree
    9335         2082 : fold_builtin_classify_type (tree arg)
    9336              : {
    9337         2082 :   if (arg == 0)
    9338            0 :     return build_int_cst (integer_type_node, no_type_class);
    9339              : 
    9340         2082 :   return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
    9341              : }
    9342              : 
    9343              : /* Fold a call EXPR (which may be null) to __builtin_strlen with argument
    9344              :    ARG.  */
    9345              : 
    9346              : static tree
    9347       452090 : fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg)
    9348              : {
    9349       452090 :   if (!validate_arg (arg, POINTER_TYPE))
    9350              :     return NULL_TREE;
    9351              :   else
    9352              :     {
    9353       452087 :       c_strlen_data lendata = { };
    9354       452087 :       tree len = c_strlen (arg, 0, &lendata);
    9355              : 
    9356       452087 :       if (len)
    9357         1911 :         return fold_convert_loc (loc, type, len);
    9358              : 
    9359              :       /* TODO: Move this to gimple-ssa-warn-access once the pass runs
    9360              :          also early enough to detect invalid reads in multimensional
    9361              :          arrays and struct members.  */
    9362       450176 :       if (!lendata.decl)
    9363       442998 :          c_strlen (arg, 1, &lendata);
    9364              : 
    9365       450176 :       if (lendata.decl)
    9366              :         {
    9367         7192 :           if (EXPR_HAS_LOCATION (arg))
    9368         2800 :             loc = EXPR_LOCATION (arg);
    9369         4392 :           else if (loc == UNKNOWN_LOCATION)
    9370            0 :             loc = input_location;
    9371         7192 :           warn_string_no_nul (loc, expr, "strlen", arg, lendata.decl);
    9372              :         }
    9373              : 
    9374       450176 :       return NULL_TREE;
    9375              :     }
    9376              : }
    9377              : 
    9378              : /* Fold a call to __builtin_inf or __builtin_huge_val.  */
    9379              : 
    9380              : static tree
    9381       261793 : fold_builtin_inf (location_t loc, tree type, int warn)
    9382              : {
    9383              :   /* __builtin_inff is intended to be usable to define INFINITY on all
    9384              :      targets.  If an infinity is not available, INFINITY expands "to a
    9385              :      positive constant of type float that overflows at translation
    9386              :      time", footnote "In this case, using INFINITY will violate the
    9387              :      constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
    9388              :      Thus we pedwarn to ensure this constraint violation is
    9389              :      diagnosed.  */
    9390      1046363 :   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
    9391            0 :     pedwarn (loc, 0, "target format does not support infinity");
    9392              : 
    9393       261793 :   return build_real (type, dconstinf);
    9394              : }
    9395              : 
    9396              : /* Fold function call to builtin sincos, sincosf, or sincosl.  Return
    9397              :    NULL_TREE if no simplification can be made.  */
    9398              : 
    9399              : static tree
    9400          145 : fold_builtin_sincos (location_t loc,
    9401              :                      tree arg0, tree arg1, tree arg2)
    9402              : {
    9403          145 :   tree type;
    9404          145 :   tree fndecl, call = NULL_TREE;
    9405              : 
    9406          145 :   if (!validate_arg (arg0, REAL_TYPE)
    9407          145 :       || !validate_arg (arg1, POINTER_TYPE)
    9408          290 :       || !validate_arg (arg2, POINTER_TYPE))
    9409              :     return NULL_TREE;
    9410              : 
    9411          145 :   type = TREE_TYPE (arg0);
    9412              : 
    9413              :   /* Calculate the result when the argument is a constant.  */
    9414          145 :   built_in_function fn = mathfn_built_in_2 (type, CFN_BUILT_IN_CEXPI);
    9415          145 :   if (fn == END_BUILTINS)
    9416              :     return NULL_TREE;
    9417              : 
    9418              :   /* Canonicalize sincos to cexpi.  */
    9419          145 :   if (TREE_CODE (arg0) == REAL_CST)
    9420              :     {
    9421           86 :       tree complex_type = build_complex_type (type);
    9422           86 :       call = fold_const_call (as_combined_fn (fn), complex_type, arg0);
    9423              :     }
    9424           86 :   if (!call)
    9425              :     {
    9426           59 :       if (!targetm.libc_has_function (function_c99_math_complex, type)
    9427           59 :           || !builtin_decl_implicit_p (fn))
    9428              :         return NULL_TREE;
    9429           59 :       fndecl = builtin_decl_explicit (fn);
    9430           59 :       call = build_call_expr_loc (loc, fndecl, 1, arg0);
    9431           59 :       call = builtin_save_expr (call);
    9432              :     }
    9433              : 
    9434          145 :   tree ptype = build_pointer_type (type);
    9435          145 :   arg1 = fold_convert (ptype, arg1);
    9436          145 :   arg2 = fold_convert (ptype, arg2);
    9437          145 :   return build2 (COMPOUND_EXPR, void_type_node,
    9438              :                  build2 (MODIFY_EXPR, void_type_node,
    9439              :                          build_fold_indirect_ref_loc (loc, arg1),
    9440              :                          fold_build1_loc (loc, IMAGPART_EXPR, type, call)),
    9441              :                  build2 (MODIFY_EXPR, void_type_node,
    9442              :                          build_fold_indirect_ref_loc (loc, arg2),
    9443          145 :                          fold_build1_loc (loc, REALPART_EXPR, type, call)));
    9444              : }
    9445              : 
    9446              : /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
    9447              :    Return NULL_TREE if no simplification can be made.  */
    9448              : 
    9449              : static tree
    9450      2538325 : fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
    9451              : {
    9452      2538325 :   if (!validate_arg (arg1, POINTER_TYPE)
    9453      2538325 :       || !validate_arg (arg2, POINTER_TYPE)
    9454      5076650 :       || !validate_arg (len, INTEGER_TYPE))
    9455              :     return NULL_TREE;
    9456              : 
    9457              :   /* If the LEN parameter is zero, return zero.  */
    9458      2538325 :   if (integer_zerop (len))
    9459            0 :     return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
    9460            0 :                               arg1, arg2);
    9461              : 
    9462              :   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
    9463      2538325 :   if (operand_equal_p (arg1, arg2, 0))
    9464          697 :     return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
    9465              : 
    9466              :   /* If len parameter is one, return an expression corresponding to
    9467              :      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
    9468      2537628 :   if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
    9469              :     {
    9470        54873 :       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
    9471        54873 :       tree cst_uchar_ptr_node
    9472        54873 :         = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
    9473              : 
    9474        54873 :       tree ind1
    9475        54873 :         = fold_convert_loc (loc, integer_type_node,
    9476              :                             build1 (INDIRECT_REF, cst_uchar_node,
    9477              :                                     fold_convert_loc (loc,
    9478              :                                                       cst_uchar_ptr_node,
    9479              :                                                       arg1)));
    9480        54873 :       tree ind2
    9481        54873 :         = fold_convert_loc (loc, integer_type_node,
    9482              :                             build1 (INDIRECT_REF, cst_uchar_node,
    9483              :                                     fold_convert_loc (loc,
    9484              :                                                       cst_uchar_ptr_node,
    9485              :                                                       arg2)));
    9486        54873 :       return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
    9487              :     }
    9488              : 
    9489              :   return NULL_TREE;
    9490              : }
    9491              : 
    9492              : /* Fold a call to builtin isascii with argument ARG.  */
    9493              : 
    9494              : static tree
    9495          211 : fold_builtin_isascii (location_t loc, tree arg)
    9496              : {
    9497          211 :   if (!validate_arg (arg, INTEGER_TYPE))
    9498              :     return NULL_TREE;
    9499              :   else
    9500              :     {
    9501              :       /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
    9502          211 :       arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
    9503              :                          build_int_cst (integer_type_node,
    9504              :                                         ~ HOST_WIDE_INT_UC (0x7f)));
    9505          211 :       return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
    9506          211 :                               arg, integer_zero_node);
    9507              :     }
    9508              : }
    9509              : 
    9510              : /* Fold a call to builtin toascii with argument ARG.  */
    9511              : 
    9512              : static tree
    9513          168 : fold_builtin_toascii (location_t loc, tree arg)
    9514              : {
    9515          168 :   if (!validate_arg (arg, INTEGER_TYPE))
    9516              :     return NULL_TREE;
    9517              : 
    9518              :   /* Transform toascii(c) -> (c & 0x7f).  */
    9519          168 :   return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
    9520              :                           build_int_cst (integer_type_node, 0x7f));
    9521              : }
    9522              : 
    9523              : /* Fold a call to builtin isdigit with argument ARG.  */
    9524              : 
    9525              : static tree
    9526          325 : fold_builtin_isdigit (location_t loc, tree arg)
    9527              : {
    9528          325 :   if (!validate_arg (arg, INTEGER_TYPE))
    9529              :     return NULL_TREE;
    9530              :   else
    9531              :     {
    9532              :       /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
    9533              :       /* According to the C standard, isdigit is unaffected by locale.
    9534              :          However, it definitely is affected by the target character set.  */
    9535          313 :       unsigned HOST_WIDE_INT target_digit0
    9536          313 :         = lang_hooks.to_target_charset ('0');
    9537              : 
    9538          313 :       if (target_digit0 == 0)
    9539              :         return NULL_TREE;
    9540              : 
    9541          313 :       arg = fold_convert_loc (loc, unsigned_type_node, arg);
    9542          313 :       arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
    9543              :                          build_int_cst (unsigned_type_node, target_digit0));
    9544          313 :       return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
    9545              :                           build_int_cst (unsigned_type_node, 9));
    9546              :     }
    9547              : }
    9548              : 
    9549              : /* Fold a call to fabs, fabsf or fabsl with argument ARG.  */
    9550              : 
    9551              : static tree
    9552       375037 : fold_builtin_fabs (location_t loc, tree arg, tree type)
    9553              : {
    9554       375037 :   if (!validate_arg (arg, REAL_TYPE))
    9555              :     return NULL_TREE;
    9556              : 
    9557       374952 :   arg = fold_convert_loc (loc, type, arg);
    9558       374952 :   return fold_build1_loc (loc, ABS_EXPR, type, arg);
    9559              : }
    9560              : 
    9561              : /* Fold a call to abs, labs, llabs, imaxabs, uabs, ulabs, ullabs or uimaxabs
    9562              :    with argument ARG.  */
    9563              : 
    9564              : static tree
    9565       100472 : fold_builtin_abs (location_t loc, tree arg, tree type)
    9566              : {
    9567       100472 :   if (!validate_arg (arg, INTEGER_TYPE) || !INTEGRAL_TYPE_P (type))
    9568              :     return NULL_TREE;
    9569              : 
    9570       100424 :   if (TYPE_UNSIGNED (type))
    9571              :     {
    9572         1168 :       if (TYPE_PRECISION (TREE_TYPE (arg))
    9573         1168 :           != TYPE_PRECISION (type)
    9574         1168 :           || TYPE_UNSIGNED (TREE_TYPE (arg)))
    9575              :         return NULL_TREE;
    9576         1168 :       return fold_build1_loc (loc, ABSU_EXPR, type, arg);
    9577              :     }
    9578        99256 :   arg = fold_convert_loc (loc, type, arg);
    9579        99256 :   return fold_build1_loc (loc, ABS_EXPR, type, arg);
    9580              : }
    9581              : 
    9582              : /* Fold a call to builtin carg(a+bi) -> atan2(b,a).  */
    9583              : 
    9584              : static tree
    9585       102695 : fold_builtin_carg (location_t loc, tree arg, tree type)
    9586              : {
    9587       102695 :   if (validate_arg (arg, COMPLEX_TYPE)
    9588       102695 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
    9589              :     {
    9590       102695 :       tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
    9591              : 
    9592       102695 :       if (atan2_fn)
    9593              :         {
    9594        99814 :           tree new_arg = builtin_save_expr (arg);
    9595        99814 :           tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
    9596        99814 :           tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
    9597        99814 :           return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
    9598              :         }
    9599              :     }
    9600              : 
    9601              :   return NULL_TREE;
    9602              : }
    9603              : 
    9604              : /* Fold a call to builtin frexp, we can assume the base is 2.  */
    9605              : 
    9606              : static tree
    9607        92055 : fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
    9608              : {
    9609        92055 :   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
    9610              :     return NULL_TREE;
    9611              : 
    9612        92055 :   STRIP_NOPS (arg0);
    9613              : 
    9614        92055 :   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
    9615              :     return NULL_TREE;
    9616              : 
    9617         2210 :   arg1 = build_fold_indirect_ref_loc (loc, arg1);
    9618              : 
    9619              :   /* Proceed if a valid pointer type was passed in.  */
    9620         2210 :   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
    9621              :     {
    9622         2210 :       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
    9623         2210 :       tree frac, exp, res;
    9624              : 
    9625         2210 :       switch (value->cl)
    9626              :       {
    9627          276 :       case rvc_zero:
    9628          276 :       case rvc_nan:
    9629          276 :       case rvc_inf:
    9630              :         /* For +-0, return (*exp = 0, +-0).  */
    9631              :         /* For +-NaN or +-Inf, *exp is unspecified, but something should
    9632              :            be stored there so that it isn't read from uninitialized object.
    9633              :            As glibc and newlib store *exp = 0 for +-Inf/NaN, storing
    9634              :            0 here as well is easiest.  */
    9635          276 :         exp = integer_zero_node;
    9636          276 :         frac = arg0;
    9637          276 :         break;
    9638         1934 :       case rvc_normal:
    9639         1934 :         {
    9640              :           /* Since the frexp function always expects base 2, and in
    9641              :              GCC normalized significands are already in the range
    9642              :              [0.5, 1.0), we have exactly what frexp wants.  */
    9643         1934 :           REAL_VALUE_TYPE frac_rvt = *value;
    9644         1934 :           SET_REAL_EXP (&frac_rvt, 0);
    9645         1934 :           frac = build_real (rettype, frac_rvt);
    9646         1934 :           exp = build_int_cst (integer_type_node, REAL_EXP (value));
    9647              :         }
    9648         1934 :         break;
    9649            0 :       default:
    9650            0 :         gcc_unreachable ();
    9651              :       }
    9652              : 
    9653              :       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
    9654         2210 :       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
    9655         2210 :       TREE_SIDE_EFFECTS (arg1) = 1;
    9656         2210 :       res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
    9657         2210 :       suppress_warning (res, OPT_Wunused_value);
    9658         2210 :       return res;
    9659              :     }
    9660              : 
    9661              :   return NULL_TREE;
    9662              : }
    9663              : 
    9664              : /* Fold a call to builtin modf.  */
    9665              : 
    9666              : static tree
    9667        69262 : fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
    9668              : {
    9669        69262 :   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
    9670              :     return NULL_TREE;
    9671              : 
    9672        69262 :   STRIP_NOPS (arg0);
    9673              : 
    9674        69262 :   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
    9675              :     return NULL_TREE;
    9676              : 
    9677         2474 :   arg1 = build_fold_indirect_ref_loc (loc, arg1);
    9678              : 
    9679              :   /* Proceed if a valid pointer type was passed in.  */
    9680         2474 :   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
    9681              :     {
    9682         2474 :       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
    9683         2474 :       REAL_VALUE_TYPE trunc, frac;
    9684         2474 :       tree res;
    9685              : 
    9686         2474 :       switch (value->cl)
    9687              :       {
    9688          228 :       case rvc_nan:
    9689          228 :       case rvc_zero:
    9690              :         /* For +-NaN or +-0, return (*arg1 = arg0, arg0).  */
    9691          228 :         trunc = frac = *value;
    9692          228 :         break;
    9693           96 :       case rvc_inf:
    9694              :         /* For +-Inf, return (*arg1 = arg0, +-0).  */
    9695           96 :         frac = dconst0;
    9696           96 :         frac.sign = value->sign;
    9697           96 :         trunc = *value;
    9698           96 :         break;
    9699         2150 :       case rvc_normal:
    9700              :         /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)).  */
    9701         2150 :         real_trunc (&trunc, VOIDmode, value);
    9702         2150 :         real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
    9703              :         /* If the original number was negative and already
    9704              :            integral, then the fractional part is -0.0.  */
    9705         2150 :         if (value->sign && frac.cl == rvc_zero)
    9706           69 :           frac.sign = value->sign;
    9707              :         break;
    9708              :       }
    9709              : 
    9710              :       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
    9711         2474 :       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
    9712              :                           build_real (rettype, trunc));
    9713         2474 :       TREE_SIDE_EFFECTS (arg1) = 1;
    9714         2474 :       res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
    9715              :                              build_real (rettype, frac));
    9716         2474 :       suppress_warning (res, OPT_Wunused_value);
    9717         2474 :       return res;
    9718              :     }
    9719              : 
    9720              :   return NULL_TREE;
    9721              : }
    9722              : 
    9723              : /* Given a location LOC, an interclass builtin function decl FNDECL
    9724              :    and its single argument ARG, return an folded expression computing
    9725              :    the same, or NULL_TREE if we either couldn't or didn't want to fold
    9726              :    (the latter happen if there's an RTL instruction available).  */
    9727              : 
    9728              : static tree
    9729      1387054 : fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
    9730              : {
    9731      1387054 :   machine_mode mode;
    9732              : 
    9733      1387054 :   if (!validate_arg (arg, REAL_TYPE))
    9734              :     return NULL_TREE;
    9735              : 
    9736      1387054 :   if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
    9737              :     return NULL_TREE;
    9738              : 
    9739      1387054 :   mode = TYPE_MODE (TREE_TYPE (arg));
    9740              : 
    9741      9705536 :   bool is_ibm_extended = MODE_COMPOSITE_P (mode);
    9742              : 
    9743              :   /* If there is no optab, try generic code.  */
    9744      1387054 :   switch (DECL_FUNCTION_CODE (fndecl))
    9745              :     {
    9746       414370 :       tree result;
    9747              : 
    9748       414370 :     CASE_FLT_FN (BUILT_IN_ISINF):
    9749       414370 :       {
    9750              :         /* isinf(x) -> isgreater(fabs(x),DBL_MAX).  */
    9751       414370 :         tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
    9752       414370 :         tree type = TREE_TYPE (arg);
    9753       414370 :         REAL_VALUE_TYPE r;
    9754       414370 :         char buf[128];
    9755              : 
    9756       414370 :         if (is_ibm_extended)
    9757              :           {
    9758              :             /* NaN and Inf are encoded in the high-order double value
    9759              :                only.  The low-order value is not significant.  */
    9760            0 :             type = double_type_node;
    9761            0 :             mode = DFmode;
    9762            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9763              :           }
    9764       414370 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9765       414370 :         real_from_string3 (&r, buf, mode);
    9766       414370 :         result = build_call_expr (isgr_fn, 2,
    9767              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9768              :                                   build_real (type, r));
    9769       414370 :         return result;
    9770              :       }
    9771       491771 :     CASE_FLT_FN (BUILT_IN_FINITE):
    9772       491771 :     case BUILT_IN_ISFINITE:
    9773       491771 :       {
    9774              :         /* isfinite(x) -> islessequal(fabs(x),DBL_MAX).  */
    9775       491771 :         tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
    9776       491771 :         tree type = TREE_TYPE (arg);
    9777       491771 :         REAL_VALUE_TYPE r;
    9778       491771 :         char buf[128];
    9779              : 
    9780       491771 :         if (is_ibm_extended)
    9781              :           {
    9782              :             /* NaN and Inf are encoded in the high-order double value
    9783              :                only.  The low-order value is not significant.  */
    9784            0 :             type = double_type_node;
    9785            0 :             mode = DFmode;
    9786            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9787              :           }
    9788       491771 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9789       491771 :         real_from_string3 (&r, buf, mode);
    9790       491771 :         result = build_call_expr (isle_fn, 2,
    9791              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9792              :                                   build_real (type, r));
    9793              :         /*result = fold_build2_loc (loc, UNGT_EXPR,
    9794              :                                   TREE_TYPE (TREE_TYPE (fndecl)),
    9795              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9796              :                                   build_real (type, r));
    9797              :         result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
    9798              :                                   TREE_TYPE (TREE_TYPE (fndecl)),
    9799              :                                   result);*/
    9800       491771 :         return result;
    9801              :       }
    9802       238188 :     case BUILT_IN_ISNORMAL:
    9803       238188 :       {
    9804              :         /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
    9805              :            islessequal(fabs(x),DBL_MAX).  */
    9806       238188 :         tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
    9807       238188 :         tree type = TREE_TYPE (arg);
    9808       238188 :         tree orig_arg, max_exp, min_exp;
    9809       238188 :         machine_mode orig_mode = mode;
    9810       238188 :         REAL_VALUE_TYPE rmax, rmin;
    9811       238188 :         char buf[128];
    9812              : 
    9813       238188 :         orig_arg = arg = builtin_save_expr (arg);
    9814       238188 :         if (is_ibm_extended)
    9815              :           {
    9816              :             /* Use double to test the normal range of IBM extended
    9817              :                precision.  Emin for IBM extended precision is
    9818              :                different to emin for IEEE double, being 53 higher
    9819              :                since the low double exponent is at least 53 lower
    9820              :                than the high double exponent.  */
    9821            0 :             type = double_type_node;
    9822            0 :             mode = DFmode;
    9823            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9824              :           }
    9825       238188 :         arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
    9826              : 
    9827       238188 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9828       238188 :         real_from_string3 (&rmax, buf, mode);
    9829       238188 :         if (DECIMAL_FLOAT_MODE_P (mode))
    9830            1 :           sprintf (buf, "1E%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
    9831              :         else
    9832       238187 :           sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
    9833       238188 :         real_from_string3 (&rmin, buf, orig_mode);
    9834       238188 :         max_exp = build_real (type, rmax);
    9835       238188 :         min_exp = build_real (type, rmin);
    9836              : 
    9837       238188 :         max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
    9838       238188 :         if (is_ibm_extended)
    9839              :           {
    9840              :             /* Testing the high end of the range is done just using
    9841              :                the high double, using the same test as isfinite().
    9842              :                For the subnormal end of the range we first test the
    9843              :                high double, then if its magnitude is equal to the
    9844              :                limit of 0x1p-969, we test whether the low double is
    9845              :                non-zero and opposite sign to the high double.  */
    9846            0 :             tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS);
    9847            0 :             tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
    9848            0 :             tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
    9849            0 :             tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
    9850              :                                        arg, min_exp);
    9851            0 :             tree as_complex = build1 (VIEW_CONVERT_EXPR,
    9852              :                                       complex_double_type_node, orig_arg);
    9853            0 :             tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
    9854            0 :             tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
    9855            0 :             tree zero = build_real (type, dconst0);
    9856            0 :             tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
    9857            0 :             tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
    9858            0 :             tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
    9859            0 :             tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
    9860              :                                       fold_build3 (COND_EXPR,
    9861              :                                                    integer_type_node,
    9862              :                                                    hilt, logt, lolt));
    9863            0 :             eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
    9864              :                                   eq_min, ok_lo);
    9865            0 :             min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
    9866              :                                    gt_min, eq_min);
    9867              :           }
    9868              :         else
    9869              :           {
    9870       238188 :             tree const isge_fn
    9871       238188 :               = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
    9872       238188 :             min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
    9873              :           }
    9874       238188 :         result = fold_build2 (BIT_AND_EXPR, integer_type_node,
    9875              :                               max_exp, min_exp);
    9876       238188 :         return result;
    9877              :       }
    9878       241191 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    9879       241191 :     case BUILT_IN_ISNAND32:
    9880       241191 :     case BUILT_IN_ISNAND64:
    9881       241191 :     case BUILT_IN_ISNAND128:
    9882       241191 :       {
    9883              :         /* In IBM extended NaN and Inf are encoded in the high-order double
    9884              :            value only.  The low-order value is not significant.  */
    9885       241191 :         if (is_ibm_extended)
    9886            0 :           arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
    9887       241191 :         arg = builtin_save_expr (arg);
    9888       241191 :         tree type = TREE_TYPE (TREE_TYPE (fndecl));
    9889       241191 :         return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
    9890              :       }
    9891              :     default:
    9892              :       break;
    9893              :     }
    9894              : 
    9895              :   return NULL_TREE;
    9896              : }
    9897              : 
    9898              : /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
    9899              :    ARG is the argument for the call.  */
    9900              : 
    9901              : static tree
    9902      1177946 : fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
    9903              : {
    9904      1177946 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
    9905              : 
    9906      1177946 :   if (!validate_arg (arg, REAL_TYPE))
    9907              :     return NULL_TREE;
    9908              : 
    9909      1177946 :   switch (builtin_index)
    9910              :     {
    9911       416065 :     case BUILT_IN_ISINF:
    9912       416065 :       if (tree_expr_infinite_p (arg))
    9913            0 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9914       416065 :       if (!tree_expr_maybe_infinite_p (arg))
    9915          161 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9916              :       return NULL_TREE;
    9917              : 
    9918          708 :     case BUILT_IN_ISINF_SIGN:
    9919          708 :       {
    9920              :         /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
    9921              :         /* In a boolean context, GCC will fold the inner COND_EXPR to
    9922              :            1.  So e.g. "if (isinf_sign(x))" would be folded to just
    9923              :            "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
    9924          708 :         tree signbit_fn = builtin_decl_explicit (BUILT_IN_SIGNBIT);
    9925          708 :         tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
    9926          708 :         tree tmp = NULL_TREE;
    9927              : 
    9928          708 :         arg = builtin_save_expr (arg);
    9929              : 
    9930          708 :         if (signbit_fn && isinf_fn)
    9931              :           {
    9932          708 :             tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
    9933          708 :             tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
    9934              : 
    9935          708 :             signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
    9936              :                                         signbit_call, integer_zero_node);
    9937          708 :             isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
    9938              :                                       isinf_call, integer_zero_node);
    9939              : 
    9940          708 :             tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
    9941              :                                integer_minus_one_node, integer_one_node);
    9942          708 :             tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
    9943              :                                isinf_call, tmp,
    9944              :                                integer_zero_node);
    9945              :           }
    9946              : 
    9947              :         return tmp;
    9948              :       }
    9949              : 
    9950       492043 :     case BUILT_IN_ISFINITE:
    9951       492043 :       if (tree_expr_finite_p (arg))
    9952          272 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9953       491771 :       if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
    9954            0 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9955              :       return NULL_TREE;
    9956              : 
    9957       241315 :     case BUILT_IN_ISNAN:
    9958       241315 :       if (tree_expr_nan_p (arg))
    9959            0 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9960       241315 :       if (!tree_expr_maybe_nan_p (arg))
    9961          124 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9962              :       return NULL_TREE;
    9963              : 
    9964        27815 :     case BUILT_IN_ISSIGNALING:
    9965              :       /* Folding to true for REAL_CST is done in fold_const_call_ss.
    9966              :          Don't use tree_expr_signaling_nan_p (arg) -> integer_one_node
    9967              :          and !tree_expr_maybe_signaling_nan_p (arg) -> integer_zero_node
    9968              :          here, so there is some possibility of __builtin_issignaling working
    9969              :          without -fsignaling-nans.  Especially when -fno-signaling-nans is
    9970              :          the default.  */
    9971        27815 :       if (!tree_expr_maybe_nan_p (arg))
    9972            0 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9973              :       return NULL_TREE;
    9974              : 
    9975            0 :     default:
    9976            0 :       gcc_unreachable ();
    9977              :     }
    9978              : }
    9979              : 
    9980              : /* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
    9981              :    This builtin will generate code to return the appropriate floating
    9982              :    point classification depending on the value of the floating point
    9983              :    number passed in.  The possible return values must be supplied as
    9984              :    int arguments to the call in the following order: FP_NAN, FP_INFINITE,
    9985              :    FP_NORMAL, FP_SUBNORMAL and FP_ZERO.  The ellipses is for exactly
    9986              :    one floating point argument which is "type generic".  */
    9987              : 
    9988              : static tree
    9989       103782 : fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
    9990              : {
    9991       103782 :   tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
    9992              :     arg, type, res, tmp;
    9993       103782 :   machine_mode mode;
    9994       103782 :   REAL_VALUE_TYPE r;
    9995       103782 :   char buf[128];
    9996              : 
    9997              :   /* Verify the required arguments in the original call.  */
    9998       103782 :   if (nargs != 6
    9999       103782 :       || !validate_arg (args[0], INTEGER_TYPE)
   10000       103782 :       || !validate_arg (args[1], INTEGER_TYPE)
   10001       103782 :       || !validate_arg (args[2], INTEGER_TYPE)
   10002       103782 :       || !validate_arg (args[3], INTEGER_TYPE)
   10003       103782 :       || !validate_arg (args[4], INTEGER_TYPE)
   10004       207564 :       || !validate_arg (args[5], REAL_TYPE))
   10005              :     return NULL_TREE;
   10006              : 
   10007       103782 :   fp_nan = args[0];
   10008       103782 :   fp_infinite = args[1];
   10009       103782 :   fp_normal = args[2];
   10010       103782 :   fp_subnormal = args[3];
   10011       103782 :   fp_zero = args[4];
   10012       103782 :   arg = args[5];
   10013       103782 :   type = TREE_TYPE (arg);
   10014       103782 :   mode = TYPE_MODE (type);
   10015       103782 :   arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
   10016              : 
   10017              :   /* fpclassify(x) ->
   10018              :        isnan(x) ? FP_NAN :
   10019              :          (fabs(x) == Inf ? FP_INFINITE :
   10020              :            (fabs(x) >= DBL_MIN ? FP_NORMAL :
   10021              :              (x == 0 ? FP_ZERO : FP_SUBNORMAL))).  */
   10022              : 
   10023       103782 :   tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   10024              :                          build_real (type, dconst0));
   10025       103782 :   res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
   10026              :                          tmp, fp_zero, fp_subnormal);
   10027              : 
   10028       103782 :   if (DECIMAL_FLOAT_MODE_P (mode))
   10029            3 :     sprintf (buf, "1E%d", REAL_MODE_FORMAT (mode)->emin - 1);
   10030              :   else
   10031       103779 :     sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
   10032       103782 :   real_from_string3 (&r, buf, mode);
   10033       103782 :   tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
   10034              :                          arg, build_real (type, r));
   10035       103782 :   res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10036              :                          fp_normal, res);
   10037              : 
   10038       103782 :   if (tree_expr_maybe_infinite_p (arg))
   10039              :     {
   10040       103694 :       tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   10041              :                              build_real (type, dconstinf));
   10042       103694 :       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10043              :                              fp_infinite, res);
   10044              :     }
   10045              : 
   10046       103782 :   if (tree_expr_maybe_nan_p (arg))
   10047              :     {
   10048       103692 :       tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
   10049       103692 :       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10050              :                              res, fp_nan);
   10051              :     }
   10052              : 
   10053              :   return res;
   10054              : }
   10055              : 
   10056              : /* Fold a call to an unordered comparison function such as
   10057              :    __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
   10058              :    being called and ARG0 and ARG1 are the arguments for the call.
   10059              :    UNORDERED_CODE and ORDERED_CODE are comparison codes that give
   10060              :    the opposite of the desired result.  UNORDERED_CODE is used
   10061              :    for modes that can hold NaNs and ORDERED_CODE is used for
   10062              :    the rest.  */
   10063              : 
   10064              : static tree
   10065      2815982 : fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
   10066              :                             enum tree_code unordered_code,
   10067              :                             enum tree_code ordered_code)
   10068              : {
   10069      2815982 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10070      2815982 :   enum tree_code code;
   10071      2815982 :   tree type0, type1;
   10072      2815982 :   enum tree_code code0, code1;
   10073      2815982 :   tree cmp_type = NULL_TREE;
   10074              : 
   10075      2815982 :   type0 = TREE_TYPE (arg0);
   10076      2815982 :   type1 = TREE_TYPE (arg1);
   10077              : 
   10078      2815982 :   code0 = TREE_CODE (type0);
   10079      2815982 :   code1 = TREE_CODE (type1);
   10080              : 
   10081      2815982 :   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
   10082              :     /* Choose the wider of two real types.  */
   10083      2815802 :     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   10084      2815802 :       ? type0 : type1;
   10085          180 :   else if (code0 == REAL_TYPE
   10086           91 :            && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
   10087              :     cmp_type = type0;
   10088           89 :   else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
   10089           89 :            && code1 == REAL_TYPE)
   10090          135 :     cmp_type = type1;
   10091              : 
   10092      2815982 :   arg0 = fold_convert_loc (loc, cmp_type, arg0);
   10093      2815982 :   arg1 = fold_convert_loc (loc, cmp_type, arg1);
   10094              : 
   10095      2815982 :   if (unordered_code == UNORDERED_EXPR)
   10096              :     {
   10097       239175 :       if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
   10098           16 :         return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
   10099       239159 :       if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
   10100          141 :         return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
   10101       239018 :       return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
   10102              :     }
   10103              : 
   10104      2579658 :   code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
   10105      2576807 :          ? unordered_code : ordered_code;
   10106      2576807 :   return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
   10107      2576807 :                       fold_build2_loc (loc, code, type, arg0, arg1));
   10108              : }
   10109              : 
   10110              : /* Fold a call to __builtin_iseqsig().  ARG0 and ARG1 are the arguments.
   10111              :    After choosing the wider floating-point type for the comparison,
   10112              :    the code is folded to:
   10113              :      SAVE_EXPR<ARG0> >= SAVE_EXPR<ARG1> && SAVE_EXPR<ARG0> <= SAVE_EXPR<ARG1>  */
   10114              : 
   10115              : static tree
   10116          709 : fold_builtin_iseqsig (location_t loc, tree arg0, tree arg1)
   10117              : {
   10118          709 :   tree type0, type1;
   10119          709 :   enum tree_code code0, code1;
   10120          709 :   tree cmp1, cmp2, cmp_type = NULL_TREE;
   10121              : 
   10122          709 :   type0 = TREE_TYPE (arg0);
   10123          709 :   type1 = TREE_TYPE (arg1);
   10124              : 
   10125          709 :   code0 = TREE_CODE (type0);
   10126          709 :   code1 = TREE_CODE (type1);
   10127              : 
   10128          709 :   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
   10129              :     /* Choose the wider of two real types.  */
   10130          690 :     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   10131          690 :       ? type0 : type1;
   10132           19 :   else if (code0 == REAL_TYPE
   10133            6 :            && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
   10134              :     cmp_type = type0;
   10135           13 :   else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
   10136           13 :            && code1 == REAL_TYPE)
   10137           13 :     cmp_type = type1;
   10138              : 
   10139          709 :   arg0 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg0));
   10140          709 :   arg1 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg1));
   10141              : 
   10142          709 :   cmp1 = fold_build2_loc (loc, GE_EXPR, integer_type_node, arg0, arg1);
   10143          709 :   cmp2 = fold_build2_loc (loc, LE_EXPR, integer_type_node, arg0, arg1);
   10144              : 
   10145          709 :   return fold_build2_loc (loc, TRUTH_AND_EXPR, integer_type_node, cmp1, cmp2);
   10146              : }
   10147              : 
   10148              : /* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
   10149              :    arithmetics if it can never overflow, or into internal functions that
   10150              :    return both result of arithmetics and overflowed boolean flag in
   10151              :    a complex integer result, or some other check for overflow.
   10152              :    Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
   10153              :    checking part of that.  */
   10154              : 
   10155              : static tree
   10156       505085 : fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
   10157              :                              tree arg0, tree arg1, tree arg2)
   10158              : {
   10159       505085 :   enum internal_fn ifn = IFN_LAST;
   10160              :   /* The code of the expression corresponding to the built-in.  */
   10161       505085 :   enum tree_code opcode = ERROR_MARK;
   10162       505085 :   bool ovf_only = false;
   10163              : 
   10164       505085 :   switch (fcode)
   10165              :     {
   10166              :     case BUILT_IN_ADD_OVERFLOW_P:
   10167              :       ovf_only = true;
   10168              :       /* FALLTHRU */
   10169              :     case BUILT_IN_ADD_OVERFLOW:
   10170              :     case BUILT_IN_SADD_OVERFLOW:
   10171              :     case BUILT_IN_SADDL_OVERFLOW:
   10172              :     case BUILT_IN_SADDLL_OVERFLOW:
   10173              :     case BUILT_IN_UADD_OVERFLOW:
   10174              :     case BUILT_IN_UADDL_OVERFLOW:
   10175              :     case BUILT_IN_UADDLL_OVERFLOW:
   10176              :       opcode = PLUS_EXPR;
   10177              :       ifn = IFN_ADD_OVERFLOW;
   10178              :       break;
   10179        15577 :     case BUILT_IN_SUB_OVERFLOW_P:
   10180        15577 :       ovf_only = true;
   10181              :       /* FALLTHRU */
   10182        37511 :     case BUILT_IN_SUB_OVERFLOW:
   10183        37511 :     case BUILT_IN_SSUB_OVERFLOW:
   10184        37511 :     case BUILT_IN_SSUBL_OVERFLOW:
   10185        37511 :     case BUILT_IN_SSUBLL_OVERFLOW:
   10186        37511 :     case BUILT_IN_USUB_OVERFLOW:
   10187        37511 :     case BUILT_IN_USUBL_OVERFLOW:
   10188        37511 :     case BUILT_IN_USUBLL_OVERFLOW:
   10189        37511 :       opcode = MINUS_EXPR;
   10190        37511 :       ifn = IFN_SUB_OVERFLOW;
   10191        37511 :       break;
   10192        15871 :     case BUILT_IN_MUL_OVERFLOW_P:
   10193        15871 :       ovf_only = true;
   10194              :       /* FALLTHRU */
   10195       428384 :     case BUILT_IN_MUL_OVERFLOW:
   10196       428384 :     case BUILT_IN_SMUL_OVERFLOW:
   10197       428384 :     case BUILT_IN_SMULL_OVERFLOW:
   10198       428384 :     case BUILT_IN_SMULLL_OVERFLOW:
   10199       428384 :     case BUILT_IN_UMUL_OVERFLOW:
   10200       428384 :     case BUILT_IN_UMULL_OVERFLOW:
   10201       428384 :     case BUILT_IN_UMULLL_OVERFLOW:
   10202       428384 :       opcode = MULT_EXPR;
   10203       428384 :       ifn = IFN_MUL_OVERFLOW;
   10204       428384 :       break;
   10205            0 :     default:
   10206            0 :       gcc_unreachable ();
   10207              :     }
   10208              : 
   10209              :   /* For the "generic" overloads, the first two arguments can have different
   10210              :      types and the last argument determines the target type to use to check
   10211              :      for overflow.  The arguments of the other overloads all have the same
   10212              :      type.  */
   10213       505085 :   tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
   10214              : 
   10215              :   /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
   10216              :      arguments are constant, attempt to fold the built-in call into a constant
   10217              :      expression indicating whether or not it detected an overflow.  */
   10218       505085 :   if (ovf_only
   10219        43258 :       && TREE_CODE (arg0) == INTEGER_CST
   10220        13131 :       && TREE_CODE (arg1) == INTEGER_CST)
   10221              :     /* Perform the computation in the target type and check for overflow.  */
   10222         7347 :     return omit_one_operand_loc (loc, boolean_type_node,
   10223         7347 :                                  arith_overflowed_p (opcode, type, arg0, arg1)
   10224              :                                  ? boolean_true_node : boolean_false_node,
   10225         7347 :                                  arg2);
   10226              : 
   10227       497738 :   tree intres, ovfres;
   10228       497738 :   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
   10229              :     {
   10230        86952 :       intres = fold_binary_loc (loc, opcode, type,
   10231              :                                 fold_convert_loc (loc, type, arg0),
   10232              :                                 fold_convert_loc (loc, type, arg1));
   10233        86952 :       if (TREE_OVERFLOW (intres))
   10234         1629 :         intres = drop_tree_overflow (intres);
   10235       173904 :       ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
   10236        86952 :                 ? boolean_true_node : boolean_false_node);
   10237              :     }
   10238              :   else
   10239              :     {
   10240       410786 :       tree ctype = build_complex_type (type);
   10241       410786 :       tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10242              :                                                 arg0, arg1);
   10243       410786 :       tree tgt;
   10244       410786 :       if (ovf_only)
   10245              :         {
   10246              :           tgt = call;
   10247       410786 :           intres = NULL_TREE;
   10248              :         }
   10249              :       else
   10250              :         {
   10251              :           /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
   10252              :              as while the call itself is const, the REALPART_EXPR store is
   10253              :              certainly not.  And in any case, we want just one call,
   10254              :              not multiple and trying to CSE them later.  */
   10255       374875 :           TREE_SIDE_EFFECTS (call) = 1;
   10256       374875 :           tgt = save_expr (call);
   10257              :         }
   10258       410786 :       intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10259       410786 :       ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10260       410786 :       ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
   10261              :     }
   10262              : 
   10263       497738 :   if (ovf_only)
   10264        35911 :     return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
   10265              : 
   10266       461827 :   tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
   10267       461827 :   tree store
   10268       461827 :     = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
   10269       461827 :   return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
   10270              : }
   10271              : 
   10272              : /* Fold __builtin_{clz,ctz,clrsb,ffs,parity,popcount}g into corresponding
   10273              :    internal function.  */
   10274              : 
   10275              : static tree
   10276       263396 : fold_builtin_bit_query (location_t loc, enum built_in_function fcode,
   10277              :                         tree arg0, tree arg1)
   10278              : {
   10279       263396 :   enum internal_fn ifn;
   10280       263396 :   enum built_in_function fcodei, fcodel, fcodell;
   10281       263396 :   tree arg0_type = TREE_TYPE (arg0);
   10282       263396 :   tree cast_type = NULL_TREE;
   10283       263396 :   int addend = 0;
   10284              : 
   10285       263396 :   switch (fcode)
   10286              :     {
   10287       186245 :     case BUILT_IN_CLZG:
   10288       186245 :       if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
   10289              :         return NULL_TREE;
   10290              :       ifn = IFN_CLZ;
   10291              :       fcodei = BUILT_IN_CLZ;
   10292              :       fcodel = BUILT_IN_CLZL;
   10293              :       fcodell = BUILT_IN_CLZLL;
   10294              :       break;
   10295        66419 :     case BUILT_IN_CTZG:
   10296        66419 :       if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
   10297              :         return NULL_TREE;
   10298              :       ifn = IFN_CTZ;
   10299              :       fcodei = BUILT_IN_CTZ;
   10300              :       fcodel = BUILT_IN_CTZL;
   10301              :       fcodell = BUILT_IN_CTZLL;
   10302              :       break;
   10303              :     case BUILT_IN_CLRSBG:
   10304              :       ifn = IFN_CLRSB;
   10305              :       fcodei = BUILT_IN_CLRSB;
   10306              :       fcodel = BUILT_IN_CLRSBL;
   10307              :       fcodell = BUILT_IN_CLRSBLL;
   10308              :       break;
   10309           84 :     case BUILT_IN_FFSG:
   10310           84 :       ifn = IFN_FFS;
   10311           84 :       fcodei = BUILT_IN_FFS;
   10312           84 :       fcodel = BUILT_IN_FFSL;
   10313           84 :       fcodell = BUILT_IN_FFSLL;
   10314           84 :       break;
   10315           77 :     case BUILT_IN_PARITYG:
   10316           77 :       ifn = IFN_PARITY;
   10317           77 :       fcodei = BUILT_IN_PARITY;
   10318           77 :       fcodel = BUILT_IN_PARITYL;
   10319           77 :       fcodell = BUILT_IN_PARITYLL;
   10320           77 :       break;
   10321        10489 :     case BUILT_IN_POPCOUNTG:
   10322        10489 :       ifn = IFN_POPCOUNT;
   10323        10489 :       fcodei = BUILT_IN_POPCOUNT;
   10324        10489 :       fcodel = BUILT_IN_POPCOUNTL;
   10325        10489 :       fcodell = BUILT_IN_POPCOUNTLL;
   10326        10489 :       break;
   10327            0 :     default:
   10328            0 :       gcc_unreachable ();
   10329              :     }
   10330              : 
   10331       263226 :   if (TYPE_PRECISION (arg0_type)
   10332       263226 :       <= TYPE_PRECISION (long_long_unsigned_type_node))
   10333              :     {
   10334       224380 :       if (TYPE_PRECISION (arg0_type) <= TYPE_PRECISION (unsigned_type_node))
   10335              : 
   10336        78531 :         cast_type = (TYPE_UNSIGNED (arg0_type)
   10337        78477 :                      ? unsigned_type_node : integer_type_node);
   10338       145903 :       else if (TYPE_PRECISION (arg0_type)
   10339       145903 :                <= TYPE_PRECISION (long_unsigned_type_node))
   10340              :         {
   10341       145873 :           cast_type = (TYPE_UNSIGNED (arg0_type)
   10342       145801 :                        ? long_unsigned_type_node : long_integer_type_node);
   10343              :           fcodei = fcodel;
   10344              :         }
   10345              :       else
   10346              :         {
   10347          102 :           cast_type = (TYPE_UNSIGNED (arg0_type)
   10348          102 :                        ? long_long_unsigned_type_node
   10349              :                        : long_long_integer_type_node);
   10350              :           fcodei = fcodell;
   10351              :         }
   10352              :     }
   10353        77692 :   else if (TYPE_PRECISION (arg0_type) <= MAX_FIXED_MODE_SIZE)
   10354              :     {
   10355        38740 :       cast_type
   10356        38740 :         = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
   10357        38740 :                                           TYPE_UNSIGNED (arg0_type));
   10358        38740 :       gcc_assert (TYPE_PRECISION (cast_type)
   10359              :                   == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
   10360              :       fcodei = END_BUILTINS;
   10361              :     }
   10362              :   else
   10363              :     fcodei = END_BUILTINS;
   10364       263120 :   if (cast_type)
   10365              :     {
   10366       263120 :       switch (fcode)
   10367              :         {
   10368       186209 :         case BUILT_IN_CLZG:
   10369       186209 :         case BUILT_IN_CLRSBG:
   10370       186209 :           addend = TYPE_PRECISION (arg0_type) - TYPE_PRECISION (cast_type);
   10371       186209 :           break;
   10372              :         default:
   10373              :           break;
   10374              :         }
   10375       263120 :       arg0 = fold_convert (cast_type, arg0);
   10376       263120 :       arg0_type = cast_type;
   10377              :     }
   10378              : 
   10379       263226 :   if (arg1)
   10380       174896 :     arg1 = fold_convert (integer_type_node, arg1);
   10381              : 
   10382       263226 :   tree arg2 = arg1;
   10383       263226 :   if (fcode == BUILT_IN_CLZG && addend)
   10384              :     {
   10385         4230 :       if (arg1)
   10386         4197 :         arg0 = save_expr (arg0);
   10387              :       arg2 = NULL_TREE;
   10388              :     }
   10389       263226 :   tree call = NULL_TREE, tem;
   10390       263226 :   if (TYPE_PRECISION (arg0_type) == MAX_FIXED_MODE_SIZE
   10391        38842 :       && (TYPE_PRECISION (arg0_type)
   10392        38842 :           == 2 * TYPE_PRECISION (long_long_unsigned_type_node))
   10393              :       /* If the target supports the optab, then don't do the expansion. */
   10394       301966 :       && !direct_internal_fn_supported_p (ifn, arg0_type, OPTIMIZE_FOR_BOTH))
   10395              :     {
   10396              :       /* __int128 expansions using up to 2 long long builtins.  */
   10397        38740 :       arg0 = save_expr (arg0);
   10398        38740 :       tree type = (TYPE_UNSIGNED (arg0_type)
   10399        38740 :                    ? long_long_unsigned_type_node
   10400        38740 :                    : long_long_integer_type_node);
   10401        77480 :       tree hi = fold_build2 (RSHIFT_EXPR, arg0_type, arg0,
   10402              :                              build_int_cst (integer_type_node,
   10403              :                                             MAX_FIXED_MODE_SIZE / 2));
   10404        38740 :       hi = fold_convert (type, hi);
   10405        38740 :       tree lo = fold_convert (type, arg0);
   10406        38740 :       switch (fcode)
   10407              :         {
   10408        38657 :         case BUILT_IN_CLZG:
   10409        38657 :           call = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
   10410        77314 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10411              :                               build_int_cst (integer_type_node,
   10412              :                                              MAX_FIXED_MODE_SIZE / 2));
   10413        38657 :           if (arg2)
   10414        38637 :             call = fold_build3 (COND_EXPR, integer_type_node,
   10415              :                                 fold_build2 (NE_EXPR, boolean_type_node,
   10416              :                                              lo, build_zero_cst (type)),
   10417              :                                 call, arg2);
   10418        38657 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10419              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10420              :                                            hi, build_zero_cst (type)),
   10421              :                               fold_builtin_bit_query (loc, fcode, hi,
   10422              :                                                       NULL_TREE),
   10423              :                               call);
   10424        38657 :           break;
   10425           27 :         case BUILT_IN_CTZG:
   10426           27 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10427           54 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10428              :                               build_int_cst (integer_type_node,
   10429              :                                              MAX_FIXED_MODE_SIZE / 2));
   10430           27 :           if (arg2)
   10431           18 :             call = fold_build3 (COND_EXPR, integer_type_node,
   10432              :                                 fold_build2 (NE_EXPR, boolean_type_node,
   10433              :                                              hi, build_zero_cst (type)),
   10434              :                                 call, arg2);
   10435           27 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10436              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10437              :                                            lo, build_zero_cst (type)),
   10438              :                               fold_builtin_bit_query (loc, fcode, lo,
   10439              :                                                       NULL_TREE),
   10440              :                               call);
   10441           27 :           break;
   10442            9 :         case BUILT_IN_CLRSBG:
   10443            9 :           tem = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
   10444           18 :           tem = fold_build2 (PLUS_EXPR, integer_type_node, tem,
   10445              :                              build_int_cst (integer_type_node,
   10446              :                                             MAX_FIXED_MODE_SIZE / 2));
   10447           18 :           tem = fold_build3 (COND_EXPR, integer_type_node,
   10448              :                              fold_build2 (LT_EXPR, boolean_type_node,
   10449              :                                           fold_build2 (BIT_XOR_EXPR, type,
   10450              :                                                        lo, hi),
   10451              :                                           build_zero_cst (type)),
   10452              :                              build_int_cst (integer_type_node,
   10453              :                                             MAX_FIXED_MODE_SIZE / 2 - 1),
   10454              :                              tem);
   10455            9 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10456            9 :           call = save_expr (call);
   10457           18 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10458              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10459              :                                            call,
   10460              :                                            build_int_cst (integer_type_node,
   10461              :                                                           MAX_FIXED_MODE_SIZE
   10462              :                                                           / 2 - 1)),
   10463              :                               call, tem);
   10464            9 :           break;
   10465            9 :         case BUILT_IN_FFSG:
   10466            9 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10467           18 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10468              :                               build_int_cst (integer_type_node,
   10469              :                                              MAX_FIXED_MODE_SIZE / 2));
   10470            9 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10471              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10472              :                                            hi, build_zero_cst (type)),
   10473              :                               call, integer_zero_node);
   10474            9 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10475              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10476              :                                            lo, build_zero_cst (type)),
   10477              :                               fold_builtin_bit_query (loc, fcode, lo,
   10478              :                                                       NULL_TREE),
   10479              :                               call);
   10480            9 :           break;
   10481            9 :         case BUILT_IN_PARITYG:
   10482            9 :           call = fold_builtin_bit_query (loc, fcode,
   10483              :                                          fold_build2 (BIT_XOR_EXPR, type,
   10484              :                                                       lo, hi), NULL_TREE);
   10485            9 :           break;
   10486           29 :         case BUILT_IN_POPCOUNTG:
   10487           29 :           call = fold_build2 (PLUS_EXPR, integer_type_node,
   10488              :                               fold_builtin_bit_query (loc, fcode, hi,
   10489              :                                                       NULL_TREE),
   10490              :                               fold_builtin_bit_query (loc, fcode, lo,
   10491              :                                                       NULL_TREE));
   10492           29 :           break;
   10493            0 :         default:
   10494            0 :           gcc_unreachable ();
   10495              :         }
   10496              :     }
   10497              :   else
   10498              :     {
   10499              :       /* Only keep second argument to IFN_CLZ/IFN_CTZ if it is the
   10500              :          value defined at zero during GIMPLE, or for large/huge _BitInt
   10501              :          (which are then lowered during bitint lowering).  */
   10502       224486 :       if (arg2 && !BITINT_TYPE_P (TREE_TYPE (arg0)))
   10503              :         {
   10504       132024 :           int val;
   10505       132024 :           if (fcode == BUILT_IN_CLZG)
   10506              :             {
   10507        65881 :               if (CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
   10508              :                                              val) != 2
   10509        65881 :                   || wi::to_widest (arg2) != val)
   10510        65851 :                 arg2 = NULL_TREE;
   10511              :             }
   10512        66143 :           else if (CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
   10513              :                                               val) != 2
   10514        66143 :                    || wi::to_widest (arg2) != val)
   10515        66134 :             arg2 = NULL_TREE;
   10516       132024 :           if (!direct_internal_fn_supported_p (ifn, arg0_type,
   10517              :                                                OPTIMIZE_FOR_BOTH))
   10518              :             arg2 = NULL_TREE;
   10519       131925 :           if (arg2 == NULL_TREE)
   10520       131985 :             arg0 = save_expr (arg0);
   10521              :         }
   10522       224486 :       if (fcodei == END_BUILTINS || arg2)
   10523          231 :         call = build_call_expr_internal_loc (loc, ifn, integer_type_node,
   10524              :                                              arg2 ? 2 : 1, arg0, arg2);
   10525              :       else
   10526       224341 :         call = build_call_expr_loc (loc, builtin_decl_explicit (fcodei), 1,
   10527              :                                     arg0);
   10528              :     }
   10529       263226 :   if (addend)
   10530         4248 :     call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10531              :                         build_int_cst (integer_type_node, addend));
   10532       263226 :   if (arg1 && arg2 == NULL_TREE)
   10533       136182 :     call = fold_build3 (COND_EXPR, integer_type_node,
   10534              :                         fold_build2 (NE_EXPR, boolean_type_node,
   10535              :                                      arg0, build_zero_cst (arg0_type)),
   10536              :                         call, arg1);
   10537              : 
   10538              :   return call;
   10539              : }
   10540              : 
   10541              : /* Fold or build a __builtin_bswapg (ARG) (if IFN is IFN_BSWAP) or
   10542              :    __builtin_bitreverseg (ARG (otherwise) call.  The FE should have
   10543              :    verified earlier that the argument type is unsigned INTEGER_TYPE
   10544              :    or BITINT_TYPE, for __builtin_bswapg with precision divisible by 8.  */
   10545              : 
   10546              : tree
   10547          148 : fold_build_builtin_bswapg_bitreverseg (location_t loc, enum internal_fn ifn,
   10548              :                                        tree arg)
   10549              : {
   10550          148 :   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
   10551          148 :   if (ifn == IFN_BSWAP && TYPE_PRECISION (type) == 8)
   10552           11 :     return fold_convert_loc (loc, type, arg);
   10553          137 :   struct { tree type; built_in_function bswap, bitreverse; } fns[]
   10554          137 :     = { { unsigned_char_type_node, END_BUILTINS, BUILT_IN_BITREVERSE8 },
   10555          137 :         { uint16_type_node, BUILT_IN_BSWAP16, BUILT_IN_BITREVERSE16 },
   10556          137 :         { uint32_type_node, BUILT_IN_BSWAP32, BUILT_IN_BITREVERSE32 },
   10557          137 :         { uint64_type_node, BUILT_IN_BSWAP64, BUILT_IN_BITREVERSE64 },
   10558          137 :         { uint128_type_node, BUILT_IN_BSWAP128, BUILT_IN_BITREVERSE128 } };
   10559          137 :   if (TREE_CODE (arg) == INTEGER_CST)
   10560              :     {
   10561           76 :       wide_int res;
   10562           76 :       if (ifn == IFN_BSWAP)
   10563           37 :         res = wi::bswap (wi::to_wide (arg));
   10564              :       else
   10565           45 :         res = wi::bitreverse (wi::to_wide (arg));
   10566           76 :       return wide_int_to_tree (type, res);
   10567           76 :     }
   10568          232 :   for (unsigned i = 0; i < ARRAY_SIZE (fns); ++i)
   10569          219 :     if (fns[i].type
   10570          219 :         && TYPE_PRECISION (fns[i].type) >= TYPE_PRECISION (type))
   10571              :       {
   10572           48 :         arg = fold_convert_loc (loc, fns[i].type, arg);
   10573           48 :         tree fndecl
   10574           48 :           = builtin_decl_explicit (ifn == IFN_BSWAP
   10575              :                                    ? fns[i].bswap : fns[i].bitreverse);
   10576           48 :         tree ret = build_call_expr_loc (loc, fndecl, 1, arg);
   10577           48 :         if (TYPE_PRECISION (type) != TYPE_PRECISION (fns[i].type))
   10578            4 :           ret = fold_build2_loc (loc, RSHIFT_EXPR, fns[i].type, ret,
   10579              :                                  build_int_cst (unsigned_type_node,
   10580            4 :                                                 TYPE_PRECISION (fns[i].type)
   10581            4 :                                                 - TYPE_PRECISION (type)));
   10582           48 :         return fold_convert_loc (loc, type, ret);
   10583              :       }
   10584           13 :   gcc_assert (TREE_CODE (type) == BITINT_TYPE);
   10585           13 :   return build_call_expr_internal_loc (loc, ifn, type, 1, arg);
   10586              : }
   10587              : 
   10588              : /* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
   10589              :    that return both result of arithmetics and overflowed boolean
   10590              :    flag in a complex integer result.  */
   10591              : 
   10592              : static tree
   10593           54 : fold_builtin_addc_subc (location_t loc, enum built_in_function fcode,
   10594              :                         tree *args)
   10595              : {
   10596           54 :   enum internal_fn ifn;
   10597              : 
   10598           54 :   switch (fcode)
   10599              :     {
   10600              :     case BUILT_IN_ADDC:
   10601              :     case BUILT_IN_ADDCL:
   10602              :     case BUILT_IN_ADDCLL:
   10603              :       ifn = IFN_ADD_OVERFLOW;
   10604              :       break;
   10605           28 :     case BUILT_IN_SUBC:
   10606           28 :     case BUILT_IN_SUBCL:
   10607           28 :     case BUILT_IN_SUBCLL:
   10608           28 :       ifn = IFN_SUB_OVERFLOW;
   10609           28 :       break;
   10610            0 :     default:
   10611            0 :       gcc_unreachable ();
   10612              :     }
   10613              : 
   10614           54 :   tree type = TREE_TYPE (args[0]);
   10615           54 :   tree ctype = build_complex_type (type);
   10616           54 :   tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10617              :                                             args[0], args[1]);
   10618              :   /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
   10619              :      as while the call itself is const, the REALPART_EXPR store is
   10620              :      certainly not.  And in any case, we want just one call,
   10621              :      not multiple and trying to CSE them later.  */
   10622           54 :   TREE_SIDE_EFFECTS (call) = 1;
   10623           54 :   tree tgt = save_expr (call);
   10624           54 :   tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10625           54 :   tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10626           54 :   call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10627              :                                        intres, args[2]);
   10628           54 :   TREE_SIDE_EFFECTS (call) = 1;
   10629           54 :   tgt = save_expr (call);
   10630           54 :   intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10631           54 :   tree ovfres2 = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10632           54 :   ovfres = build2_loc (loc, BIT_IOR_EXPR, type, ovfres, ovfres2);
   10633           54 :   tree mem_arg3 = build_fold_indirect_ref_loc (loc, args[3]);
   10634           54 :   tree store
   10635           54 :     = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg3, ovfres);
   10636           54 :   return build2_loc (loc, COMPOUND_EXPR, type, store, intres);
   10637              : }
   10638              : 
   10639              : /* Fold a call to __builtin_FILE to a constant string.  */
   10640              : 
   10641              : static inline tree
   10642         5784 : fold_builtin_FILE (location_t loc)
   10643              : {
   10644         5784 :   if (const char *fname = LOCATION_FILE (loc))
   10645              :     {
   10646              :       /* The documentation says this builtin is equivalent to the preprocessor
   10647              :          __FILE__ macro so it appears appropriate to use the same file prefix
   10648              :          mappings.  */
   10649         5784 :       fname = remap_macro_filename (fname);
   10650         5784 :       return build_string_literal (fname);
   10651              :     }
   10652              : 
   10653            0 :   return build_string_literal ("");
   10654              : }
   10655              : 
   10656              : /* Fold a call to __builtin_FUNCTION to a constant string.  */
   10657              : 
   10658              : static inline tree
   10659           68 : fold_builtin_FUNCTION ()
   10660              : {
   10661           68 :   const char *name = "";
   10662              : 
   10663           68 :   if (current_function_decl)
   10664           43 :     name = lang_hooks.decl_printable_name (current_function_decl, 0);
   10665              : 
   10666           68 :   return build_string_literal (name);
   10667              : }
   10668              : 
   10669              : /* Fold a call to __builtin_LINE to an integer constant.  */
   10670              : 
   10671              : static inline tree
   10672        11541 : fold_builtin_LINE (location_t loc, tree type)
   10673              : {
   10674        11541 :   return build_int_cst (type, LOCATION_LINE (loc));
   10675              : }
   10676              : 
   10677              : /* Fold a call to built-in function FNDECL with 0 arguments.
   10678              :    This function returns NULL_TREE if no simplification was possible.  */
   10679              : 
   10680              : static tree
   10681     23857150 : fold_builtin_0 (location_t loc, tree fndecl)
   10682              : {
   10683     23857150 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10684     23857150 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10685     23857150 :   switch (fcode)
   10686              :     {
   10687         5784 :     case BUILT_IN_FILE:
   10688         5784 :       return fold_builtin_FILE (loc);
   10689              : 
   10690           68 :     case BUILT_IN_FUNCTION:
   10691           68 :       return fold_builtin_FUNCTION ();
   10692              : 
   10693        11541 :     case BUILT_IN_LINE:
   10694        11541 :       return fold_builtin_LINE (loc, type);
   10695              : 
   10696        33716 :     CASE_FLT_FN (BUILT_IN_INF):
   10697        33716 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
   10698        33716 :     case BUILT_IN_INFD32:
   10699        33716 :     case BUILT_IN_INFD64:
   10700        33716 :     case BUILT_IN_INFD128:
   10701        33716 :     case BUILT_IN_INFD64X:
   10702        33716 :       return fold_builtin_inf (loc, type, true);
   10703              : 
   10704       228077 :     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
   10705       228077 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
   10706       228077 :       return fold_builtin_inf (loc, type, false);
   10707              : 
   10708            0 :     case BUILT_IN_CLASSIFY_TYPE:
   10709            0 :       return fold_builtin_classify_type (NULL_TREE);
   10710              : 
   10711     20450302 :     case BUILT_IN_UNREACHABLE:
   10712              :       /* Rewrite any explicit calls to __builtin_unreachable.  */
   10713     20450302 :       if (sanitize_flags_p (SANITIZE_UNREACHABLE))
   10714           87 :         return build_builtin_unreachable (loc);
   10715              :       break;
   10716              : 
   10717              :     default:
   10718              :       break;
   10719              :     }
   10720              :   return NULL_TREE;
   10721              : }
   10722              : 
   10723              : /* Fold a call to built-in function FNDECL with 1 argument, ARG0.
   10724              :    This function returns NULL_TREE if no simplification was possible.  */
   10725              : 
   10726              : static tree
   10727     17911713 : fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
   10728              : {
   10729     17911713 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10730     17911713 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10731              : 
   10732     17911713 :   if (error_operand_p (arg0))
   10733              :     return NULL_TREE;
   10734              : 
   10735     17911713 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0))
   10736              :     return ret;
   10737              : 
   10738     17288592 :   switch (fcode)
   10739              :     {
   10740      3063842 :     case BUILT_IN_CONSTANT_P:
   10741      3063842 :       {
   10742      3063842 :         tree val = fold_builtin_constant_p (arg0);
   10743              : 
   10744              :         /* Gimplification will pull the CALL_EXPR for the builtin out of
   10745              :            an if condition.  When not optimizing, we'll not CSE it back.
   10746              :            To avoid link error types of regressions, return false now.  */
   10747      3063842 :         if (!val && !optimize)
   10748         1548 :           val = integer_zero_node;
   10749              : 
   10750              :         return val;
   10751              :       }
   10752              : 
   10753         2082 :     case BUILT_IN_CLASSIFY_TYPE:
   10754         2082 :       return fold_builtin_classify_type (arg0);
   10755              : 
   10756       452090 :     case BUILT_IN_STRLEN:
   10757       452090 :       return fold_builtin_strlen (loc, expr, type, arg0);
   10758              : 
   10759       375037 :     CASE_FLT_FN (BUILT_IN_FABS):
   10760       375037 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   10761       375037 :     case BUILT_IN_FABSD32:
   10762       375037 :     case BUILT_IN_FABSD64:
   10763       375037 :     case BUILT_IN_FABSD128:
   10764       375037 :     case BUILT_IN_FABSD64X:
   10765       375037 :       return fold_builtin_fabs (loc, arg0, type);
   10766              : 
   10767       100472 :     case BUILT_IN_ABS:
   10768       100472 :     case BUILT_IN_LABS:
   10769       100472 :     case BUILT_IN_LLABS:
   10770       100472 :     case BUILT_IN_IMAXABS:
   10771       100472 :     case BUILT_IN_UABS:
   10772       100472 :     case BUILT_IN_ULABS:
   10773       100472 :     case BUILT_IN_ULLABS:
   10774       100472 :     case BUILT_IN_UMAXABS:
   10775       100472 :       return fold_builtin_abs (loc, arg0, type);
   10776              : 
   10777        25461 :     CASE_FLT_FN (BUILT_IN_CONJ):
   10778        25461 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10779        25461 :         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10780        25461 :         return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
   10781              :     break;
   10782              : 
   10783          764 :     CASE_FLT_FN (BUILT_IN_CREAL):
   10784          764 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10785          764 :         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10786          764 :         return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
   10787              :     break;
   10788              : 
   10789         1884 :     CASE_FLT_FN (BUILT_IN_CIMAG):
   10790         1884 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10791         1884 :           && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10792         1884 :         return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
   10793              :     break;
   10794              : 
   10795       102695 :     CASE_FLT_FN (BUILT_IN_CARG):
   10796       102695 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_CARG):
   10797       102695 :       return fold_builtin_carg (loc, arg0, type);
   10798              : 
   10799          211 :     case BUILT_IN_ISASCII:
   10800          211 :       return fold_builtin_isascii (loc, arg0);
   10801              : 
   10802          168 :     case BUILT_IN_TOASCII:
   10803          168 :       return fold_builtin_toascii (loc, arg0);
   10804              : 
   10805          325 :     case BUILT_IN_ISDIGIT:
   10806          325 :       return fold_builtin_isdigit (loc, arg0);
   10807              : 
   10808       492043 :     CASE_FLT_FN (BUILT_IN_FINITE):
   10809       492043 :     case BUILT_IN_FINITED32:
   10810       492043 :     case BUILT_IN_FINITED64:
   10811       492043 :     case BUILT_IN_FINITED128:
   10812       492043 :     case BUILT_IN_ISFINITE:
   10813       492043 :       {
   10814       492043 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
   10815       492043 :         if (ret)
   10816              :           return ret;
   10817       491771 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10818              :       }
   10819              : 
   10820       416065 :     CASE_FLT_FN (BUILT_IN_ISINF):
   10821       416065 :     case BUILT_IN_ISINFD32:
   10822       416065 :     case BUILT_IN_ISINFD64:
   10823       416065 :     case BUILT_IN_ISINFD128:
   10824       416065 :       {
   10825       416065 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
   10826       416065 :         if (ret)
   10827              :           return ret;
   10828       415904 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10829              :       }
   10830              : 
   10831       238188 :     case BUILT_IN_ISNORMAL:
   10832       238188 :       return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10833              : 
   10834          708 :     case BUILT_IN_ISINF_SIGN:
   10835          708 :       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
   10836              : 
   10837       241315 :     CASE_FLT_FN (BUILT_IN_ISNAN):
   10838       241315 :     case BUILT_IN_ISNAND32:
   10839       241315 :     case BUILT_IN_ISNAND64:
   10840       241315 :     case BUILT_IN_ISNAND128:
   10841       241315 :       {
   10842       241315 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
   10843       241315 :         if (ret)
   10844              :           return ret;
   10845       241191 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10846              :       }
   10847              : 
   10848        27815 :     case BUILT_IN_ISSIGNALING:
   10849        27815 :       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISSIGNALING);
   10850              : 
   10851       624417 :     case BUILT_IN_FREE:
   10852       624417 :       if (integer_zerop (arg0))
   10853         1063 :         return build_empty_stmt (loc);
   10854              :       break;
   10855              : 
   10856        10859 :     case BUILT_IN_CLZG:
   10857        10859 :     case BUILT_IN_CTZG:
   10858        10859 :     case BUILT_IN_CLRSBG:
   10859        10859 :     case BUILT_IN_FFSG:
   10860        10859 :     case BUILT_IN_PARITYG:
   10861        10859 :     case BUILT_IN_POPCOUNTG:
   10862        10859 :       return fold_builtin_bit_query (loc, fcode, arg0, NULL_TREE);
   10863              : 
   10864              :     default:
   10865              :       break;
   10866              :     }
   10867              : 
   10868              :   return NULL_TREE;
   10869              : 
   10870              : }
   10871              : 
   10872              : /* Folds a call EXPR (which may be null) to built-in function FNDECL
   10873              :    with 2 arguments, ARG0 and ARG1.  This function returns NULL_TREE
   10874              :    if no simplification was possible.  */
   10875              : 
   10876              : static tree
   10877     18129395 : fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
   10878              : {
   10879     18129395 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10880     18129395 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10881              : 
   10882     18129395 :   if (error_operand_p (arg0)
   10883     18129395 :       || error_operand_p (arg1))
   10884              :     return NULL_TREE;
   10885              : 
   10886     18129391 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0, arg1))
   10887              :     return ret;
   10888              : 
   10889     17914347 :   switch (fcode)
   10890              :     {
   10891         6504 :     CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
   10892         6504 :     CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
   10893         6504 :       if (validate_arg (arg0, REAL_TYPE)
   10894         6504 :           && validate_arg (arg1, POINTER_TYPE))
   10895         6504 :         return do_mpfr_lgamma_r (arg0, arg1, type);
   10896              :     break;
   10897              : 
   10898        92055 :     CASE_FLT_FN (BUILT_IN_FREXP):
   10899        92055 :       return fold_builtin_frexp (loc, arg0, arg1, type);
   10900              : 
   10901        69262 :     CASE_FLT_FN (BUILT_IN_MODF):
   10902        69262 :       return fold_builtin_modf (loc, arg0, arg1, type);
   10903              : 
   10904         2560 :     case BUILT_IN_STRSPN:
   10905         2560 :       return fold_builtin_strspn (loc, expr, arg0, arg1, type);
   10906              : 
   10907         2465 :     case BUILT_IN_STRCSPN:
   10908         2465 :       return fold_builtin_strcspn (loc, expr, arg0, arg1, type);
   10909              : 
   10910        80063 :     case BUILT_IN_STRPBRK:
   10911        80063 :       return fold_builtin_strpbrk (loc, expr, arg0, arg1, type);
   10912              : 
   10913      6541292 :     case BUILT_IN_EXPECT:
   10914      6541292 :       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
   10915              : 
   10916       654247 :     case BUILT_IN_ISGREATER:
   10917       654247 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10918       654247 :                                          arg0, arg1, UNLE_EXPR, LE_EXPR);
   10919       476466 :     case BUILT_IN_ISGREATEREQUAL:
   10920       476466 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10921       476466 :                                          arg0, arg1, UNLT_EXPR, LT_EXPR);
   10922       239847 :     case BUILT_IN_ISLESS:
   10923       239847 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10924       239847 :                                          arg0, arg1, UNGE_EXPR, GE_EXPR);
   10925       968266 :     case BUILT_IN_ISLESSEQUAL:
   10926       968266 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10927       968266 :                                          arg0, arg1, UNGT_EXPR, GT_EXPR);
   10928       237981 :     case BUILT_IN_ISLESSGREATER:
   10929       237981 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10930       237981 :                                          arg0, arg1, UNEQ_EXPR, EQ_EXPR);
   10931       239175 :     case BUILT_IN_ISUNORDERED:
   10932       239175 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10933              :                                          arg0, arg1, UNORDERED_EXPR,
   10934       239175 :                                          NOP_EXPR);
   10935              : 
   10936          709 :     case BUILT_IN_ISEQSIG:
   10937          709 :       return fold_builtin_iseqsig (loc, arg0, arg1);
   10938              : 
   10939              :       /* We do the folding for va_start in the expander.  */
   10940              :     case BUILT_IN_VA_START:
   10941              :       break;
   10942              : 
   10943       200235 :     case BUILT_IN_OBJECT_SIZE:
   10944       200235 :     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
   10945       200235 :       return fold_builtin_object_size (arg0, arg1, fcode);
   10946              : 
   10947       105027 :     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
   10948       105027 :       return fold_builtin_atomic_always_lock_free (arg0, arg1);
   10949              : 
   10950        38439 :     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
   10951        38439 :       return fold_builtin_atomic_is_lock_free (arg0, arg1);
   10952              : 
   10953       175066 :     case BUILT_IN_CLZG:
   10954       175066 :     case BUILT_IN_CTZG:
   10955       175066 :       return fold_builtin_bit_query (loc, fcode, arg0, arg1);
   10956              : 
   10957              :     default:
   10958              :       break;
   10959              :     }
   10960              :   return NULL_TREE;
   10961              : }
   10962              : 
   10963              : /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
   10964              :    and ARG2.
   10965              :    This function returns NULL_TREE if no simplification was possible.  */
   10966              : 
   10967              : static tree
   10968      7045749 : fold_builtin_3 (location_t loc, tree fndecl,
   10969              :                 tree arg0, tree arg1, tree arg2)
   10970              : {
   10971      7045749 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10972      7045749 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10973              : 
   10974      7045749 :   if (error_operand_p (arg0)
   10975      7045749 :       || error_operand_p (arg1)
   10976     14091498 :       || error_operand_p (arg2))
   10977              :     return NULL_TREE;
   10978              : 
   10979      7045747 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type,
   10980              :                                   arg0, arg1, arg2))
   10981              :     return ret;
   10982              : 
   10983      7028751 :   switch (fcode)
   10984              :     {
   10985              : 
   10986          145 :     CASE_FLT_FN (BUILT_IN_SINCOS):
   10987          145 :       return fold_builtin_sincos (loc, arg0, arg1, arg2);
   10988              : 
   10989        76253 :     CASE_FLT_FN (BUILT_IN_REMQUO):
   10990        76253 :       if (validate_arg (arg0, REAL_TYPE)
   10991        76253 :           && validate_arg (arg1, REAL_TYPE)
   10992       152506 :           && validate_arg (arg2, POINTER_TYPE))
   10993        76253 :         return do_mpfr_remquo (arg0, arg1, arg2);
   10994              :     break;
   10995              : 
   10996      2538325 :     case BUILT_IN_MEMCMP:
   10997      2538325 :       return fold_builtin_memcmp (loc, arg0, arg1, arg2);
   10998              : 
   10999       510954 :     case BUILT_IN_EXPECT:
   11000       510954 :       return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
   11001              : 
   11002          337 :     case BUILT_IN_EXPECT_WITH_PROBABILITY:
   11003          337 :       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg2);
   11004              : 
   11005       505085 :     case BUILT_IN_ADD_OVERFLOW:
   11006       505085 :     case BUILT_IN_SUB_OVERFLOW:
   11007       505085 :     case BUILT_IN_MUL_OVERFLOW:
   11008       505085 :     case BUILT_IN_ADD_OVERFLOW_P:
   11009       505085 :     case BUILT_IN_SUB_OVERFLOW_P:
   11010       505085 :     case BUILT_IN_MUL_OVERFLOW_P:
   11011       505085 :     case BUILT_IN_SADD_OVERFLOW:
   11012       505085 :     case BUILT_IN_SADDL_OVERFLOW:
   11013       505085 :     case BUILT_IN_SADDLL_OVERFLOW:
   11014       505085 :     case BUILT_IN_SSUB_OVERFLOW:
   11015       505085 :     case BUILT_IN_SSUBL_OVERFLOW:
   11016       505085 :     case BUILT_IN_SSUBLL_OVERFLOW:
   11017       505085 :     case BUILT_IN_SMUL_OVERFLOW:
   11018       505085 :     case BUILT_IN_SMULL_OVERFLOW:
   11019       505085 :     case BUILT_IN_SMULLL_OVERFLOW:
   11020       505085 :     case BUILT_IN_UADD_OVERFLOW:
   11021       505085 :     case BUILT_IN_UADDL_OVERFLOW:
   11022       505085 :     case BUILT_IN_UADDLL_OVERFLOW:
   11023       505085 :     case BUILT_IN_USUB_OVERFLOW:
   11024       505085 :     case BUILT_IN_USUBL_OVERFLOW:
   11025       505085 :     case BUILT_IN_USUBLL_OVERFLOW:
   11026       505085 :     case BUILT_IN_UMUL_OVERFLOW:
   11027       505085 :     case BUILT_IN_UMULL_OVERFLOW:
   11028       505085 :     case BUILT_IN_UMULLL_OVERFLOW:
   11029       505085 :       return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
   11030              : 
   11031              :     default:
   11032              :       break;
   11033              :     }
   11034              :   return NULL_TREE;
   11035              : }
   11036              : 
   11037              : /* Folds a call EXPR (which may be null) to built-in function FNDECL.
   11038              :    ARGS is an array of NARGS arguments.  IGNORE is true if the result
   11039              :    of the function call is ignored.  This function returns NULL_TREE
   11040              :    if no simplification was possible.  */
   11041              : 
   11042              : static tree
   11043     69526743 : fold_builtin_n (location_t loc, tree expr, tree fndecl, tree *args,
   11044              :                 int nargs, bool)
   11045              : {
   11046     69526743 :   tree ret = NULL_TREE;
   11047              : 
   11048     69526743 :   switch (nargs)
   11049              :     {
   11050     23857150 :     case 0:
   11051     23857150 :       ret = fold_builtin_0 (loc, fndecl);
   11052     23857150 :       break;
   11053     17911713 :     case 1:
   11054     17911713 :       ret = fold_builtin_1 (loc, expr, fndecl, args[0]);
   11055     17911713 :       break;
   11056     18129395 :     case 2:
   11057     18129395 :       ret = fold_builtin_2 (loc, expr, fndecl, args[0], args[1]);
   11058     18129395 :       break;
   11059      7045749 :     case 3:
   11060      7045749 :       ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]);
   11061      7045749 :       break;
   11062      2582736 :     default:
   11063      2582736 :       ret = fold_builtin_varargs (loc, fndecl, args, nargs);
   11064      2582736 :       break;
   11065              :     }
   11066     69526743 :   if (ret)
   11067              :     {
   11068      9152838 :       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   11069      9152838 :       SET_EXPR_LOCATION (ret, loc);
   11070      9152838 :       return ret;
   11071              :     }
   11072              :   return NULL_TREE;
   11073              : }
   11074              : 
   11075              : /* Construct a new CALL_EXPR to FNDECL using the tail of the argument
   11076              :    list ARGS along with N new arguments in NEWARGS.  SKIP is the number
   11077              :    of arguments in ARGS to be omitted.  OLDNARGS is the number of
   11078              :    elements in ARGS.  */
   11079              : 
   11080              : static tree
   11081            4 : rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
   11082              :                           int skip, tree fndecl, int n, va_list newargs)
   11083              : {
   11084            4 :   int nargs = oldnargs - skip + n;
   11085            4 :   tree *buffer;
   11086              : 
   11087            4 :   if (n > 0)
   11088              :     {
   11089            0 :       int i, j;
   11090              : 
   11091            0 :       buffer = XALLOCAVEC (tree, nargs);
   11092            0 :       for (i = 0; i < n; i++)
   11093            0 :         buffer[i] = va_arg (newargs, tree);
   11094            0 :       for (j = skip; j < oldnargs; j++, i++)
   11095            0 :         buffer[i] = args[j];
   11096              :     }
   11097              :   else
   11098            4 :     buffer = args + skip;
   11099              : 
   11100            4 :   return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
   11101              : }
   11102              : 
   11103              : /* Return true if FNDECL shouldn't be folded right now.
   11104              :    If a built-in function has an inline attribute always_inline
   11105              :    wrapper, defer folding it after always_inline functions have
   11106              :    been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
   11107              :    might not be performed.  */
   11108              : 
   11109              : bool
   11110    147306831 : avoid_folding_inline_builtin (tree fndecl)
   11111              : {
   11112    147306831 :   return (DECL_DECLARED_INLINE_P (fndecl)
   11113        13189 :           && DECL_DISREGARD_INLINE_LIMITS (fndecl)
   11114        13147 :           && cfun
   11115        13147 :           && !cfun->always_inline_functions_inlined
   11116    147319978 :           && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
   11117              : }
   11118              : 
   11119              : /* A wrapper function for builtin folding that prevents warnings for
   11120              :    "statement without effect" and the like, caused by removing the
   11121              :    call node earlier than the warning is generated.  */
   11122              : 
   11123              : tree
   11124    200068396 : fold_call_expr (location_t loc, tree exp, bool ignore)
   11125              : {
   11126    200068396 :   tree ret = NULL_TREE;
   11127    200068396 :   tree fndecl = get_callee_fndecl (exp);
   11128    198324850 :   if (fndecl && fndecl_built_in_p (fndecl)
   11129              :       /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
   11130              :          yet.  Defer folding until we see all the arguments
   11131              :          (after inlining).  */
   11132    258369588 :       && !CALL_EXPR_VA_ARG_PACK (exp))
   11133              :     {
   11134     58301162 :       int nargs = call_expr_nargs (exp);
   11135              : 
   11136              :       /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
   11137              :          instead last argument is __builtin_va_arg_pack ().  Defer folding
   11138              :          even in that case, until arguments are finalized.  */
   11139     58301162 :       if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
   11140              :         {
   11141       222227 :           tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
   11142       222227 :           if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   11143              :             return NULL_TREE;
   11144              :         }
   11145              : 
   11146     58301095 :       if (avoid_folding_inline_builtin (fndecl))
   11147              :         return NULL_TREE;
   11148              : 
   11149     58297560 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   11150     69527014 :         return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
   11151     69527014 :                                      CALL_EXPR_ARGP (exp), ignore);
   11152              :       else
   11153              :         {
   11154     23534053 :           tree *args = CALL_EXPR_ARGP (exp);
   11155     23534053 :           ret = fold_builtin_n (loc, exp, fndecl, args, nargs, ignore);
   11156     23534053 :           if (ret)
   11157              :             return ret;
   11158              :         }
   11159              :     }
   11160              :   return NULL_TREE;
   11161              : }
   11162              : 
   11163              : /* Fold a CALL_EXPR with type TYPE with FN as the function expression.
   11164              :    N arguments are passed in the array ARGARRAY.  Return a folded
   11165              :    expression or NULL_TREE if no simplification was possible.  */
   11166              : 
   11167              : tree
   11168     73903522 : fold_builtin_call_array (location_t loc, tree,
   11169              :                          tree fn,
   11170              :                          int n,
   11171              :                          tree *argarray)
   11172              : {
   11173     73903522 :   if (TREE_CODE (fn) != ADDR_EXPR)
   11174              :     return NULL_TREE;
   11175              : 
   11176     73903522 :   tree fndecl = TREE_OPERAND (fn, 0);
   11177     73903522 :   if (TREE_CODE (fndecl) == FUNCTION_DECL
   11178     73903522 :       && fndecl_built_in_p (fndecl))
   11179              :     {
   11180              :       /* If last argument is __builtin_va_arg_pack (), arguments to this
   11181              :          function are not finalized yet.  Defer folding until they are.  */
   11182     73300475 :       if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
   11183              :         {
   11184       105732 :           tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
   11185       105732 :           if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   11186              :             return NULL_TREE;
   11187              :         }
   11188     73300447 :       if (avoid_folding_inline_builtin (fndecl))
   11189              :         return NULL_TREE;
   11190     73300447 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   11191     33435196 :         return targetm.fold_builtin (fndecl, n, argarray, false);
   11192              :       else
   11193     39865251 :         return fold_builtin_n (loc, NULL_TREE, fndecl, argarray, n, false);
   11194              :     }
   11195              : 
   11196              :   return NULL_TREE;
   11197              : }
   11198              : 
   11199              : /* Construct a new CALL_EXPR using the tail of the argument list of EXP
   11200              :    along with N new arguments specified as the "..." parameters.  SKIP
   11201              :    is the number of arguments in EXP to be omitted.  This function is used
   11202              :    to do varargs-to-varargs transformations.  */
   11203              : 
   11204              : static tree
   11205            4 : rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
   11206              : {
   11207            4 :   va_list ap;
   11208            4 :   tree t;
   11209              : 
   11210            4 :   va_start (ap, n);
   11211            8 :   t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
   11212            4 :                                 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
   11213            4 :   va_end (ap);
   11214              : 
   11215            4 :   return t;
   11216              : }
   11217              : 
   11218              : /* Validate a single argument ARG against a tree code CODE representing
   11219              :    a type.  Return true when argument is valid.  */
   11220              : 
   11221              : static bool
   11222     14254137 : validate_arg (const_tree arg, enum tree_code code)
   11223              : {
   11224     14254137 :   if (!arg)
   11225              :     return false;
   11226     14254114 :   else if (code == POINTER_TYPE)
   11227      6971889 :     return POINTER_TYPE_P (TREE_TYPE (arg));
   11228      7282225 :   else if (code == INTEGER_TYPE)
   11229      3759474 :     return INTEGRAL_TYPE_P (TREE_TYPE (arg));
   11230      3522751 :   return code == TREE_CODE (TREE_TYPE (arg));
   11231              : }
   11232              : 
   11233              : /* This function validates the types of a function call argument list
   11234              :    against a specified list of tree_codes.  If the last specifier is a 0,
   11235              :    that represents an ellipses, otherwise the last specifier must be a
   11236              :    VOID_TYPE.
   11237              : 
   11238              :    This is the GIMPLE version of validate_arglist.  Eventually we want to
   11239              :    completely convert builtins.cc to work from GIMPLEs and the tree based
   11240              :    validate_arglist will then be removed.  */
   11241              : 
   11242              : bool
   11243          136 : validate_gimple_arglist (const gcall *call, ...)
   11244              : {
   11245          136 :   enum tree_code code;
   11246          136 :   bool res = 0;
   11247          136 :   va_list ap;
   11248          136 :   const_tree arg;
   11249          136 :   size_t i;
   11250              : 
   11251          136 :   va_start (ap, call);
   11252          136 :   i = 0;
   11253              : 
   11254          544 :   do
   11255              :     {
   11256          544 :       code = (enum tree_code) va_arg (ap, int);
   11257          544 :       switch (code)
   11258              :         {
   11259            0 :         case 0:
   11260              :           /* This signifies an ellipses, any further arguments are all ok.  */
   11261            0 :           res = true;
   11262            0 :           goto end;
   11263          136 :         case VOID_TYPE:
   11264              :           /* This signifies an endlink, if no arguments remain, return
   11265              :              true, otherwise return false.  */
   11266          136 :           res = (i == gimple_call_num_args (call));
   11267          136 :           goto end;
   11268          408 :         default:
   11269              :           /* If no parameters remain or the parameter's code does not
   11270              :              match the specified code, return false.  Otherwise continue
   11271              :              checking any remaining arguments.  */
   11272          408 :           arg = gimple_call_arg (call, i++);
   11273          408 :           if (!validate_arg (arg, code))
   11274            0 :             goto end;
   11275              :           break;
   11276              :         }
   11277              :     }
   11278              :   while (1);
   11279              : 
   11280              :   /* We need gotos here since we can only have one VA_CLOSE in a
   11281              :      function.  */
   11282          136 :  end: ;
   11283          136 :   va_end (ap);
   11284              : 
   11285          136 :   return res;
   11286              : }
   11287              : 
   11288              : /* Default target-specific builtin expander that does nothing.  */
   11289              : 
   11290              : rtx
   11291            0 : default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
   11292              :                         rtx target ATTRIBUTE_UNUSED,
   11293              :                         rtx subtarget ATTRIBUTE_UNUSED,
   11294              :                         machine_mode mode ATTRIBUTE_UNUSED,
   11295              :                         int ignore ATTRIBUTE_UNUSED)
   11296              : {
   11297            0 :   return NULL_RTX;
   11298              : }
   11299              : 
   11300              : /* Returns true is EXP represents data that would potentially reside
   11301              :    in a readonly section.  */
   11302              : 
   11303              : bool
   11304       206702 : readonly_data_expr (tree exp)
   11305              : {
   11306       206702 :   STRIP_NOPS (exp);
   11307              : 
   11308       206702 :   if (TREE_CODE (exp) != ADDR_EXPR)
   11309              :     return false;
   11310              : 
   11311        25920 :   exp = get_base_address (TREE_OPERAND (exp, 0));
   11312        25920 :   if (!exp)
   11313              :     return false;
   11314              : 
   11315              :   /* Make sure we call decl_readonly_section only for trees it
   11316              :      can handle (since it returns true for everything it doesn't
   11317              :      understand).  */
   11318        25920 :   if (TREE_CODE (exp) == STRING_CST
   11319         5752 :       || TREE_CODE (exp) == CONSTRUCTOR
   11320         5752 :       || (VAR_P (exp) && TREE_STATIC (exp)))
   11321        22787 :     return decl_readonly_section (exp, 0);
   11322              :   else
   11323              :     return false;
   11324              : }
   11325              : 
   11326              : /* Simplify a call to the strpbrk builtin.  S1 and S2 are the arguments
   11327              :    to the call, and TYPE is its return type.
   11328              : 
   11329              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11330              :    simplified form of the call as a tree.
   11331              : 
   11332              :    The simplified form may be a constant or other expression which
   11333              :    computes the same value, but in a more efficient manner (including
   11334              :    calls to other builtin functions).
   11335              : 
   11336              :    The call may contain arguments which need to be evaluated, but
   11337              :    which are not useful to determine the result of the call.  In
   11338              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11339              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11340              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11341              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11342              :    form of the builtin function call.  */
   11343              : 
   11344              : static tree
   11345        80063 : fold_builtin_strpbrk (location_t loc, tree, tree s1, tree s2, tree type)
   11346              : {
   11347        80063 :   if (!validate_arg (s1, POINTER_TYPE)
   11348        80063 :       || !validate_arg (s2, POINTER_TYPE))
   11349              :     return NULL_TREE;
   11350              : 
   11351        80063 :   tree fn;
   11352        80063 :   const char *p1, *p2;
   11353              : 
   11354        80063 :   p2 = c_getstr (s2);
   11355        80063 :   if (p2 == NULL)
   11356              :     return NULL_TREE;
   11357              : 
   11358           92 :   p1 = c_getstr (s1);
   11359           92 :   if (p1 != NULL)
   11360              :     {
   11361           22 :       const char *r = strpbrk (p1, p2);
   11362           22 :       tree tem;
   11363              : 
   11364           22 :       if (r == NULL)
   11365            0 :         return build_int_cst (TREE_TYPE (s1), 0);
   11366              : 
   11367              :       /* Return an offset into the constant string argument.  */
   11368           22 :       tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
   11369           22 :       return fold_convert_loc (loc, type, tem);
   11370              :     }
   11371              : 
   11372           70 :   if (p2[0] == '\0')
   11373              :     /* strpbrk(x, "") == NULL.
   11374              :        Evaluate and ignore s1 in case it had side-effects.  */
   11375           26 :     return omit_one_operand_loc (loc, type, integer_zero_node, s1);
   11376              : 
   11377           44 :   if (p2[1] != '\0')
   11378              :     return NULL_TREE;  /* Really call strpbrk.  */
   11379              : 
   11380        80015 :   fn = builtin_decl_implicit (BUILT_IN_STRCHR);
   11381           41 :   if (!fn)
   11382              :     return NULL_TREE;
   11383              : 
   11384              :   /* New argument list transforming strpbrk(s1, s2) to
   11385              :      strchr(s1, s2[0]).  */
   11386           41 :   return build_call_expr_loc (loc, fn, 2, s1,
   11387           41 :                               build_int_cst (integer_type_node, p2[0]));
   11388              : }
   11389              : 
   11390              : /* Simplify a call to the strspn builtin.  S1 and S2 are the arguments
   11391              :    to the call.
   11392              : 
   11393              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11394              :    simplified form of the call as a tree.
   11395              : 
   11396              :    The simplified form may be a constant or other expression which
   11397              :    computes the same value, but in a more efficient manner (including
   11398              :    calls to other builtin functions).
   11399              : 
   11400              :    The call may contain arguments which need to be evaluated, but
   11401              :    which are not useful to determine the result of the call.  In
   11402              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11403              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11404              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11405              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11406              :    form of the builtin function call.  */
   11407              : 
   11408              : static tree
   11409         2560 : fold_builtin_strspn (location_t loc, tree expr, tree s1, tree s2, tree type)
   11410              : {
   11411         2560 :   if (!validate_arg (s1, POINTER_TYPE)
   11412         2560 :       || !validate_arg (s2, POINTER_TYPE))
   11413              :     return NULL_TREE;
   11414              : 
   11415         2560 :   if (!check_nul_terminated_array (expr, s1)
   11416         2560 :       || !check_nul_terminated_array (expr, s2))
   11417           58 :     return NULL_TREE;
   11418              : 
   11419         2502 :   const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
   11420              : 
   11421              :   /* If either argument is "", return NULL_TREE.  */
   11422         2502 :   if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
   11423              :     /* Evaluate and ignore both arguments in case either one has
   11424              :        side-effects.  */
   11425          147 :     return omit_two_operands_loc (loc, type, size_zero_node, s1, s2);
   11426              :   return NULL_TREE;
   11427              : }
   11428              : 
   11429              : /* Simplify a call to the strcspn builtin.  S1 and S2 are the arguments
   11430              :    to the call.
   11431              : 
   11432              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11433              :    simplified form of the call as a tree.
   11434              : 
   11435              :    The simplified form may be a constant or other expression which
   11436              :    computes the same value, but in a more efficient manner (including
   11437              :    calls to other builtin functions).
   11438              : 
   11439              :    The call may contain arguments which need to be evaluated, but
   11440              :    which are not useful to determine the result of the call.  In
   11441              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11442              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11443              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11444              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11445              :    form of the builtin function call.  */
   11446              : 
   11447              : static tree
   11448         2465 : fold_builtin_strcspn (location_t loc, tree expr, tree s1, tree s2, tree type)
   11449              : {
   11450         2465 :   if (!validate_arg (s1, POINTER_TYPE)
   11451         2465 :       || !validate_arg (s2, POINTER_TYPE))
   11452              :     return NULL_TREE;
   11453              : 
   11454         2465 :   if (!check_nul_terminated_array (expr, s1)
   11455         2465 :       || !check_nul_terminated_array (expr, s2))
   11456           58 :     return NULL_TREE;
   11457              : 
   11458              :   /* If the first argument is "", return NULL_TREE.  */
   11459         2407 :   const char *p1 = c_getstr (s1);
   11460         2407 :   if (p1 && *p1 == '\0')
   11461              :     {
   11462              :       /* Evaluate and ignore argument s2 in case it has
   11463              :          side-effects.  */
   11464           65 :       return omit_one_operand_loc (loc, type, size_zero_node, s2);
   11465              :     }
   11466              : 
   11467              :   /* If the second argument is "", return __builtin_strlen(s1).  */
   11468         2342 :   const char *p2 = c_getstr (s2);
   11469         2342 :   if (p2 && *p2 == '\0')
   11470              :     {
   11471         2400 :       tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
   11472              : 
   11473              :       /* If the replacement _DECL isn't initialized, don't do the
   11474              :          transformation.  */
   11475           81 :       if (!fn)
   11476              :         return NULL_TREE;
   11477              : 
   11478           81 :       return fold_convert_loc (loc, type,
   11479           81 :                                build_call_expr_loc (loc, fn, 1, s1));
   11480              :     }
   11481              :   return NULL_TREE;
   11482              : }
   11483              : 
   11484              : /* Fold the next_arg or va_start call EXP. Returns true if there was an error
   11485              :    produced.  False otherwise.  This is done so that we don't output the error
   11486              :    or warning twice or three times.  */
   11487              : 
   11488              : bool
   11489        42127 : fold_builtin_next_arg (tree exp, bool va_start_p)
   11490              : {
   11491        42127 :   tree fntype = TREE_TYPE (current_function_decl);
   11492        42127 :   int nargs = call_expr_nargs (exp);
   11493        42127 :   tree arg;
   11494              :   /* There is good chance the current input_location points inside the
   11495              :      definition of the va_start macro (perhaps on the token for
   11496              :      builtin) in a system header, so warnings will not be emitted.
   11497              :      Use the location in real source code.  */
   11498        42127 :   location_t current_location =
   11499        42127 :     linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
   11500              :                                               NULL);
   11501              : 
   11502        42127 :   if (!stdarg_p (fntype))
   11503              :     {
   11504            8 :       error ("%<va_start%> used in function with fixed arguments");
   11505            8 :       return true;
   11506              :     }
   11507              : 
   11508        42119 :   if (va_start_p)
   11509              :     {
   11510        41961 :       if (va_start_p && (nargs != 2))
   11511              :         {
   11512            0 :           error ("wrong number of arguments to function %<va_start%>");
   11513            0 :           return true;
   11514              :         }
   11515        41961 :       arg = CALL_EXPR_ARG (exp, 1);
   11516              :     }
   11517              :   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
   11518              :      when we checked the arguments and if needed issued a warning.  */
   11519              :   else
   11520              :     {
   11521          158 :       if (nargs == 0)
   11522              :         {
   11523              :           /* Evidently an out of date version of <stdarg.h>; can't validate
   11524              :              va_start's second argument, but can still work as intended.  */
   11525            0 :           warning_at (current_location,
   11526            0 :                       OPT_Wvarargs,
   11527              :                    "%<__builtin_next_arg%> called without an argument");
   11528            0 :           return true;
   11529              :         }
   11530          158 :       else if (nargs > 1)
   11531              :         {
   11532            0 :           error ("wrong number of arguments to function %<__builtin_next_arg%>");
   11533            0 :           return true;
   11534              :         }
   11535          158 :       arg = CALL_EXPR_ARG (exp, 0);
   11536              :     }
   11537              : 
   11538        42119 :   if (TREE_CODE (arg) == SSA_NAME
   11539        42119 :       && SSA_NAME_VAR (arg))
   11540              :     arg = SSA_NAME_VAR (arg);
   11541              : 
   11542              :   /* We destructively modify the call to be __builtin_va_start (ap, 0)
   11543              :      or __builtin_next_arg (0) the first time we see it, after checking
   11544              :      the arguments and if needed issuing a warning.  */
   11545        42119 :   if (!integer_zerop (arg))
   11546              :     {
   11547         7025 :       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
   11548              : 
   11549              :       /* Strip off all nops for the sake of the comparison.  This
   11550              :          is not quite the same as STRIP_NOPS.  It does more.
   11551              :          We must also strip off INDIRECT_EXPR for C++ reference
   11552              :          parameters.  */
   11553        14052 :       while (CONVERT_EXPR_P (arg)
   11554        14063 :              || INDIRECT_REF_P (arg))
   11555           11 :         arg = TREE_OPERAND (arg, 0);
   11556         7025 :       if (arg != last_parm)
   11557              :         {
   11558              :           /* FIXME: Sometimes with the tree optimizers we can get the
   11559              :              not the last argument even though the user used the last
   11560              :              argument.  We just warn and set the arg to be the last
   11561              :              argument so that we will get wrong-code because of
   11562              :              it.  */
   11563           12 :           warning_at (current_location,
   11564           12 :                       OPT_Wvarargs,
   11565              :                       "second parameter of %<va_start%> not last named argument");
   11566              :         }
   11567              : 
   11568              :       /* Undefined by C99 7.15.1.4p4 (va_start):
   11569              :          "If the parameter parmN is declared with the register storage
   11570              :          class, with a function or array type, or with a type that is
   11571              :          not compatible with the type that results after application of
   11572              :          the default argument promotions, the behavior is undefined."
   11573              :       */
   11574         7013 :       else if (DECL_REGISTER (arg))
   11575              :         {
   11576           12 :           warning_at (current_location,
   11577           12 :                       OPT_Wvarargs,
   11578              :                       "undefined behavior when second parameter of "
   11579              :                       "%<va_start%> is declared with %<register%> storage");
   11580              :         }
   11581              : 
   11582              :       /* We want to verify the second parameter just once before the tree
   11583              :          optimizers are run and then avoid keeping it in the tree,
   11584              :          as otherwise we could warn even for correct code like:
   11585              :          void foo (int i, ...)
   11586              :          { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
   11587         7025 :       if (va_start_p)
   11588         7023 :         CALL_EXPR_ARG (exp, 1) = integer_zero_node;
   11589              :       else
   11590            2 :         CALL_EXPR_ARG (exp, 0) = integer_zero_node;
   11591              :     }
   11592              :   return false;
   11593              : }
   11594              : 
   11595              : 
   11596              : /* Expand a call EXP to __builtin_object_size.  */
   11597              : 
   11598              : static rtx
   11599          618 : expand_builtin_object_size (tree exp)
   11600              : {
   11601          618 :   tree ost;
   11602          618 :   int object_size_type;
   11603          618 :   tree fndecl = get_callee_fndecl (exp);
   11604              : 
   11605          618 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   11606              :     {
   11607            0 :       error ("first argument of %qD must be a pointer, second integer constant",
   11608              :              fndecl);
   11609            0 :       expand_builtin_trap ();
   11610            0 :       return const0_rtx;
   11611              :     }
   11612              : 
   11613          618 :   ost = CALL_EXPR_ARG (exp, 1);
   11614          618 :   STRIP_NOPS (ost);
   11615              : 
   11616          618 :   if (TREE_CODE (ost) != INTEGER_CST
   11617          618 :       || tree_int_cst_sgn (ost) < 0
   11618         1236 :       || compare_tree_int (ost, 3) > 0)
   11619              :     {
   11620            0 :       error ("last argument of %qD is not integer constant between 0 and 3",
   11621              :               fndecl);
   11622            0 :       expand_builtin_trap ();
   11623            0 :       return const0_rtx;
   11624              :     }
   11625              : 
   11626          618 :   object_size_type = tree_to_shwi (ost);
   11627              : 
   11628          618 :   return object_size_type < 2 ? constm1_rtx : const0_rtx;
   11629              : }
   11630              : 
   11631              : /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
   11632              :    FCODE is the BUILT_IN_* to use.
   11633              :    Return NULL_RTX if we failed; the caller should emit a normal call,
   11634              :    otherwise try to get the result in TARGET, if convenient (and in
   11635              :    mode MODE if that's convenient).  */
   11636              : 
   11637              : static rtx
   11638          837 : expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
   11639              :                            enum built_in_function fcode)
   11640              : {
   11641         1410 :   if (!validate_arglist (exp,
   11642              :                          POINTER_TYPE,
   11643              :                          fcode == BUILT_IN_MEMSET_CHK
   11644              :                          ? INTEGER_TYPE : POINTER_TYPE,
   11645              :                          INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
   11646              :     return NULL_RTX;
   11647              : 
   11648          837 :   tree dest = CALL_EXPR_ARG (exp, 0);
   11649          837 :   tree src = CALL_EXPR_ARG (exp, 1);
   11650          837 :   tree len = CALL_EXPR_ARG (exp, 2);
   11651          837 :   tree size = CALL_EXPR_ARG (exp, 3);
   11652              : 
   11653              :   /* FIXME: Set access mode to write only for memset et al.  */
   11654          837 :   bool sizes_ok = check_access (exp, len, /*maxread=*/NULL_TREE,
   11655              :                                 /*srcstr=*/NULL_TREE, size, access_read_write);
   11656              : 
   11657          837 :   if (!tree_fits_uhwi_p (size))
   11658              :     return NULL_RTX;
   11659              : 
   11660          627 :   if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
   11661              :     {
   11662              :       /* Avoid transforming the checking call to an ordinary one when
   11663              :          an overflow has been detected or when the call couldn't be
   11664              :          validated because the size is not constant.  */
   11665          186 :       if (!sizes_ok && !integer_all_onesp (size) && tree_int_cst_lt (size, len))
   11666              :         return NULL_RTX;
   11667              : 
   11668            0 :       tree fn = NULL_TREE;
   11669              :       /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
   11670              :          mem{cpy,pcpy,move,set} is available.  */
   11671            0 :       switch (fcode)
   11672              :         {
   11673            0 :         case BUILT_IN_MEMCPY_CHK:
   11674            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
   11675            0 :           break;
   11676            0 :         case BUILT_IN_MEMPCPY_CHK:
   11677            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
   11678            0 :           break;
   11679            0 :         case BUILT_IN_MEMMOVE_CHK:
   11680            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
   11681            0 :           break;
   11682            0 :         case BUILT_IN_MEMSET_CHK:
   11683            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMSET);
   11684            0 :           break;
   11685              :         default:
   11686              :           break;
   11687              :         }
   11688              : 
   11689            0 :       if (! fn)
   11690              :         return NULL_RTX;
   11691              : 
   11692            0 :       fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
   11693            0 :       gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   11694            0 :       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   11695            0 :       return expand_expr (fn, target, mode, EXPAND_NORMAL);
   11696              :     }
   11697          441 :   else if (fcode == BUILT_IN_MEMSET_CHK)
   11698              :     return NULL_RTX;
   11699              :   else
   11700              :     {
   11701          293 :       unsigned int dest_align = get_pointer_alignment (dest);
   11702              : 
   11703              :       /* If DEST is not a pointer type, call the normal function.  */
   11704          293 :       if (dest_align == 0)
   11705              :         return NULL_RTX;
   11706              : 
   11707              :       /* If SRC and DEST are the same (and not volatile), do nothing.  */
   11708          293 :       if (operand_equal_p (src, dest, 0))
   11709              :         {
   11710            0 :           tree expr;
   11711              : 
   11712            0 :           if (fcode != BUILT_IN_MEMPCPY_CHK)
   11713              :             {
   11714              :               /* Evaluate and ignore LEN in case it has side-effects.  */
   11715            0 :               expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
   11716            0 :               return expand_expr (dest, target, mode, EXPAND_NORMAL);
   11717              :             }
   11718              : 
   11719            0 :           expr = fold_build_pointer_plus (dest, len);
   11720            0 :           return expand_expr (expr, target, mode, EXPAND_NORMAL);
   11721              :         }
   11722              : 
   11723              :       /* __memmove_chk special case.  */
   11724          293 :       if (fcode == BUILT_IN_MEMMOVE_CHK)
   11725              :         {
   11726           79 :           unsigned int src_align = get_pointer_alignment (src);
   11727              : 
   11728           79 :           if (src_align == 0)
   11729              :             return NULL_RTX;
   11730              : 
   11731              :           /* If src is categorized for a readonly section we can use
   11732              :              normal __memcpy_chk.  */
   11733           79 :           if (readonly_data_expr (src))
   11734              :             {
   11735           15 :               tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
   11736           15 :               if (!fn)
   11737              :                 return NULL_RTX;
   11738           15 :               fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
   11739              :                                           dest, src, len, size);
   11740           15 :               gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   11741           15 :               CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   11742           15 :               return expand_expr (fn, target, mode, EXPAND_NORMAL);
   11743              :             }
   11744              :         }
   11745          278 :       return NULL_RTX;
   11746              :     }
   11747              : }
   11748              : 
   11749              : /* Emit warning if a buffer overflow is detected at compile time.  */
   11750              : 
   11751              : static void
   11752         1086 : maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
   11753              : {
   11754              :   /* The source string.  */
   11755         1086 :   tree srcstr = NULL_TREE;
   11756              :   /* The size of the destination object returned by __builtin_object_size.  */
   11757         1086 :   tree objsize = NULL_TREE;
   11758              :   /* The string that is being concatenated with (as in __strcat_chk)
   11759              :      or null if it isn't.  */
   11760         1086 :   tree catstr = NULL_TREE;
   11761              :   /* The maximum length of the source sequence in a bounded operation
   11762              :      (such as __strncat_chk) or null if the operation isn't bounded
   11763              :      (such as __strcat_chk).  */
   11764         1086 :   tree maxread = NULL_TREE;
   11765              :   /* The exact size of the access (such as in __strncpy_chk).  */
   11766         1086 :   tree size = NULL_TREE;
   11767              :   /* The access by the function that's checked.  Except for snprintf
   11768              :      both writing and reading is checked.  */
   11769         1086 :   access_mode mode = access_read_write;
   11770              : 
   11771         1086 :   switch (fcode)
   11772              :     {
   11773          275 :     case BUILT_IN_STRCPY_CHK:
   11774          275 :     case BUILT_IN_STPCPY_CHK:
   11775          275 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11776          275 :       objsize = CALL_EXPR_ARG (exp, 2);
   11777          275 :       break;
   11778              : 
   11779          151 :     case BUILT_IN_STRCAT_CHK:
   11780              :       /* For __strcat_chk the warning will be emitted only if overflowing
   11781              :          by at least strlen (dest) + 1 bytes.  */
   11782          151 :       catstr = CALL_EXPR_ARG (exp, 0);
   11783          151 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11784          151 :       objsize = CALL_EXPR_ARG (exp, 2);
   11785          151 :       break;
   11786              : 
   11787          108 :     case BUILT_IN_STRNCAT_CHK:
   11788          108 :       catstr = CALL_EXPR_ARG (exp, 0);
   11789          108 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11790          108 :       maxread = CALL_EXPR_ARG (exp, 2);
   11791          108 :       objsize = CALL_EXPR_ARG (exp, 3);
   11792          108 :       break;
   11793              : 
   11794          243 :     case BUILT_IN_STRNCPY_CHK:
   11795          243 :     case BUILT_IN_STPNCPY_CHK:
   11796          243 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11797          243 :       size = CALL_EXPR_ARG (exp, 2);
   11798          243 :       objsize = CALL_EXPR_ARG (exp, 3);
   11799          243 :       break;
   11800              : 
   11801          309 :     case BUILT_IN_SNPRINTF_CHK:
   11802          309 :     case BUILT_IN_VSNPRINTF_CHK:
   11803          309 :       maxread = CALL_EXPR_ARG (exp, 1);
   11804          309 :       objsize = CALL_EXPR_ARG (exp, 3);
   11805              :       /* The only checked access the write to the destination.  */
   11806          309 :       mode = access_write_only;
   11807          309 :       break;
   11808            0 :     default:
   11809            0 :       gcc_unreachable ();
   11810              :     }
   11811              : 
   11812         1086 :   if (catstr && maxread)
   11813              :     {
   11814              :       /* Check __strncat_chk.  There is no way to determine the length
   11815              :          of the string to which the source string is being appended so
   11816              :          just warn when the length of the source string is not known.  */
   11817          108 :       check_strncat_sizes (exp, objsize);
   11818          108 :       return;
   11819              :     }
   11820              : 
   11821          978 :   check_access (exp, size, maxread, srcstr, objsize, mode);
   11822              : }
   11823              : 
   11824              : /* Emit warning if a buffer overflow is detected at compile time
   11825              :    in __sprintf_chk/__vsprintf_chk calls.  */
   11826              : 
   11827              : static void
   11828         1327 : maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
   11829              : {
   11830         1327 :   tree size, len, fmt;
   11831         1327 :   const char *fmt_str;
   11832         1327 :   int nargs = call_expr_nargs (exp);
   11833              : 
   11834              :   /* Verify the required arguments in the original call.  */
   11835              : 
   11836         1327 :   if (nargs < 4)
   11837              :     return;
   11838         1327 :   size = CALL_EXPR_ARG (exp, 2);
   11839         1327 :   fmt = CALL_EXPR_ARG (exp, 3);
   11840              : 
   11841         1327 :   if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
   11842           21 :     return;
   11843              : 
   11844              :   /* Check whether the format is a literal string constant.  */
   11845         1306 :   fmt_str = c_getstr (fmt);
   11846         1306 :   if (fmt_str == NULL)
   11847              :     return;
   11848              : 
   11849         1270 :   if (!init_target_chars ())
   11850              :     return;
   11851              : 
   11852              :   /* If the format doesn't contain % args or %%, we know its size.  */
   11853         1270 :   if (strchr (fmt_str, target_percent) == 0)
   11854           22 :     len = build_int_cstu (size_type_node, strlen (fmt_str));
   11855              :   /* If the format is "%s" and first ... argument is a string literal,
   11856              :      we know it too.  */
   11857         1248 :   else if (fcode == BUILT_IN_SPRINTF_CHK
   11858         1094 :            && strcmp (fmt_str, target_percent_s) == 0)
   11859              :     {
   11860           49 :       tree arg;
   11861              : 
   11862           49 :       if (nargs < 5)
   11863              :         return;
   11864           49 :       arg = CALL_EXPR_ARG (exp, 4);
   11865           49 :       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
   11866              :         return;
   11867              : 
   11868           45 :       len = c_strlen (arg, 1);
   11869           45 :       if (!len || ! tree_fits_uhwi_p (len))
   11870              :         return;
   11871              :     }
   11872              :   else
   11873              :     return;
   11874              : 
   11875              :   /* Add one for the terminating nul.  */
   11876           34 :   len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
   11877              : 
   11878           34 :   check_access (exp, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, len, size,
   11879              :                 access_write_only);
   11880              : }
   11881              : 
   11882              : /* Fold a call to __builtin_object_size with arguments PTR and OST,
   11883              :    if possible.  */
   11884              : 
   11885              : static tree
   11886       200235 : fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode)
   11887              : {
   11888       200235 :   tree bytes;
   11889       200235 :   int object_size_type;
   11890              : 
   11891       200235 :   if (!validate_arg (ptr, POINTER_TYPE)
   11892       200235 :       || !validate_arg (ost, INTEGER_TYPE))
   11893              :     return NULL_TREE;
   11894              : 
   11895       200235 :   STRIP_NOPS (ost);
   11896              : 
   11897       200235 :   if (TREE_CODE (ost) != INTEGER_CST
   11898       200235 :       || tree_int_cst_sgn (ost) < 0
   11899       400470 :       || compare_tree_int (ost, 3) > 0)
   11900            0 :     return NULL_TREE;
   11901              : 
   11902       200235 :   object_size_type = tree_to_shwi (ost);
   11903              : 
   11904              :   /* __builtin_object_size doesn't evaluate side-effects in its arguments;
   11905              :      if there are any side-effects, it returns (size_t) -1 for types 0 and 1
   11906              :      and (size_t) 0 for types 2 and 3.  */
   11907       200235 :   if (TREE_SIDE_EFFECTS (ptr))
   11908          603 :     return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
   11909              : 
   11910       199632 :   if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE)
   11911        67050 :     object_size_type |= OST_DYNAMIC;
   11912              : 
   11913       199632 :   if (TREE_CODE (ptr) == ADDR_EXPR)
   11914              :     {
   11915        12149 :       compute_builtin_object_size (ptr, object_size_type, &bytes);
   11916        12149 :       if ((object_size_type & OST_DYNAMIC)
   11917        10885 :           || int_fits_type_p (bytes, size_type_node))
   11918        12149 :         return fold_convert (size_type_node, bytes);
   11919              :     }
   11920       187483 :   else if (TREE_CODE (ptr) == SSA_NAME)
   11921              :     {
   11922              :       /* If object size is not known yet, delay folding until
   11923              :        later.  Maybe subsequent passes will help determining
   11924              :        it.  */
   11925       102020 :       if (compute_builtin_object_size (ptr, object_size_type, &bytes)
   11926       102020 :           && ((object_size_type & OST_DYNAMIC)
   11927         2538 :               || int_fits_type_p (bytes, size_type_node)))
   11928         4808 :         return fold_convert (size_type_node, bytes);
   11929              :     }
   11930              : 
   11931              :   return NULL_TREE;
   11932              : }
   11933              : 
   11934              : /* Builtins with folding operations that operate on "..." arguments
   11935              :    need special handling; we need to store the arguments in a convenient
   11936              :    data structure before attempting any folding.  Fortunately there are
   11937              :    only a few builtins that fall into this category.  FNDECL is the
   11938              :    function, EXP is the CALL_EXPR for the call.  */
   11939              : 
   11940              : static tree
   11941      2582736 : fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
   11942              : {
   11943      2582736 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   11944      2582736 :   tree ret = NULL_TREE;
   11945              : 
   11946      2582736 :   switch (fcode)
   11947              :     {
   11948       103782 :     case BUILT_IN_FPCLASSIFY:
   11949       103782 :       ret = fold_builtin_fpclassify (loc, args, nargs);
   11950       103782 :       break;
   11951              : 
   11952           54 :     case BUILT_IN_ADDC:
   11953           54 :     case BUILT_IN_ADDCL:
   11954           54 :     case BUILT_IN_ADDCLL:
   11955           54 :     case BUILT_IN_SUBC:
   11956           54 :     case BUILT_IN_SUBCL:
   11957           54 :     case BUILT_IN_SUBCLL:
   11958           54 :       return fold_builtin_addc_subc (loc, fcode, args);
   11959              : 
   11960              :     default:
   11961              :       break;
   11962              :     }
   11963       103782 :   if (ret)
   11964              :     {
   11965       103782 :       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   11966       103782 :       SET_EXPR_LOCATION (ret, loc);
   11967       103782 :       suppress_warning (ret);
   11968       103782 :       return ret;
   11969              :     }
   11970              :   return NULL_TREE;
   11971              : }
   11972              : 
   11973              : /* Initialize format string characters in the target charset.  */
   11974              : 
   11975              : bool
   11976       289122 : init_target_chars (void)
   11977              : {
   11978       289122 :   static bool init;
   11979       289122 :   if (!init)
   11980              :     {
   11981       114088 :       target_newline = lang_hooks.to_target_charset ('\n');
   11982       114088 :       target_percent = lang_hooks.to_target_charset ('%');
   11983       114088 :       target_c = lang_hooks.to_target_charset ('c');
   11984       114088 :       target_s = lang_hooks.to_target_charset ('s');
   11985       114088 :       if (target_newline == 0 || target_percent == 0 || target_c == 0
   11986       114088 :           || target_s == 0)
   11987              :         return false;
   11988              : 
   11989       114088 :       target_percent_c[0] = target_percent;
   11990       114088 :       target_percent_c[1] = target_c;
   11991       114088 :       target_percent_c[2] = '\0';
   11992              : 
   11993       114088 :       target_percent_s[0] = target_percent;
   11994       114088 :       target_percent_s[1] = target_s;
   11995       114088 :       target_percent_s[2] = '\0';
   11996              : 
   11997       114088 :       target_percent_s_newline[0] = target_percent;
   11998       114088 :       target_percent_s_newline[1] = target_s;
   11999       114088 :       target_percent_s_newline[2] = target_newline;
   12000       114088 :       target_percent_s_newline[3] = '\0';
   12001              : 
   12002       114088 :       init = true;
   12003              :     }
   12004              :   return true;
   12005              : }
   12006              : 
   12007              : /* Helper function for do_mpfr_arg*().  Ensure M is a normal number
   12008              :    and no overflow/underflow occurred.  INEXACT is true if M was not
   12009              :    exactly calculated.  TYPE is the tree type for the result.  This
   12010              :    function assumes that you cleared the MPFR flags and then
   12011              :    calculated M to see if anything subsequently set a flag prior to
   12012              :    entering this function.  Return NULL_TREE if any checks fail.  */
   12013              : 
   12014              : static tree
   12015         2979 : do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
   12016              : {
   12017              :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   12018              :      overflow/underflow occurred.  If -frounding-math, proceed iff the
   12019              :      result of calling FUNC was exact.  */
   12020         4832 :   if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
   12021         4832 :       && (!flag_rounding_math || !inexact))
   12022              :     {
   12023         1853 :       REAL_VALUE_TYPE rr;
   12024              : 
   12025         1853 :       real_from_mpfr (&rr, m, type, MPFR_RNDN);
   12026              :       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
   12027              :          check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   12028              :          but the mpfr_t is not, then we underflowed in the
   12029              :          conversion.  */
   12030         1853 :       if (real_isfinite (&rr)
   12031         1853 :           && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
   12032              :         {
   12033         1853 :           REAL_VALUE_TYPE rmode;
   12034              : 
   12035         1853 :           real_convert (&rmode, TYPE_MODE (type), &rr);
   12036              :           /* Proceed iff the specified mode can hold the value.  */
   12037         1853 :           if (real_identical (&rmode, &rr))
   12038         1853 :             return build_real (type, rmode);
   12039              :         }
   12040              :     }
   12041              :   return NULL_TREE;
   12042              : }
   12043              : 
   12044              : /* Helper function for do_mpc_arg*().  Ensure M is a normal complex
   12045              :    number and no overflow/underflow occurred.  INEXACT is true if M
   12046              :    was not exactly calculated.  TYPE is the tree type for the result.
   12047              :    This function assumes that you cleared the MPFR flags and then
   12048              :    calculated M to see if anything subsequently set a flag prior to
   12049              :    entering this function.  Return NULL_TREE if any checks fail, if
   12050              :    FORCE_CONVERT is true, then bypass the checks.  */
   12051              : 
   12052              : static tree
   12053         4171 : do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
   12054              : {
   12055              :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   12056              :      overflow/underflow occurred.  If -frounding-math, proceed iff the
   12057              :      result of calling FUNC was exact.  */
   12058         4171 :   if (force_convert
   12059         4171 :       || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
   12060         3852 :           && !mpfr_overflow_p () && !mpfr_underflow_p ()
   12061         3852 :           && (!flag_rounding_math || !inexact)))
   12062              :     {
   12063         3992 :       REAL_VALUE_TYPE re, im;
   12064              : 
   12065         3992 :       real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
   12066         3992 :       real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
   12067              :       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
   12068              :          check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   12069              :          but the mpfr_t is not, then we underflowed in the
   12070              :          conversion.  */
   12071         3992 :       if (force_convert
   12072         3992 :           || (real_isfinite (&re) && real_isfinite (&im)
   12073         3852 :               && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
   12074         3852 :               && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
   12075              :         {
   12076         3992 :           REAL_VALUE_TYPE re_mode, im_mode;
   12077              : 
   12078         3992 :           real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
   12079         3992 :           real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
   12080              :           /* Proceed iff the specified mode can hold the value.  */
   12081         3992 :           if (force_convert
   12082         3992 :               || (real_identical (&re_mode, &re)
   12083         3852 :                   && real_identical (&im_mode, &im)))
   12084         3992 :             return build_complex (type, build_real (TREE_TYPE (type), re_mode),
   12085         7984 :                                   build_real (TREE_TYPE (type), im_mode));
   12086              :         }
   12087              :     }
   12088              :   return NULL_TREE;
   12089              : }
   12090              : 
   12091              : /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
   12092              :    the pointer *(ARG_QUO) and return the result.  The type is taken
   12093              :    from the type of ARG0 and is used for setting the precision of the
   12094              :    calculation and results.  */
   12095              : 
   12096              : static tree
   12097        76253 : do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
   12098              : {
   12099        76253 :   tree const type = TREE_TYPE (arg0);
   12100        76253 :   tree result = NULL_TREE;
   12101              : 
   12102        76253 :   STRIP_NOPS (arg0);
   12103        76253 :   STRIP_NOPS (arg1);
   12104              : 
   12105              :   /* To proceed, MPFR must exactly represent the target floating point
   12106              :      format, which only happens when the target base equals two.  */
   12107        76253 :   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   12108        76253 :       && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
   12109        78558 :       && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
   12110              :     {
   12111         2305 :       const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
   12112         2305 :       const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
   12113              : 
   12114         2305 :       if (real_isfinite (ra0) && real_isfinite (ra1))
   12115              :         {
   12116         2305 :           const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   12117         2305 :           const int prec = fmt->p;
   12118         2305 :           const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   12119         2305 :           tree result_rem;
   12120         2305 :           long integer_quo;
   12121         2305 :           mpfr_t m0, m1;
   12122              : 
   12123         2305 :           mpfr_inits2 (prec, m0, m1, NULL);
   12124         2305 :           mpfr_from_real (m0, ra0, MPFR_RNDN);
   12125         2305 :           mpfr_from_real (m1, ra1, MPFR_RNDN);
   12126         2305 :           mpfr_clear_flags ();
   12127         2305 :           mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
   12128              :           /* Remquo is independent of the rounding mode, so pass
   12129              :              inexact=0 to do_mpfr_ckconv().  */
   12130         2305 :           result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
   12131         2305 :           mpfr_clears (m0, m1, NULL);
   12132         2305 :           if (result_rem)
   12133              :             {
   12134              :               /* MPFR calculates quo in the host's long so it may
   12135              :                  return more bits in quo than the target int can hold
   12136              :                  if sizeof(host long) > sizeof(target int).  This can
   12137              :                  happen even for native compilers in LP64 mode.  In
   12138              :                  these cases, modulo the quo value with the largest
   12139              :                  number that the target int can hold while leaving one
   12140              :                  bit for the sign.  */
   12141         1179 :               if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
   12142         1179 :                 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
   12143              : 
   12144              :               /* Dereference the quo pointer argument.  */
   12145         1179 :               arg_quo = build_fold_indirect_ref (arg_quo);
   12146              :               /* Proceed iff a valid pointer type was passed in.  */
   12147         1179 :               if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
   12148              :                 {
   12149              :                   /* Set the value. */
   12150         1179 :                   tree result_quo
   12151         1179 :                     = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
   12152              :                                    build_int_cst (TREE_TYPE (arg_quo),
   12153              :                                                   integer_quo));
   12154         1179 :                   TREE_SIDE_EFFECTS (result_quo) = 1;
   12155              :                   /* Combine the quo assignment with the rem.  */
   12156         1179 :                   result = fold_build2 (COMPOUND_EXPR, type,
   12157              :                                         result_quo, result_rem);
   12158         1179 :                   suppress_warning (result, OPT_Wunused_value);
   12159         1179 :                   result = non_lvalue (result);
   12160              :                 }
   12161              :             }
   12162              :         }
   12163              :     }
   12164        76253 :   return result;
   12165              : }
   12166              : 
   12167              : /* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
   12168              :    resulting value as a tree with type TYPE.  The mpfr precision is
   12169              :    set to the precision of TYPE.  We assume that this mpfr function
   12170              :    returns zero if the result could be calculated exactly within the
   12171              :    requested precision.  In addition, the integer pointer represented
   12172              :    by ARG_SG will be dereferenced and set to the appropriate signgam
   12173              :    (-1,1) value.  */
   12174              : 
   12175              : static tree
   12176         6504 : do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
   12177              : {
   12178         6504 :   tree result = NULL_TREE;
   12179              : 
   12180         6504 :   STRIP_NOPS (arg);
   12181              : 
   12182              :   /* To proceed, MPFR must exactly represent the target floating point
   12183              :      format, which only happens when the target base equals two.  Also
   12184              :      verify ARG is a constant and that ARG_SG is an int pointer.  */
   12185         6504 :   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   12186         6504 :       && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
   12187         6470 :       && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
   12188        12974 :       && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
   12189              :     {
   12190         6470 :       const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
   12191              : 
   12192              :       /* In addition to NaN and Inf, the argument cannot be zero or a
   12193              :          negative integer.  */
   12194         6470 :       if (real_isfinite (ra)
   12195         6470 :           && ra->cl != rvc_zero
   12196        12940 :           && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
   12197              :         {
   12198          674 :           const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   12199          674 :           const int prec = fmt->p;
   12200          674 :           const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   12201          674 :           int inexact, sg;
   12202          674 :           tree result_lg;
   12203              : 
   12204          674 :           auto_mpfr m (prec);
   12205          674 :           mpfr_from_real (m, ra, MPFR_RNDN);
   12206          674 :           mpfr_clear_flags ();
   12207          674 :           inexact = mpfr_lgamma (m, &sg, m, rnd);
   12208          674 :           result_lg = do_mpfr_ckconv (m, type, inexact);
   12209          674 :           if (result_lg)
   12210              :             {
   12211          674 :               tree result_sg;
   12212              : 
   12213              :               /* Dereference the arg_sg pointer argument.  */
   12214          674 :               arg_sg = build_fold_indirect_ref (arg_sg);
   12215              :               /* Assign the signgam value into *arg_sg. */
   12216          674 :               result_sg = fold_build2 (MODIFY_EXPR,
   12217              :                                        TREE_TYPE (arg_sg), arg_sg,
   12218              :                                        build_int_cst (TREE_TYPE (arg_sg), sg));
   12219          674 :               TREE_SIDE_EFFECTS (result_sg) = 1;
   12220              :               /* Combine the signgam assignment with the lgamma result.  */
   12221          674 :               result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
   12222              :                                                 result_sg, result_lg));
   12223              :             }
   12224          674 :         }
   12225              :     }
   12226              : 
   12227         6504 :   return result;
   12228              : }
   12229              : 
   12230              : /* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
   12231              :    mpc function FUNC on it and return the resulting value as a tree
   12232              :    with type TYPE.  The mpfr precision is set to the precision of
   12233              :    TYPE.  We assume that function FUNC returns zero if the result
   12234              :    could be calculated exactly within the requested precision.  If
   12235              :    DO_NONFINITE is true, then fold expressions containing Inf or NaN
   12236              :    in the arguments and/or results.  */
   12237              : 
   12238              : tree
   12239         4523 : do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
   12240              :              int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
   12241              : {
   12242         4523 :   tree result = NULL_TREE;
   12243              : 
   12244         4523 :   STRIP_NOPS (arg0);
   12245         4523 :   STRIP_NOPS (arg1);
   12246              : 
   12247              :   /* To proceed, MPFR must exactly represent the target floating point
   12248              :      format, which only happens when the target base equals two.  */
   12249         4523 :   if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
   12250         4523 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
   12251         4523 :       && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
   12252         4523 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))
   12253         9046 :       && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
   12254              :     {
   12255         4523 :       const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
   12256         4523 :       const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
   12257         4523 :       const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
   12258         4523 :       const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
   12259              : 
   12260         4523 :       if (do_nonfinite
   12261         4523 :           || (real_isfinite (re0) && real_isfinite (im0)
   12262         4059 :               && real_isfinite (re1) && real_isfinite (im1)))
   12263              :         {
   12264         4171 :           const struct real_format *const fmt =
   12265         4171 :             REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
   12266         4171 :           const int prec = fmt->p;
   12267         4171 :           const mpfr_rnd_t rnd = fmt->round_towards_zero
   12268         4171 :                                  ? MPFR_RNDZ : MPFR_RNDN;
   12269         4171 :           const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
   12270         4171 :           int inexact;
   12271         4171 :           mpc_t m0, m1;
   12272              : 
   12273         4171 :           mpc_init2 (m0, prec);
   12274         4171 :           mpc_init2 (m1, prec);
   12275         4171 :           mpfr_from_real (mpc_realref (m0), re0, rnd);
   12276         4171 :           mpfr_from_real (mpc_imagref (m0), im0, rnd);
   12277         4171 :           mpfr_from_real (mpc_realref (m1), re1, rnd);
   12278         4171 :           mpfr_from_real (mpc_imagref (m1), im1, rnd);
   12279         4171 :           mpfr_clear_flags ();
   12280         4171 :           inexact = func (m0, m0, m1, crnd);
   12281         4171 :           result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
   12282         4171 :           mpc_clear (m0);
   12283         4171 :           mpc_clear (m1);
   12284              :         }
   12285              :     }
   12286              : 
   12287         4523 :   return result;
   12288              : }
   12289              : 
   12290              : /* A wrapper function for builtin folding that prevents warnings for
   12291              :    "statement without effect" and the like, caused by removing the
   12292              :    call node earlier than the warning is generated.  */
   12293              : 
   12294              : tree
   12295      6127505 : fold_call_stmt (gcall *stmt, bool ignore)
   12296              : {
   12297      6127505 :   tree ret = NULL_TREE;
   12298      6127505 :   tree fndecl = gimple_call_fndecl (stmt);
   12299      6127505 :   location_t loc = gimple_location (stmt);
   12300      6127505 :   if (fndecl && fndecl_built_in_p (fndecl)
   12301     12255010 :       && !gimple_call_va_arg_pack_p (stmt))
   12302              :     {
   12303      6127439 :       int nargs = gimple_call_num_args (stmt);
   12304      6127439 :       tree *args = (nargs > 0
   12305      6127439 :                     ? gimple_call_arg_ptr (stmt, 0)
   12306              :                     : &error_mark_node);
   12307              : 
   12308      6127439 :       if (avoid_folding_inline_builtin (fndecl))
   12309              :         return NULL_TREE;
   12310      6127439 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   12311              :         {
   12312            0 :           return targetm.fold_builtin (fndecl, nargs, args, ignore);
   12313              :         }
   12314              :       else
   12315              :         {
   12316      6127439 :           ret = fold_builtin_n (loc, NULL_TREE, fndecl, args, nargs, ignore);
   12317      6127439 :           if (ret)
   12318              :             {
   12319              :               /* Propagate location information from original call to
   12320              :                  expansion of builtin.  Otherwise things like
   12321              :                  maybe_emit_chk_warning, that operate on the expansion
   12322              :                  of a builtin, will use the wrong location information.  */
   12323         4990 :               if (gimple_has_location (stmt))
   12324              :                 {
   12325         4989 :                   tree realret = ret;
   12326         4989 :                   if (TREE_CODE (ret) == NOP_EXPR)
   12327         4989 :                     realret = TREE_OPERAND (ret, 0);
   12328         4989 :                   if (CAN_HAVE_LOCATION_P (realret)
   12329         9200 :                       && !EXPR_HAS_LOCATION (realret))
   12330            6 :                     SET_EXPR_LOCATION (realret, loc);
   12331         4989 :                   return realret;
   12332              :                 }
   12333              :               return ret;
   12334              :             }
   12335              :         }
   12336              :     }
   12337              :   return NULL_TREE;
   12338              : }
   12339              : 
   12340              : /* Look up the function in builtin_decl that corresponds to DECL
   12341              :    and set ASMSPEC as its user assembler name.  DECL must be a
   12342              :    function decl that declares a builtin.  */
   12343              : 
   12344              : void
   12345       155728 : set_builtin_user_assembler_name (tree decl, const char *asmspec)
   12346              : {
   12347       155728 :   gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
   12348              :               && asmspec != 0);
   12349              : 
   12350       155728 :   tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
   12351       155728 :   set_user_assembler_name (builtin, asmspec);
   12352              : 
   12353       155728 :   if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
   12354       155728 :       && INT_TYPE_SIZE < BITS_PER_WORD)
   12355              :     {
   12356            1 :       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
   12357            1 :       set_user_assembler_libfunc ("ffs", asmspec);
   12358            1 :       set_optab_libfunc (ffs_optab, mode, "ffs");
   12359              :     }
   12360       155728 : }
   12361              : 
   12362              : /* Return true if DECL is a builtin that expands to a constant or similarly
   12363              :    simple code.  */
   12364              : bool
   12365     33099281 : is_simple_builtin (tree decl)
   12366              : {
   12367     33099281 :   if (decl && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
   12368     31782337 :     switch (DECL_FUNCTION_CODE (decl))
   12369              :       {
   12370              :         /* Builtins that expand to constants.  */
   12371              :       case BUILT_IN_CONSTANT_P:
   12372              :       case BUILT_IN_EXPECT:
   12373              :       case BUILT_IN_OBJECT_SIZE:
   12374              :       case BUILT_IN_UNREACHABLE:
   12375              :         /* Simple register moves or loads from stack.  */
   12376              :       case BUILT_IN_ASSUME_ALIGNED:
   12377              :       case BUILT_IN_RETURN_ADDRESS:
   12378              :       case BUILT_IN_EXTRACT_RETURN_ADDR:
   12379              :       case BUILT_IN_FROB_RETURN_ADDR:
   12380              :       case BUILT_IN_RETURN:
   12381              :       case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
   12382              :       case BUILT_IN_FRAME_ADDRESS:
   12383              :       case BUILT_IN_VA_END:
   12384              :       case BUILT_IN_STACK_SAVE:
   12385              :       case BUILT_IN_STACK_RESTORE:
   12386              :       case BUILT_IN_DWARF_CFA:
   12387              :       case BUILT_IN_CALL_CODE_ADDRESS:
   12388              :       case BUILT_IN_CALL_STATIC_CHAIN:
   12389              :         /* Exception state returns or moves registers around.  */
   12390              :       case BUILT_IN_EH_FILTER:
   12391              :       case BUILT_IN_EH_POINTER:
   12392              :       case BUILT_IN_EH_COPY_VALUES:
   12393              :         return true;
   12394              : 
   12395     28550740 :       default:
   12396     28550740 :         return false;
   12397              :       }
   12398              : 
   12399              :   return false;
   12400              : }
   12401              : 
   12402              : /* Return true if DECL is a builtin that is not expensive, i.e., they are
   12403              :    most probably expanded inline into reasonably simple code.  This is a
   12404              :    superset of is_simple_builtin.  */
   12405              : bool
   12406     19772580 : is_inexpensive_builtin (tree decl)
   12407              : {
   12408     19772580 :   if (!decl)
   12409              :     return false;
   12410     19758183 :   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
   12411              :     return true;
   12412     18413447 :   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   12413     15464417 :     switch (DECL_FUNCTION_CODE (decl))
   12414              :       {
   12415              :       case BUILT_IN_ABS:
   12416              :       CASE_BUILT_IN_ALLOCA:
   12417              :       case BUILT_IN_BSWAP16:
   12418              :       case BUILT_IN_BSWAP32:
   12419              :       case BUILT_IN_BSWAP64:
   12420              :       case BUILT_IN_BSWAP128:
   12421              :       case BUILT_IN_BITREVERSE8:
   12422              :       case BUILT_IN_BITREVERSE16:
   12423              :       case BUILT_IN_BITREVERSE32:
   12424              :       case BUILT_IN_BITREVERSE64:
   12425              :       case BUILT_IN_BITREVERSE128:
   12426              :       case BUILT_IN_CLZ:
   12427              :       case BUILT_IN_CLZIMAX:
   12428              :       case BUILT_IN_CLZL:
   12429              :       case BUILT_IN_CLZLL:
   12430              :       case BUILT_IN_CTZ:
   12431              :       case BUILT_IN_CTZIMAX:
   12432              :       case BUILT_IN_CTZL:
   12433              :       case BUILT_IN_CTZLL:
   12434              :       case BUILT_IN_FFS:
   12435              :       case BUILT_IN_FFSIMAX:
   12436              :       case BUILT_IN_FFSL:
   12437              :       case BUILT_IN_FFSLL:
   12438              :       case BUILT_IN_IMAXABS:
   12439              :       case BUILT_IN_FINITE:
   12440              :       case BUILT_IN_FINITEF:
   12441              :       case BUILT_IN_FINITEL:
   12442              :       case BUILT_IN_FINITED32:
   12443              :       case BUILT_IN_FINITED64:
   12444              :       case BUILT_IN_FINITED128:
   12445              :       case BUILT_IN_FPCLASSIFY:
   12446              :       case BUILT_IN_ISFINITE:
   12447              :       case BUILT_IN_ISINF_SIGN:
   12448              :       case BUILT_IN_ISINF:
   12449              :       case BUILT_IN_ISINFF:
   12450              :       case BUILT_IN_ISINFL:
   12451              :       case BUILT_IN_ISINFD32:
   12452              :       case BUILT_IN_ISINFD64:
   12453              :       case BUILT_IN_ISINFD128:
   12454              :       case BUILT_IN_ISNAN:
   12455              :       case BUILT_IN_ISNANF:
   12456              :       case BUILT_IN_ISNANL:
   12457              :       case BUILT_IN_ISNAND32:
   12458              :       case BUILT_IN_ISNAND64:
   12459              :       case BUILT_IN_ISNAND128:
   12460              :       case BUILT_IN_ISNORMAL:
   12461              :       case BUILT_IN_ISGREATER:
   12462              :       case BUILT_IN_ISGREATEREQUAL:
   12463              :       case BUILT_IN_ISLESS:
   12464              :       case BUILT_IN_ISLESSEQUAL:
   12465              :       case BUILT_IN_ISLESSGREATER:
   12466              :       case BUILT_IN_ISUNORDERED:
   12467              :       case BUILT_IN_ISEQSIG:
   12468              :       case BUILT_IN_VA_ARG_PACK:
   12469              :       case BUILT_IN_VA_ARG_PACK_LEN:
   12470              :       case BUILT_IN_VA_COPY:
   12471              :       case BUILT_IN_TRAP:
   12472              :       case BUILT_IN_UNREACHABLE_TRAP:
   12473              :       case BUILT_IN_SAVEREGS:
   12474              :       case BUILT_IN_POPCOUNTL:
   12475              :       case BUILT_IN_POPCOUNTLL:
   12476              :       case BUILT_IN_POPCOUNTIMAX:
   12477              :       case BUILT_IN_POPCOUNT:
   12478              :       case BUILT_IN_PARITYL:
   12479              :       case BUILT_IN_PARITYLL:
   12480              :       case BUILT_IN_PARITYIMAX:
   12481              :       case BUILT_IN_PARITY:
   12482              :       case BUILT_IN_LABS:
   12483              :       case BUILT_IN_LLABS:
   12484              :       case BUILT_IN_PREFETCH:
   12485              :       case BUILT_IN_ACC_ON_DEVICE:
   12486              :         return true;
   12487              : 
   12488     14742325 :       default:
   12489     14742325 :         return is_simple_builtin (decl);
   12490              :       }
   12491              : 
   12492              :   return false;
   12493              : }
   12494              : 
   12495              : /* Return true if T is a constant and the value cast to a target char
   12496              :    can be represented by a host char.
   12497              :    Store the casted char constant in *P if so.  */
   12498              : 
   12499              : bool
   12500         3580 : target_char_cst_p (tree t, char *p)
   12501              : {
   12502         3580 :   if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
   12503              :     return false;
   12504              : 
   12505         1910 :   *p = (char)tree_to_uhwi (t);
   12506         1910 :   return true;
   12507              : }
   12508              : 
   12509              : /* Return true if the builtin DECL is implemented in a standard library.
   12510              :    Otherwise return false which doesn't guarantee it is not (thus the list
   12511              :    of handled builtins below may be incomplete).  */
   12512              : 
   12513              : bool
   12514        41760 : builtin_with_linkage_p (tree decl)
   12515              : {
   12516        41760 :   if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   12517        41476 :     switch (DECL_FUNCTION_CODE (decl))
   12518              :     {
   12519         1304 :       CASE_FLT_FN (BUILT_IN_ACOS):
   12520         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
   12521         1304 :       CASE_FLT_FN (BUILT_IN_ACOSH):
   12522         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
   12523         1304 :       CASE_FLT_FN (BUILT_IN_ASIN):
   12524         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
   12525         1304 :       CASE_FLT_FN (BUILT_IN_ASINH):
   12526         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINH):
   12527         1304 :       CASE_FLT_FN (BUILT_IN_ATAN):
   12528         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN):
   12529         1304 :       CASE_FLT_FN (BUILT_IN_ATANH):
   12530         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
   12531         1304 :       CASE_FLT_FN (BUILT_IN_ATAN2):
   12532         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2):
   12533         1304 :       CASE_FLT_FN (BUILT_IN_CBRT):
   12534         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_CBRT):
   12535         1304 :       CASE_FLT_FN (BUILT_IN_CEIL):
   12536         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
   12537         1304 :       CASE_FLT_FN (BUILT_IN_COPYSIGN):
   12538         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
   12539         1304 :       CASE_FLT_FN (BUILT_IN_COS):
   12540         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS):
   12541         1304 :       CASE_FLT_FN (BUILT_IN_COSH):
   12542         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH):
   12543         1304 :       CASE_FLT_FN (BUILT_IN_ERF):
   12544         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERF):
   12545         1304 :       CASE_FLT_FN (BUILT_IN_ERFC):
   12546         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERFC):
   12547         1304 :       CASE_FLT_FN (BUILT_IN_EXP):
   12548         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP):
   12549         1304 :       CASE_FLT_FN (BUILT_IN_EXP2):
   12550         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2):
   12551         1304 :       CASE_FLT_FN (BUILT_IN_EXPM1):
   12552         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1):
   12553         1304 :       CASE_FLT_FN (BUILT_IN_FABS):
   12554         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   12555         1304 :       CASE_FLT_FN (BUILT_IN_FDIM):
   12556         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FDIM):
   12557         1304 :       CASE_FLT_FN (BUILT_IN_FLOOR):
   12558         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
   12559         1304 :       CASE_FLT_FN (BUILT_IN_FMA):
   12560         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
   12561         1304 :       CASE_FLT_FN (BUILT_IN_FMAX):
   12562         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMAX):
   12563         1304 :       CASE_FLT_FN (BUILT_IN_FMIN):
   12564         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN):
   12565         1304 :       CASE_FLT_FN (BUILT_IN_FMOD):
   12566         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD):
   12567         1304 :       CASE_FLT_FN (BUILT_IN_FREXP):
   12568         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FREXP):
   12569         1304 :       CASE_FLT_FN (BUILT_IN_HYPOT):
   12570         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_HYPOT):
   12571         1304 :       CASE_FLT_FN (BUILT_IN_ILOGB):
   12572         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ILOGB):
   12573         1304 :       CASE_FLT_FN (BUILT_IN_LDEXP):
   12574         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LDEXP):
   12575         1304 :       CASE_FLT_FN (BUILT_IN_LGAMMA):
   12576         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LGAMMA):
   12577         1304 :       CASE_FLT_FN (BUILT_IN_LLRINT):
   12578         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLRINT):
   12579         1304 :       CASE_FLT_FN (BUILT_IN_LLROUND):
   12580         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLROUND):
   12581         1304 :       CASE_FLT_FN (BUILT_IN_LOG):
   12582         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
   12583         1304 :       CASE_FLT_FN (BUILT_IN_LOG10):
   12584         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
   12585         1304 :       CASE_FLT_FN (BUILT_IN_LOG1P):
   12586         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
   12587         1304 :       CASE_FLT_FN (BUILT_IN_LOG2):
   12588         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
   12589         1304 :       CASE_FLT_FN (BUILT_IN_LOGB):
   12590         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOGB):
   12591         1304 :       CASE_FLT_FN (BUILT_IN_LRINT):
   12592         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LRINT):
   12593         1304 :       CASE_FLT_FN (BUILT_IN_LROUND):
   12594         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LROUND):
   12595         1304 :       CASE_FLT_FN (BUILT_IN_MODF):
   12596         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_MODF):
   12597         1304 :       CASE_FLT_FN (BUILT_IN_NAN):
   12598         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NAN):
   12599         1304 :       CASE_FLT_FN (BUILT_IN_NEARBYINT):
   12600         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT):
   12601         1304 :       CASE_FLT_FN (BUILT_IN_NEXTAFTER):
   12602         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEXTAFTER):
   12603         1304 :       CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
   12604         1304 :       CASE_FLT_FN (BUILT_IN_POW):
   12605         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_POW):
   12606         1304 :       CASE_FLT_FN (BUILT_IN_REMAINDER):
   12607         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER):
   12608         1304 :       CASE_FLT_FN (BUILT_IN_REMQUO):
   12609         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMQUO):
   12610         1304 :       CASE_FLT_FN (BUILT_IN_RINT):
   12611         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
   12612         1304 :       CASE_FLT_FN (BUILT_IN_ROUND):
   12613         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
   12614         1304 :       CASE_FLT_FN (BUILT_IN_SCALBLN):
   12615         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBLN):
   12616         1304 :       CASE_FLT_FN (BUILT_IN_SCALBN):
   12617         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBN):
   12618         1304 :       CASE_FLT_FN (BUILT_IN_SIN):
   12619         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN):
   12620         1304 :       CASE_FLT_FN (BUILT_IN_SINH):
   12621         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH):
   12622         1304 :       CASE_FLT_FN (BUILT_IN_SINCOS):
   12623         1304 :       CASE_FLT_FN (BUILT_IN_SQRT):
   12624         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
   12625         1304 :       CASE_FLT_FN (BUILT_IN_TAN):
   12626         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TAN):
   12627         1304 :       CASE_FLT_FN (BUILT_IN_TANH):
   12628         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANH):
   12629         1304 :       CASE_FLT_FN (BUILT_IN_TGAMMA):
   12630         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TGAMMA):
   12631         1304 :       CASE_FLT_FN (BUILT_IN_TRUNC):
   12632         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC):
   12633         1304 :         return true;
   12634              : 
   12635           16 :       case BUILT_IN_STPCPY:
   12636           16 :       case BUILT_IN_STPNCPY:
   12637              :         /* stpcpy is both referenced in libiberty's pex-win32.c and provided
   12638              :            by libiberty's stpcpy.c for MinGW targets so we need to return true
   12639              :            in order to be able to build libiberty in LTO mode for them.  */
   12640           16 :         return true;
   12641              : 
   12642              :       default:
   12643              :         break;
   12644              :     }
   12645              :   return false;
   12646              : }
   12647              : 
   12648              : /* Return true if OFFRNG is bounded to a subrange of offset values
   12649              :    valid for the largest possible object.  */
   12650              : 
   12651              : bool
   12652          501 : access_ref::offset_bounded () const
   12653              : {
   12654          501 :   tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
   12655          501 :   tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
   12656          975 :   return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max);
   12657              : }
   12658              : 
   12659              : /* If CALLEE has known side effects, fill in INFO and return true.
   12660              :    See tree-ssa-structalias.cc:find_func_aliases
   12661              :    for the list of builtins we might need to handle here.  */
   12662              : 
   12663              : attr_fnspec
   12664    111910839 : builtin_fnspec (tree callee)
   12665              : {
   12666    111910839 :   built_in_function code = DECL_FUNCTION_CODE (callee);
   12667              : 
   12668    111910839 :   switch (code)
   12669              :     {
   12670              :       /* All the following functions read memory pointed to by
   12671              :          their second argument and write memory pointed to by first
   12672              :          argument.
   12673              :          strcat/strncat additionally reads memory pointed to by the first
   12674              :          argument.  */
   12675       133249 :       case BUILT_IN_STRCAT:
   12676       133249 :       case BUILT_IN_STRCAT_CHK:
   12677       133249 :         return "1cW 1 ";
   12678        42125 :       case BUILT_IN_STRNCAT:
   12679        42125 :       case BUILT_IN_STRNCAT_CHK:
   12680        42125 :         return "1cW 13";
   12681       263014 :       case BUILT_IN_STRCPY:
   12682       263014 :       case BUILT_IN_STRCPY_CHK:
   12683       263014 :         return "1cO 1 ";
   12684        32263 :       case BUILT_IN_STPCPY:
   12685        32263 :       case BUILT_IN_STPCPY_CHK:
   12686        32263 :         return ".cO 1 ";
   12687     19045406 :       case BUILT_IN_STRNCPY:
   12688     19045406 :       case BUILT_IN_MEMCPY:
   12689     19045406 :       case BUILT_IN_MEMMOVE:
   12690     19045406 :       case BUILT_IN_TM_MEMCPY:
   12691     19045406 :       case BUILT_IN_TM_MEMMOVE:
   12692     19045406 :       case BUILT_IN_STRNCPY_CHK:
   12693     19045406 :       case BUILT_IN_MEMCPY_CHK:
   12694     19045406 :       case BUILT_IN_MEMMOVE_CHK:
   12695     19045406 :         return "1cO313";
   12696       142792 :       case BUILT_IN_MEMPCPY:
   12697       142792 :       case BUILT_IN_MEMPCPY_CHK:
   12698       142792 :         return ".cO313";
   12699        57623 :       case BUILT_IN_STPNCPY:
   12700        57623 :       case BUILT_IN_STPNCPY_CHK:
   12701        57623 :         return ".cO313";
   12702            0 :       case BUILT_IN_BCOPY:
   12703            0 :         return ".c23O3";
   12704            0 :       case BUILT_IN_BZERO:
   12705            0 :         return ".cO2";
   12706      9174488 :       case BUILT_IN_MEMCMP:
   12707      9174488 :       case BUILT_IN_MEMCMP_EQ:
   12708      9174488 :       case BUILT_IN_BCMP:
   12709      9174488 :       case BUILT_IN_STRNCMP:
   12710      9174488 :       case BUILT_IN_STRNCMP_EQ:
   12711      9174488 :       case BUILT_IN_STRNCASECMP:
   12712      9174488 :         return ".cR3R3";
   12713              : 
   12714              :       /* The following functions read memory pointed to by their
   12715              :          first argument.  */
   12716          744 :       CASE_BUILT_IN_TM_LOAD (1):
   12717          744 :       CASE_BUILT_IN_TM_LOAD (2):
   12718          744 :       CASE_BUILT_IN_TM_LOAD (4):
   12719          744 :       CASE_BUILT_IN_TM_LOAD (8):
   12720          744 :       CASE_BUILT_IN_TM_LOAD (FLOAT):
   12721          744 :       CASE_BUILT_IN_TM_LOAD (DOUBLE):
   12722          744 :       CASE_BUILT_IN_TM_LOAD (LDOUBLE):
   12723          744 :       CASE_BUILT_IN_TM_LOAD (M64):
   12724          744 :       CASE_BUILT_IN_TM_LOAD (M128):
   12725          744 :       CASE_BUILT_IN_TM_LOAD (M256):
   12726          744 :       case BUILT_IN_TM_LOG:
   12727          744 :       case BUILT_IN_TM_LOG_1:
   12728          744 :       case BUILT_IN_TM_LOG_2:
   12729          744 :       case BUILT_IN_TM_LOG_4:
   12730          744 :       case BUILT_IN_TM_LOG_8:
   12731          744 :       case BUILT_IN_TM_LOG_FLOAT:
   12732          744 :       case BUILT_IN_TM_LOG_DOUBLE:
   12733          744 :       case BUILT_IN_TM_LOG_LDOUBLE:
   12734          744 :       case BUILT_IN_TM_LOG_M64:
   12735          744 :       case BUILT_IN_TM_LOG_M128:
   12736          744 :       case BUILT_IN_TM_LOG_M256:
   12737          744 :         return ".cR ";
   12738              : 
   12739       518422 :       case BUILT_IN_INDEX:
   12740       518422 :       case BUILT_IN_RINDEX:
   12741       518422 :       case BUILT_IN_STRCHR:
   12742       518422 :       case BUILT_IN_STRLEN:
   12743       518422 :       case BUILT_IN_STRRCHR:
   12744       518422 :         return ".cR ";
   12745        70319 :       case BUILT_IN_STRNLEN:
   12746        70319 :         return ".cR2";
   12747              : 
   12748              :       /* These read memory pointed to by the first argument.
   12749              :          Allocating memory does not have any side-effects apart from
   12750              :          being the definition point for the pointer.
   12751              :          Unix98 specifies that errno is set on allocation failure.  */
   12752        18018 :       case BUILT_IN_STRDUP:
   12753        18018 :         return "mCR ";
   12754        13292 :       case BUILT_IN_STRNDUP:
   12755        13292 :         return "mCR2";
   12756              :       /* Allocating memory does not have any side-effects apart from
   12757              :          being the definition point for the pointer.  */
   12758     10999667 :       case BUILT_IN_MALLOC:
   12759     10999667 :       case BUILT_IN_ALIGNED_ALLOC:
   12760     10999667 :       case BUILT_IN_CALLOC:
   12761     10999667 :       case BUILT_IN_GOMP_ALLOC:
   12762     10999667 :         return "mC";
   12763       841061 :       CASE_BUILT_IN_ALLOCA:
   12764       841061 :         return "mc";
   12765              :       /* These read memory pointed to by the first argument with size
   12766              :          in the third argument.  */
   12767       687262 :       case BUILT_IN_MEMCHR:
   12768       687262 :         return ".cR3";
   12769              :       /* These read memory pointed to by the first and second arguments.  */
   12770     11299864 :       case BUILT_IN_STRSTR:
   12771     11299864 :       case BUILT_IN_STRPBRK:
   12772     11299864 :       case BUILT_IN_STRCASECMP:
   12773     11299864 :       case BUILT_IN_STRCSPN:
   12774     11299864 :       case BUILT_IN_STRSPN:
   12775     11299864 :       case BUILT_IN_STRCMP:
   12776     11299864 :       case BUILT_IN_STRCMP_EQ:
   12777     11299864 :         return ".cR R ";
   12778              :       /* Freeing memory kills the pointed-to memory.  More importantly
   12779              :          the call has to serve as a barrier for moving loads and stores
   12780              :          across it.  */
   12781      6408633 :       case BUILT_IN_STACK_RESTORE:
   12782      6408633 :       case BUILT_IN_FREE:
   12783      6408633 :       case BUILT_IN_GOMP_FREE:
   12784      6408633 :         return ".co ";
   12785       108055 :       case BUILT_IN_VA_END:
   12786       108055 :         return ".cO ";
   12787              :       /* Realloc serves both as allocation point and deallocation point.  */
   12788      1060927 :       case BUILT_IN_REALLOC:
   12789      1060927 :       case BUILT_IN_GOMP_REALLOC:
   12790      1060927 :         return ".Cw ";
   12791        15732 :       case BUILT_IN_GAMMA_R:
   12792        15732 :       case BUILT_IN_GAMMAF_R:
   12793        15732 :       case BUILT_IN_GAMMAL_R:
   12794        15732 :       case BUILT_IN_LGAMMA_R:
   12795        15732 :       case BUILT_IN_LGAMMAF_R:
   12796        15732 :       case BUILT_IN_LGAMMAL_R:
   12797        15732 :         return ".C. Ot";
   12798        48780 :       case BUILT_IN_FREXP:
   12799        48780 :       case BUILT_IN_FREXPF:
   12800        48780 :       case BUILT_IN_FREXPL:
   12801        48780 :       case BUILT_IN_MODF:
   12802        48780 :       case BUILT_IN_MODFF:
   12803        48780 :       case BUILT_IN_MODFL:
   12804        48780 :         return ".c. Ot";
   12805         7586 :       case BUILT_IN_REMQUO:
   12806         7586 :       case BUILT_IN_REMQUOF:
   12807         7586 :       case BUILT_IN_REMQUOL:
   12808         7586 :         return ".c. . Ot";
   12809          164 :       case BUILT_IN_SINCOS:
   12810          164 :       case BUILT_IN_SINCOSF:
   12811          164 :       case BUILT_IN_SINCOSL:
   12812          164 :         return ".c. OtOt";
   12813      4331293 :       case BUILT_IN_MEMSET:
   12814      4331293 :       case BUILT_IN_MEMSET_CHK:
   12815      4331293 :       case BUILT_IN_TM_MEMSET:
   12816      4331293 :         return "1cO3";
   12817          366 :       CASE_BUILT_IN_TM_STORE (1):
   12818          366 :       CASE_BUILT_IN_TM_STORE (2):
   12819          366 :       CASE_BUILT_IN_TM_STORE (4):
   12820          366 :       CASE_BUILT_IN_TM_STORE (8):
   12821          366 :       CASE_BUILT_IN_TM_STORE (FLOAT):
   12822          366 :       CASE_BUILT_IN_TM_STORE (DOUBLE):
   12823          366 :       CASE_BUILT_IN_TM_STORE (LDOUBLE):
   12824          366 :       CASE_BUILT_IN_TM_STORE (M64):
   12825          366 :       CASE_BUILT_IN_TM_STORE (M128):
   12826          366 :       CASE_BUILT_IN_TM_STORE (M256):
   12827          366 :         return ".cO ";
   12828      2388208 :       case BUILT_IN_STACK_SAVE:
   12829      2388208 :       case BUILT_IN_RETURN:
   12830      2388208 :       case BUILT_IN_EH_POINTER:
   12831      2388208 :       case BUILT_IN_EH_FILTER:
   12832      2388208 :       case BUILT_IN_UNWIND_RESUME:
   12833      2388208 :       case BUILT_IN_CXA_END_CLEANUP:
   12834      2388208 :       case BUILT_IN_EH_COPY_VALUES:
   12835      2388208 :       case BUILT_IN_FRAME_ADDRESS:
   12836      2388208 :       case BUILT_IN_APPLY_ARGS:
   12837      2388208 :       case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
   12838      2388208 :       case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
   12839      2388208 :       case BUILT_IN_PREFETCH:
   12840      2388208 :       case BUILT_IN_DWARF_CFA:
   12841      2388208 :       case BUILT_IN_RETURN_ADDRESS:
   12842      2388208 :         return ".c";
   12843      2208636 :       case BUILT_IN_ASSUME_ALIGNED:
   12844      2208636 :       case BUILT_IN_EXPECT:
   12845      2208636 :       case BUILT_IN_EXPECT_WITH_PROBABILITY:
   12846      2208636 :         return "1cX ";
   12847              :       /* But posix_memalign stores a pointer into the memory pointed to
   12848              :          by its first argument.  */
   12849         5680 :       case BUILT_IN_POSIX_MEMALIGN:
   12850         5680 :         return ".cOt";
   12851         4438 :       case BUILT_IN_OMP_GET_MAPPED_PTR:
   12852         4438 :         return ". R ";
   12853              : 
   12854     41982732 :       default:
   12855     41982732 :         return "";
   12856              :     }
   12857              : }
        

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