LCOV - code coverage report
Current view: top level - gcc - builtins.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.8 % 5826 5000
Test Date: 2026-10-17 16:30:31 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 "tree-eh.h"
      34              : #include "predict.h"
      35              : #include "tm_p.h"
      36              : #include "stringpool.h"
      37              : #include "tree-vrp.h"
      38              : #include "tree-ssanames.h"
      39              : #include "expmed.h"
      40              : #include "optabs.h"
      41              : #include "emit-rtl.h"
      42              : #include "recog.h"
      43              : #include "diagnostic-core.h"
      44              : #include "alias.h"
      45              : #include "fold-const.h"
      46              : #include "fold-const-call.h"
      47              : #include "gimple-ssa-warn-access.h"
      48              : #include "stor-layout.h"
      49              : #include "calls.h"
      50              : #include "varasm.h"
      51              : #include "tree-object-size.h"
      52              : #include "tree-ssa-strlen.h"
      53              : #include "realmpfr.h"
      54              : #include "cfgrtl.h"
      55              : #include "except.h"
      56              : #include "dojump.h"
      57              : #include "explow.h"
      58              : #include "stmt.h"
      59              : #include "expr.h"
      60              : #include "libfuncs.h"
      61              : #include "output.h"
      62              : #include "typeclass.h"
      63              : #include "langhooks.h"
      64              : #include "value-prof.h"
      65              : #include "builtins.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       536578 : is_builtin_name (const char *name)
     203              : {
     204       536578 :   return (startswith (name, "__builtin_")
     205       194775 :           || startswith (name, "__sync_")
     206       730488 :           || 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       536578 : 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       536578 :   const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
     220       536578 :   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    113259061 : get_object_alignment_2 (tree exp, unsigned int *alignp,
     240              :                         unsigned HOST_WIDE_INT *bitposp, bool addr_p)
     241              : {
     242    113259061 :   poly_int64 bitsize, bitpos;
     243    113259061 :   tree offset;
     244    113259061 :   machine_mode mode;
     245    113259061 :   int unsignedp, reversep, volatilep;
     246    113259061 :   unsigned int align = BITS_PER_UNIT;
     247    113259061 :   bool known_alignment = false;
     248              : 
     249              :   /* Get the innermost object and the constant (bitpos) and possibly
     250              :      variable (offset) offset of the access.  */
     251    113259061 :   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    113259061 :   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    112792431 :   else if (TREE_CODE (exp) == LABEL_DECL)
     266              :     ;
     267    112755512 :   else if (TREE_CODE (exp) == CONST_DECL)
     268              :     {
     269              :       /* The alignment of a CONST_DECL is determined by its initializer.  */
     270        59818 :       exp = DECL_INITIAL (exp);
     271        59818 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     272        59818 :       if (CONSTANT_CLASS_P (exp))
     273        59817 :         align = targetm.constant_alignment (exp, align);
     274              : 
     275              :       known_alignment = true;
     276              :     }
     277    112695694 :   else if (DECL_P (exp))
     278              :     {
     279     67441785 :       align = DECL_ALIGN (exp);
     280              :       known_alignment = true;
     281              :     }
     282     45253909 :   else if (TREE_CODE (exp) == INDIRECT_REF
     283     45252853 :            || TREE_CODE (exp) == MEM_REF
     284      5424235 :            || TREE_CODE (exp) == TARGET_MEM_REF)
     285              :     {
     286     43534513 :       tree addr = TREE_OPERAND (exp, 0);
     287     43534513 :       unsigned ptr_align;
     288     43534513 :       unsigned HOST_WIDE_INT ptr_bitpos;
     289     43534513 :       unsigned HOST_WIDE_INT ptr_bitmask = ~0;
     290              : 
     291              :       /* If the address is explicitly aligned, handle that.  */
     292     43534513 :       if (TREE_CODE (addr) == BIT_AND_EXPR
     293     43534513 :           && 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     43534513 :       known_alignment
     302     43534513 :         = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
     303     43534513 :       align = MAX (ptr_align, align);
     304              : 
     305              :       /* Re-apply explicit alignment to the bitpos.  */
     306     43534513 :       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     43534513 :       if (TREE_CODE (exp) == TARGET_MEM_REF)
     311              :         {
     312      3704839 :           if (TMR_INDEX (exp))
     313              :             {
     314      1607280 :               unsigned HOST_WIDE_INT step = 1;
     315      1607280 :               if (TMR_STEP (exp))
     316      1474699 :                 step = TREE_INT_CST_LOW (TMR_STEP (exp));
     317      1607280 :               align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
     318              :             }
     319      3704839 :           if (TMR_INDEX2 (exp))
     320        41779 :             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     43534513 :       unsigned int talign;
     330     43534513 :       if (!addr_p && !known_alignment
     331     41047675 :           && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
     332     84582182 :           && talign > align)
     333              :         align = talign;
     334              :       else
     335              :         {
     336              :           /* Else adjust bitpos accordingly.  */
     337     11861408 :           bitpos += ptr_bitpos;
     338     11861408 :           if (TREE_CODE (exp) == MEM_REF
     339     11861408 :               || TREE_CODE (exp) == TARGET_MEM_REF)
     340     11860352 :             bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
     341              :         }
     342     43534513 :     }
     343      1719396 :   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      1718776 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     348      1718776 :       if (CONSTANT_CLASS_P (exp))
     349      1718776 :         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    113259061 :   if (offset)
     357              :     {
     358     10028514 :       unsigned int trailing_zeros = tree_ctz (offset);
     359     10028514 :       if (trailing_zeros < HOST_BITS_PER_INT)
     360              :         {
     361     10028436 :           unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     362     10028436 :           if (inner)
     363     10028436 :             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    113259061 :   unsigned int alt_align = ::known_alignment (bitpos - bitpos.coeffs[0]);
     370    113259061 :   if (alt_align != 0 && alt_align < align)
     371              :     {
     372              :       align = alt_align;
     373              :       known_alignment = false;
     374              :     }
     375              : 
     376    113259061 :   *alignp = align;
     377    113259061 :   *bitposp = bitpos.coeffs[0] & (align - 1);
     378    113259061 :   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     89834413 : 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     89834413 :   if (TREE_CODE (exp) == WITH_SIZE_EXPR)
     393            0 :     exp = TREE_OPERAND (exp, 0);
     394     89834413 :   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     37092734 : get_object_alignment (tree exp)
     401              : {
     402     37092734 :   unsigned HOST_WIDE_INT bitpos = 0;
     403     37092734 :   unsigned int align;
     404              : 
     405     37092734 :   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     37092734 :   if (bitpos != 0)
     411      2777629 :     align = least_bit_hwi (bitpos);
     412     37092734 :   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     86052519 : get_pointer_alignment_1 (tree exp, unsigned int *alignp,
     424              :                          unsigned HOST_WIDE_INT *bitposp)
     425              : {
     426     86052519 :   STRIP_NOPS (exp);
     427              : 
     428     86052519 :   if (TREE_CODE (exp) == ADDR_EXPR)
     429     23423009 :     return get_object_alignment_2 (TREE_OPERAND (exp, 0),
     430     23423009 :                                    alignp, bitposp, true);
     431     62629510 :   else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
     432              :     {
     433      1032010 :       unsigned int align;
     434      1032010 :       unsigned HOST_WIDE_INT bitpos;
     435      1032010 :       bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
     436              :                                           &align, &bitpos);
     437      1032010 :       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
     438         3758 :         bitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT;
     439              :       else
     440              :         {
     441      1028252 :           unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
     442      1028252 :           if (trailing_zeros < HOST_BITS_PER_INT)
     443              :             {
     444      1028244 :               unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     445      1028244 :               if (inner)
     446      1028244 :                 align = MIN (align, inner);
     447              :             }
     448              :         }
     449      1032010 :       *alignp = align;
     450      1032010 :       *bitposp = bitpos & (align - 1);
     451      1032010 :       return res;
     452              :     }
     453     61597500 :   else if (TREE_CODE (exp) == SSA_NAME
     454     61597500 :            && POINTER_TYPE_P (TREE_TYPE (exp)))
     455              :     {
     456     59224138 :       unsigned int ptr_align, ptr_misalign;
     457     59224138 :       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
     458              : 
     459     59224138 :       if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
     460              :         {
     461      6501205 :           *bitposp = ptr_misalign * BITS_PER_UNIT;
     462      6501205 :           *alignp = ptr_align * BITS_PER_UNIT;
     463              :           /* Make sure to return a sensible alignment when the multiplication
     464              :              by BITS_PER_UNIT overflowed.  */
     465      6501205 :           if (*alignp == 0)
     466           30 :             *alignp = 1u << (HOST_BITS_PER_INT - 1);
     467              :           /* We cannot really tell whether this result is an approximation.  */
     468              :           return false;
     469              :         }
     470              :       else
     471              :         {
     472     52722933 :           *bitposp = 0;
     473     52722933 :           *alignp = BITS_PER_UNIT;
     474     52722933 :           return false;
     475              :         }
     476              :     }
     477      2373362 :   else if (TREE_CODE (exp) == INTEGER_CST)
     478              :     {
     479        18212 :       *alignp = BIGGEST_ALIGNMENT;
     480        18212 :       *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
     481        18212 :                   & (BIGGEST_ALIGNMENT - 1));
     482        18212 :       return true;
     483              :     }
     484              : 
     485      2355150 :   *bitposp = 0;
     486      2355150 :   *alignp = BITS_PER_UNIT;
     487      2355150 :   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     11718229 : get_pointer_alignment (tree exp)
     499              : {
     500     11718229 :   unsigned HOST_WIDE_INT bitpos = 0;
     501     11718229 :   unsigned int align;
     502              : 
     503     11718229 :   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     11718229 :   if (bitpos != 0)
     509        79994 :     align = least_bit_hwi (bitpos);
     510              : 
     511     11718229 :   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       775613 : string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
     520              : {
     521       775613 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     522              : 
     523       775613 :   unsigned n;
     524              : 
     525       775613 :   if (eltsize == 1)
     526              :     {
     527              :       /* Optimize the common case of plain char.  */
     528    244955405 :       for (n = 0; n < maxelts; n++)
     529              :         {
     530    244864951 :           const char *elt = (const char*) ptr + n;
     531    244864951 :           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       775613 :   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      2640648 : 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      2640648 :   c_strlen_data local_strlen_data = { };
     583      2640648 :   if (!data)
     584       606624 :     data = &local_strlen_data;
     585              : 
     586      2640648 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     587              : 
     588      2640648 :   tree src = STRIP_NOPS (arg);
     589      2640648 :   if (TREE_CODE (src) == COND_EXPR
     590      2640648 :       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     591              :     {
     592          690 :       tree len1, len2;
     593              : 
     594          690 :       len1 = c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
     595          690 :       len2 = c_strlen (TREE_OPERAND (src, 2), only_value, data, eltsize);
     596          690 :       if (tree_int_cst_equal (len1, len2))
     597              :         return len1;
     598              :     }
     599              : 
     600      2640482 :   if (TREE_CODE (src) == COMPOUND_EXPR
     601      2640482 :       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     602           45 :     return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
     603              : 
     604      2640437 :   location_t loc = EXPR_LOC_OR_LOC (src, input_location);
     605              : 
     606              :   /* Offset from the beginning of the string in bytes.  */
     607      2640437 :   tree byteoff;
     608      2640437 :   tree memsize;
     609      2640437 :   tree decl;
     610      2640437 :   src = string_constant (src, &byteoff, &memsize, &decl);
     611      2640437 :   if (src == 0)
     612              :     return NULL_TREE;
     613              : 
     614              :   /* Determine the size of the string element.  */
     615       791860 :   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       779441 :   HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
     625       779441 :   strelts = strelts / eltsize;
     626              : 
     627       779441 :   if (!tree_fits_uhwi_p (memsize))
     628              :     return NULL_TREE;
     629              : 
     630       779441 :   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       779441 :   const char *ptr = TREE_STRING_POINTER (src);
     635              : 
     636       779441 :   if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
     637              :     {
     638              :       /* The code below works only for single byte character types.  */
     639         5050 :       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         5050 :       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         5050 :       if (len + 1 < strelts)
     652              :         return NULL_TREE;
     653         4480 :       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         3378 :       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         3339 :       tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
     671              :                                                  : byteoff;
     672         3339 :       offsave = fold_convert_loc (loc, sizetype, offsave);
     673         3339 :       tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
     674         3339 :                                       size_int (len));
     675         3339 :       tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
     676              :                                      offsave);
     677         3339 :       lenexp = fold_convert_loc (loc, ssizetype, lenexp);
     678         3339 :       return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
     679         3339 :                               build_zero_cst (ssizetype));
     680              :     }
     681              : 
     682              :   /* Offset from the beginning of the string in elements.  */
     683       774391 :   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       774391 :   if (byteoff == 0)
     688              :     eltoff = 0;
     689       774391 :   else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
     690              :     eltoff = -1;
     691              :   else
     692       773203 :     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       774391 :   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              :       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       770563 :   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       770563 :   unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
     724       770563 :                                 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       770563 :   if (len >= maxelts - eltoff)
     730              :     {
     731        84856 :       data->decl = decl;
     732        84856 :       data->off = byteoff;
     733        84856 :       data->minlen = ssize_int (len);
     734        84856 :       return NULL_TREE;
     735              :     }
     736              : 
     737       685707 :   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       298361 : c_readstr (const char *str, fixed_size_mode mode,
     748              :            bool null_terminated_p/*=true*/)
     749              : {
     750       298361 :   auto_vec<target_unit, MAX_BITSIZE_MODE_ANY_INT / BITS_PER_UNIT> bytes;
     751              : 
     752       596722 :   bytes.reserve (GET_MODE_SIZE (mode));
     753              : 
     754       298361 :   target_unit ch = 1;
     755      4954346 :   for (unsigned int i = 0; i < GET_MODE_SIZE (mode); ++i)
     756              :     {
     757      2178812 :       if (ch || !null_terminated_p)
     758      2090070 :         ch = (unsigned char) str[i];
     759      2178812 :       bytes.quick_push (ch);
     760              :     }
     761              : 
     762       298361 :   return native_decode_rtx (mode, bytes, 0);
     763       298361 : }
     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        60996 : target_char_cast (tree cst, char *p)
     771              : {
     772        60996 :   unsigned HOST_WIDE_INT val, hostval;
     773              : 
     774        60996 :   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        60996 :   val = TREE_INT_CST_LOW (cst);
     780              : 
     781        60996 :   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
     782        60996 :     val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
     783              : 
     784        60996 :   hostval = val;
     785        60996 :   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
     786        60996 :     hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
     787              : 
     788        60996 :   if (val != hostval)
     789              :     return 1;
     790              : 
     791        60996 :   *p = hostval;
     792        60996 :   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      1138207 : builtin_save_expr (tree exp)
     801              : {
     802      1138207 :   if (TREE_CODE (exp) == SSA_NAME
     803       973862 :       || (TREE_ADDRESSABLE (exp) == 0
     804       973670 :           && (TREE_CODE (exp) == PARM_DECL
     805       435239 :               || (VAR_P (exp) && !TREE_STATIC (exp)))))
     806              :     return exp;
     807              : 
     808       433430 :   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        15936 : expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
     817              : {
     818        15936 :   int i;
     819        15936 :   rtx tem = INITIAL_FRAME_ADDRESS_RTX;
     820        15936 :   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        15936 :       if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
     832         4333 :         tem = frame_pointer_rtx;
     833              :       else
     834              :         {
     835        11603 :           tem = hard_frame_pointer_rtx;
     836              : 
     837              :           /* Tell reload not to eliminate the frame pointer.  */
     838        11603 :           crtl->accesses_prior_frames = 1;
     839              :         }
     840              :     }
     841              : 
     842        15936 :   if (count > 0)
     843          938 :     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        15936 :   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        51818 :   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        35882 :       tem = DYNAMIC_CHAIN_ADDRESS (tem);
     858        35882 :       tem = memory_address (Pmode, tem);
     859        35882 :       tem = gen_frame_mem (Pmode, tem);
     860        35882 :       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        15936 :   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
     866              :     return FRAME_ADDR_RTX (count, tem);
     867              : 
     868              :   /* For __builtin_return_address, get the return address from that frame.  */
     869              : #ifdef RETURN_ADDR_RTX
     870         7402 :   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         5173 :   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          842 : expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
     888              : {
     889          842 :   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
     890          842 :   rtx stack_save;
     891          842 :   rtx mem;
     892              : 
     893          842 :   if (setjmp_alias_set == -1)
     894          241 :     setjmp_alias_set = new_alias_set ();
     895              : 
     896          843 :   buf_addr = convert_memory_address (Pmode, buf_addr);
     897              : 
     898          843 :   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          843 :   mem = gen_rtx_MEM (Pmode, buf_addr);
     905          842 :   set_mem_alias_set (mem, setjmp_alias_set);
     906          842 :   emit_move_insn (mem, hard_frame_pointer_rtx);
     907              : 
     908          843 :   mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
     909         1684 :                                            GET_MODE_SIZE (Pmode))),
     910          842 :   set_mem_alias_set (mem, setjmp_alias_set);
     911              : 
     912         1684 :   emit_move_insn (validize_mem (mem),
     913         1684 :                   force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
     914              : 
     915          842 :   stack_save = gen_rtx_MEM (sa_mode,
     916              :                             plus_constant (Pmode, buf_addr,
     917         1684 :                                            2 * GET_MODE_SIZE (Pmode)));
     918          842 :   set_mem_alias_set (stack_save, setjmp_alias_set);
     919          842 :   emit_stack_save (SAVE_NONLOCAL, &stack_save);
     920              : 
     921              :   /* If there is further processing to do, do it.  */
     922          842 :   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          842 :   cfun->has_nonlocal_label = 1;
     927          842 : }
     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         1346 : expand_builtin_setjmp_receiver (rtx receiver_label)
     935              : {
     936         1346 :   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         1346 :   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         1346 :   chain = rtx_for_static_chain (current_function_decl, true);
     945         1346 :   if (chain && REG_P (chain))
     946            1 :     emit_clobber (chain);
     947              : 
     948         1346 :   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         2692 :       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
     959         2692 :         if (elim_regs[i].from == ARG_POINTER_REGNUM
     960         2692 :             && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
     961              :           break;
     962              : 
     963         1346 :       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         1346 :   if (receiver_label != NULL && targetm.have_builtin_setjmp_receiver ())
     973            0 :     emit_insn (targetm.gen_builtin_setjmp_receiver (receiver_label));
     974         1346 :   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         1346 :   emit_insn (gen_blockage ());
     983         1346 : }
     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          392 : expand_builtin_longjmp (rtx buf_addr, rtx value)
     992              : {
     993          392 :   rtx fp, lab, stack;
     994          392 :   rtx_insn *insn, *last;
     995          392 :   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          392 :   if (SUPPORTS_STACK_ALIGNMENT)
    1000          392 :     crtl->need_drap = true;
    1001              : 
    1002          392 :   if (setjmp_alias_set == -1)
    1003          331 :     setjmp_alias_set = new_alias_set ();
    1004              : 
    1005          393 :   buf_addr = convert_memory_address (Pmode, buf_addr);
    1006              : 
    1007          393 :   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          392 :   gcc_assert (value == const1_rtx);
    1012              : 
    1013          392 :   last = get_last_insn ();
    1014          392 :   if (targetm.have_builtin_longjmp ())
    1015            0 :     emit_insn (targetm.gen_builtin_longjmp (buf_addr));
    1016              :   else
    1017              :     {
    1018          393 :       fp = gen_rtx_MEM (Pmode, buf_addr);
    1019          393 :       lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
    1020          784 :                                                GET_MODE_SIZE (Pmode)));
    1021              : 
    1022          392 :       stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
    1023          784 :                                                    2 * GET_MODE_SIZE (Pmode)));
    1024          392 :       set_mem_alias_set (fp, setjmp_alias_set);
    1025          392 :       set_mem_alias_set (lab, setjmp_alias_set);
    1026          392 :       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          392 :       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          392 :           emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
    1038          392 :           emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
    1039              : 
    1040          392 :           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          392 :           fp = copy_to_reg (fp);
    1045          392 :           emit_stack_restore (SAVE_NONLOCAL, stack);
    1046              : 
    1047              :           /* Ensure the frame pointer move is not optimized.  */
    1048          392 :           emit_insn (gen_blockage ());
    1049          392 :           emit_clobber (hard_frame_pointer_rtx);
    1050          392 :           emit_clobber (frame_pointer_rtx);
    1051          392 :           emit_move_insn (hard_frame_pointer_rtx, fp);
    1052              : 
    1053          392 :           emit_use (hard_frame_pointer_rtx);
    1054          392 :           emit_use (stack_pointer_rtx);
    1055          392 :           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          784 :   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
    1065              :     {
    1066          784 :       gcc_assert (insn != last);
    1067              : 
    1068          784 :       if (JUMP_P (insn))
    1069              :         {
    1070          392 :           add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
    1071          392 :           break;
    1072              :         }
    1073          392 :       else if (CALL_P (insn))
    1074              :         break;
    1075              :     }
    1076          392 : }
    1077              : 
    1078              : static inline bool
    1079      1960109 : more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
    1080              : {
    1081      1960109 :   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       509770 : validate_arglist (const_tree callexpr, ...)
    1091              : {
    1092       509770 :   enum tree_code code;
    1093       509770 :   bool res = 0;
    1094       509770 :   va_list ap;
    1095       509770 :   const_call_expr_arg_iterator iter;
    1096       509770 :   const_tree arg;
    1097              : 
    1098       509770 :   va_start (ap, callexpr);
    1099       509770 :   init_const_call_expr_arg_iterator (callexpr, &iter);
    1100              : 
    1101              :   /* Get a bitmap of pointer argument numbers declared attribute nonnull.  */
    1102       509770 :   tree fn = CALL_EXPR_FN (callexpr);
    1103       509770 :   bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
    1104              : 
    1105      1779848 :   for (unsigned argno = 1; ; ++argno)
    1106              :     {
    1107      1779848 :       code = (enum tree_code) va_arg (ap, int);
    1108              : 
    1109      1779848 :       switch (code)
    1110              :         {
    1111         2058 :         case 0:
    1112              :           /* This signifies an ellipses, any further arguments are all ok.  */
    1113         2058 :           res = true;
    1114         2058 :           goto end;
    1115       507480 :         case VOID_TYPE:
    1116              :           /* This signifies an endlink, if no arguments remain, return
    1117              :              true, otherwise return false.  */
    1118       507480 :           res = !more_const_call_expr_args_p (&iter);
    1119       507480 :           goto end;
    1120       836468 :         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       836468 :           if (argmap
    1125       836468 :               && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
    1126              :             {
    1127       281938 :               arg = next_const_call_expr_arg (&iter);
    1128       281938 :               if (!validate_arg (arg, code) || integer_zerop (arg))
    1129           58 :                 goto end;
    1130              :               break;
    1131              :             }
    1132              :           /* FALLTHRU */
    1133       988372 :         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       988372 :           arg = next_const_call_expr_arg (&iter);
    1138       988372 :           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       509770 :  end: ;
    1147       509770 :   va_end (ap);
    1148              : 
    1149       509770 :   BITMAP_FREE (argmap);
    1150              : 
    1151       509770 :   if (res)
    1152       509538 :     for (tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_TYPE (fn)));
    1153       743356 :          (attrs = lookup_attribute ("nonnull_if_nonzero", attrs));
    1154       233818 :          attrs = TREE_CHAIN (attrs))
    1155              :       {
    1156       233840 :         tree args = TREE_VALUE (attrs);
    1157       233840 :         unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
    1158       233840 :         unsigned int idx2
    1159       233840 :           = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
    1160       233840 :         unsigned int idx3 = idx2;
    1161       233840 :         if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args)))
    1162            0 :           idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1;
    1163       233840 :         if (idx < (unsigned) call_expr_nargs (callexpr)
    1164       233840 :             && idx2 < (unsigned) call_expr_nargs (callexpr)
    1165       233840 :             && idx3 < (unsigned) call_expr_nargs (callexpr)
    1166       233840 :             && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx)))
    1167       233840 :             && integer_zerop (CALL_EXPR_ARG (callexpr, idx))
    1168          101 :             && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx2)))
    1169          101 :             && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx2))
    1170           22 :             && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx3)))
    1171       233862 :             && 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         2058 : expand_builtin_prefetch (tree exp)
    1292              : {
    1293         2058 :   tree arg0, arg1, arg2;
    1294         2058 :   int nargs;
    1295         2058 :   rtx op0, op1, op2;
    1296              : 
    1297         2058 :   if (!validate_arglist (exp, POINTER_TYPE, 0))
    1298              :     return;
    1299              : 
    1300         2058 :   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         2058 :   nargs = call_expr_nargs (exp);
    1306         2058 :   arg1 = nargs > 1 ? CALL_EXPR_ARG (exp, 1) : NULL_TREE;
    1307         2018 :   arg2 = nargs > 2 ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
    1308              : 
    1309              :   /* Argument 0 is an address.  */
    1310         2154 :   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
    1311              : 
    1312              :   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
    1313         2058 :   if (arg1 == NULL_TREE)
    1314           40 :     op1 = const0_rtx;
    1315         2018 :   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         2018 :     op1 = expand_normal (arg1);
    1322              :   /* Argument 1 must be 0, 1 or 2.  */
    1323         2058 :   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         2058 :   if (arg2 == NULL_TREE)
    1332           77 :     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         2058 :   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         2058 :   if (targetm.have_prefetch ())
    1348              :     {
    1349         2058 :       class expand_operand ops[3];
    1350              : 
    1351         2058 :       create_address_operand (&ops[0], op0);
    1352         2058 :       create_integer_operand (&ops[1], INTVAL (op1));
    1353         2058 :       create_integer_operand (&ops[2], INTVAL (op2));
    1354         2058 :       if (maybe_expand_insn (targetm.code_for_prefetch, 3, ops))
    1355         2058 :         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.  STORE_P is true when EXP is the destination.  */
    1368              : 
    1369              : rtx
    1370       765942 : get_memory_rtx (tree exp, tree len, bool store_p)
    1371              : {
    1372       765942 :   tree orig_exp = exp, base;
    1373       765942 :   rtx addr, mem;
    1374              : 
    1375       765942 :   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       765942 :   if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
    1381         1630 :     exp = TREE_OPERAND (exp, 0);
    1382              : 
    1383       765942 :   addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    1384       765942 :   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      1531884 :   while (CONVERT_EXPR_P (exp)
    1389       765945 :          && 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       765942 :   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       765942 :   if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
    1404       765930 :     set_mem_attributes (mem, exp, 0, store_p);
    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, store_p);
    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       765942 :   set_mem_alias_set (mem, 0);
    1424       765942 :   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        34200 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1472        33840 :         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        28440 :           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        33725 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1510        33370 :         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        31240 :           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        45885 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1553        45402 :     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        44080 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1590        43616 :     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        45885 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1747        45402 :     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         5317 :       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        36005 :   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1860        35626 :     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         2355 : type_to_class (tree type)
    1886              : {
    1887         2355 :   switch (TREE_CODE (type))
    1888              :     {
    1889              :     case VOID_TYPE:        return void_type_class;
    1890          891 :     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          977 :     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       610544 : mathfn_built_in_2 (tree type, combined_fn fn)
    1958              : {
    1959       610544 :   tree mtype;
    1960       610544 :   built_in_function fcode, fcodef, fcodel;
    1961       610544 :   built_in_function fcodef16 = END_BUILTINS;
    1962       610544 :   built_in_function fcodef32 = END_BUILTINS;
    1963       610544 :   built_in_function fcodef64 = END_BUILTINS;
    1964       610544 :   built_in_function fcodef128 = END_BUILTINS;
    1965       610544 :   built_in_function fcodef32x = END_BUILTINS;
    1966       610544 :   built_in_function fcodef64x = END_BUILTINS;
    1967       610544 :   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       610544 :   switch (fn)
    1975              :     {
    1976              : #define SEQ_OF_CASE_MATHFN                      \
    1977              :     CASE_MATHFN_FLOATN (ACOS)                   \
    1978              :     CASE_MATHFN_FLOATN (ACOSH)                  \
    1979              :     CASE_MATHFN_FLOATN (ACOSPI)                 \
    1980              :     CASE_MATHFN_FLOATN (ASIN)                   \
    1981              :     CASE_MATHFN_FLOATN (ASINH)                  \
    1982              :     CASE_MATHFN_FLOATN (ASINPI)                 \
    1983              :     CASE_MATHFN_FLOATN (ATAN)                   \
    1984              :     CASE_MATHFN_FLOATN (ATAN2)                  \
    1985              :     CASE_MATHFN_FLOATN (ATAN2PI)                \
    1986              :     CASE_MATHFN_FLOATN (ATANH)                  \
    1987              :     CASE_MATHFN_FLOATN (ATANPI)                 \
    1988              :     CASE_MATHFN_FLOATN (CBRT)                   \
    1989              :     CASE_MATHFN_FLOATN (CEIL)                   \
    1990              :     CASE_MATHFN (CEXPI)                         \
    1991              :     CASE_MATHFN_FLOATN (COPYSIGN)               \
    1992              :     CASE_MATHFN_FLOATN (COS)                    \
    1993              :     CASE_MATHFN_FLOATN (COSH)                   \
    1994              :     CASE_MATHFN_FLOATN (COSPI)                  \
    1995              :     CASE_MATHFN (DREM)                          \
    1996              :     CASE_MATHFN_FLOATN (ERF)                    \
    1997              :     CASE_MATHFN_FLOATN (ERFC)                   \
    1998              :     CASE_MATHFN_FLOATN (EXP)                    \
    1999              :     CASE_MATHFN (EXP10)                         \
    2000              :     CASE_MATHFN_FLOATN (EXP2)                   \
    2001              :     CASE_MATHFN_FLOATN (EXPM1)                  \
    2002              :     CASE_MATHFN_FLOATN (FABS)                   \
    2003              :     CASE_MATHFN_FLOATN (FDIM)                   \
    2004              :     CASE_MATHFN_FLOATN (FLOOR)                  \
    2005              :     CASE_MATHFN_FLOATN (FMA)                    \
    2006              :     CASE_MATHFN_FLOATN (FMAX)                   \
    2007              :     CASE_MATHFN_FLOATN (FMIN)                   \
    2008              :     CASE_MATHFN_FLOATN (FMOD)                   \
    2009              :     CASE_MATHFN_FLOATN (FREXP)                  \
    2010              :     CASE_MATHFN (GAMMA)                         \
    2011              :     CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */     \
    2012              :     CASE_MATHFN_FLOATN (HUGE_VAL)               \
    2013              :     CASE_MATHFN_FLOATN (HYPOT)                  \
    2014              :     CASE_MATHFN_FLOATN (ILOGB)                  \
    2015              :     CASE_MATHFN (ICEIL)                         \
    2016              :     CASE_MATHFN (IFLOOR)                        \
    2017              :     CASE_MATHFN_FLOATN (INF)                    \
    2018              :     CASE_MATHFN (IRINT)                         \
    2019              :     CASE_MATHFN (IROUND)                        \
    2020              :     CASE_MATHFN (ISINF)                         \
    2021              :     CASE_MATHFN (J0)                            \
    2022              :     CASE_MATHFN (J1)                            \
    2023              :     CASE_MATHFN (JN)                            \
    2024              :     CASE_MATHFN (LCEIL)                         \
    2025              :     CASE_MATHFN_FLOATN (LDEXP)                  \
    2026              :     CASE_MATHFN (LFLOOR)                        \
    2027              :     CASE_MATHFN_FLOATN (LGAMMA)                 \
    2028              :     CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */   \
    2029              :     CASE_MATHFN (LLCEIL)                        \
    2030              :     CASE_MATHFN (LLFLOOR)                       \
    2031              :     CASE_MATHFN_FLOATN (LLRINT)                 \
    2032              :     CASE_MATHFN_FLOATN (LLROUND)                \
    2033              :     CASE_MATHFN_FLOATN (LOG)                    \
    2034              :     CASE_MATHFN_FLOATN (LOG10)                  \
    2035              :     CASE_MATHFN_FLOATN (LOG1P)                  \
    2036              :     CASE_MATHFN_FLOATN (LOG2)                   \
    2037              :     CASE_MATHFN_FLOATN (LOGB)                   \
    2038              :     CASE_MATHFN_FLOATN (LRINT)                  \
    2039              :     CASE_MATHFN_FLOATN (LROUND)                 \
    2040              :     CASE_MATHFN_FLOATN (MODF)                   \
    2041              :     CASE_MATHFN_FLOATN (NAN)                    \
    2042              :     CASE_MATHFN_FLOATN (NANS)                   \
    2043              :     CASE_MATHFN_FLOATN (NEARBYINT)              \
    2044              :     CASE_MATHFN_FLOATN (NEXTAFTER)              \
    2045              :     CASE_MATHFN (NEXTTOWARD)                    \
    2046              :     CASE_MATHFN_FLOATN (POW)                    \
    2047              :     CASE_MATHFN (POWI)                          \
    2048              :     CASE_MATHFN (POW10)                         \
    2049              :     CASE_MATHFN_FLOATN (REMAINDER)              \
    2050              :     CASE_MATHFN_FLOATN (REMQUO)                 \
    2051              :     CASE_MATHFN_FLOATN (RINT)                   \
    2052              :     CASE_MATHFN_FLOATN (ROUND)                  \
    2053              :     CASE_MATHFN_FLOATN (ROUNDEVEN)              \
    2054              :     CASE_MATHFN (SCALB)                         \
    2055              :     CASE_MATHFN_FLOATN (SCALBLN)                \
    2056              :     CASE_MATHFN_FLOATN (SCALBN)                 \
    2057              :     CASE_MATHFN (SIGNBIT)                       \
    2058              :     CASE_MATHFN (SIGNIFICAND)                   \
    2059              :     CASE_MATHFN_FLOATN (SIN)                    \
    2060              :     CASE_MATHFN (SINCOS)                        \
    2061              :     CASE_MATHFN_FLOATN (SINH)                   \
    2062              :     CASE_MATHFN_FLOATN (SINPI)                  \
    2063              :     CASE_MATHFN_FLOATN (SQRT)                   \
    2064              :     CASE_MATHFN_FLOATN (TAN)                    \
    2065              :     CASE_MATHFN_FLOATN (TANH)                   \
    2066              :     CASE_MATHFN_FLOATN (TANPI)                  \
    2067              :     CASE_MATHFN_FLOATN (TGAMMA)                 \
    2068              :     CASE_MATHFN_FLOATN (TRUNC)                  \
    2069              :     CASE_MATHFN (Y0)                            \
    2070              :     CASE_MATHFN (Y1)                            \
    2071              :     CASE_MATHFN (YN)
    2072              : 
    2073       610480 :     SEQ_OF_CASE_MATHFN
    2074              : 
    2075              :     default:
    2076              :       return END_BUILTINS;
    2077              :     }
    2078              : 
    2079       610544 :   mtype = TYPE_MAIN_VARIANT (type);
    2080       610544 :   if (mtype == double_type_node)
    2081              :     return fcode;
    2082       570846 :   else if (mtype == float_type_node)
    2083              :     return fcodef;
    2084       525152 :   else if (mtype == long_double_type_node)
    2085              :     return fcodel;
    2086       492527 :   else if (mtype == float16_type_node)
    2087              :     return fcodef16;
    2088       492479 :   else if (mtype == float32_type_node)
    2089              :     return fcodef32;
    2090       492479 :   else if (mtype == float64_type_node)
    2091              :     return fcodef64;
    2092       492479 :   else if (mtype == float128_type_node)
    2093              :     return fcodef128;
    2094       484975 :   else if (mtype == float32x_type_node)
    2095              :     return fcodef32x;
    2096       484975 :   else if (mtype == float64x_type_node)
    2097              :     return fcodef64x;
    2098       484975 :   else if (mtype == float128x_type_node)
    2099              :     return fcodef128x;
    2100              :   else
    2101       484975 :     return END_BUILTINS;
    2102              : }
    2103              : 
    2104              : #undef CASE_MATHFN
    2105              : #undef CASE_MATHFN_FLOATN
    2106              : #undef CASE_MATHFN_REENT
    2107              : 
    2108              : /* Return mathematic function equivalent to FN but operating directly on TYPE,
    2109              :    if available.  If IMPLICIT_P is true use the implicit builtin declaration,
    2110              :    otherwise use the explicit declaration.  If we can't do the conversion,
    2111              :    return null.  */
    2112              : 
    2113              : static tree
    2114       610399 : mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
    2115              : {
    2116       610399 :   built_in_function fcode2 = mathfn_built_in_2 (type, fn);
    2117       610399 :   if (fcode2 == END_BUILTINS)
    2118              :     return NULL_TREE;
    2119              : 
    2120       121776 :   if (implicit_p && !builtin_decl_implicit_p (fcode2))
    2121              :     return NULL_TREE;
    2122              : 
    2123       117823 :   return builtin_decl_explicit (fcode2);
    2124              : }
    2125              : 
    2126              : /* Like mathfn_built_in_1, but always use the implicit array.  */
    2127              : 
    2128              : tree
    2129          276 : mathfn_built_in (tree type, combined_fn fn)
    2130              : {
    2131          276 :   return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
    2132              : }
    2133              : 
    2134              : /* Like mathfn_built_in_1, but always use the explicit array.  */
    2135              : 
    2136              : tree
    2137            0 : mathfn_built_in_explicit (tree type, combined_fn fn)
    2138              : {
    2139            0 :   return mathfn_built_in_1 (type, fn, /*implicit=*/ 0);
    2140              : }
    2141              : 
    2142              : /* Like mathfn_built_in_1, but take a built_in_function and
    2143              :    always use the implicit array.  */
    2144              : 
    2145              : tree
    2146       609900 : mathfn_built_in (tree type, enum built_in_function fn)
    2147              : {
    2148       609900 :   return mathfn_built_in_1 (type, as_combined_fn (fn), /*implicit=*/ 1);
    2149              : }
    2150              : 
    2151              : /* Return the type associated with a built in function, i.e., the one
    2152              :    to be passed to mathfn_built_in to get the type-specific
    2153              :    function.  */
    2154              : 
    2155              : tree
    2156         1290 : mathfn_built_in_type (combined_fn fn)
    2157              : {
    2158              : #define CASE_MATHFN(MATHFN)                     \
    2159              :   case CFN_BUILT_IN_##MATHFN:                   \
    2160              :     return double_type_node;                    \
    2161              :   case CFN_BUILT_IN_##MATHFN##F:                \
    2162              :     return float_type_node;                     \
    2163              :   case CFN_BUILT_IN_##MATHFN##L:                \
    2164              :     return long_double_type_node;
    2165              : 
    2166              : #define CASE_MATHFN_FLOATN(MATHFN)              \
    2167              :   CASE_MATHFN(MATHFN)                           \
    2168              :   case CFN_BUILT_IN_##MATHFN##F16:              \
    2169              :     return float16_type_node;                   \
    2170              :   case CFN_BUILT_IN_##MATHFN##F32:              \
    2171              :     return float32_type_node;                   \
    2172              :   case CFN_BUILT_IN_##MATHFN##F64:              \
    2173              :     return float64_type_node;                   \
    2174              :   case CFN_BUILT_IN_##MATHFN##F128:             \
    2175              :     return float128_type_node;                  \
    2176              :   case CFN_BUILT_IN_##MATHFN##F32X:             \
    2177              :     return float32x_type_node;                  \
    2178              :   case CFN_BUILT_IN_##MATHFN##F64X:             \
    2179              :     return float64x_type_node;                  \
    2180              :   case CFN_BUILT_IN_##MATHFN##F128X:            \
    2181              :     return float128x_type_node;
    2182              : 
    2183              : /* Similar to above, but appends _R after any F/L suffix.  */
    2184              : #define CASE_MATHFN_REENT(MATHFN) \
    2185              :   case CFN_BUILT_IN_##MATHFN##_R:               \
    2186              :     return double_type_node;                    \
    2187              :   case CFN_BUILT_IN_##MATHFN##F_R:              \
    2188              :     return float_type_node;                     \
    2189              :   case CFN_BUILT_IN_##MATHFN##L_R:              \
    2190              :     return long_double_type_node;
    2191              : 
    2192         1290 :   switch (fn)
    2193              :     {
    2194         1288 :     SEQ_OF_CASE_MATHFN
    2195              : 
    2196              :     default:
    2197              :       return NULL_TREE;
    2198              :     }
    2199              : 
    2200              : #undef CASE_MATHFN
    2201              : #undef CASE_MATHFN_FLOATN
    2202              : #undef CASE_MATHFN_REENT
    2203              : #undef SEQ_OF_CASE_MATHFN
    2204              : }
    2205              : 
    2206              : /* Check whether there is an internal function associated with function FN
    2207              :    and return type RETURN_TYPE.  Return the function if so, otherwise return
    2208              :    IFN_LAST.
    2209              : 
    2210              :    Note that this function only tests whether the function is defined in
    2211              :    internals.def, not whether it is actually available on the target.  */
    2212              : 
    2213              : static internal_fn
    2214     14153889 : associated_internal_fn (built_in_function fn, tree return_type)
    2215              : {
    2216     14153889 :   switch (fn)
    2217              :     {
    2218              : #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2219              :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2220              : #define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
    2221              :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME; \
    2222              :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_##NAME): return IFN_##NAME;
    2223              : #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2224              :     CASE_INT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2225              : #include "internal-fn.def"
    2226              : 
    2227              :     CASE_FLT_FN (BUILT_IN_POW10):
    2228              :       return IFN_EXP10;
    2229              : 
    2230              :     CASE_FLT_FN (BUILT_IN_DREM):
    2231              :       return IFN_REMAINDER;
    2232              : 
    2233        19587 :     CASE_FLT_FN (BUILT_IN_SCALBN):
    2234        19587 :     CASE_FLT_FN (BUILT_IN_SCALBLN):
    2235        19587 :       if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
    2236              :         return IFN_LDEXP;
    2237              :       return IFN_LAST;
    2238          715 :     case BUILT_IN_CRC8_DATA8:
    2239          715 :     case BUILT_IN_CRC16_DATA8:
    2240          715 :     case BUILT_IN_CRC16_DATA16:
    2241          715 :     case BUILT_IN_CRC32_DATA8:
    2242          715 :     case BUILT_IN_CRC32_DATA16:
    2243          715 :     case BUILT_IN_CRC32_DATA32:
    2244          715 :     case BUILT_IN_CRC64_DATA8:
    2245          715 :     case BUILT_IN_CRC64_DATA16:
    2246          715 :     case BUILT_IN_CRC64_DATA32:
    2247          715 :     case BUILT_IN_CRC64_DATA64:
    2248          715 :       return IFN_CRC;
    2249          369 :     case BUILT_IN_REV_CRC8_DATA8:
    2250          369 :     case BUILT_IN_REV_CRC16_DATA8:
    2251          369 :     case BUILT_IN_REV_CRC16_DATA16:
    2252          369 :     case BUILT_IN_REV_CRC32_DATA8:
    2253          369 :     case BUILT_IN_REV_CRC32_DATA16:
    2254          369 :     case BUILT_IN_REV_CRC32_DATA32:
    2255          369 :     case BUILT_IN_REV_CRC64_DATA8:
    2256          369 :     case BUILT_IN_REV_CRC64_DATA16:
    2257          369 :     case BUILT_IN_REV_CRC64_DATA32:
    2258          369 :     case BUILT_IN_REV_CRC64_DATA64:
    2259          369 :       return IFN_CRC_REV;
    2260              :     default:
    2261              :       return IFN_LAST;
    2262              :     }
    2263              : }
    2264              : 
    2265              : /* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
    2266              :    return its code, otherwise return IFN_LAST.  Note that this function
    2267              :    only tests whether the function is defined in internals.def, not whether
    2268              :    it is actually available on the target.  */
    2269              : 
    2270              : internal_fn
    2271       642368 : associated_internal_fn (tree fndecl)
    2272              : {
    2273       642368 :   gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
    2274       642368 :   return associated_internal_fn (DECL_FUNCTION_CODE (fndecl),
    2275       642368 :                                  TREE_TYPE (TREE_TYPE (fndecl)));
    2276              : }
    2277              : 
    2278              : /* Check whether there is an internal function associated with function CFN
    2279              :    and return type RETURN_TYPE.  Return the function if so, otherwise return
    2280              :    IFN_LAST.
    2281              : 
    2282              :    Note that this function only tests whether the function is defined in
    2283              :    internals.def, not whether it is actually available on the target.  */
    2284              : 
    2285              : internal_fn
    2286     34758488 : associated_internal_fn (combined_fn cfn, tree return_type)
    2287              : {
    2288     34758488 :   if (internal_fn_p (cfn))
    2289     21246967 :     return as_internal_fn (cfn);
    2290     13511521 :   return associated_internal_fn (as_builtin_fn (cfn), return_type);
    2291              : }
    2292              : 
    2293              : /* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
    2294              :    on the current target by a call to an internal function, return the
    2295              :    code of that internal function, otherwise return IFN_LAST.  The caller
    2296              :    is responsible for ensuring that any side-effects of the built-in
    2297              :    call are dealt with correctly.  E.g. if CALL sets errno, the caller
    2298              :    must decide that the errno result isn't needed or make it available
    2299              :    in some other way.  */
    2300              : 
    2301              : internal_fn
    2302       878024 : replacement_internal_fn (gcall *call)
    2303              : {
    2304       878024 :   if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    2305              :     {
    2306       639478 :       internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
    2307       639478 :       if (ifn != IFN_LAST)
    2308              :         {
    2309        59402 :           tree_pair types = direct_internal_fn_types (ifn, call);
    2310        59402 :           optimization_type opt_type = bb_optimization_type (gimple_bb (call));
    2311        59402 :           if (direct_internal_fn_supported_p (ifn, types, opt_type))
    2312        37313 :             return ifn;
    2313              :         }
    2314              :     }
    2315              :   return IFN_LAST;
    2316              : }
    2317              : 
    2318              : /* Expand a call to the builtin trinary math functions (fma).
    2319              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2320              :    function in-line.  EXP is the expression that is a call to the builtin
    2321              :    function; if convenient, the result should be placed in TARGET.
    2322              :    SUBTARGET may be used as the target for computing one of EXP's
    2323              :    operands.  */
    2324              : 
    2325              : static rtx
    2326          368 : expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
    2327              : {
    2328          368 :   optab builtin_optab;
    2329          368 :   rtx op0, op1, op2, result;
    2330          368 :   rtx_insn *insns;
    2331          368 :   tree fndecl = get_callee_fndecl (exp);
    2332          368 :   tree arg0, arg1, arg2;
    2333          368 :   machine_mode mode;
    2334              : 
    2335          368 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    2336              :     return NULL_RTX;
    2337              : 
    2338          368 :   arg0 = CALL_EXPR_ARG (exp, 0);
    2339          368 :   arg1 = CALL_EXPR_ARG (exp, 1);
    2340          368 :   arg2 = CALL_EXPR_ARG (exp, 2);
    2341              : 
    2342          368 :   switch (DECL_FUNCTION_CODE (fndecl))
    2343              :     {
    2344          368 :     CASE_FLT_FN (BUILT_IN_FMA):
    2345          368 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
    2346          368 :       builtin_optab = fma_optab; break;
    2347            0 :     default:
    2348            0 :       gcc_unreachable ();
    2349              :     }
    2350              : 
    2351              :   /* Make a suitable register to place result in.  */
    2352          368 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2353              : 
    2354              :   /* Before working hard, check whether the instruction is available.  */
    2355          368 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2356              :     return NULL_RTX;
    2357              : 
    2358            0 :   result = gen_reg_rtx (mode);
    2359              : 
    2360              :   /* Always stabilize the argument list.  */
    2361            0 :   CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
    2362            0 :   CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
    2363            0 :   CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
    2364              : 
    2365            0 :   op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
    2366            0 :   op1 = expand_normal (arg1);
    2367            0 :   op2 = expand_normal (arg2);
    2368              : 
    2369            0 :   start_sequence ();
    2370              : 
    2371              :   /* Compute into RESULT.
    2372              :      Set RESULT to wherever the result comes back.  */
    2373            0 :   result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
    2374              :                               result, 0);
    2375              : 
    2376              :   /* If we were unable to expand via the builtin, stop the sequence
    2377              :      (without outputting the insns) and call to the library function
    2378              :      with the stabilized argument list.  */
    2379            0 :   if (result == 0)
    2380              :     {
    2381            0 :       end_sequence ();
    2382            0 :       return expand_call (exp, target, target == const0_rtx);
    2383              :     }
    2384              : 
    2385              :   /* Output the entire sequence.  */
    2386            0 :   insns = end_sequence ();
    2387            0 :   emit_insn (insns);
    2388              : 
    2389            0 :   return result;
    2390              : }
    2391              : 
    2392              : /* Expand a call to the builtin sin and cos math functions.
    2393              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2394              :    function in-line.  EXP is the expression that is a call to the builtin
    2395              :    function; if convenient, the result should be placed in TARGET.
    2396              :    SUBTARGET may be used as the target for computing one of EXP's
    2397              :    operands.  */
    2398              : 
    2399              : static rtx
    2400           47 : expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
    2401              : {
    2402           47 :   optab builtin_optab;
    2403           47 :   rtx op0;
    2404           47 :   rtx_insn *insns;
    2405           47 :   tree fndecl = get_callee_fndecl (exp);
    2406           47 :   machine_mode mode;
    2407           47 :   tree arg;
    2408              : 
    2409           47 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2410              :     return NULL_RTX;
    2411              : 
    2412           39 :   arg = CALL_EXPR_ARG (exp, 0);
    2413              : 
    2414           39 :   switch (DECL_FUNCTION_CODE (fndecl))
    2415              :     {
    2416           39 :     CASE_FLT_FN (BUILT_IN_SIN):
    2417           39 :     CASE_FLT_FN (BUILT_IN_COS):
    2418           39 :       builtin_optab = sincos_optab; break;
    2419            0 :     default:
    2420            0 :       gcc_unreachable ();
    2421              :     }
    2422              : 
    2423              :   /* Make a suitable register to place result in.  */
    2424           39 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2425              : 
    2426              :   /* Check if sincos insn is available, otherwise fallback
    2427              :      to sin or cos insn.  */
    2428           39 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2429           39 :     switch (DECL_FUNCTION_CODE (fndecl))
    2430              :       {
    2431              :       CASE_FLT_FN (BUILT_IN_SIN):
    2432              :         builtin_optab = sin_optab; break;
    2433           14 :       CASE_FLT_FN (BUILT_IN_COS):
    2434           14 :         builtin_optab = cos_optab; break;
    2435            0 :       default:
    2436            0 :         gcc_unreachable ();
    2437              :       }
    2438              : 
    2439              :   /* Before working hard, check whether the instruction is available.  */
    2440           39 :   if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
    2441              :     {
    2442            0 :       rtx result = gen_reg_rtx (mode);
    2443              : 
    2444              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2445              :          need to expand the argument again.  This way, we will not perform
    2446              :          side-effects more the once.  */
    2447            0 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2448              : 
    2449            0 :       op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    2450              : 
    2451            0 :       start_sequence ();
    2452              : 
    2453              :       /* Compute into RESULT.
    2454              :          Set RESULT to wherever the result comes back.  */
    2455            0 :       if (builtin_optab == sincos_optab)
    2456              :         {
    2457            0 :           int ok;
    2458              : 
    2459            0 :           switch (DECL_FUNCTION_CODE (fndecl))
    2460              :             {
    2461            0 :             CASE_FLT_FN (BUILT_IN_SIN):
    2462            0 :               ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
    2463            0 :               break;
    2464            0 :             CASE_FLT_FN (BUILT_IN_COS):
    2465            0 :               ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
    2466            0 :               break;
    2467            0 :             default:
    2468            0 :               gcc_unreachable ();
    2469              :             }
    2470            0 :           gcc_assert (ok);
    2471              :         }
    2472              :       else
    2473            0 :         result = expand_unop (mode, builtin_optab, op0, result, 0);
    2474              : 
    2475            0 :       if (result != 0)
    2476              :         {
    2477              :           /* Output the entire sequence.  */
    2478            0 :           insns = end_sequence ();
    2479            0 :           emit_insn (insns);
    2480            0 :           return result;
    2481              :         }
    2482              : 
    2483              :       /* If we were unable to expand via the builtin, stop the sequence
    2484              :          (without outputting the insns) and call to the library function
    2485              :          with the stabilized argument list.  */
    2486            0 :       end_sequence ();
    2487              :     }
    2488              : 
    2489           39 :   return expand_call (exp, target, target == const0_rtx);
    2490              : }
    2491              : 
    2492              : /* Given an interclass math builtin decl FNDECL and it's argument ARG
    2493              :    return an RTL instruction code that implements the functionality.
    2494              :    If that isn't possible or available return CODE_FOR_nothing.  */
    2495              : 
    2496              : static enum insn_code
    2497      1826619 : interclass_mathfn_icode (tree arg, tree fndecl)
    2498              : {
    2499      1826619 :   bool errno_set = false;
    2500      1826619 :   optab builtin_optab = unknown_optab;
    2501      1826619 :   machine_mode mode;
    2502              : 
    2503      1826619 :   switch (DECL_FUNCTION_CODE (fndecl))
    2504              :     {
    2505            4 :     CASE_FLT_FN (BUILT_IN_ILOGB):
    2506            4 :       errno_set = true;
    2507            4 :       builtin_optab = ilogb_optab;
    2508            4 :       break;
    2509       711704 :     CASE_FLT_FN (BUILT_IN_ISINF):
    2510       711704 :       builtin_optab = isinf_optab;
    2511       711704 :       break;
    2512       628227 :     case BUILT_IN_ISFINITE:
    2513       628227 :       builtin_optab = isfinite_optab;
    2514       628227 :       break;
    2515       240988 :     case BUILT_IN_ISNORMAL:
    2516       240988 :       builtin_optab = isnormal_optab;
    2517       240988 :       break;
    2518       243619 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    2519       243619 :       builtin_optab = isnan_optab;
    2520       243619 :       break;
    2521              :     CASE_FLT_FN (BUILT_IN_FINITE):
    2522              :     case BUILT_IN_FINITED32:
    2523              :     case BUILT_IN_FINITED64:
    2524              :     case BUILT_IN_FINITED128:
    2525              :     case BUILT_IN_ISINFD32:
    2526              :     case BUILT_IN_ISINFD64:
    2527              :     case BUILT_IN_ISINFD128:
    2528              :     case BUILT_IN_ISNAND32:
    2529              :     case BUILT_IN_ISNAND64:
    2530              :     case BUILT_IN_ISNAND128:
    2531              :       /* These builtins have no optabs (yet).  */
    2532              :       break;
    2533            0 :     default:
    2534            0 :       gcc_unreachable ();
    2535              :     }
    2536              : 
    2537              :   /* There's no easy way to detect the case we need to set EDOM.  */
    2538      1826619 :   if (flag_errno_math && errno_set)
    2539              :     return CODE_FOR_nothing;
    2540              : 
    2541              :   /* Optab mode depends on the mode of the input argument.  */
    2542      1826619 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2543              : 
    2544      1826619 :   if (builtin_optab)
    2545      1824542 :     return optab_handler (builtin_optab, mode);
    2546              :   return CODE_FOR_nothing;
    2547              : }
    2548              : 
    2549              : /* Expand a call to one of the builtin math functions that operate on
    2550              :    floating point argument and output an integer result (ilogb, isinf,
    2551              :    isnan, etc).
    2552              :    Return 0 if a normal call should be emitted rather than expanding the
    2553              :    function in-line.  EXP is the expression that is a call to the builtin
    2554              :    function; if convenient, the result should be placed in TARGET.  */
    2555              : 
    2556              : static rtx
    2557            4 : expand_builtin_interclass_mathfn (tree exp, rtx target)
    2558              : {
    2559            4 :   enum insn_code icode = CODE_FOR_nothing;
    2560            4 :   rtx op0;
    2561            4 :   tree fndecl = get_callee_fndecl (exp);
    2562            4 :   machine_mode mode;
    2563            4 :   tree arg;
    2564              : 
    2565            4 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2566              :     return NULL_RTX;
    2567              : 
    2568            4 :   arg = CALL_EXPR_ARG (exp, 0);
    2569            4 :   icode = interclass_mathfn_icode (arg, fndecl);
    2570            4 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2571              : 
    2572            4 :   if (icode != CODE_FOR_nothing)
    2573              :     {
    2574            2 :       class expand_operand ops[1];
    2575            2 :       rtx_insn *last = get_last_insn ();
    2576            2 :       tree orig_arg = arg;
    2577              : 
    2578              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2579              :          need to expand the argument again.  This way, we will not perform
    2580              :          side-effects more the once.  */
    2581            2 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2582              : 
    2583            2 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2584              : 
    2585            2 :       if (mode != GET_MODE (op0))
    2586            0 :         op0 = convert_to_mode (mode, op0, 0);
    2587              : 
    2588            2 :       create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
    2589            2 :       if (maybe_legitimize_operands (icode, 0, 1, ops)
    2590            2 :           && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
    2591            1 :         return ops[0].value;
    2592              : 
    2593            1 :       delete_insns_since (last);
    2594            1 :       CALL_EXPR_ARG (exp, 0) = orig_arg;
    2595              :     }
    2596              : 
    2597              :   return NULL_RTX;
    2598              : }
    2599              : 
    2600              : /* Expand a call to the builtin sincos math function.
    2601              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2602              :    function in-line.  EXP is the expression that is a call to the builtin
    2603              :    function.  */
    2604              : 
    2605              : static rtx
    2606            3 : expand_builtin_sincos (tree exp)
    2607              : {
    2608            3 :   rtx op0, op1, op2, target1, target2;
    2609            3 :   machine_mode mode;
    2610            3 :   tree arg, sinp, cosp;
    2611            3 :   int result;
    2612            3 :   location_t loc = EXPR_LOCATION (exp);
    2613            3 :   tree alias_type, alias_off;
    2614              : 
    2615            3 :   if (!validate_arglist (exp, REAL_TYPE,
    2616              :                          POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    2617              :     return NULL_RTX;
    2618              : 
    2619            3 :   arg = CALL_EXPR_ARG (exp, 0);
    2620            3 :   sinp = CALL_EXPR_ARG (exp, 1);
    2621            3 :   cosp = CALL_EXPR_ARG (exp, 2);
    2622              : 
    2623              :   /* Make a suitable register to place result in.  */
    2624            3 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2625              : 
    2626              :   /* Check if sincos insn is available, otherwise emit the call.  */
    2627            3 :   if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
    2628              :     return NULL_RTX;
    2629              : 
    2630            0 :   target1 = gen_reg_rtx (mode);
    2631            0 :   target2 = gen_reg_rtx (mode);
    2632              : 
    2633            0 :   op0 = expand_normal (arg);
    2634            0 :   alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
    2635            0 :   alias_off = build_int_cst (alias_type, 0);
    2636            0 :   op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2637              :                                         sinp, alias_off));
    2638            0 :   op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2639              :                                         cosp, alias_off));
    2640              : 
    2641              :   /* Compute into target1 and target2.
    2642              :      Set TARGET to wherever the result comes back.  */
    2643            0 :   result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
    2644            0 :   gcc_assert (result);
    2645              : 
    2646              :   /* Move target1 and target2 to the memory locations indicated
    2647              :      by op1 and op2.  */
    2648            0 :   emit_move_insn (op1, target1);
    2649            0 :   emit_move_insn (op2, target2);
    2650              : 
    2651            0 :   return const0_rtx;
    2652              : }
    2653              : 
    2654              : /* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the
    2655              :    result and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
    2656              : static rtx
    2657           60 : expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode)
    2658              : {
    2659           60 :   if (!validate_arglist (exp, VOID_TYPE))
    2660              :     return NULL_RTX;
    2661              : 
    2662           60 :   insn_code icode = direct_optab_handler (fegetround_optab, SImode);
    2663           60 :   if (icode == CODE_FOR_nothing)
    2664              :     return NULL_RTX;
    2665              : 
    2666            0 :   if (target == 0
    2667            0 :       || GET_MODE (target) != target_mode
    2668            0 :       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
    2669            0 :     target = gen_reg_rtx (target_mode);
    2670              : 
    2671            0 :   rtx pat = GEN_FCN (icode) (target);
    2672            0 :   if (!pat)
    2673              :     return NULL_RTX;
    2674            0 :   emit_insn (pat);
    2675              : 
    2676            0 :   return target;
    2677              : }
    2678              : 
    2679              : /* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99
    2680              :    fenv.h), returning the result and setting it in TARGET.  Otherwise return
    2681              :    NULL_RTX on failure.  */
    2682              : static rtx
    2683         1896 : expand_builtin_feclear_feraise_except (tree exp, rtx target,
    2684              :                                        machine_mode target_mode, optab op_optab)
    2685              : {
    2686         1896 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    2687              :     return NULL_RTX;
    2688         1896 :   rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
    2689              : 
    2690         1896 :   insn_code icode = direct_optab_handler (op_optab, SImode);
    2691         1896 :   if (icode == CODE_FOR_nothing)
    2692              :     return NULL_RTX;
    2693              : 
    2694            0 :   if (!(*insn_data[icode].operand[1].predicate) (op0, GET_MODE (op0)))
    2695              :     return NULL_RTX;
    2696              : 
    2697            0 :   if (target == 0
    2698            0 :       || GET_MODE (target) != target_mode
    2699            0 :       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
    2700            0 :     target = gen_reg_rtx (target_mode);
    2701              : 
    2702            0 :   rtx pat = GEN_FCN (icode) (target, op0);
    2703            0 :   if (!pat)
    2704              :     return NULL_RTX;
    2705            0 :   emit_insn (pat);
    2706              : 
    2707            0 :   return target;
    2708              : }
    2709              : 
    2710              : /* Expand a call to the internal cexpi builtin to the sincos math function.
    2711              :    EXP is the expression that is a call to the builtin function; if convenient,
    2712              :    the result should be placed in TARGET.  */
    2713              : 
    2714              : static rtx
    2715          170 : expand_builtin_cexpi (tree exp, rtx target)
    2716              : {
    2717          170 :   tree fndecl = get_callee_fndecl (exp);
    2718          170 :   tree arg, type;
    2719          170 :   machine_mode mode;
    2720          170 :   rtx op0, op1, op2;
    2721          170 :   location_t loc = EXPR_LOCATION (exp);
    2722              : 
    2723          170 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2724              :     return NULL_RTX;
    2725              : 
    2726          170 :   arg = CALL_EXPR_ARG (exp, 0);
    2727          170 :   type = TREE_TYPE (arg);
    2728          170 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2729              : 
    2730              :   /* Try expanding via a sincos optab, fall back to emitting a libcall
    2731              :      to sincos or cexp.  We are sure we have sincos or cexp because cexpi
    2732              :      is only generated from sincos, cexp or if we have either of them.  */
    2733          170 :   if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
    2734              :     {
    2735            6 :       op1 = gen_reg_rtx (mode);
    2736            6 :       op2 = gen_reg_rtx (mode);
    2737              : 
    2738            6 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2739              : 
    2740              :       /* Compute into op1 and op2.  */
    2741            6 :       expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
    2742              :     }
    2743          164 :   else if (targetm.libc_has_function (function_sincos, type))
    2744              :     {
    2745          164 :       tree call, fn = NULL_TREE;
    2746          164 :       tree top1, top2;
    2747          164 :       rtx op1a, op2a;
    2748              : 
    2749          164 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2750           54 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
    2751          110 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2752           89 :         fn = builtin_decl_explicit (BUILT_IN_SINCOS);
    2753           21 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2754           21 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
    2755              :       else
    2756            0 :         gcc_unreachable ();
    2757              : 
    2758          164 :       op1 = assign_temp (TREE_TYPE (arg), 1, 1);
    2759          164 :       op2 = assign_temp (TREE_TYPE (arg), 1, 1);
    2760          164 :       op1a = copy_addr_to_reg (XEXP (op1, 0));
    2761          164 :       op2a = copy_addr_to_reg (XEXP (op2, 0));
    2762          164 :       top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
    2763          164 :       top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
    2764              : 
    2765              :       /* Make sure not to fold the sincos call again.  */
    2766          164 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2767          164 :       expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
    2768              :                                       call, 3, arg, top1, top2));
    2769              :     }
    2770              :   else
    2771              :     {
    2772            0 :       tree call, fn = NULL_TREE, narg;
    2773            0 :       tree ctype = build_complex_type (type);
    2774              : 
    2775            0 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2776            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPF);
    2777            0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2778            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXP);
    2779            0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2780            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPL);
    2781              :       else
    2782            0 :         gcc_unreachable ();
    2783              : 
    2784              :       /* If we don't have a decl for cexp create one.  This is the
    2785              :          friendliest fallback if the user calls __builtin_cexpi
    2786              :          without full target C99 function support.  */
    2787            0 :       if (fn == NULL_TREE)
    2788              :         {
    2789            0 :           tree fntype;
    2790            0 :           const char *name = NULL;
    2791              : 
    2792            0 :           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2793              :             name = "cexpf";
    2794            0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2795              :             name = "cexp";
    2796            0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2797            0 :             name = "cexpl";
    2798              : 
    2799            0 :           fntype = build_function_type_list (ctype, ctype, NULL_TREE);
    2800            0 :           fn = build_fn_decl (name, fntype);
    2801              :         }
    2802              : 
    2803            0 :       narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
    2804              :                           build_real (type, dconst0), arg);
    2805              : 
    2806              :       /* Make sure not to fold the cexp call again.  */
    2807            0 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2808            0 :       return expand_expr (build_call_nary (ctype, call, 1, narg),
    2809            0 :                           target, VOIDmode, EXPAND_NORMAL);
    2810              :     }
    2811              : 
    2812              :   /* Now build the proper return type.  */
    2813          340 :   return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
    2814          170 :                               make_tree (TREE_TYPE (arg), op2),
    2815          170 :                               make_tree (TREE_TYPE (arg), op1)),
    2816          170 :                       target, VOIDmode, EXPAND_NORMAL);
    2817              : }
    2818              : 
    2819              : /* Conveniently construct a function call expression.  FNDECL names the
    2820              :    function to be called, N is the number of arguments, and the "..."
    2821              :    parameters are the argument expressions.  Unlike build_call_exr
    2822              :    this doesn't fold the call, hence it will always return a CALL_EXPR.  */
    2823              : 
    2824              : static tree
    2825       136167 : build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
    2826              : {
    2827       136167 :   va_list ap;
    2828       136167 :   tree fntype = TREE_TYPE (fndecl);
    2829       136167 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
    2830              : 
    2831       136167 :   va_start (ap, n);
    2832       136167 :   fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
    2833       136167 :   va_end (ap);
    2834       136167 :   SET_EXPR_LOCATION (fn, loc);
    2835       136167 :   return fn;
    2836              : }
    2837              : 
    2838              : /* Expand the __builtin_issignaling builtin.  This needs to handle
    2839              :    all floating point formats that do support NaNs (for those that
    2840              :    don't it just sets target to 0).  */
    2841              : 
    2842              : static rtx
    2843          784 : expand_builtin_issignaling (tree exp, rtx target)
    2844              : {
    2845          784 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2846              :     return NULL_RTX;
    2847              : 
    2848          784 :   tree arg = CALL_EXPR_ARG (exp, 0);
    2849          784 :   scalar_float_mode fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
    2850          784 :   const struct real_format *fmt = REAL_MODE_FORMAT (fmode);
    2851              : 
    2852              :   /* Expand the argument yielding a RTX expression. */
    2853          784 :   rtx temp = expand_normal (arg);
    2854              : 
    2855              :   /* If mode doesn't support NaN, always return 0.
    2856              :      Don't use !HONOR_SNANS (fmode) here, so there is some possibility of
    2857              :      __builtin_issignaling working without -fsignaling-nans.  Especially
    2858              :      when -fno-signaling-nans is the default.
    2859              :      On the other side, MODE_HAS_NANS (fmode) is unnecessary, with
    2860              :      -ffinite-math-only even __builtin_isnan or __builtin_fpclassify
    2861              :      fold to 0 or non-NaN/Inf classification.  */
    2862          784 :   if (!HONOR_NANS (fmode))
    2863              :     {
    2864            0 :       emit_move_insn (target, const0_rtx);
    2865            0 :       return target;
    2866              :     }
    2867              : 
    2868              :   /* Check if the back end provides an insn that handles issignaling for the
    2869              :      argument's mode. */
    2870          784 :   enum insn_code icode = optab_handler (issignaling_optab, fmode);
    2871          784 :   if (icode != CODE_FOR_nothing)
    2872              :     {
    2873          142 :       rtx_insn *last = get_last_insn ();
    2874          142 :       rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    2875          142 :       if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
    2876              :         return this_target;
    2877            0 :       delete_insns_since (last);
    2878              :     }
    2879              : 
    2880          642 :   if (DECIMAL_FLOAT_MODE_P (fmode))
    2881              :     {
    2882           63 :       scalar_int_mode imode;
    2883           63 :       rtx hi;
    2884           63 :       switch (fmt->ieee_bits)
    2885              :         {
    2886           42 :         case 32:
    2887           42 :         case 64:
    2888           42 :           imode = int_mode_for_mode (fmode).require ();
    2889           42 :           temp = gen_lowpart (imode, temp);
    2890           42 :           break;
    2891           21 :         case 128:
    2892           21 :           imode = int_mode_for_size (64, 1).require ();
    2893           21 :           hi = NULL_RTX;
    2894              :           /* For decimal128, TImode support isn't always there and even when
    2895              :              it is, working on the DImode high part is usually better.  */
    2896           21 :           if (!MEM_P (temp))
    2897              :             {
    2898            6 :               if (rtx t = force_highpart_subreg (imode, temp, fmode))
    2899              :                 hi = t;
    2900              :               else
    2901              :                 {
    2902            0 :                   scalar_int_mode imode2;
    2903            0 :                   if (int_mode_for_mode (fmode).exists (&imode2))
    2904              :                     {
    2905            0 :                       rtx temp2 = gen_lowpart (imode2, temp);
    2906            0 :                       if (rtx t = force_highpart_subreg (imode, temp2, imode2))
    2907              :                         hi = t;
    2908              :                     }
    2909              :                 }
    2910            0 :               if (!hi)
    2911              :                 {
    2912            0 :                   rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    2913            0 :                   emit_move_insn (mem, temp);
    2914            0 :                   temp = mem;
    2915              :                 }
    2916              :             }
    2917            0 :           if (!hi)
    2918              :             {
    2919           15 :               poly_int64 offset
    2920           15 :                 = subreg_highpart_offset (imode, GET_MODE (temp));
    2921           15 :               hi = adjust_address (temp, imode, offset);
    2922              :             }
    2923              :           temp = hi;
    2924              :           break;
    2925            0 :         default:
    2926            0 :           gcc_unreachable ();
    2927              :         }
    2928              :       /* In all of decimal{32,64,128}, there is MSB sign bit and sNaN
    2929              :          have 6 bits below it all set.  */
    2930           63 :       rtx val
    2931           63 :         = GEN_INT (HOST_WIDE_INT_C (0x3f) << (GET_MODE_BITSIZE (imode) - 7));
    2932           63 :       temp = expand_binop (imode, and_optab, temp, val,
    2933              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2934           63 :       temp = emit_store_flag_force (target, EQ, temp, val, imode, 1, 1);
    2935           63 :       return temp;
    2936              :     }
    2937              : 
    2938              :   /* Only PDP11 has these defined differently but doesn't support NaNs.  */
    2939          579 :   gcc_assert (FLOAT_WORDS_BIG_ENDIAN == WORDS_BIG_ENDIAN);
    2940          579 :   gcc_assert (fmt->signbit_ro > 0 && fmt->b == 2);
    2941         4053 :   gcc_assert (MODE_COMPOSITE_P (fmode)
    2942              :               || (fmt->pnan == fmt->p
    2943              :                   && fmt->signbit_ro == fmt->signbit_rw));
    2944              : 
    2945          579 :   switch (fmt->p)
    2946              :     {
    2947            0 :     case 106: /* IBM double double  */
    2948              :       /* For IBM double double, recurse on the most significant double.  */
    2949            0 :       gcc_assert (MODE_COMPOSITE_P (fmode));
    2950            0 :       temp = convert_modes (DFmode, fmode, temp, 0);
    2951            0 :       fmode = DFmode;
    2952            0 :       fmt = REAL_MODE_FORMAT (DFmode);
    2953              :       /* FALLTHRU */
    2954          479 :     case 8: /* bfloat */
    2955          479 :     case 11: /* IEEE half */
    2956          479 :     case 24: /* IEEE single */
    2957          479 :     case 53: /* IEEE double or Intel extended with rounding to double */
    2958          479 :       if (fmt->p == 53 && fmt->signbit_ro == 79)
    2959            0 :         goto extended;
    2960          479 :       {
    2961          479 :         scalar_int_mode imode = int_mode_for_mode (fmode).require ();
    2962          479 :         temp = gen_lowpart (imode, temp);
    2963          479 :         rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2))
    2964              :                            & ~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
    2965          479 :         if (fmt->qnan_msb_set)
    2966              :           {
    2967          479 :             rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
    2968          479 :             rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2));
    2969              :             /* For non-MIPS/PA IEEE single/double/half or bfloat, expand to:
    2970              :                ((temp ^ bit) & mask) > val.  */
    2971          479 :             temp = expand_binop (imode, xor_optab, temp, bit,
    2972              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2973          479 :             temp = expand_binop (imode, and_optab, temp, mask,
    2974              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2975          479 :             temp = emit_store_flag_force (target, GTU, temp, val, imode,
    2976              :                                           1, 1);
    2977              :           }
    2978              :         else
    2979              :           {
    2980              :             /* For MIPS/PA IEEE single/double, expand to:
    2981              :                (temp & val) == val.  */
    2982            0 :             temp = expand_binop (imode, and_optab, temp, val,
    2983              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2984            0 :             temp = emit_store_flag_force (target, EQ, temp, val, imode,
    2985              :                                           1, 1);
    2986              :           }
    2987              :       }
    2988              :       break;
    2989          100 :     case 113: /* IEEE quad */
    2990          100 :       {
    2991          100 :         rtx hi = NULL_RTX, lo = NULL_RTX;
    2992          100 :         scalar_int_mode imode = int_mode_for_size (64, 1).require ();
    2993              :         /* For IEEE quad, TImode support isn't always there and even when
    2994              :            it is, working on DImode parts is usually better.  */
    2995          100 :         if (!MEM_P (temp))
    2996              :           {
    2997           85 :             hi = force_highpart_subreg (imode, temp, fmode);
    2998           85 :             lo = force_lowpart_subreg (imode, temp, fmode);
    2999           85 :             if (!hi || !lo)
    3000              :               {
    3001            0 :                 scalar_int_mode imode2;
    3002            0 :                 if (int_mode_for_mode (fmode).exists (&imode2))
    3003              :                   {
    3004            0 :                     rtx temp2 = gen_lowpart (imode2, temp);
    3005            0 :                     hi = force_highpart_subreg (imode, temp2, imode2);
    3006            0 :                     lo = force_lowpart_subreg (imode, temp2, imode2);
    3007              :                   }
    3008              :               }
    3009           85 :             if (!hi || !lo)
    3010              :               {
    3011            0 :                 rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    3012            0 :                 emit_move_insn (mem, temp);
    3013            0 :                 temp = mem;
    3014              :               }
    3015              :           }
    3016          100 :         if (!hi || !lo)
    3017              :           {
    3018           15 :             poly_int64 offset
    3019           15 :               = subreg_highpart_offset (imode, GET_MODE (temp));
    3020           15 :             hi = adjust_address (temp, imode, offset);
    3021           15 :             offset = subreg_lowpart_offset (imode, GET_MODE (temp));
    3022           15 :             lo = adjust_address (temp, imode, offset);
    3023              :           }
    3024          100 :         rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2 - 64))
    3025              :                            & ~(HOST_WIDE_INT_M1U << (fmt->signbit_ro - 64)));
    3026          100 :         if (fmt->qnan_msb_set)
    3027              :           {
    3028          100 :             rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << (fmt->signbit_ro
    3029              :                                                         - 64)));
    3030          100 :             rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2 - 64));
    3031              :             /* For non-MIPS/PA IEEE quad, expand to:
    3032              :                (((hi ^ bit) | ((lo | -lo) >> 63)) & mask) > val.  */
    3033          100 :             rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
    3034          100 :             lo = expand_binop (imode, ior_optab, lo, nlo,
    3035              :                                NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3036          100 :             lo = expand_shift (RSHIFT_EXPR, imode, lo, 63, NULL_RTX, 1);
    3037          100 :             temp = expand_binop (imode, xor_optab, hi, bit,
    3038              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3039          100 :             temp = expand_binop (imode, ior_optab, temp, lo,
    3040              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3041          100 :             temp = expand_binop (imode, and_optab, temp, mask,
    3042              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3043          100 :             temp = emit_store_flag_force (target, GTU, temp, val, imode,
    3044              :                                           1, 1);
    3045              :           }
    3046              :         else
    3047              :           {
    3048              :             /* For MIPS/PA IEEE quad, expand to:
    3049              :                (hi & val) == val.  */
    3050            0 :             temp = expand_binop (imode, and_optab, hi, val,
    3051              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3052            0 :             temp = emit_store_flag_force (target, EQ, temp, val, imode,
    3053              :                                           1, 1);
    3054              :           }
    3055              :       }
    3056              :       break;
    3057            0 :     case 64: /* Intel or Motorola extended */
    3058            0 :     extended:
    3059            0 :       {
    3060            0 :         rtx ex, hi, lo;
    3061            0 :         scalar_int_mode imode = int_mode_for_size (32, 1).require ();
    3062            0 :         scalar_int_mode iemode = int_mode_for_size (16, 1).require ();
    3063            0 :         if (!MEM_P (temp))
    3064              :           {
    3065            0 :             rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    3066            0 :             emit_move_insn (mem, temp);
    3067            0 :             temp = mem;
    3068              :           }
    3069            0 :         if (fmt->signbit_ro == 95)
    3070              :           {
    3071              :             /* Motorola, always big endian, with 16-bit gap in between
    3072              :                16-bit sign+exponent and 64-bit mantissa.  */
    3073            0 :             ex = adjust_address (temp, iemode, 0);
    3074            0 :             hi = adjust_address (temp, imode, 4);
    3075            0 :             lo = adjust_address (temp, imode, 8);
    3076              :           }
    3077            0 :         else if (!WORDS_BIG_ENDIAN)
    3078              :           {
    3079              :             /* Intel little endian, 64-bit mantissa followed by 16-bit
    3080              :                sign+exponent and then either 16 or 48 bits of gap.  */
    3081            0 :             ex = adjust_address (temp, iemode, 8);
    3082            0 :             hi = adjust_address (temp, imode, 4);
    3083            0 :             lo = adjust_address (temp, imode, 0);
    3084              :           }
    3085              :         else
    3086              :           {
    3087              :             /* Big endian Itanium.  */
    3088              :             ex = adjust_address (temp, iemode, 0);
    3089              :             hi = adjust_address (temp, imode, 2);
    3090              :             lo = adjust_address (temp, imode, 6);
    3091              :           }
    3092            0 :         rtx val = GEN_INT (HOST_WIDE_INT_M1U << 30);
    3093            0 :         gcc_assert (fmt->qnan_msb_set);
    3094            0 :         rtx mask = GEN_INT (0x7fff);
    3095            0 :         rtx bit = GEN_INT (HOST_WIDE_INT_1U << 30);
    3096              :         /* For Intel/Motorola extended format, expand to:
    3097              :            (ex & mask) == mask && ((hi ^ bit) | ((lo | -lo) >> 31)) > val.  */
    3098            0 :         rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
    3099            0 :         lo = expand_binop (imode, ior_optab, lo, nlo,
    3100              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3101            0 :         lo = expand_shift (RSHIFT_EXPR, imode, lo, 31, NULL_RTX, 1);
    3102            0 :         temp = expand_binop (imode, xor_optab, hi, bit,
    3103              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3104            0 :         temp = expand_binop (imode, ior_optab, temp, lo,
    3105              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3106            0 :         temp = emit_store_flag_force (target, GTU, temp, val, imode, 1, 1);
    3107            0 :         ex = expand_binop (iemode, and_optab, ex, mask,
    3108              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3109            0 :         ex = emit_store_flag_force (gen_reg_rtx (GET_MODE (temp)), EQ,
    3110              :                                     ex, mask, iemode, 1, 1);
    3111            0 :         temp = expand_binop (GET_MODE (temp), and_optab, temp, ex,
    3112              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3113              :       }
    3114            0 :       break;
    3115            0 :     default:
    3116            0 :       gcc_unreachable ();
    3117              :     }
    3118              : 
    3119              :   return temp;
    3120              : }
    3121              : 
    3122              : /* Expand a call to one of the builtin rounding functions gcc defines
    3123              :    as an extension (lfloor and lceil).  As these are gcc extensions we
    3124              :    do not need to worry about setting errno to EDOM.
    3125              :    If expanding via optab fails, lower expression to (int)(floor(x)).
    3126              :    EXP is the expression that is a call to the builtin function;
    3127              :    if convenient, the result should be placed in TARGET.  */
    3128              : 
    3129              : static rtx
    3130          223 : expand_builtin_int_roundingfn (tree exp, rtx target)
    3131              : {
    3132          223 :   convert_optab builtin_optab;
    3133          223 :   rtx op0, tmp;
    3134          223 :   rtx_insn *insns;
    3135          223 :   tree fndecl = get_callee_fndecl (exp);
    3136          223 :   enum built_in_function fallback_fn;
    3137          223 :   tree fallback_fndecl;
    3138          223 :   machine_mode mode;
    3139          223 :   tree arg;
    3140              : 
    3141          223 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    3142              :     return NULL_RTX;
    3143              : 
    3144          223 :   arg = CALL_EXPR_ARG (exp, 0);
    3145              : 
    3146          223 :   switch (DECL_FUNCTION_CODE (fndecl))
    3147              :     {
    3148              :     CASE_FLT_FN (BUILT_IN_ICEIL):
    3149              :     CASE_FLT_FN (BUILT_IN_LCEIL):
    3150              :     CASE_FLT_FN (BUILT_IN_LLCEIL):
    3151              :       builtin_optab = lceil_optab;
    3152              :       fallback_fn = BUILT_IN_CEIL;
    3153              :       break;
    3154              : 
    3155          112 :     CASE_FLT_FN (BUILT_IN_IFLOOR):
    3156          112 :     CASE_FLT_FN (BUILT_IN_LFLOOR):
    3157          112 :     CASE_FLT_FN (BUILT_IN_LLFLOOR):
    3158          112 :       builtin_optab = lfloor_optab;
    3159          112 :       fallback_fn = BUILT_IN_FLOOR;
    3160          112 :       break;
    3161              : 
    3162            0 :     default:
    3163            0 :       gcc_unreachable ();
    3164              :     }
    3165              : 
    3166              :   /* Make a suitable register to place result in.  */
    3167          223 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3168              : 
    3169          223 :   target = gen_reg_rtx (mode);
    3170              : 
    3171              :   /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    3172              :      need to expand the argument again.  This way, we will not perform
    3173              :      side-effects more the once.  */
    3174          223 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    3175              : 
    3176          223 :   op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    3177              : 
    3178          223 :   start_sequence ();
    3179              : 
    3180              :   /* Compute into TARGET.  */
    3181          223 :   if (expand_sfix_optab (target, op0, builtin_optab))
    3182              :     {
    3183              :       /* Output the entire sequence.  */
    3184           32 :       insns = end_sequence ();
    3185           32 :       emit_insn (insns);
    3186           32 :       return target;
    3187              :     }
    3188              : 
    3189              :   /* If we were unable to expand via the builtin, stop the sequence
    3190              :      (without outputting the insns).  */
    3191          191 :   end_sequence ();
    3192              : 
    3193              :   /* Fall back to floating point rounding optab.  */
    3194          191 :   fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
    3195              : 
    3196              :   /* For non-C99 targets we may end up without a fallback fndecl here
    3197              :      if the user called __builtin_lfloor directly.  In this case emit
    3198              :      a call to the floor/ceil variants nevertheless.  This should result
    3199              :      in the best user experience for not full C99 targets.  */
    3200          191 :   if (fallback_fndecl == NULL_TREE)
    3201              :     {
    3202            0 :       tree fntype;
    3203            0 :       const char *name = NULL;
    3204              : 
    3205            0 :       switch (DECL_FUNCTION_CODE (fndecl))
    3206              :         {
    3207              :         case BUILT_IN_ICEIL:
    3208              :         case BUILT_IN_LCEIL:
    3209              :         case BUILT_IN_LLCEIL:
    3210              :           name = "ceil";
    3211              :           break;
    3212            0 :         case BUILT_IN_ICEILF:
    3213            0 :         case BUILT_IN_LCEILF:
    3214            0 :         case BUILT_IN_LLCEILF:
    3215            0 :           name = "ceilf";
    3216            0 :           break;
    3217            0 :         case BUILT_IN_ICEILL:
    3218            0 :         case BUILT_IN_LCEILL:
    3219            0 :         case BUILT_IN_LLCEILL:
    3220            0 :           name = "ceill";
    3221            0 :           break;
    3222            0 :         case BUILT_IN_IFLOOR:
    3223            0 :         case BUILT_IN_LFLOOR:
    3224            0 :         case BUILT_IN_LLFLOOR:
    3225            0 :           name = "floor";
    3226            0 :           break;
    3227            0 :         case BUILT_IN_IFLOORF:
    3228            0 :         case BUILT_IN_LFLOORF:
    3229            0 :         case BUILT_IN_LLFLOORF:
    3230            0 :           name = "floorf";
    3231            0 :           break;
    3232            0 :         case BUILT_IN_IFLOORL:
    3233            0 :         case BUILT_IN_LFLOORL:
    3234            0 :         case BUILT_IN_LLFLOORL:
    3235            0 :           name = "floorl";
    3236            0 :           break;
    3237            0 :         default:
    3238            0 :           gcc_unreachable ();
    3239              :         }
    3240              : 
    3241            0 :       fntype = build_function_type_list (TREE_TYPE (arg),
    3242            0 :                                          TREE_TYPE (arg), NULL_TREE);
    3243            0 :       fallback_fndecl = build_fn_decl (name, fntype);
    3244              :     }
    3245              : 
    3246          191 :   exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
    3247              : 
    3248          191 :   tmp = expand_normal (exp);
    3249          191 :   tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
    3250              : 
    3251              :   /* Truncate the result of floating point optab to integer
    3252              :      via expand_fix ().  */
    3253          191 :   target = gen_reg_rtx (mode);
    3254          191 :   expand_fix (target, tmp, 0);
    3255              : 
    3256          191 :   return target;
    3257              : }
    3258              : 
    3259              : /* Expand a call to one of the builtin math functions doing integer
    3260              :    conversion (lrint).
    3261              :    Return 0 if a normal call should be emitted rather than expanding the
    3262              :    function in-line.  EXP is the expression that is a call to the builtin
    3263              :    function; if convenient, the result should be placed in TARGET.  */
    3264              : 
    3265              : static rtx
    3266          588 : expand_builtin_int_roundingfn_2 (tree exp, rtx target)
    3267              : {
    3268          588 :   convert_optab builtin_optab;
    3269          588 :   rtx op0;
    3270          588 :   rtx_insn *insns;
    3271          588 :   tree fndecl = get_callee_fndecl (exp);
    3272          588 :   tree arg;
    3273          588 :   machine_mode mode;
    3274          588 :   enum built_in_function fallback_fn = BUILT_IN_NONE;
    3275              : 
    3276          588 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    3277              :     return NULL_RTX;
    3278              : 
    3279          488 :   arg = CALL_EXPR_ARG (exp, 0);
    3280              : 
    3281          488 :   switch (DECL_FUNCTION_CODE (fndecl))
    3282              :     {
    3283            4 :     CASE_FLT_FN (BUILT_IN_IRINT):
    3284            4 :       fallback_fn = BUILT_IN_LRINT;
    3285              :       gcc_fallthrough ();
    3286              :     CASE_FLT_FN (BUILT_IN_LRINT):
    3287              :     CASE_FLT_FN (BUILT_IN_LLRINT):
    3288              :       builtin_optab = lrint_optab;
    3289              :       break;
    3290              : 
    3291          223 :     CASE_FLT_FN (BUILT_IN_IROUND):
    3292          223 :       fallback_fn = BUILT_IN_LROUND;
    3293              :       gcc_fallthrough ();
    3294              :     CASE_FLT_FN (BUILT_IN_LROUND):
    3295              :     CASE_FLT_FN (BUILT_IN_LLROUND):
    3296              :       builtin_optab = lround_optab;
    3297              :       break;
    3298              : 
    3299            0 :     default:
    3300            0 :       gcc_unreachable ();
    3301              :     }
    3302              : 
    3303              :   /* There's no easy way to detect the case we need to set EDOM.  */
    3304          488 :   if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
    3305              :     return NULL_RTX;
    3306              : 
    3307              :   /* Make a suitable register to place result in.  */
    3308          257 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3309              : 
    3310              :   /* There's no easy way to detect the case we need to set EDOM.  */
    3311          257 :   if (!flag_errno_math)
    3312              :     {
    3313          257 :       rtx result = gen_reg_rtx (mode);
    3314              : 
    3315              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    3316              :          need to expand the argument again.  This way, we will not perform
    3317              :          side-effects more the once.  */
    3318          257 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    3319              : 
    3320          257 :       op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    3321              : 
    3322          257 :       start_sequence ();
    3323              : 
    3324          257 :       if (expand_sfix_optab (result, op0, builtin_optab))
    3325              :         {
    3326              :           /* Output the entire sequence.  */
    3327           20 :           insns = end_sequence ();
    3328           20 :           emit_insn (insns);
    3329           20 :           return result;
    3330              :         }
    3331              : 
    3332              :       /* If we were unable to expand via the builtin, stop the sequence
    3333              :          (without outputting the insns) and call to the library function
    3334              :          with the stabilized argument list.  */
    3335          237 :       end_sequence ();
    3336              :     }
    3337              : 
    3338          237 :   if (fallback_fn != BUILT_IN_NONE)
    3339              :     {
    3340              :       /* Fall back to rounding to long int.  Use implicit_p 0 - for non-C99
    3341              :          targets, (int) round (x) should never be transformed into
    3342              :          BUILT_IN_IROUND and if __builtin_iround is called directly, emit
    3343              :          a call to lround in the hope that the target provides at least some
    3344              :          C99 functions.  This should result in the best user experience for
    3345              :          not full C99 targets.
    3346              :          As scalar float conversions with same mode are useless in GIMPLE,
    3347              :          we can end up e.g. with _Float32 argument passed to float builtin,
    3348              :          try to get the type from the builtin prototype first.  */
    3349          223 :       tree fallback_fndecl = NULL_TREE;
    3350          223 :       if (tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
    3351          223 :         fallback_fndecl
    3352          223 :           = mathfn_built_in_1 (TREE_VALUE (argtypes),
    3353              :                                as_combined_fn (fallback_fn), 0);
    3354          223 :       if (fallback_fndecl == NULL_TREE)
    3355            0 :         fallback_fndecl
    3356            0 :           = mathfn_built_in_1 (TREE_TYPE (arg),
    3357              :                                as_combined_fn (fallback_fn), 0);
    3358            0 :       if (fallback_fndecl)
    3359              :         {
    3360          223 :           exp = build_call_nofold_loc (EXPR_LOCATION (exp),
    3361              :                                        fallback_fndecl, 1, arg);
    3362              : 
    3363          223 :           target = expand_call (exp, NULL_RTX, target == const0_rtx);
    3364          223 :           target = maybe_emit_group_store (target, TREE_TYPE (exp));
    3365          223 :           return convert_to_mode (mode, target, 0);
    3366              :         }
    3367              :     }
    3368              : 
    3369           14 :   return expand_call (exp, target, target == const0_rtx);
    3370              : }
    3371              : 
    3372              : /* Expand a call to the powi built-in mathematical function.  Return NULL_RTX if
    3373              :    a normal call should be emitted rather than expanding the function
    3374              :    in-line.  EXP is the expression that is a call to the builtin
    3375              :    function; if convenient, the result should be placed in TARGET.  */
    3376              : 
    3377              : static rtx
    3378          292 : expand_builtin_powi (tree exp, rtx target)
    3379              : {
    3380          292 :   tree arg0, arg1;
    3381          292 :   rtx op0, op1;
    3382          292 :   machine_mode mode;
    3383          292 :   machine_mode mode2;
    3384              : 
    3385          292 :   if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
    3386              :     return NULL_RTX;
    3387              : 
    3388          292 :   arg0 = CALL_EXPR_ARG (exp, 0);
    3389          292 :   arg1 = CALL_EXPR_ARG (exp, 1);
    3390          292 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3391              : 
    3392              :   /* Emit a libcall to libgcc.  */
    3393              : 
    3394              :   /* Mode of the 2nd argument must match that of an int.  */
    3395          292 :   mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
    3396              : 
    3397          292 :   if (target == NULL_RTX)
    3398            0 :     target = gen_reg_rtx (mode);
    3399              : 
    3400          292 :   op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    3401          292 :   if (GET_MODE (op0) != mode)
    3402            0 :     op0 = convert_to_mode (mode, op0, 0);
    3403          292 :   op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
    3404          292 :   if (GET_MODE (op1) != mode2)
    3405           52 :     op1 = convert_to_mode (mode2, op1, 0);
    3406              : 
    3407          292 :   target = emit_library_call_value (optab_libfunc (powi_optab, mode),
    3408              :                                     target, LCT_CONST, mode,
    3409              :                                     op0, mode, op1, mode2);
    3410              : 
    3411          292 :   return target;
    3412              : }
    3413              : 
    3414              : /* Expand expression EXP which is a call to the strlen builtin.  Return
    3415              :    NULL_RTX if we failed and the caller should emit a normal call, otherwise
    3416              :    try to get the result in TARGET, if convenient.  */
    3417              : 
    3418              : static rtx
    3419        14752 : expand_builtin_strlen (tree exp, rtx target,
    3420              :                        machine_mode target_mode)
    3421              : {
    3422        14752 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    3423              :     return NULL_RTX;
    3424              : 
    3425        14733 :   tree src = CALL_EXPR_ARG (exp, 0);
    3426              : 
    3427              :   /* If the length can be computed at compile-time, return it.  */
    3428        14733 :   if (tree len = c_strlen (src, 0))
    3429          141 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3430              : 
    3431              :   /* If the length can be computed at compile-time and is constant
    3432              :      integer, but there are side-effects in src, evaluate
    3433              :      src for side-effects, then return len.
    3434              :      E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
    3435              :      can be optimized into: i++; x = 3;  */
    3436        14592 :   tree len = c_strlen (src, 1);
    3437        14592 :   if (len && TREE_CODE (len) == INTEGER_CST)
    3438              :     {
    3439            0 :       expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
    3440            0 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3441              :     }
    3442              : 
    3443        14592 :   unsigned int align = get_pointer_alignment (src) / BITS_PER_UNIT;
    3444              : 
    3445              :   /* If SRC is not a pointer type, don't do this operation inline.  */
    3446        14592 :   if (align == 0)
    3447              :     return NULL_RTX;
    3448              : 
    3449              :   /* Bail out if we can't compute strlen in the right mode.  */
    3450              :   machine_mode insn_mode;
    3451              :   enum insn_code icode = CODE_FOR_nothing;
    3452        14592 :   FOR_EACH_MODE_FROM (insn_mode, target_mode)
    3453              :     {
    3454        14592 :       icode = optab_handler (strlen_optab, insn_mode);
    3455        14592 :       if (icode != CODE_FOR_nothing)
    3456              :         break;
    3457              :     }
    3458        14592 :   if (insn_mode == VOIDmode)
    3459              :     return NULL_RTX;
    3460              : 
    3461              :   /* Make a place to hold the source address.  We will not expand
    3462              :      the actual source until we are sure that the expansion will
    3463              :      not fail -- there are trees that cannot be expanded twice.  */
    3464        15208 :   rtx src_reg = gen_reg_rtx (Pmode);
    3465              : 
    3466              :   /* Mark the beginning of the strlen sequence so we can emit the
    3467              :      source operand later.  */
    3468        14592 :   rtx_insn *before_strlen = get_last_insn ();
    3469              : 
    3470        14592 :   class expand_operand ops[4];
    3471        14592 :   create_output_operand (&ops[0], target, insn_mode);
    3472        14592 :   create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
    3473        14592 :   create_integer_operand (&ops[2], 0);
    3474        14592 :   create_integer_operand (&ops[3], align);
    3475        14592 :   if (!maybe_expand_insn (icode, 4, ops))
    3476              :     return NULL_RTX;
    3477              : 
    3478              :   /* Check to see if the argument was declared attribute nonstring
    3479              :      and if so, issue a warning since at this point it's not known
    3480              :      to be nul-terminated.  */
    3481           11 :   maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    3482              : 
    3483              :   /* Now that we are assured of success, expand the source.  */
    3484           11 :   start_sequence ();
    3485           15 :   rtx pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
    3486           11 :   if (pat != src_reg)
    3487              :     {
    3488              : #ifdef POINTERS_EXTEND_UNSIGNED
    3489           15 :       if (GET_MODE (pat) != Pmode)
    3490            0 :         pat = convert_to_mode (Pmode, pat,
    3491              :                                POINTERS_EXTEND_UNSIGNED);
    3492              : #endif
    3493           11 :       emit_move_insn (src_reg, pat);
    3494              :     }
    3495           11 :   pat = end_sequence ();
    3496              : 
    3497           11 :   if (before_strlen)
    3498           11 :     emit_insn_after (pat, before_strlen);
    3499              :   else
    3500            0 :     emit_insn_before (pat, get_insns ());
    3501              : 
    3502              :   /* Return the value in the proper mode for this function.  */
    3503           11 :   if (GET_MODE (ops[0].value) == target_mode)
    3504              :     target = ops[0].value;
    3505            0 :   else if (target != 0)
    3506            0 :     convert_move (target, ops[0].value, 0);
    3507              :   else
    3508            0 :     target = convert_to_mode (target_mode, ops[0].value, 0);
    3509              : 
    3510              :   return target;
    3511              : }
    3512              : 
    3513              : /* Expand call EXP to the strnlen built-in, returning the result
    3514              :    and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
    3515              : 
    3516              : static rtx
    3517          580 : expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
    3518              : {
    3519          580 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3520              :     return NULL_RTX;
    3521              : 
    3522          571 :   tree src = CALL_EXPR_ARG (exp, 0);
    3523          571 :   tree bound = CALL_EXPR_ARG (exp, 1);
    3524              : 
    3525          571 :   if (!bound)
    3526              :     return NULL_RTX;
    3527              : 
    3528          571 :   location_t loc = UNKNOWN_LOCATION;
    3529          571 :   if (EXPR_HAS_LOCATION (exp))
    3530          571 :     loc = EXPR_LOCATION (exp);
    3531              : 
    3532              :   /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
    3533              :      so these conversions aren't necessary.  */
    3534          571 :   c_strlen_data lendata = { };
    3535          571 :   tree len = c_strlen (src, 0, &lendata, 1);
    3536          571 :   if (len)
    3537           63 :     len = fold_convert_loc (loc, TREE_TYPE (bound), len);
    3538              : 
    3539          571 :   if (TREE_CODE (bound) == INTEGER_CST)
    3540              :     {
    3541          304 :       if (!len)
    3542              :         return NULL_RTX;
    3543              : 
    3544           23 :       len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
    3545           23 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3546              :     }
    3547              : 
    3548          267 :   if (TREE_CODE (bound) != SSA_NAME)
    3549              :     return NULL_RTX;
    3550              : 
    3551          267 :   wide_int min, max;
    3552          267 :   int_range_max r;
    3553          534 :   get_range_query (cfun)->range_of_expr (r, bound,
    3554              :                                          currently_expanding_gimple_stmt);
    3555          267 :   if (r.varying_p () || r.undefined_p ())
    3556              :     return NULL_RTX;
    3557          152 :   min = r.lower_bound ();
    3558          152 :   max = r.upper_bound ();
    3559              : 
    3560          152 :   if (!len || TREE_CODE (len) != INTEGER_CST)
    3561              :     {
    3562          115 :       bool exact;
    3563          115 :       lendata.decl = unterminated_array (src, &len, &exact);
    3564          115 :       if (!lendata.decl)
    3565           95 :         return NULL_RTX;
    3566              :     }
    3567              : 
    3568           57 :   if (lendata.decl)
    3569              :     return NULL_RTX;
    3570              : 
    3571           37 :   if (wi::gtu_p (min, wi::to_wide (len)))
    3572            7 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3573              : 
    3574           30 :   len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, bound);
    3575           30 :   return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3576          267 : }
    3577              : 
    3578              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    3579              :    bytes from bytes at DATA + OFFSET and return it reinterpreted as
    3580              :    a target constant.  */
    3581              : 
    3582              : static rtx
    3583       172450 : builtin_memcpy_read_str (void *data, void *, HOST_WIDE_INT offset,
    3584              :                          fixed_size_mode mode)
    3585              : {
    3586              :   /* The REPresentation pointed to by DATA need not be a nul-terminated
    3587              :      string but the caller guarantees it's large enough for MODE.  */
    3588       172450 :   const char *rep = (const char *) data;
    3589              : 
    3590       172450 :   return c_readstr (rep + offset, mode, /*nul_terminated=*/false);
    3591              : }
    3592              : 
    3593              : /* LEN specify length of the block of memcpy/memset operation.
    3594              :    Figure out its range and put it into MIN_SIZE/MAX_SIZE.
    3595              :    In some cases we can make very likely guess on max size, then we
    3596              :    set it into PROBABLE_MAX_SIZE.  */
    3597              : 
    3598              : static void
    3599       191851 : determine_block_size (tree len, rtx &len_rtx,
    3600              :                       unsigned HOST_WIDE_INT *min_size,
    3601              :                       unsigned HOST_WIDE_INT *max_size,
    3602              :                       unsigned HOST_WIDE_INT *probable_max_size)
    3603              : {
    3604       191851 :   if (CONST_INT_P (len_rtx))
    3605              :     {
    3606        96241 :       *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
    3607        96241 :       return;
    3608              :     }
    3609              :   else
    3610              :     {
    3611        95610 :       wide_int min, max;
    3612        95610 :       enum value_range_kind range_type = VR_UNDEFINED;
    3613              : 
    3614              :       /* Determine bounds from the type.  */
    3615        95610 :       if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
    3616        95609 :         *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
    3617              :       else
    3618              :         *min_size = 0;
    3619        95610 :       if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
    3620        95610 :         *probable_max_size = *max_size
    3621        95610 :           = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
    3622              :       else
    3623            0 :         *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
    3624              : 
    3625        95610 :       if (TREE_CODE (len) == SSA_NAME)
    3626              :         {
    3627        95610 :           int_range_max r;
    3628        95610 :           tree tmin, tmax;
    3629        95610 :           gimple *cg = currently_expanding_gimple_stmt;
    3630       191220 :           get_range_query (cfun)->range_of_expr (r, len, cg);
    3631        95610 :           range_type = get_legacy_range (r, tmin, tmax);
    3632        95610 :           if (range_type != VR_UNDEFINED)
    3633              :             {
    3634        95608 :               min = wi::to_wide (tmin);
    3635        95608 :               max = wi::to_wide (tmax);
    3636              :             }
    3637        95610 :         }
    3638        95610 :       if (range_type == VR_RANGE)
    3639              :         {
    3640        69257 :           if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
    3641        56513 :             *min_size = min.to_uhwi ();
    3642        69257 :           if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
    3643        62506 :             *probable_max_size = *max_size = max.to_uhwi ();
    3644              :         }
    3645        26353 :       else if (range_type == VR_ANTI_RANGE)
    3646              :         {
    3647              :           /* Code like
    3648              : 
    3649              :              int n;
    3650              :              if (n < 100)
    3651              :                memcpy (a, b, n)
    3652              : 
    3653              :              Produce anti range allowing negative values of N.  We still
    3654              :              can use the information and make a guess that N is not negative.
    3655              :              */
    3656         3077 :           if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
    3657         2928 :             *probable_max_size = min.to_uhwi () - 1;
    3658              :         }
    3659        95610 :     }
    3660              : 
    3661        95610 :   if (*min_size == *max_size)
    3662           13 :     len_rtx = GEN_INT (*min_size);
    3663              :   else
    3664        95597 :     gcc_checking_assert (*max_size <=
    3665              :                          (unsigned HOST_WIDE_INT)
    3666              :                          GET_MODE_MASK (GET_MODE (len_rtx)));
    3667              : }
    3668              : 
    3669              : /* Expand a call EXP to the memcpy builtin.
    3670              :    Return NULL_RTX if we failed, the caller should emit a normal call,
    3671              :    otherwise try to get the result in TARGET, if convenient (and in
    3672              :    mode MODE if that's convenient).  */
    3673              : 
    3674              : static rtx
    3675       110102 : expand_builtin_memcpy (tree exp, rtx target)
    3676              : {
    3677       110102 :   if (!validate_arglist (exp,
    3678              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3679              :     return NULL_RTX;
    3680              : 
    3681       110084 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3682       110084 :   tree src = CALL_EXPR_ARG (exp, 1);
    3683       110084 :   tree len = CALL_EXPR_ARG (exp, 2);
    3684              : 
    3685       110084 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    3686       110084 :                                           /*retmode=*/ RETURN_BEGIN, false);
    3687              : }
    3688              : 
    3689              : /* Check a call EXP to the memmove built-in for validity.
    3690              :    Return NULL_RTX on both success and failure.  */
    3691              : 
    3692              : static rtx
    3693        17646 : expand_builtin_memmove (tree exp, rtx target)
    3694              : {
    3695        17646 :   if (!validate_arglist (exp,
    3696              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3697              :     return NULL_RTX;
    3698              : 
    3699        17631 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3700        17631 :   tree src = CALL_EXPR_ARG (exp, 1);
    3701        17631 :   tree len = CALL_EXPR_ARG (exp, 2);
    3702              : 
    3703        17631 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    3704        17631 :                                           /*retmode=*/ RETURN_BEGIN, true);
    3705              : }
    3706              : 
    3707              : /* Expand a call EXP to the mempcpy builtin.
    3708              :    Return NULL_RTX if we failed; the caller should emit a normal call,
    3709              :    otherwise try to get the result in TARGET, if convenient (and in
    3710              :    mode MODE if that's convenient).  */
    3711              : 
    3712              : static rtx
    3713         1395 : expand_builtin_mempcpy (tree exp, rtx target)
    3714              : {
    3715         1395 :   if (!validate_arglist (exp,
    3716              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3717              :     return NULL_RTX;
    3718              : 
    3719         1390 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3720         1390 :   tree src = CALL_EXPR_ARG (exp, 1);
    3721         1390 :   tree len = CALL_EXPR_ARG (exp, 2);
    3722              : 
    3723              :   /* Policy does not generally allow using compute_objsize (which
    3724              :      is used internally by check_memop_size) to change code generation
    3725              :      or drive optimization decisions.
    3726              : 
    3727              :      In this instance it is safe because the code we generate has
    3728              :      the same semantics regardless of the return value of
    3729              :      check_memop_sizes.   Exactly the same amount of data is copied
    3730              :      and the return value is exactly the same in both cases.
    3731              : 
    3732              :      Furthermore, check_memop_size always uses mode 0 for the call to
    3733              :      compute_objsize, so the imprecise nature of compute_objsize is
    3734              :      avoided.  */
    3735              : 
    3736              :   /* Avoid expanding mempcpy into memcpy when the call is determined
    3737              :      to overflow the buffer.  This also prevents the same overflow
    3738              :      from being diagnosed again when expanding memcpy.  */
    3739              : 
    3740         1390 :   return expand_builtin_mempcpy_args (dest, src, len,
    3741         1390 :                                       target, exp, /*retmode=*/ RETURN_END);
    3742              : }
    3743              : 
    3744              : /* Helper function to do the actual work for expand of memory copy family
    3745              :    functions (memcpy, mempcpy, stpcpy).  Expansing should assign LEN bytes
    3746              :    of memory from SRC to DEST and assign to TARGET if convenient.  Return
    3747              :    value is based on RETMODE argument.  */
    3748              : 
    3749              : static rtx
    3750       129128 : expand_builtin_memory_copy_args (tree dest, tree src, tree len,
    3751              :                                  rtx target, tree exp, memop_ret retmode,
    3752              :                                  bool might_overlap)
    3753              : {
    3754       129128 :   unsigned int src_align = get_pointer_alignment (src);
    3755       129128 :   unsigned int dest_align = get_pointer_alignment (dest);
    3756       129128 :   rtx dest_mem, src_mem, dest_addr, len_rtx;
    3757       129128 :   HOST_WIDE_INT expected_size = -1;
    3758       129128 :   unsigned int expected_align = 0;
    3759       129128 :   unsigned HOST_WIDE_INT min_size;
    3760       129128 :   unsigned HOST_WIDE_INT max_size;
    3761       129128 :   unsigned HOST_WIDE_INT probable_max_size;
    3762              : 
    3763       129128 :   bool is_move_done;
    3764              : 
    3765              :   /* If DEST is not a pointer type, call the normal function.  */
    3766       129128 :   if (dest_align == 0)
    3767              :     return NULL_RTX;
    3768              : 
    3769              :   /* If either SRC is not a pointer type, don't do this
    3770              :      operation in-line.  */
    3771       129128 :   if (src_align == 0)
    3772              :     return NULL_RTX;
    3773              : 
    3774       129128 :   if (currently_expanding_gimple_stmt)
    3775       129128 :     stringop_block_profile (currently_expanding_gimple_stmt,
    3776              :                             &expected_align, &expected_size);
    3777              : 
    3778       129128 :   if (expected_align < dest_align)
    3779       129106 :     expected_align = dest_align;
    3780       129128 :   dest_mem = get_memory_rtx (dest, len, true);
    3781       129128 :   set_mem_align (dest_mem, dest_align);
    3782       129128 :   len_rtx = expand_normal (len);
    3783       129128 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    3784              :                         &probable_max_size);
    3785              : 
    3786              :   /* Try to get the byte representation of the constant SRC points to,
    3787              :      with its byte size in NBYTES.  */
    3788       129128 :   unsigned HOST_WIDE_INT nbytes;
    3789       129128 :   const char *rep = getbyterep (src, &nbytes);
    3790              : 
    3791              :   /* If the function's constant bound LEN_RTX is less than or equal
    3792              :      to the byte size of the representation of the constant argument,
    3793              :      and if block move would be done by pieces, we can avoid loading
    3794              :      the bytes from memory and only store the computed constant.
    3795              :      This works in the overlap (memmove) case as well because
    3796              :      store_by_pieces just generates a series of stores of constants
    3797              :      from the representation returned by getbyterep().  */
    3798       129128 :   if (rep
    3799        31380 :       && CONST_INT_P (len_rtx)
    3800        29717 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes
    3801       158579 :       && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
    3802              :                               const_cast<char *> (rep),
    3803              :                               dest_align, false))
    3804              :     {
    3805        28972 :       dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
    3806              :                                   builtin_memcpy_read_str,
    3807              :                                   const_cast<char *> (rep),
    3808              :                                   dest_align, false, retmode);
    3809        28972 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    3810        28972 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    3811        28972 :       return dest_mem;
    3812              :     }
    3813              : 
    3814       100156 :   src_mem = get_memory_rtx (src, len, false);
    3815       100156 :   set_mem_align (src_mem, src_align);
    3816              : 
    3817              :   /* Copy word part most expediently.  */
    3818       100156 :   enum block_op_methods method = BLOCK_OP_NORMAL;
    3819       100156 :   if (CALL_EXPR_TAILCALL (exp)
    3820       100156 :       && (retmode == RETURN_BEGIN || target == const0_rtx))
    3821              :     method = BLOCK_OP_TAILCALL;
    3822       100156 :   bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
    3823       100156 :                            && retmode == RETURN_END
    3824       100156 :                            && !might_overlap
    3825       101231 :                            && target != const0_rtx);
    3826              :   if (use_mempcpy_call)
    3827       100156 :     method = BLOCK_OP_NO_LIBCALL_RET;
    3828       100156 :   dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
    3829              :                                      expected_align, expected_size,
    3830              :                                      min_size, max_size, probable_max_size,
    3831              :                                      use_mempcpy_call, &is_move_done,
    3832              :                                      might_overlap, tree_ctz (len));
    3833              : 
    3834              :   /* Bail out when a mempcpy call would be expanded as libcall and when
    3835              :      we have a target that provides a fast implementation
    3836              :      of mempcpy routine.  */
    3837       100156 :   if (!is_move_done)
    3838              :     return NULL_RTX;
    3839              : 
    3840        87000 :   if (dest_addr == pc_rtx)
    3841              :     return NULL_RTX;
    3842              : 
    3843        87000 :   if (dest_addr == 0)
    3844              :     {
    3845        33516 :       dest_addr = force_operand (XEXP (dest_mem, 0), target);
    3846        33516 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    3847              :     }
    3848              : 
    3849        87000 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    3850              :     {
    3851          815 :       dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
    3852              :       /* stpcpy pointer to last byte.  */
    3853          815 :       if (retmode == RETURN_END_MINUS_ONE)
    3854            0 :         dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
    3855              :     }
    3856              : 
    3857              :   return dest_addr;
    3858              : }
    3859              : 
    3860              : static rtx
    3861         1413 : expand_builtin_mempcpy_args (tree dest, tree src, tree len,
    3862              :                              rtx target, tree orig_exp, memop_ret retmode)
    3863              : {
    3864         1390 :   return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
    3865            0 :                                           retmode, false);
    3866              : }
    3867              : 
    3868              : /* Expand into a movstr instruction, if one is available.  Return NULL_RTX if
    3869              :    we failed, the caller should emit a normal call, otherwise try to
    3870              :    get the result in TARGET, if convenient.
    3871              :    Return value is based on RETMODE argument.  */
    3872              : 
    3873              : static rtx
    3874         2267 : expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
    3875              : {
    3876         2267 :   class expand_operand ops[3];
    3877         2267 :   rtx dest_mem;
    3878         2267 :   rtx src_mem;
    3879              : 
    3880         2267 :   if (!targetm.have_movstr ())
    3881              :     return NULL_RTX;
    3882              : 
    3883            0 :   dest_mem = get_memory_rtx (dest, NULL, true);
    3884            0 :   src_mem = get_memory_rtx (src, NULL, false);
    3885            0 :   if (retmode == RETURN_BEGIN)
    3886              :     {
    3887            0 :       target = force_reg (Pmode, XEXP (dest_mem, 0));
    3888            0 :       dest_mem = replace_equiv_address (dest_mem, target);
    3889              :     }
    3890              : 
    3891            0 :   create_output_operand (&ops[0],
    3892            0 :                          retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
    3893            0 :   create_fixed_operand (&ops[1], dest_mem);
    3894            0 :   create_fixed_operand (&ops[2], src_mem);
    3895            0 :   if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
    3896              :     return NULL_RTX;
    3897              : 
    3898            0 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    3899              :     {
    3900            0 :       target = ops[0].value;
    3901              :       /* movstr is supposed to set end to the address of the NUL
    3902              :          terminator.  If the caller requested a mempcpy-like return value,
    3903              :          adjust it.  */
    3904            0 :       if (retmode == RETURN_END)
    3905              :         {
    3906            0 :           rtx tem = plus_constant (GET_MODE (target),
    3907            0 :                                    gen_lowpart (GET_MODE (target), target), 1);
    3908            0 :           emit_move_insn (target, force_operand (tem, NULL_RTX));
    3909              :         }
    3910              :     }
    3911              :   return target;
    3912              : }
    3913              : 
    3914              : /* Expand expression EXP, which is a call to the strcpy builtin.  Return
    3915              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    3916              :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    3917              :    convenient).  */
    3918              : 
    3919              : static rtx
    3920         1860 : expand_builtin_strcpy (tree exp, rtx target)
    3921              : {
    3922         1860 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    3923              :     return NULL_RTX;
    3924              : 
    3925         1845 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3926         1845 :   tree src = CALL_EXPR_ARG (exp, 1);
    3927              : 
    3928         1845 :   return expand_builtin_strcpy_args (exp, dest, src, target);
    3929              : }
    3930              : 
    3931              : /* Helper function to do the actual work for expand_builtin_strcpy.  The
    3932              :    arguments to the builtin_strcpy call DEST and SRC are broken out
    3933              :    so that this can also be called without constructing an actual CALL_EXPR.
    3934              :    The other arguments and return value are the same as for
    3935              :    expand_builtin_strcpy.  */
    3936              : 
    3937              : static rtx
    3938         1845 : expand_builtin_strcpy_args (tree, tree dest, tree src, rtx target)
    3939              : {
    3940         1845 :   return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
    3941              : }
    3942              : 
    3943              : /* Expand a call EXP to the stpcpy builtin.
    3944              :    Return NULL_RTX if we failed the caller should emit a normal call,
    3945              :    otherwise try to get the result in TARGET, if convenient (and in
    3946              :    mode MODE if that's convenient).  */
    3947              : 
    3948              : static rtx
    3949          454 : expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
    3950              : {
    3951          454 :   tree dst, src;
    3952          454 :   location_t loc = EXPR_LOCATION (exp);
    3953              : 
    3954          454 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    3955              :     return NULL_RTX;
    3956              : 
    3957          445 :   dst = CALL_EXPR_ARG (exp, 0);
    3958          445 :   src = CALL_EXPR_ARG (exp, 1);
    3959              : 
    3960              :   /* If return value is ignored, transform stpcpy into strcpy.  */
    3961          445 :   if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
    3962              :     {
    3963            0 :       tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
    3964            0 :       tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
    3965            0 :       return expand_expr (result, target, mode, EXPAND_NORMAL);
    3966              :     }
    3967              :   else
    3968              :     {
    3969          445 :       tree len, lenp1;
    3970          445 :       rtx ret;
    3971              : 
    3972              :       /* Ensure we get an actual string whose length can be evaluated at
    3973              :          compile-time, not an expression containing a string.  This is
    3974              :          because the latter will potentially produce pessimized code
    3975              :          when used to produce the return value.  */
    3976          445 :       c_strlen_data lendata = { };
    3977          445 :       if (!c_getstr (src)
    3978          445 :           || !(len = c_strlen (src, 0, &lendata, 1)))
    3979          422 :         return expand_movstr (dst, src, target,
    3980          422 :                               /*retmode=*/ RETURN_END_MINUS_ONE);
    3981              : 
    3982           23 :       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
    3983           23 :       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
    3984              :                                          target, exp,
    3985              :                                          /*retmode=*/ RETURN_END_MINUS_ONE);
    3986              : 
    3987           23 :       if (ret)
    3988              :         return ret;
    3989              : 
    3990            0 :       if (TREE_CODE (len) == INTEGER_CST)
    3991              :         {
    3992            0 :           rtx len_rtx = expand_normal (len);
    3993              : 
    3994            0 :           if (CONST_INT_P (len_rtx))
    3995              :             {
    3996            0 :               ret = expand_builtin_strcpy_args (exp, dst, src, target);
    3997              : 
    3998            0 :               if (ret)
    3999              :                 {
    4000            0 :                   if (! target)
    4001              :                     {
    4002            0 :                       if (mode != VOIDmode)
    4003            0 :                         target = gen_reg_rtx (mode);
    4004              :                       else
    4005            0 :                         target = gen_reg_rtx (GET_MODE (ret));
    4006              :                     }
    4007            0 :                   if (GET_MODE (target) != GET_MODE (ret))
    4008            0 :                     ret = gen_lowpart (GET_MODE (target), ret);
    4009              : 
    4010            0 :                   ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
    4011            0 :                   ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
    4012            0 :                   gcc_assert (ret);
    4013              : 
    4014              :                   return target;
    4015              :                 }
    4016              :             }
    4017              :         }
    4018              : 
    4019            0 :       return expand_movstr (dst, src, target,
    4020            0 :                             /*retmode=*/ RETURN_END_MINUS_ONE);
    4021              :     }
    4022              : }
    4023              : 
    4024              : /* Expand a call EXP to the stpcpy builtin and diagnose uses of nonstring
    4025              :    arguments while being careful to avoid duplicate warnings (which could
    4026              :    be issued if the expander were to expand the call, resulting in it
    4027              :    being emitted in expand_call().  */
    4028              : 
    4029              : static rtx
    4030          454 : expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
    4031              : {
    4032          454 :   if (rtx ret = expand_builtin_stpcpy_1 (exp, target, mode))
    4033              :     {
    4034              :       /* The call has been successfully expanded.  Check for nonstring
    4035              :          arguments and issue warnings as appropriate.  */
    4036           23 :       maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    4037           23 :       return ret;
    4038              :     }
    4039              : 
    4040              :   return NULL_RTX;
    4041              : }
    4042              : 
    4043              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4044              :    bytes from constant string DATA + OFFSET and return it as target
    4045              :    constant.  */
    4046              : 
    4047              : rtx
    4048         9879 : builtin_strncpy_read_str (void *data, void *, HOST_WIDE_INT offset,
    4049              :                           fixed_size_mode mode)
    4050              : {
    4051         9879 :   const char *str = (const char *) data;
    4052              : 
    4053         9879 :   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
    4054          260 :     return const0_rtx;
    4055              : 
    4056         9619 :   return c_readstr (str + offset, mode);
    4057              : }
    4058              : 
    4059              : /* Helper to check the sizes of sequences and the destination of calls
    4060              :    to __builtin_strncat and __builtin___strncat_chk.  Returns true on
    4061              :    success (no overflow or invalid sizes), false otherwise.  */
    4062              : 
    4063              : static bool
    4064          108 : check_strncat_sizes (tree exp, tree objsize)
    4065              : {
    4066          108 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4067          108 :   tree src = CALL_EXPR_ARG (exp, 1);
    4068          108 :   tree maxread = CALL_EXPR_ARG (exp, 2);
    4069              : 
    4070              :   /* Try to determine the range of lengths that the source expression
    4071              :      refers to.  */
    4072          108 :   c_strlen_data lendata = { };
    4073          108 :   get_range_strlen (src, &lendata, /* eltsize = */ 1);
    4074              : 
    4075              :   /* Try to verify that the destination is big enough for the shortest
    4076              :      string.  */
    4077              : 
    4078          108 :   access_data data (nullptr, exp, access_read_write, maxread, true);
    4079          108 :   if (!objsize && warn_stringop_overflow)
    4080              :     {
    4081              :       /* If it hasn't been provided by __strncat_chk, try to determine
    4082              :          the size of the destination object into which the source is
    4083              :          being copied.  */
    4084            0 :       objsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst);
    4085              :     }
    4086              : 
    4087              :   /* Add one for the terminating nul.  */
    4088          108 :   tree srclen = (lendata.minlen
    4089          108 :                  ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
    4090              :                                 size_one_node)
    4091              :                  : NULL_TREE);
    4092              : 
    4093              :   /* The strncat function copies at most MAXREAD bytes and always appends
    4094              :      the terminating nul so the specified upper bound should never be equal
    4095              :      to (or greater than) the size of the destination.  */
    4096           55 :   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
    4097          155 :       && tree_int_cst_equal (objsize, maxread))
    4098              :     {
    4099           23 :       location_t loc = EXPR_LOCATION (exp);
    4100           23 :       warning_at (loc, OPT_Wstringop_overflow_,
    4101              :                   "%qD specified bound %E equals destination size",
    4102              :                   get_callee_fndecl (exp), maxread);
    4103              : 
    4104           23 :       return false;
    4105              :     }
    4106              : 
    4107           85 :   if (!srclen
    4108           85 :       || (maxread && tree_fits_uhwi_p (maxread)
    4109           32 :           && tree_fits_uhwi_p (srclen)
    4110           32 :           && tree_int_cst_lt (maxread, srclen)))
    4111              :     srclen = maxread;
    4112              : 
    4113              :   /* The number of bytes to write is LEN but check_access will alsoa
    4114              :      check SRCLEN if LEN's value isn't known.  */
    4115           85 :   return check_access (exp, /*dstwrite=*/NULL_TREE, maxread, srclen,
    4116           85 :                        objsize, data.mode, &data);
    4117              : }
    4118              : 
    4119              : /* Expand expression EXP, which is a call to the strncpy builtin.  Return
    4120              :    NULL_RTX if we failed the caller should emit a normal call.  */
    4121              : 
    4122              : static rtx
    4123         2177 : expand_builtin_strncpy (tree exp, rtx target)
    4124              : {
    4125         2177 :   location_t loc = EXPR_LOCATION (exp);
    4126              : 
    4127         2177 :   if (!validate_arglist (exp,
    4128              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4129              :     return NULL_RTX;
    4130         2165 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4131         2165 :   tree src = CALL_EXPR_ARG (exp, 1);
    4132              :   /* The number of bytes to write (not the maximum).  */
    4133         2165 :   tree len = CALL_EXPR_ARG (exp, 2);
    4134              : 
    4135              :   /* The length of the source sequence.  */
    4136         2165 :   tree slen = c_strlen (src, 1);
    4137              : 
    4138              :   /* We must be passed a constant len and src parameter.  */
    4139         2165 :   if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
    4140              :     return NULL_RTX;
    4141              : 
    4142          237 :   slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
    4143              : 
    4144              :   /* We're required to pad with trailing zeros if the requested
    4145              :      len is greater than strlen(s2)+1.  In that case try to
    4146              :      use store_by_pieces, if it fails, punt.  */
    4147          237 :   if (tree_int_cst_lt (slen, len))
    4148              :     {
    4149          142 :       unsigned int dest_align = get_pointer_alignment (dest);
    4150          142 :       const char *p = c_getstr (src);
    4151          142 :       rtx dest_mem;
    4152              : 
    4153          136 :       if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
    4154          278 :           || !can_store_by_pieces (tree_to_uhwi (len),
    4155              :                                    builtin_strncpy_read_str,
    4156              :                                    const_cast<char *> (p),
    4157              :                                    dest_align, false))
    4158              :         return NULL_RTX;
    4159              : 
    4160          128 :       dest_mem = get_memory_rtx (dest, len, true);
    4161          128 :       store_by_pieces (dest_mem, tree_to_uhwi (len),
    4162              :                        builtin_strncpy_read_str,
    4163              :                        const_cast<char *> (p), dest_align, false,
    4164              :                        RETURN_BEGIN);
    4165          128 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    4166          128 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4167          128 :       return dest_mem;
    4168              :     }
    4169              : 
    4170              :   return NULL_RTX;
    4171              : }
    4172              : 
    4173              : /* Return the RTL of a register in MODE generated from PREV in the
    4174              :    previous iteration.  */
    4175              : 
    4176              : static rtx
    4177       254009 : gen_memset_value_from_prev (by_pieces_prev *prev, fixed_size_mode mode)
    4178              : {
    4179       254009 :   rtx target = nullptr;
    4180       254009 :   if (prev != nullptr && prev->data != nullptr)
    4181              :     {
    4182              :       /* Use the previous data in the same mode.  */
    4183       140512 :       if (prev->mode == mode)
    4184       254009 :         return prev->data;
    4185              : 
    4186        32538 :       fixed_size_mode prev_mode = prev->mode;
    4187              : 
    4188              :       /* Don't use the previous data to write QImode if it is in a
    4189              :          vector mode.  */
    4190        32538 :       if (VECTOR_MODE_P (prev_mode) && mode == QImode)
    4191              :         return target;
    4192              : 
    4193        32139 :       rtx prev_rtx = prev->data;
    4194              : 
    4195        32139 :       if (REG_P (prev_rtx)
    4196        23694 :           && HARD_REGISTER_P (prev_rtx)
    4197        32139 :           && lowpart_subreg_regno (REGNO (prev_rtx), prev_mode, mode) < 0)
    4198              :         {
    4199              :           /* This case occurs when PREV_MODE is a vector and when
    4200              :              MODE is too small to store using vector operations.
    4201              :              After register allocation, the code will need to move the
    4202              :              lowpart of the vector register into a non-vector register.
    4203              : 
    4204              :              Also, the target has chosen to use a hard register
    4205              :              instead of going with the default choice of using a
    4206              :              pseudo register.  We should respect that choice and try to
    4207              :              avoid creating a pseudo register with the same mode as the
    4208              :              current hard register.
    4209              : 
    4210              :              In principle, we could just use a lowpart MODE subreg of
    4211              :              the vector register.  However, the vector register mode might
    4212              :              be too wide for non-vector registers, and we already know
    4213              :              that the non-vector mode is too small for vector registers.
    4214              :              It's therefore likely that we'd need to spill to memory in
    4215              :              the vector mode and reload the non-vector value from there.
    4216              : 
    4217              :              Try to avoid that by reducing the vector register to the
    4218              :              smallest size that it can hold.  This should increase the
    4219              :              chances that non-vector registers can hold both the inner
    4220              :              and outer modes of the subreg that we generate later.  */
    4221            0 :           machine_mode m;
    4222            0 :           fixed_size_mode candidate;
    4223            0 :           FOR_EACH_MODE_IN_CLASS (m, GET_MODE_CLASS (mode))
    4224            0 :             if (is_a<fixed_size_mode> (m, &candidate))
    4225              :               {
    4226            0 :                 if (GET_MODE_SIZE (candidate)
    4227            0 :                     >= GET_MODE_SIZE (prev_mode))
    4228              :                   break;
    4229            0 :                 if (GET_MODE_SIZE (candidate) >= GET_MODE_SIZE (mode)
    4230            0 :                     && lowpart_subreg_regno (REGNO (prev_rtx),
    4231              :                                              prev_mode, candidate) >= 0)
    4232              :                   {
    4233            0 :                     target = lowpart_subreg (candidate, prev_rtx,
    4234              :                                              prev_mode);
    4235            0 :                     prev_rtx = target;
    4236            0 :                     prev_mode = candidate;
    4237            0 :                     break;
    4238              :                   }
    4239              :               }
    4240            0 :           if (target == nullptr)
    4241            0 :             prev_rtx = copy_to_reg (prev_rtx);
    4242              :         }
    4243              : 
    4244        32139 :       target = lowpart_subreg (mode, prev_rtx, prev_mode);
    4245              :     }
    4246              :   return target;
    4247              : }
    4248              : 
    4249              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4250              :    bytes from constant string DATA + OFFSET and return it as target
    4251              :    constant.  If PREV isn't nullptr, it has the RTL info from the
    4252              :    previous iteration.  */
    4253              : 
    4254              : rtx
    4255       252741 : builtin_memset_read_str (void *data, void *prev,
    4256              :                          HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4257              :                          fixed_size_mode mode)
    4258              : {
    4259       252741 :   const char *c = (const char *) data;
    4260       252741 :   unsigned int size = GET_MODE_SIZE (mode);
    4261              : 
    4262       252741 :   rtx target = gen_memset_value_from_prev ((by_pieces_prev *) prev,
    4263              :                                            mode);
    4264       252741 :   if (target != nullptr)
    4265              :     return target;
    4266       113173 :   rtx src = gen_int_mode (*c, QImode);
    4267              : 
    4268       113173 :   if (VECTOR_MODE_P (mode))
    4269              :     {
    4270       164238 :       gcc_assert (GET_MODE_INNER (mode) == QImode);
    4271              : 
    4272        82119 :       rtx const_vec = gen_const_vec_duplicate (mode, src);
    4273        82119 :       if (prev == NULL)
    4274              :         /* Return CONST_VECTOR when called by a query function.  */
    4275              :         return const_vec;
    4276              : 
    4277              :       /* Use the move expander with CONST_VECTOR.  */
    4278        61257 :       target = gen_reg_rtx (mode);
    4279        61257 :       emit_move_insn (target, const_vec);
    4280        61257 :       return target;
    4281              :     }
    4282              : 
    4283        31054 :   char *p = XALLOCAVEC (char, size);
    4284              : 
    4285        31054 :   memset (p, *c, size);
    4286              : 
    4287        31054 :   return c_readstr (p, mode);
    4288              : }
    4289              : 
    4290              : /* Callback routine for store_by_pieces.  Return the RTL of a register
    4291              :    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
    4292              :    char value given in the RTL register data.  For example, if mode is
    4293              :    4 bytes wide, return the RTL for 0x01010101*data.  If PREV isn't
    4294              :    nullptr, it has the RTL info from the previous iteration.  */
    4295              : 
    4296              : static rtx
    4297         1407 : builtin_memset_gen_str (void *data, void *prev,
    4298              :                         HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4299              :                         fixed_size_mode mode)
    4300              : {
    4301         1407 :   rtx target, coeff;
    4302         1407 :   size_t size;
    4303         1407 :   char *p;
    4304              : 
    4305         1407 :   size = GET_MODE_SIZE (mode);
    4306         1407 :   if (size == 1)
    4307              :     return (rtx) data;
    4308              : 
    4309         1268 :   target = gen_memset_value_from_prev ((by_pieces_prev *) prev, mode);
    4310         1268 :   if (target != nullptr)
    4311              :     return target;
    4312              : 
    4313          723 :   if (VECTOR_MODE_P (mode))
    4314              :     {
    4315          366 :       gcc_assert (GET_MODE_INNER (mode) == QImode);
    4316              : 
    4317              :       /* vec_duplicate_optab is a precondition to pick a vector mode for
    4318              :          the memset expander.  */
    4319          183 :       insn_code icode = optab_handler (vec_duplicate_optab, mode);
    4320              : 
    4321          183 :       target = gen_reg_rtx (mode);
    4322          183 :       class expand_operand ops[2];
    4323          183 :       create_output_operand (&ops[0], target, mode);
    4324          183 :       create_input_operand (&ops[1], (rtx) data, QImode);
    4325          183 :       expand_insn (icode, 2, ops);
    4326          183 :       if (!rtx_equal_p (target, ops[0].value))
    4327            0 :         emit_move_insn (target, ops[0].value);
    4328              : 
    4329          183 :       return target;
    4330              :     }
    4331              : 
    4332          540 :   p = XALLOCAVEC (char, size);
    4333          540 :   memset (p, 1, size);
    4334          540 :   coeff = c_readstr (p, mode);
    4335              : 
    4336          540 :   target = convert_to_mode (mode, (rtx) data, 1);
    4337          540 :   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
    4338          540 :   return force_reg (mode, target);
    4339              : }
    4340              : 
    4341              : /* Expand expression EXP, which is a call to the memset builtin.  Return
    4342              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    4343              :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    4344              :    convenient).  */
    4345              : 
    4346              : rtx
    4347        62732 : expand_builtin_memset (tree exp, rtx target, machine_mode mode)
    4348              : {
    4349        62732 :   if (!validate_arglist (exp,
    4350              :                          POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4351              :     return NULL_RTX;
    4352              : 
    4353        62723 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4354        62723 :   tree val = CALL_EXPR_ARG (exp, 1);
    4355        62723 :   tree len = CALL_EXPR_ARG (exp, 2);
    4356              : 
    4357        62723 :   return expand_builtin_memset_args (dest, val, len, target, mode, exp);
    4358              : }
    4359              : 
    4360              : /* Check that store_by_pieces allows BITS + LEN (so that we don't
    4361              :    expand something too unreasonably long), and every power of 2 in
    4362              :    BITS.  It is assumed that LEN has already been tested by
    4363              :    itself.  */
    4364              : static bool
    4365        24868 : can_store_by_multiple_pieces (unsigned HOST_WIDE_INT bits,
    4366              :                               by_pieces_constfn constfun,
    4367              :                               void *constfundata, unsigned int align,
    4368              :                               bool memsetp,
    4369              :                               unsigned HOST_WIDE_INT len)
    4370              : {
    4371        24868 :   if (bits
    4372        24868 :       && !can_store_by_pieces (bits + len, constfun, constfundata,
    4373              :                                align, memsetp))
    4374              :     return false;
    4375              : 
    4376              :   /* BITS set are expected to be generally in the low range and
    4377              :      contiguous.  We do NOT want to repeat the test above in case BITS
    4378              :      has a single bit set, so we terminate the loop when BITS == BIT.
    4379              :      In the unlikely case that BITS has the MSB set, also terminate in
    4380              :      case BIT gets shifted out.  */
    4381         1122 :   for (unsigned HOST_WIDE_INT bit = 1; bit < bits && bit; bit <<= 1)
    4382              :     {
    4383          840 :       if ((bits & bit) == 0)
    4384          504 :         continue;
    4385              : 
    4386          336 :       if (!can_store_by_pieces (bit, constfun, constfundata,
    4387              :                                 align, memsetp))
    4388              :         return false;
    4389              :     }
    4390              : 
    4391              :   return true;
    4392              : }
    4393              : 
    4394              : /* Try to store VAL (or, if NULL_RTX, VALC) in LEN bytes starting at TO.
    4395              :    Return TRUE if successful, FALSE otherwise.  TO is assumed to be
    4396              :    aligned at an ALIGN-bits boundary.  LEN must be a multiple of
    4397              :    1<<CTZ_LEN between MIN_LEN and MAX_LEN.
    4398              : 
    4399              :    The strategy is to issue one store_by_pieces for each power of two,
    4400              :    from most to least significant, guarded by a test on whether there
    4401              :    are at least that many bytes left to copy in LEN.
    4402              : 
    4403              :    ??? Should we skip some powers of two in favor of loops?  Maybe start
    4404              :    at the max of TO/LEN/word alignment, at least when optimizing for
    4405              :    size, instead of ensuring O(log len) dynamic compares?  */
    4406              : 
    4407              : bool
    4408        22727 : try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len,
    4409              :                               unsigned HOST_WIDE_INT min_len,
    4410              :                               unsigned HOST_WIDE_INT max_len,
    4411              :                               rtx val, char valc, unsigned int align)
    4412              : {
    4413        22727 :   int max_bits = floor_log2 (max_len);
    4414        22727 :   int min_bits = floor_log2 (min_len);
    4415        22727 :   int sctz_len = ctz_len;
    4416              : 
    4417        22727 :   gcc_checking_assert (sctz_len >= 0);
    4418              : 
    4419        22727 :   if (val)
    4420          640 :     valc = 1;
    4421              : 
    4422              :   /* Bits more significant than TST_BITS are part of the shared prefix
    4423              :      in the binary representation of both min_len and max_len.  Since
    4424              :      they're identical, we don't need to test them in the loop.  */
    4425        22727 :   int tst_bits = (max_bits != min_bits ? max_bits
    4426        10115 :                   : floor_log2 (max_len ^ min_len));
    4427              : 
    4428              :   /* Save the pre-blksize values.  */
    4429        22727 :   int orig_max_bits = max_bits;
    4430        22727 :   int orig_tst_bits = tst_bits;
    4431              : 
    4432              :   /* Check whether it's profitable to start by storing a fixed BLKSIZE
    4433              :      bytes, to lower max_bits.  In the unlikely case of a constant LEN
    4434              :      (implied by identical MAX_LEN and MIN_LEN), we want to issue a
    4435              :      single store_by_pieces, but otherwise, select the minimum multiple
    4436              :      of the ALIGN (in bytes) and of the MCD of the possible LENs, that
    4437              :      brings MAX_LEN below TST_BITS, if that's lower than min_len.  */
    4438        22727 :   unsigned HOST_WIDE_INT blksize;
    4439        22727 :   if (max_len > min_len)
    4440              :     {
    4441        12625 :       unsigned HOST_WIDE_INT alrng = MAX (HOST_WIDE_INT_1U << ctz_len,
    4442              :                                           align / BITS_PER_UNIT);
    4443        12625 :       blksize = max_len - (HOST_WIDE_INT_1U << tst_bits) + alrng;
    4444        12625 :       blksize &= ~(alrng - 1);
    4445              :     }
    4446        10102 :   else if (max_len == min_len)
    4447              :     blksize = max_len;
    4448              :   else
    4449              :     /* Huh, max_len < min_len?  Punt.  See pr100843.c.  */
    4450              :     return false;
    4451        22726 :   if (min_len >= blksize
    4452              :       /* ??? Maybe try smaller fixed-prefix blksizes before
    4453              :          punting?  */
    4454        22726 :       && can_store_by_pieces (blksize, builtin_memset_read_str,
    4455              :                               &valc, align, true))
    4456              :     {
    4457          281 :       min_len -= blksize;
    4458          281 :       min_bits = floor_log2 (min_len);
    4459          281 :       max_len -= blksize;
    4460          281 :       max_bits = floor_log2 (max_len);
    4461              : 
    4462          281 :       tst_bits = (max_bits != min_bits ? max_bits
    4463          175 :                  : floor_log2 (max_len ^ min_len));
    4464              :     }
    4465              :   else
    4466              :     blksize = 0;
    4467              : 
    4468              :   /* Check that we can use store by pieces for the maximum store count
    4469              :      we may issue (initial fixed-size block, plus conditional
    4470              :      power-of-two-sized from max_bits to ctz_len.  */
    4471        22726 :   unsigned HOST_WIDE_INT xlenest = blksize;
    4472        22726 :   if (max_bits >= 0)
    4473        22551 :     xlenest += ((HOST_WIDE_INT_1U << max_bits) * 2
    4474        22551 :                 - (HOST_WIDE_INT_1U << ctz_len));
    4475        22726 :   bool max_loop = false;
    4476        22726 :   bool use_store_by_pieces = true;
    4477              :   /* Skip the test in case of overflow in xlenest.  It shouldn't
    4478              :      happen because of the way max_bits and blksize are related, but
    4479              :      it doesn't hurt to test.  */
    4480        22726 :   if (blksize > xlenest
    4481        22726 :       || !can_store_by_multiple_pieces (xlenest - blksize,
    4482              :                                         builtin_memset_read_str,
    4483              :                                         &valc, align, true, blksize))
    4484              :     {
    4485        22551 :       if (!(flag_inline_stringops & ILSOP_MEMSET))
    4486              :         return false;
    4487              : 
    4488         2067 :       for (max_bits = orig_max_bits;
    4489         2174 :            max_bits >= sctz_len;
    4490              :            --max_bits)
    4491              :         {
    4492         2174 :           xlenest = ((HOST_WIDE_INT_1U << max_bits) * 2
    4493         2174 :                      - (HOST_WIDE_INT_1U << ctz_len));
    4494              :           /* Check that blksize plus the bits to be stored as blocks
    4495              :              sized at powers of two can be stored by pieces.  This is
    4496              :              like the test above, but with smaller max_bits.  Skip
    4497              :              orig_max_bits (it would be redundant).  Also skip in case
    4498              :              of overflow.  */
    4499         2174 :           if (max_bits < orig_max_bits
    4500         2067 :               && xlenest + blksize >= xlenest
    4501         4241 :               && can_store_by_multiple_pieces (xlenest,
    4502              :                                                builtin_memset_read_str,
    4503              :                                                &valc, align, true, blksize))
    4504              :             {
    4505              :               max_loop = true;
    4506              :               break;
    4507              :             }
    4508         2067 :           if (blksize
    4509         2067 :               && can_store_by_multiple_pieces (xlenest,
    4510              :                                                builtin_memset_read_str,
    4511              :                                                &valc, align, true, 0))
    4512              :             {
    4513            0 :               max_len += blksize;
    4514            0 :               min_len += blksize;
    4515            0 :               tst_bits = orig_tst_bits;
    4516            0 :               blksize = 0;
    4517            0 :               max_loop = true;
    4518            0 :               break;
    4519              :             }
    4520         2067 :           if (max_bits == sctz_len)
    4521              :             {
    4522              :               /* We'll get here if can_store_by_pieces refuses to
    4523              :                  store even a single QImode.  We'll fall back to
    4524              :                  QImode stores then.  */
    4525           98 :               if (!sctz_len)
    4526              :                 {
    4527              :                   blksize = 0;
    4528              :                   max_loop = true;
    4529              :                   use_store_by_pieces = false;
    4530              :                   break;
    4531              :                 }
    4532           98 :               --sctz_len;
    4533           98 :               --ctz_len;
    4534              :             }
    4535              :         }
    4536          107 :       if (!max_loop)
    4537              :         return false;
    4538              :       /* If the boundaries are such that min and max may run a
    4539              :          different number of trips in the initial loop, the remainder
    4540              :          needs not be between the moduli, so set tst_bits to cover all
    4541              :          bits.  Otherwise, if the trip counts are the same, max_len
    4542              :          has the common prefix, and the previously-computed tst_bits
    4543              :          is usable.  */
    4544          107 :       if (max_len >> max_bits > min_len >> max_bits)
    4545           64 :         tst_bits = max_bits;
    4546              :     }
    4547              : 
    4548          282 :   by_pieces_constfn constfun;
    4549          282 :   void *constfundata;
    4550          282 :   if (val)
    4551              :     {
    4552            1 :       constfun = builtin_memset_gen_str;
    4553            1 :       constfundata = val = force_reg (TYPE_MODE (unsigned_char_type_node),
    4554              :                                       val);
    4555              :     }
    4556              :   else
    4557              :     {
    4558              :       constfun = builtin_memset_read_str;
    4559              :       constfundata = &valc;
    4560              :     }
    4561              : 
    4562          282 :   rtx ptr = copy_addr_to_reg (XEXP (to, 0));
    4563          282 :   rtx rem = copy_to_mode_reg (ptr_mode, convert_to_mode (ptr_mode, len, 0));
    4564          282 :   to = replace_equiv_address (to, ptr);
    4565          282 :   set_mem_align (to, align);
    4566              : 
    4567          282 :   if (blksize)
    4568              :     {
    4569          363 :       to = store_by_pieces (to, blksize,
    4570              :                             constfun, constfundata,
    4571              :                             align, true,
    4572              :                             max_len != 0 ? RETURN_END : RETURN_BEGIN);
    4573          189 :       if (max_len == 0)
    4574              :         return true;
    4575              : 
    4576              :       /* Adjust PTR, TO and REM.  Since TO's address is likely
    4577              :          PTR+offset, we have to replace it.  */
    4578           15 :       emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
    4579           15 :       to = replace_equiv_address (to, ptr);
    4580           15 :       rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
    4581           15 :       emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
    4582              :     }
    4583              : 
    4584              :   /* Iterate over power-of-two block sizes from the maximum length to
    4585              :      the least significant bit possibly set in the length.  */
    4586          493 :   for (int i = max_bits; i >= sctz_len; i--)
    4587              :     {
    4588          385 :       rtx_code_label *loop_label = NULL;
    4589          385 :       rtx_code_label *label = NULL;
    4590              : 
    4591          385 :       blksize = HOST_WIDE_INT_1U << i;
    4592              : 
    4593              :       /* If we're past the bits shared between min_ and max_len, expand
    4594              :          a test on the dynamic length, comparing it with the
    4595              :          BLKSIZE.  */
    4596          385 :       if (i <= tst_bits)
    4597              :         {
    4598          275 :           label = gen_label_rtx ();
    4599          275 :           emit_cmp_and_jump_insns (rem, GEN_INT (blksize), LT, NULL,
    4600              :                                    ptr_mode, 1, label,
    4601              :                                    profile_probability::even ());
    4602              :         }
    4603              :       /* If we are at a bit that is in the prefix shared by min_ and
    4604              :          max_len, skip the current BLKSIZE if the bit is clear, but do
    4605              :          not skip the loop, even if it doesn't require
    4606              :          prechecking.  */
    4607          110 :       else if ((max_len & blksize) == 0
    4608           69 :                && !(max_loop && i == max_bits))
    4609           39 :         continue;
    4610              : 
    4611          346 :       if (max_loop && i == max_bits)
    4612              :         {
    4613          107 :           loop_label = gen_label_rtx ();
    4614          107 :           emit_label (loop_label);
    4615              :           /* Since we may run this multiple times, don't assume we
    4616              :              know anything about the offset.  */
    4617          107 :           clear_mem_offset (to);
    4618              :         }
    4619              : 
    4620          346 :       bool update_needed = i != sctz_len || loop_label;
    4621          346 :       rtx next_ptr = NULL_RTX;
    4622          346 :       if (!use_store_by_pieces)
    4623              :         {
    4624            0 :           gcc_checking_assert (blksize == 1);
    4625            0 :           if (!val)
    4626            0 :             val = gen_int_mode (valc, QImode);
    4627            0 :           to = change_address (to, QImode, 0);
    4628            0 :           emit_move_insn (to, val);
    4629            0 :           if (update_needed)
    4630            0 :             next_ptr = plus_constant (GET_MODE (ptr), ptr, blksize);
    4631              :         }
    4632              :       else
    4633              :         {
    4634              :           /* Issue a store of BLKSIZE bytes.  */
    4635          404 :           to = store_by_pieces (to, blksize,
    4636              :                                 constfun, constfundata,
    4637              :                                 align, true,
    4638              :                                 update_needed ? RETURN_END : RETURN_BEGIN);
    4639          346 :           next_ptr = XEXP (to, 0);
    4640              :         }
    4641              :       /* Adjust REM and PTR, unless this is the last iteration.  */
    4642          346 :       if (update_needed)
    4643              :         {
    4644          288 :           emit_move_insn (ptr, force_operand (next_ptr, NULL_RTX));
    4645          288 :           to = replace_equiv_address (to, ptr);
    4646          288 :           rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
    4647          288 :           emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
    4648              :         }
    4649              : 
    4650          288 :       if (loop_label)
    4651          107 :         emit_cmp_and_jump_insns (rem, GEN_INT (blksize), GE, NULL,
    4652              :                                  ptr_mode, 1, loop_label,
    4653              :                                  profile_probability::likely ());
    4654              : 
    4655          346 :       if (label)
    4656              :         {
    4657          275 :           emit_label (label);
    4658              : 
    4659              :           /* Given conditional stores, the offset can no longer be
    4660              :              known, so clear it.  */
    4661          275 :           clear_mem_offset (to);
    4662              :         }
    4663              :     }
    4664              : 
    4665              :   return true;
    4666              : }
    4667              : 
    4668              : /* Helper function to do the actual work for expand_builtin_memset.  The
    4669              :    arguments to the builtin_memset call DEST, VAL, and LEN are broken out
    4670              :    so that this can also be called without constructing an actual CALL_EXPR.
    4671              :    The other arguments and return value are the same as for
    4672              :    expand_builtin_memset.  */
    4673              : 
    4674              : static rtx
    4675        62723 : expand_builtin_memset_args (tree dest, tree val, tree len,
    4676              :                             rtx target, machine_mode mode, tree orig_exp)
    4677              : {
    4678        62723 :   tree fndecl, fn;
    4679        62723 :   enum built_in_function fcode;
    4680        62723 :   machine_mode val_mode;
    4681        62723 :   char c;
    4682        62723 :   unsigned int dest_align;
    4683        62723 :   rtx dest_mem, dest_addr, len_rtx;
    4684        62723 :   HOST_WIDE_INT expected_size = -1;
    4685        62723 :   unsigned int expected_align = 0;
    4686        62723 :   unsigned HOST_WIDE_INT min_size;
    4687        62723 :   unsigned HOST_WIDE_INT max_size;
    4688        62723 :   unsigned HOST_WIDE_INT probable_max_size;
    4689              : 
    4690        62723 :   dest_align = get_pointer_alignment (dest);
    4691              : 
    4692              :   /* If DEST is not a pointer type, don't do this operation in-line.  */
    4693        62723 :   if (dest_align == 0)
    4694              :     return NULL_RTX;
    4695              : 
    4696        62723 :   if (currently_expanding_gimple_stmt)
    4697        62723 :     stringop_block_profile (currently_expanding_gimple_stmt,
    4698              :                             &expected_align, &expected_size);
    4699              : 
    4700        62723 :   if (expected_align < dest_align)
    4701        62715 :     expected_align = dest_align;
    4702              : 
    4703              :   /* If the LEN parameter is zero, return DEST.  */
    4704        62723 :   if (integer_zerop (len))
    4705              :     {
    4706              :       /* Evaluate and ignore VAL in case it has side-effects.  */
    4707            0 :       expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
    4708            0 :       return expand_expr (dest, target, mode, EXPAND_NORMAL);
    4709              :     }
    4710              : 
    4711              :   /* Stabilize the arguments in case we fail.  */
    4712        62723 :   dest = builtin_save_expr (dest);
    4713        62723 :   val = builtin_save_expr (val);
    4714        62723 :   len = builtin_save_expr (len);
    4715              : 
    4716        62723 :   len_rtx = expand_normal (len);
    4717        62723 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    4718              :                         &probable_max_size);
    4719        62723 :   dest_mem = get_memory_rtx (dest, len, true);
    4720        62723 :   val_mode = TYPE_MODE (unsigned_char_type_node);
    4721              : 
    4722        62723 :   if (TREE_CODE (val) != INTEGER_CST
    4723        62723 :       || target_char_cast (val, &c))
    4724              :     {
    4725         1727 :       rtx val_rtx;
    4726              : 
    4727         1727 :       val_rtx = expand_normal (val);
    4728         1727 :       val_rtx = convert_to_mode (val_mode, val_rtx, 0);
    4729              : 
    4730              :       /* Assume that we can memset by pieces if we can store
    4731              :        * the coefficients by pieces (in the required modes).
    4732              :        * We can't pass builtin_memset_gen_str as that emits RTL.  */
    4733         1727 :       c = 1;
    4734         1727 :       if (tree_fits_uhwi_p (len)
    4735         1727 :           && can_store_by_pieces (tree_to_uhwi (len),
    4736              :                                   builtin_memset_read_str, &c, dest_align,
    4737              :                                   true))
    4738              :         {
    4739          726 :           val_rtx = force_reg (val_mode, val_rtx);
    4740          726 :           store_by_pieces (dest_mem, tree_to_uhwi (len),
    4741              :                            builtin_memset_gen_str, val_rtx, dest_align,
    4742              :                            true, RETURN_BEGIN);
    4743              :         }
    4744         1001 :       else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
    4745              :                                         dest_align, expected_align,
    4746              :                                         expected_size, min_size, max_size,
    4747              :                                         probable_max_size)
    4748         1001 :                && !try_store_by_multiple_pieces (dest_mem, len_rtx,
    4749              :                                                  tree_ctz (len),
    4750              :                                                  min_size, max_size,
    4751              :                                                  val_rtx, 0,
    4752              :                                                  dest_align))
    4753          639 :         goto do_libcall;
    4754              : 
    4755         1088 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4756         1088 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4757         1088 :       return dest_mem;
    4758              :     }
    4759              : 
    4760        60996 :   if (c)
    4761              :     {
    4762        13492 :       if (tree_fits_uhwi_p (len)
    4763        13492 :           && can_store_by_pieces (tree_to_uhwi (len),
    4764              :                                   builtin_memset_read_str, &c, dest_align,
    4765              :                                   true))
    4766         5752 :         store_by_pieces (dest_mem, tree_to_uhwi (len),
    4767              :                          builtin_memset_read_str, &c, dest_align, true,
    4768              :                          RETURN_BEGIN);
    4769         9661 :       else if (!set_storage_via_setmem (dest_mem, len_rtx,
    4770         7740 :                                         gen_int_mode (c, val_mode),
    4771              :                                         dest_align, expected_align,
    4772              :                                         expected_size, min_size, max_size,
    4773              :                                         probable_max_size)
    4774         7740 :                && !try_store_by_multiple_pieces (dest_mem, len_rtx,
    4775              :                                                  tree_ctz (len),
    4776              :                                                  min_size, max_size,
    4777              :                                                  NULL_RTX, c,
    4778              :                                                  dest_align))
    4779         5819 :         goto do_libcall;
    4780              : 
    4781         7673 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4782         7673 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4783         7673 :       return dest_mem;
    4784              :     }
    4785              : 
    4786        47504 :   set_mem_align (dest_mem, dest_align);
    4787        95008 :   dest_addr = clear_storage_hints (dest_mem, len_rtx,
    4788        47504 :                                    CALL_EXPR_TAILCALL (orig_exp)
    4789              :                                    ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
    4790              :                                    expected_align, expected_size,
    4791              :                                    min_size, max_size,
    4792              :                                    probable_max_size, tree_ctz (len));
    4793              : 
    4794        47504 :   if (dest_addr == 0)
    4795              :     {
    4796        37445 :       dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4797        37445 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    4798              :     }
    4799              : 
    4800              :   return dest_addr;
    4801              : 
    4802         6458 :  do_libcall:
    4803         6458 :   fndecl = get_callee_fndecl (orig_exp);
    4804         6458 :   fcode = DECL_FUNCTION_CODE (fndecl);
    4805         6458 :   if (fcode == BUILT_IN_MEMSET)
    4806         6458 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
    4807              :                                 dest, val, len);
    4808            0 :   else if (fcode == BUILT_IN_BZERO)
    4809            0 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
    4810              :                                 dest, len);
    4811              :   else
    4812            0 :     gcc_unreachable ();
    4813         6458 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    4814         6458 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
    4815         6458 :   return expand_call (fn, target, target == const0_rtx);
    4816              : }
    4817              : 
    4818              : /* Expand expression EXP, which is a call to the bzero builtin.  Return
    4819              :    NULL_RTX if we failed the caller should emit a normal call.  */
    4820              : 
    4821              : static rtx
    4822            0 : expand_builtin_bzero (tree exp)
    4823              : {
    4824            0 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4825              :     return NULL_RTX;
    4826              : 
    4827            0 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4828            0 :   tree size = CALL_EXPR_ARG (exp, 1);
    4829              : 
    4830              :   /* New argument list transforming bzero(ptr x, int y) to
    4831              :      memset(ptr x, int 0, size_t y).   This is done this way
    4832              :      so that if it isn't expanded inline, we fallback to
    4833              :      calling bzero instead of memset.  */
    4834              : 
    4835            0 :   location_t loc = EXPR_LOCATION (exp);
    4836              : 
    4837            0 :   return expand_builtin_memset_args (dest, integer_zero_node,
    4838              :                                      fold_convert_loc (loc,
    4839              :                                                        size_type_node, size),
    4840            0 :                                      const0_rtx, VOIDmode, exp);
    4841              : }
    4842              : 
    4843              : /* Try to expand cmpstr operation ICODE with the given operands.
    4844              :    Return the result rtx on success, otherwise return null.  */
    4845              : 
    4846              : static rtx
    4847            0 : expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
    4848              :                HOST_WIDE_INT align)
    4849              : {
    4850            0 :   machine_mode insn_mode = insn_data[icode].operand[0].mode;
    4851              : 
    4852            0 :   if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
    4853              :     target = NULL_RTX;
    4854              : 
    4855            0 :   class expand_operand ops[4];
    4856            0 :   create_output_operand (&ops[0], target, insn_mode);
    4857            0 :   create_fixed_operand (&ops[1], arg1_rtx);
    4858            0 :   create_fixed_operand (&ops[2], arg2_rtx);
    4859            0 :   create_integer_operand (&ops[3], align);
    4860            0 :   if (maybe_expand_insn (icode, 4, ops))
    4861            0 :     return ops[0].value;
    4862              :   return NULL_RTX;
    4863              : }
    4864              : 
    4865              : /* Expand expression EXP, which is a call to the memcmp built-in function.
    4866              :    Return NULL_RTX if we failed and the caller should emit a normal call,
    4867              :    otherwise try to get the result in TARGET, if convenient.
    4868              :    RESULT_EQ is true if we can relax the returned value to be either zero
    4869              :    or nonzero, without caring about the sign.  */
    4870              : 
    4871              : static rtx
    4872       107259 : expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
    4873              : {
    4874       107259 :   if (!validate_arglist (exp,
    4875              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4876              :     return NULL_RTX;
    4877              : 
    4878       107255 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    4879       107255 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    4880       107255 :   tree len = CALL_EXPR_ARG (exp, 2);
    4881              : 
    4882              :   /* Due to the performance benefit, always inline the calls first
    4883              :      when result_eq is false.  */
    4884       107255 :   rtx result = NULL_RTX;
    4885       107255 :   enum built_in_function fcode = DECL_FUNCTION_CODE (get_callee_fndecl (exp));
    4886       107255 :   if (!result_eq && fcode != BUILT_IN_BCMP)
    4887              :     {
    4888        15315 :       result = inline_expand_builtin_bytecmp (exp, target);
    4889        15315 :       if (result)
    4890              :         return result;
    4891              :     }
    4892              : 
    4893       107237 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    4894       107237 :   location_t loc = EXPR_LOCATION (exp);
    4895              : 
    4896       107237 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    4897       107237 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    4898              : 
    4899              :   /* If we don't have POINTER_TYPE, call the function.  */
    4900       107237 :   if (arg1_align == 0 || arg2_align == 0)
    4901              :     return NULL_RTX;
    4902              : 
    4903       107237 :   rtx arg1_rtx = get_memory_rtx (arg1, len, false);
    4904       107237 :   rtx arg2_rtx = get_memory_rtx (arg2, len, false);
    4905       107237 :   rtx len_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
    4906              : 
    4907              :   /* Set MEM_SIZE as appropriate.  */
    4908       107237 :   if (CONST_INT_P (len_rtx))
    4909              :     {
    4910        81477 :       set_mem_size (arg1_rtx, INTVAL (len_rtx));
    4911        81477 :       set_mem_size (arg2_rtx, INTVAL (len_rtx));
    4912              :     }
    4913              : 
    4914       107237 :   by_pieces_constfn constfn = NULL;
    4915              : 
    4916              :   /* Try to get the byte representation of the constant ARG2 (or, only
    4917              :      when the function's result is used for equality to zero, ARG1)
    4918              :      points to, with its byte size in NBYTES.  */
    4919       107237 :   unsigned HOST_WIDE_INT nbytes;
    4920       107237 :   const char *rep = getbyterep (arg2, &nbytes);
    4921       107237 :   if (result_eq && rep == NULL)
    4922              :     {
    4923              :       /* For equality to zero the arguments are interchangeable.  */
    4924        63851 :       rep = getbyterep (arg1, &nbytes);
    4925        63851 :       if (rep != NULL)
    4926              :         std::swap (arg1_rtx, arg2_rtx);
    4927              :     }
    4928              : 
    4929              :   /* If the function's constant bound LEN_RTX is less than or equal
    4930              :      to the byte size of the representation of the constant argument,
    4931              :      and if block move would be done by pieces, we can avoid loading
    4932              :      the bytes from memory and only store the computed constant result.  */
    4933        43386 :   if (rep
    4934        30227 :       && CONST_INT_P (len_rtx)
    4935        30072 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes)
    4936       107237 :     constfn = builtin_memcpy_read_str;
    4937              : 
    4938       214474 :   result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
    4939       107237 :                                  TREE_TYPE (len), target,
    4940              :                                  result_eq, constfn,
    4941              :                                  const_cast<char *> (rep),
    4942              :                                  tree_ctz (len));
    4943              : 
    4944       107237 :   if (result)
    4945              :     {
    4946              :       /* Return the value in the proper mode for this function.  */
    4947        69002 :       if (GET_MODE (result) == mode)
    4948              :         return result;
    4949              : 
    4950            0 :       if (target != 0)
    4951              :         {
    4952            0 :           convert_move (target, result, 0);
    4953            0 :           return target;
    4954              :         }
    4955              : 
    4956            0 :       return convert_to_mode (mode, result, 0);
    4957              :     }
    4958              : 
    4959              :   return NULL_RTX;
    4960              : }
    4961              : 
    4962              : /* Expand expression EXP, which is a call to the strcmp builtin.  Return NULL_RTX
    4963              :    if we failed the caller should emit a normal call, otherwise try to get
    4964              :    the result in TARGET, if convenient.  */
    4965              : 
    4966              : static rtx
    4967       127960 : expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
    4968              : {
    4969       127960 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    4970              :     return NULL_RTX;
    4971              : 
    4972       127945 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    4973       127945 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    4974              : 
    4975              :   /* Due to the performance benefit, always inline the calls first.  */
    4976       127945 :   rtx result = NULL_RTX;
    4977       127945 :   result = inline_expand_builtin_bytecmp (exp, target);
    4978       127945 :   if (result)
    4979              :     return result;
    4980              : 
    4981       127546 :   insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
    4982       127546 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    4983       127546 :   if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
    4984              :     return NULL_RTX;
    4985              : 
    4986       127546 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    4987       127546 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    4988              : 
    4989              :   /* If we don't have POINTER_TYPE, call the function.  */
    4990       127546 :   if (arg1_align == 0 || arg2_align == 0)
    4991              :     return NULL_RTX;
    4992              : 
    4993              :   /* Stabilize the arguments in case gen_cmpstr(n)si fail.  */
    4994       127546 :   arg1 = builtin_save_expr (arg1);
    4995       127546 :   arg2 = builtin_save_expr (arg2);
    4996              : 
    4997       127546 :   rtx arg1_rtx = get_memory_rtx (arg1, NULL, false);
    4998       127546 :   rtx arg2_rtx = get_memory_rtx (arg2, NULL, false);
    4999              : 
    5000              :   /* Try to call cmpstrsi.  */
    5001       127546 :   if (cmpstr_icode != CODE_FOR_nothing)
    5002            0 :     result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
    5003            0 :                             MIN (arg1_align, arg2_align));
    5004              : 
    5005              :   /* Try to determine at least one length and call cmpstrnsi.  */
    5006       127546 :   if (!result && cmpstrn_icode != CODE_FOR_nothing)
    5007              :     {
    5008       127546 :       tree len;
    5009       127546 :       rtx arg3_rtx;
    5010              : 
    5011       127546 :       tree len1 = c_strlen (arg1, 1);
    5012       127546 :       tree len2 = c_strlen (arg2, 1);
    5013              : 
    5014       127546 :       if (len1)
    5015          224 :         len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
    5016       127546 :       if (len2)
    5017       125918 :         len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
    5018              : 
    5019              :       /* If we don't have a constant length for the first, use the length
    5020              :          of the second, if we know it.  We don't require a constant for
    5021              :          this case; some cost analysis could be done if both are available
    5022              :          but neither is constant.  For now, assume they're equally cheap,
    5023              :          unless one has side effects.  If both strings have constant lengths,
    5024              :          use the smaller.  */
    5025              : 
    5026       127546 :       if (!len1)
    5027              :         len = len2;
    5028          224 :       else if (!len2)
    5029              :         len = len1;
    5030           17 :       else if (TREE_SIDE_EFFECTS (len1))
    5031              :         len = len2;
    5032           17 :       else if (TREE_SIDE_EFFECTS (len2))
    5033              :         len = len1;
    5034           17 :       else if (TREE_CODE (len1) != INTEGER_CST)
    5035              :         len = len2;
    5036           17 :       else if (TREE_CODE (len2) != INTEGER_CST)
    5037              :         len = len1;
    5038           10 :       else if (tree_int_cst_lt (len1, len2))
    5039              :         len = len1;
    5040              :       else
    5041       127546 :         len = len2;
    5042              : 
    5043              :       /* If both arguments have side effects, we cannot optimize.  */
    5044       127546 :       if (len && !TREE_SIDE_EFFECTS (len))
    5045              :         {
    5046       126125 :           arg3_rtx = expand_normal (len);
    5047       126125 :           result = expand_cmpstrn_or_cmpmem
    5048       126125 :             (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
    5049       126125 :              arg3_rtx, MIN (arg1_align, arg2_align));
    5050              :         }
    5051              :     }
    5052              : 
    5053       127546 :   tree fndecl = get_callee_fndecl (exp);
    5054       127546 :   if (result)
    5055              :     {
    5056              :       /* Return the value in the proper mode for this function.  */
    5057           52 :       machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    5058           52 :       if (GET_MODE (result) == mode)
    5059              :         return result;
    5060            0 :       if (target == 0)
    5061            0 :         return convert_to_mode (mode, result, 0);
    5062            0 :       convert_move (target, result, 0);
    5063            0 :       return target;
    5064              :     }
    5065              : 
    5066              :   /* Expand the library call ourselves using a stabilized argument
    5067              :      list to avoid re-evaluating the function's arguments twice.  */
    5068       127494 :   tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
    5069       127494 :   copy_warning (fn, exp);
    5070       127494 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    5071       127494 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    5072       127494 :   return expand_call (fn, target, target == const0_rtx);
    5073              : }
    5074              : 
    5075              : /* Expand expression EXP, which is a call to the strncmp builtin. Return
    5076              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    5077              :    try to get the result in TARGET, if convenient.  */
    5078              : 
    5079              : static rtx
    5080         2027 : expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
    5081              :                         ATTRIBUTE_UNUSED machine_mode mode)
    5082              : {
    5083         2027 :   if (!validate_arglist (exp,
    5084              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    5085              :     return NULL_RTX;
    5086              : 
    5087         2021 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    5088         2021 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    5089         2021 :   tree arg3 = CALL_EXPR_ARG (exp, 2);
    5090              : 
    5091         2021 :   location_t loc = EXPR_LOCATION (exp);
    5092         2021 :   tree len1 = c_strlen (arg1, 1);
    5093         2021 :   tree len2 = c_strlen (arg2, 1);
    5094              : 
    5095              :   /* Due to the performance benefit, always inline the calls first.  */
    5096         2021 :   rtx result = NULL_RTX;
    5097         2021 :   result = inline_expand_builtin_bytecmp (exp, target);
    5098         2021 :   if (result)
    5099              :     return result;
    5100              : 
    5101              :   /* If c_strlen can determine an expression for one of the string
    5102              :      lengths, and it doesn't have side effects, then emit cmpstrnsi
    5103              :      using length MIN(strlen(string)+1, arg3).  */
    5104         1803 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    5105         1803 :   if (cmpstrn_icode == CODE_FOR_nothing)
    5106              :     return NULL_RTX;
    5107              : 
    5108         1803 :   tree len;
    5109              : 
    5110         1803 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    5111         1803 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    5112              : 
    5113         1803 :   if (len1)
    5114          160 :     len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
    5115         1803 :   if (len2)
    5116          674 :     len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
    5117              : 
    5118         1803 :   tree len3 = fold_convert_loc (loc, sizetype, arg3);
    5119              : 
    5120              :   /* If we don't have a constant length for the first, use the length
    5121              :      of the second, if we know it.  If neither string is constant length,
    5122              :      use the given length argument.  We don't require a constant for
    5123              :      this case; some cost analysis could be done if both are available
    5124              :      but neither is constant.  For now, assume they're equally cheap,
    5125              :      unless one has side effects.  If both strings have constant lengths,
    5126              :      use the smaller.  */
    5127              : 
    5128         1803 :   if (!len1 && !len2)
    5129              :     len = len3;
    5130          717 :   else if (!len1)
    5131              :     len = len2;
    5132          160 :   else if (!len2)
    5133              :     len = len1;
    5134          117 :   else if (TREE_SIDE_EFFECTS (len1))
    5135              :     len = len2;
    5136          117 :   else if (TREE_SIDE_EFFECTS (len2))
    5137              :     len = len1;
    5138          117 :   else if (TREE_CODE (len1) != INTEGER_CST)
    5139              :     len = len2;
    5140          117 :   else if (TREE_CODE (len2) != INTEGER_CST)
    5141              :     len = len1;
    5142          117 :   else if (tree_int_cst_lt (len1, len2))
    5143              :     len = len1;
    5144              :   else
    5145         1803 :     len = len2;
    5146              : 
    5147              :   /* If we are not using the given length, we must incorporate it here.
    5148              :      The actual new length parameter will be MIN(len,arg3) in this case.  */
    5149         1803 :   if (len != len3)
    5150              :     {
    5151          717 :       len = fold_convert_loc (loc, sizetype, len);
    5152          717 :       len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
    5153              :     }
    5154         1803 :   rtx arg1_rtx = get_memory_rtx (arg1, len, false);
    5155         1803 :   rtx arg2_rtx = get_memory_rtx (arg2, len, false);
    5156         1803 :   rtx arg3_rtx = expand_normal (len);
    5157         1803 :   result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
    5158         1803 :                                      arg2_rtx, TREE_TYPE (len), arg3_rtx,
    5159         1803 :                                      MIN (arg1_align, arg2_align));
    5160              : 
    5161         1803 :   tree fndecl = get_callee_fndecl (exp);
    5162         1803 :   if (result)
    5163              :     {
    5164              :       /* Return the value in the proper mode for this function.  */
    5165           17 :       mode = TYPE_MODE (TREE_TYPE (exp));
    5166           17 :       if (GET_MODE (result) == mode)
    5167              :         return result;
    5168            0 :       if (target == 0)
    5169            0 :         return convert_to_mode (mode, result, 0);
    5170            0 :       convert_move (target, result, 0);
    5171            0 :       return target;
    5172              :     }
    5173              : 
    5174              :   /* Expand the library call ourselves using a stabilized argument
    5175              :      list to avoid re-evaluating the function's arguments twice.  */
    5176         1786 :   tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
    5177         1786 :   copy_warning (call, exp);
    5178         1786 :   gcc_assert (TREE_CODE (call) == CALL_EXPR);
    5179         1786 :   CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
    5180         1786 :   return expand_call (call, target, target == const0_rtx);
    5181              : }
    5182              : 
    5183              : /* Expand a call to __builtin_saveregs, generating the result in TARGET,
    5184              :    if that's convenient.  */
    5185              : 
    5186              : rtx
    5187            0 : expand_builtin_saveregs (void)
    5188              : {
    5189            0 :   rtx val;
    5190            0 :   rtx_insn *seq;
    5191              : 
    5192              :   /* Don't do __builtin_saveregs more than once in a function.
    5193              :      Save the result of the first call and reuse it.  */
    5194            0 :   if (saveregs_value != 0)
    5195              :     return saveregs_value;
    5196              : 
    5197              :   /* When this function is called, it means that registers must be
    5198              :      saved on entry to this function.  So we migrate the call to the
    5199              :      first insn of this function.  */
    5200              : 
    5201            0 :   start_sequence ();
    5202              : 
    5203              :   /* Do whatever the machine needs done in this case.  */
    5204            0 :   val = targetm.calls.expand_builtin_saveregs ();
    5205              : 
    5206            0 :   seq = end_sequence ();
    5207              : 
    5208            0 :   saveregs_value = val;
    5209              : 
    5210              :   /* Put the insns after the NOTE that starts the function.  If this
    5211              :      is inside a start_sequence, make the outer-level insn chain current, so
    5212              :      the code is placed at the start of the function.  */
    5213            0 :   push_topmost_sequence ();
    5214            0 :   emit_insn_after (seq, entry_of_function ());
    5215            0 :   pop_topmost_sequence ();
    5216              : 
    5217            0 :   return val;
    5218              : }
    5219              : 
    5220              : /* Expand a call to __builtin_next_arg.  */
    5221              : 
    5222              : static rtx
    5223        21245 : expand_builtin_next_arg (void)
    5224              : {
    5225              :   /* Checking arguments is already done in fold_builtin_next_arg
    5226              :      that must be called before this function.  */
    5227        21245 :   return expand_binop (ptr_mode, add_optab,
    5228              :                        crtl->args.internal_arg_pointer,
    5229              :                        crtl->args.arg_offset_rtx,
    5230        21245 :                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
    5231              : }
    5232              : 
    5233              : /* Make it easier for the backends by protecting the valist argument
    5234              :    from multiple evaluations.  */
    5235              : 
    5236              : static tree
    5237        21567 : stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
    5238              : {
    5239        21567 :   tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
    5240              : 
    5241              :   /* The current way of determining the type of valist is completely
    5242              :      bogus.  We should have the information on the va builtin instead.  */
    5243        21567 :   if (!vatype)
    5244        21443 :     vatype = targetm.fn_abi_va_list (cfun->decl);
    5245              : 
    5246        21567 :   if (TREE_CODE (vatype) == ARRAY_TYPE)
    5247              :     {
    5248        15899 :       if (TREE_SIDE_EFFECTS (valist))
    5249            0 :         valist = save_expr (valist);
    5250              : 
    5251              :       /* For this case, the backends will be expecting a pointer to
    5252              :          vatype, but it's possible we've actually been given an array
    5253              :          (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
    5254              :          So fix it.  */
    5255        15899 :       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
    5256              :         {
    5257            0 :           tree p1 = build_pointer_type (TREE_TYPE (vatype));
    5258            0 :           valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
    5259              :         }
    5260              :     }
    5261              :   else
    5262              :     {
    5263         5668 :       tree pt = build_pointer_type (vatype);
    5264              : 
    5265         5668 :       if (! needs_lvalue)
    5266              :         {
    5267            6 :           if (! TREE_SIDE_EFFECTS (valist))
    5268              :             return valist;
    5269              : 
    5270            0 :           valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
    5271            0 :           TREE_SIDE_EFFECTS (valist) = 1;
    5272              :         }
    5273              : 
    5274         5662 :       if (TREE_SIDE_EFFECTS (valist))
    5275            0 :         valist = save_expr (valist);
    5276         5662 :       valist = fold_build2_loc (loc, MEM_REF,
    5277              :                                 vatype, valist, build_int_cst (pt, 0));
    5278              :     }
    5279              : 
    5280              :   return valist;
    5281              : }
    5282              : 
    5283              : /* The "standard" definition of va_list is void*.  */
    5284              : 
    5285              : tree
    5286            0 : std_build_builtin_va_list (void)
    5287              : {
    5288            0 :   return ptr_type_node;
    5289              : }
    5290              : 
    5291              : /* The "standard" abi va_list is va_list_type_node.  */
    5292              : 
    5293              : tree
    5294            0 : std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
    5295              : {
    5296            0 :   return va_list_type_node;
    5297              : }
    5298              : 
    5299              : /* The "standard" type of va_list is va_list_type_node.  */
    5300              : 
    5301              : tree
    5302          502 : std_canonical_va_list_type (tree type)
    5303              : {
    5304          502 :   tree wtype, htype;
    5305              : 
    5306          502 :   wtype = va_list_type_node;
    5307          502 :   htype = type;
    5308              : 
    5309          502 :   if (TREE_CODE (wtype) == ARRAY_TYPE)
    5310              :     {
    5311              :       /* If va_list is an array type, the argument may have decayed
    5312              :          to a pointer type, e.g. by being passed to another function.
    5313              :          In that case, unwrap both types so that we can compare the
    5314              :          underlying records.  */
    5315            0 :       if (TREE_CODE (htype) == ARRAY_TYPE
    5316            0 :           || POINTER_TYPE_P (htype))
    5317              :         {
    5318            0 :           wtype = TREE_TYPE (wtype);
    5319            0 :           htype = TREE_TYPE (htype);
    5320              :         }
    5321              :     }
    5322          502 :   if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
    5323          332 :     return va_list_type_node;
    5324              : 
    5325              :   return NULL_TREE;
    5326              : }
    5327              : 
    5328              : /* The "standard" implementation of va_start: just assign `nextarg' to
    5329              :    the variable.  */
    5330              : 
    5331              : void
    5332         5658 : std_expand_builtin_va_start (tree valist, rtx nextarg)
    5333              : {
    5334         5658 :   rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
    5335         5658 :   convert_move (va_r, nextarg, 0);
    5336         5658 : }
    5337              : 
    5338              : /* Expand EXP, a call to __builtin_va_start.  */
    5339              : 
    5340              : static rtx
    5341        21087 : expand_builtin_va_start (tree exp)
    5342              : {
    5343        21087 :   rtx nextarg;
    5344        21087 :   tree valist;
    5345        21087 :   location_t loc = EXPR_LOCATION (exp);
    5346              : 
    5347        21087 :   if (call_expr_nargs (exp) < 2)
    5348              :     {
    5349            0 :       error_at (loc, "too few arguments to function %<va_start%>");
    5350            0 :       return const0_rtx;
    5351              :     }
    5352              : 
    5353        21087 :   if (fold_builtin_next_arg (exp, true))
    5354            0 :     return const0_rtx;
    5355              : 
    5356        21087 :   nextarg = expand_builtin_next_arg ();
    5357        21087 :   valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
    5358              : 
    5359        21087 :   if (targetm.expand_builtin_va_start)
    5360        21087 :     targetm.expand_builtin_va_start (valist, nextarg);
    5361              :   else
    5362            0 :     std_expand_builtin_va_start (valist, nextarg);
    5363              : 
    5364        21087 :   return const0_rtx;
    5365              : }
    5366              : 
    5367              : /* Expand EXP, a call to __builtin_va_end.  */
    5368              : 
    5369              : static rtx
    5370        12162 : expand_builtin_va_end (tree exp)
    5371              : {
    5372        12162 :   tree valist = CALL_EXPR_ARG (exp, 0);
    5373              : 
    5374              :   /* Evaluate for side effects, if needed.  I hate macros that don't
    5375              :      do that.  */
    5376        12162 :   if (TREE_SIDE_EFFECTS (valist))
    5377            0 :     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5378              : 
    5379        12162 :   return const0_rtx;
    5380              : }
    5381              : 
    5382              : /* Expand EXP, a call to __builtin_va_copy.  We do this as a
    5383              :    builtin rather than just as an assignment in stdarg.h because of the
    5384              :    nastiness of array-type va_list types.  */
    5385              : 
    5386              : static rtx
    5387          240 : expand_builtin_va_copy (tree exp)
    5388              : {
    5389          240 :   tree dst, src, t;
    5390          240 :   location_t loc = EXPR_LOCATION (exp);
    5391              : 
    5392          240 :   dst = CALL_EXPR_ARG (exp, 0);
    5393          240 :   src = CALL_EXPR_ARG (exp, 1);
    5394              : 
    5395          240 :   dst = stabilize_va_list_loc (loc, dst, 1);
    5396          240 :   src = stabilize_va_list_loc (loc, src, 0);
    5397              : 
    5398          240 :   gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
    5399              : 
    5400          240 :   if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
    5401              :     {
    5402            0 :       t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
    5403            0 :       TREE_SIDE_EFFECTS (t) = 1;
    5404            0 :       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5405              :     }
    5406              :   else
    5407              :     {
    5408          240 :       rtx dstb, srcb, size;
    5409              : 
    5410              :       /* Evaluate to pointers.  */
    5411          240 :       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
    5412          240 :       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
    5413          240 :       size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
    5414              :                   NULL_RTX, VOIDmode, EXPAND_NORMAL);
    5415              : 
    5416          240 :       dstb = convert_memory_address (Pmode, dstb);
    5417          240 :       srcb = convert_memory_address (Pmode, srcb);
    5418              : 
    5419              :       /* "Dereference" to BLKmode memories.  */
    5420          240 :       dstb = gen_rtx_MEM (BLKmode, dstb);
    5421          240 :       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
    5422          240 :       set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5423          240 :       srcb = gen_rtx_MEM (BLKmode, srcb);
    5424          240 :       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
    5425          240 :       set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5426              : 
    5427              :       /* Copy.  */
    5428          240 :       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
    5429              :     }
    5430              : 
    5431          240 :   return const0_rtx;
    5432              : }
    5433              : 
    5434              : /* Expand a call to one of the builtin functions __builtin_frame_address or
    5435              :    __builtin_return_address.  */
    5436              : 
    5437              : static rtx
    5438        15936 : expand_builtin_frame_address (tree fndecl, tree exp)
    5439              : {
    5440              :   /* The argument must be a nonnegative integer constant.
    5441              :      It counts the number of frames to scan up the stack.
    5442              :      The value is either the frame pointer value or the return
    5443              :      address saved in that frame.  */
    5444        15936 :   if (call_expr_nargs (exp) == 0)
    5445              :     /* Warning about missing arg was already issued.  */
    5446            0 :     return const0_rtx;
    5447        15936 :   else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
    5448              :     {
    5449            0 :       error ("invalid argument to %qD", fndecl);
    5450            0 :       return const0_rtx;
    5451              :     }
    5452              :   else
    5453              :     {
    5454              :       /* Number of frames to scan up the stack.  */
    5455        15936 :       unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
    5456              : 
    5457        15936 :       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
    5458              : 
    5459              :       /* Some ports cannot access arbitrary stack frames.  */
    5460        15936 :       if (tem == NULL)
    5461              :         {
    5462            0 :           warning (0, "unsupported argument to %qD", fndecl);
    5463            0 :           return const0_rtx;
    5464              :         }
    5465              : 
    5466        15936 :       if (count)
    5467              :         {
    5468              :           /* Warn since no effort is made to ensure that any frame
    5469              :              beyond the current one exists or can be safely reached.  */
    5470          938 :           warning (OPT_Wframe_address, "calling %qD with "
    5471              :                    "a nonzero argument is unsafe", fndecl);
    5472              :         }
    5473              : 
    5474              :       /* For __builtin_frame_address, return what we've got.  */
    5475        15936 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
    5476              :         return tem;
    5477              : 
    5478         5173 :       if (!REG_P (tem)
    5479         5173 :           && ! CONSTANT_P (tem))
    5480         5173 :         tem = copy_addr_to_reg (tem);
    5481              :       return tem;
    5482              :     }
    5483              : }
    5484              : 
    5485              : #if ! STACK_GROWS_DOWNWARD
    5486              : # define STACK_TOPS GT
    5487              : #else
    5488              : # define STACK_TOPS LT
    5489              : #endif
    5490              : 
    5491              : #ifdef POINTERS_EXTEND_UNSIGNED
    5492              : # define STACK_UNSIGNED POINTERS_EXTEND_UNSIGNED
    5493              : #else
    5494              : # define STACK_UNSIGNED true
    5495              : #endif
    5496              : 
    5497              : /* Expand a call to builtin function __builtin_stack_address.  */
    5498              : 
    5499              : static rtx
    5500         3455 : expand_builtin_stack_address ()
    5501              : {
    5502         3455 :   rtx ret = convert_to_mode (ptr_mode, copy_to_reg (stack_pointer_rtx),
    5503              :                              STACK_UNSIGNED);
    5504              : 
    5505              : #ifdef STACK_ADDRESS_OFFSET
    5506              :   /* Unbias the stack pointer, bringing it to the boundary between the
    5507              :      stack area claimed by the active function calling this builtin,
    5508              :      and stack ranges that could get clobbered if it called another
    5509              :      function.  It should NOT encompass any stack red zone, that is
    5510              :      used in leaf functions.
    5511              : 
    5512              :      On SPARC, the register save area is *not* considered active or
    5513              :      used by the active function, but rather as akin to the area in
    5514              :      which call-preserved registers are saved by callees.  This
    5515              :      enables __strub_leave to clear what would otherwise overlap with
    5516              :      its own register save area.
    5517              : 
    5518              :      If the address is computed too high or too low, parts of a stack
    5519              :      range that should be scrubbed may be left unscrubbed, scrubbing
    5520              :      may corrupt active portions of the stack frame, and stack ranges
    5521              :      may be doubly-scrubbed by caller and callee.
    5522              : 
    5523              :      In order for it to be just right, the area delimited by
    5524              :      @code{__builtin_stack_address} and @code{__builtin_frame_address
    5525              :      (0)} should encompass caller's registers saved by the function,
    5526              :      local on-stack variables and @code{alloca} stack areas.
    5527              :      Accumulated outgoing on-stack arguments, preallocated as part of
    5528              :      a function's own prologue, are to be regarded as part of the
    5529              :      (caller) function's active area as well, whereas those pushed or
    5530              :      allocated temporarily for a call are regarded as part of the
    5531              :      callee's stack range, rather than the caller's.  */
    5532              :   ret = plus_constant (ptr_mode, ret, STACK_ADDRESS_OFFSET);
    5533              : #endif
    5534              : 
    5535         3455 :   return force_reg (ptr_mode, ret);
    5536              : }
    5537              : 
    5538              : /* Expand a call to builtin function __builtin_strub_enter.  */
    5539              : 
    5540              : static rtx
    5541         2170 : expand_builtin_strub_enter (tree exp)
    5542              : {
    5543         2170 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5544              :     return NULL_RTX;
    5545              : 
    5546         2170 :   if (optimize < 1 || flag_no_inline)
    5547              :     return NULL_RTX;
    5548              : 
    5549         1526 :   rtx stktop = expand_builtin_stack_address ();
    5550              : 
    5551         1526 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5552         1526 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5553         1526 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5554              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5555         1526 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5556              : 
    5557         1526 :   emit_move_insn (wmark, stktop);
    5558              : 
    5559         1526 :   return const0_rtx;
    5560              : }
    5561              : 
    5562              : /* Expand a call to builtin function __builtin_strub_update.  */
    5563              : 
    5564              : static rtx
    5565         1084 : expand_builtin_strub_update (tree exp)
    5566              : {
    5567         1084 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5568              :     return NULL_RTX;
    5569              : 
    5570         1084 :   if (optimize < 2 || flag_no_inline)
    5571              :     return NULL_RTX;
    5572              : 
    5573          663 :   rtx stktop = expand_builtin_stack_address ();
    5574              : 
    5575              : #ifdef RED_ZONE_SIZE
    5576              :   /* Here's how the strub enter, update and leave functions deal with red zones.
    5577              : 
    5578              :      If it weren't for red zones, update, called from within a strub context,
    5579              :      would bump the watermark to the top of the stack.  Enter and leave, running
    5580              :      in the caller, would use the caller's top of stack address both to
    5581              :      initialize the watermark passed to the callee, and to start strubbing the
    5582              :      stack afterwards.
    5583              : 
    5584              :      Ideally, we'd update the watermark so as to cover the used amount of red
    5585              :      zone, and strub starting at the caller's other end of the (presumably
    5586              :      unused) red zone.  Normally, only leaf functions use the red zone, but at
    5587              :      this point we can't tell whether a function is a leaf, nor can we tell how
    5588              :      much of the red zone it uses.  Furthermore, some strub contexts may have
    5589              :      been inlined so that update and leave are called from the same stack frame,
    5590              :      and the strub builtins may all have been inlined, turning a strub function
    5591              :      into a leaf.
    5592              : 
    5593              :      So cleaning the range from the caller's stack pointer (one end of the red
    5594              :      zone) to the (potentially inlined) callee's (other end of the) red zone
    5595              :      could scribble over the caller's own red zone.
    5596              : 
    5597              :      We avoid this possibility by arranging for callers that are strub contexts
    5598              :      to use their own watermark as the strub starting point.  So, if A calls B,
    5599              :      and B calls C, B will tell A to strub up to the end of B's red zone, and
    5600              :      will strub itself only the part of C's stack frame and red zone that
    5601              :      doesn't overlap with B's.  With that, we don't need to know who's leaf and
    5602              :      who isn't: inlined calls will shrink their strub window to zero, each
    5603              :      remaining call will strub some portion of the stack, and eventually the
    5604              :      strub context will return to a caller that isn't a strub context itself,
    5605              :      that will therefore use its own stack pointer as the strub starting point.
    5606              :      It's not a leaf, because strub contexts can't be inlined into non-strub
    5607              :      contexts, so it doesn't use the red zone, and it will therefore correctly
    5608              :      strub up the callee's stack frame up to the end of the callee's red zone.
    5609              :      Neat!  */
    5610          663 :   if (true /* (flags_from_decl_or_type (current_function_decl) & ECF_LEAF) */)
    5611              :     {
    5612          663 :       poly_int64 red_zone_size = RED_ZONE_SIZE;
    5613              : #if STACK_GROWS_DOWNWARD
    5614          663 :       red_zone_size = -red_zone_size;
    5615              : #endif
    5616          663 :       stktop = plus_constant (ptr_mode, stktop, red_zone_size);
    5617          663 :       stktop = force_reg (ptr_mode, stktop);
    5618              :     }
    5619              : #endif
    5620              : 
    5621          663 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5622          663 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5623          663 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5624              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5625          663 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5626              : 
    5627          663 :   rtx wmark_load = shallow_copy_rtx (wmark);
    5628          663 :   MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
    5629          663 :   rtx wmarkr = force_reg (ptr_mode, wmark_load);
    5630              : 
    5631          663 :   rtx_code_label *lab = gen_label_rtx ();
    5632          663 :   do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
    5633              :                            ptr_mode, NULL_RTX, lab, NULL,
    5634              :                            profile_probability::very_likely ());
    5635          663 :   emit_move_insn (wmark, stktop);
    5636              : 
    5637              :   /* If this is an inlined strub function, also bump the watermark for the
    5638              :      enclosing function.  This avoids a problem with the following scenario: A
    5639              :      calls B and B calls C, and both B and C get inlined into A.  B allocates
    5640              :      temporary stack space before calling C.  If we don't update A's watermark,
    5641              :      we may use an outdated baseline for the post-C strub_leave, erasing B's
    5642              :      temporary stack allocation.  We only need this if we're fully expanding
    5643              :      strub_leave inline.  */
    5644          663 :   tree xwmptr = (optimize > 2
    5645          663 :                  ? strub_watermark_parm (current_function_decl)
    5646              :                  : wmptr);
    5647          663 :   if (wmptr != xwmptr)
    5648              :     {
    5649          156 :       wmptr = xwmptr;
    5650          156 :       wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5651          156 :       wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5652              :                             build_int_cst (TREE_TYPE (wmptr), 0));
    5653          156 :       wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5654          156 :       wmark_load = shallow_copy_rtx (wmark);
    5655          156 :       MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
    5656          156 :       wmarkr = force_reg (ptr_mode, wmark_load);
    5657              : 
    5658          156 :       do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
    5659              :                                ptr_mode, NULL_RTX, lab, NULL,
    5660              :                                profile_probability::very_likely ());
    5661          156 :       emit_move_insn (wmark, stktop);
    5662              :     }
    5663              : 
    5664          663 :   emit_label (lab);
    5665              : 
    5666          663 :   return const0_rtx;
    5667              : }
    5668              : 
    5669              : 
    5670              : /* Expand a call to builtin function __builtin_strub_leave.  */
    5671              : 
    5672              : static rtx
    5673         2740 : expand_builtin_strub_leave (tree exp)
    5674              : {
    5675         2740 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5676              :     return NULL_RTX;
    5677              : 
    5678         2740 :   if (optimize < 2 || optimize_size || flag_no_inline)
    5679              :     return NULL_RTX;
    5680              : 
    5681         1239 :   rtx stktop = NULL_RTX;
    5682              : 
    5683         1239 :   if (tree wmptr = (optimize
    5684         1239 :                     ? strub_watermark_parm (current_function_decl)
    5685              :                     : NULL_TREE))
    5686              :     {
    5687          513 :       tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5688          513 :       tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5689              :                                  build_int_cst (TREE_TYPE (wmptr), 0));
    5690          513 :       rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5691          513 :       MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
    5692          513 :       stktop = force_reg (ptr_mode, wmark);
    5693              :     }
    5694              : 
    5695          513 :   if (!stktop)
    5696          726 :     stktop = expand_builtin_stack_address ();
    5697              : 
    5698         1239 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5699         1239 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5700         1239 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5701              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5702         1239 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5703         1239 :   MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
    5704              : 
    5705         1239 :   rtx wmarkr = force_reg (ptr_mode, wmark);
    5706              : 
    5707              : #if ! STACK_GROWS_DOWNWARD
    5708              :   rtx base = stktop;
    5709              :   rtx end = wmarkr;
    5710              : #else
    5711         1239 :   rtx base = wmarkr;
    5712         1239 :   rtx end = stktop;
    5713              : #endif
    5714              : 
    5715              :   /* We're going to modify it, so make sure it's not e.g. the stack pointer.  */
    5716         1239 :   base = copy_to_reg (base);
    5717              : 
    5718         1239 :   rtx_code_label *done = gen_label_rtx ();
    5719         1239 :   do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
    5720              :                            ptr_mode, NULL_RTX, done, NULL,
    5721              :                            profile_probability::very_likely ());
    5722              : 
    5723         1239 :   if (optimize < 3)
    5724          919 :     expand_call (exp, NULL_RTX, true);
    5725              :   else
    5726              :     {
    5727              :       /* Ok, now we've determined we want to copy the block, so convert the
    5728              :          addresses to Pmode, as needed to dereference them to access ptr_mode
    5729              :          memory locations, so that we don't have to convert anything within the
    5730              :          loop.  */
    5731          320 :       base = memory_address (ptr_mode, base);
    5732          320 :       end = memory_address (ptr_mode, end);
    5733              : 
    5734          320 :       rtx zero = force_operand (const0_rtx, NULL_RTX);
    5735          320 :       int ulen = GET_MODE_SIZE (ptr_mode);
    5736              : 
    5737              :       /* ??? It would be nice to use setmem or similar patterns here,
    5738              :          but they do not necessarily obey the stack growth direction,
    5739              :          which has security implications.  We also have to avoid calls
    5740              :          (memset, bzero or any machine-specific ones), which are
    5741              :          likely unsafe here (see TARGET_STRUB_MAY_USE_MEMSET).  */
    5742              : #if ! STACK_GROWS_DOWNWARD
    5743              :       rtx incr = plus_constant (Pmode, base, ulen);
    5744              :       rtx dstm = gen_rtx_MEM (ptr_mode, base);
    5745              : 
    5746              :       rtx_code_label *loop = gen_label_rtx ();
    5747              :       emit_label (loop);
    5748              :       emit_move_insn (dstm, zero);
    5749              :       emit_move_insn (base, force_operand (incr, NULL_RTX));
    5750              : #else
    5751          320 :       rtx decr = plus_constant (Pmode, end, -ulen);
    5752          320 :       rtx dstm = gen_rtx_MEM (ptr_mode, end);
    5753              : 
    5754          320 :       rtx_code_label *loop = gen_label_rtx ();
    5755          320 :       emit_label (loop);
    5756          320 :       emit_move_insn (end, force_operand (decr, NULL_RTX));
    5757          320 :       emit_move_insn (dstm, zero);
    5758              : #endif
    5759          640 :       do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
    5760          320 :                                Pmode, NULL_RTX, NULL, loop,
    5761              :                                profile_probability::very_likely ());
    5762              :     }
    5763              : 
    5764         1239 :   emit_label (done);
    5765              : 
    5766         1239 :   return const0_rtx;
    5767              : }
    5768              : 
    5769              : /* Expand EXP, a call to the alloca builtin.  Return NULL_RTX if we
    5770              :    failed and the caller should emit a normal call.  */
    5771              : 
    5772              : static rtx
    5773        27543 : expand_builtin_alloca (tree exp)
    5774              : {
    5775        27543 :   rtx op0;
    5776        27543 :   rtx result;
    5777        27543 :   unsigned int align;
    5778        27543 :   tree fndecl = get_callee_fndecl (exp);
    5779        27543 :   HOST_WIDE_INT max_size;
    5780        27543 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    5781        27543 :   bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
    5782        27543 :   bool valid_arglist
    5783              :     = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5784        27543 :        ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
    5785              :                            VOID_TYPE)
    5786              :        : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
    5787        27541 :          ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
    5788        27543 :          : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
    5789              : 
    5790        27543 :   if (!valid_arglist)
    5791              :     return NULL_RTX;
    5792              : 
    5793              :   /* Compute the argument.  */
    5794        27538 :   op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
    5795              : 
    5796              :   /* Compute the alignment.  */
    5797        51085 :   align = (fcode == BUILT_IN_ALLOCA
    5798        23548 :            ? BIGGEST_ALIGNMENT
    5799         3990 :            : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
    5800              : 
    5801              :   /* Compute the maximum size.  */
    5802            2 :   max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5803        27540 :               ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
    5804              :               : -1);
    5805              : 
    5806              :   /* Allocate the desired space.  If the allocation stems from the declaration
    5807              :      of a variable-sized object, it cannot accumulate.  */
    5808        27538 :   result
    5809        27538 :     = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
    5810        27538 :   result = convert_memory_address (ptr_mode, result);
    5811              : 
    5812              :   /* Dynamic allocations for variables are recorded during gimplification.  */
    5813        27538 :   if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
    5814            0 :     record_dynamic_alloc (exp);
    5815              : 
    5816              :   return result;
    5817              : }
    5818              : 
    5819              : /* Emit a call to __asan_allocas_unpoison call in EXP.  Add to second argument
    5820              :    of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
    5821              :    STACK_DYNAMIC_OFFSET value.  See motivation for this in comment to
    5822              :    handle_builtin_stack_restore function.  */
    5823              : 
    5824              : static rtx
    5825          204 : expand_asan_emit_allocas_unpoison (tree exp)
    5826              : {
    5827          204 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    5828          204 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    5829          204 :   rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5830          204 :   rtx bot = expand_expr (arg1, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5831          204 :   rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
    5832              :                                  stack_pointer_rtx, NULL_RTX, 0,
    5833              :                                  OPTAB_LIB_WIDEN);
    5834          204 :   off = convert_modes (ptr_mode, Pmode, off, 0);
    5835          204 :   bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
    5836              :                              OPTAB_LIB_WIDEN);
    5837          204 :   rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
    5838          204 :   ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
    5839              :                                  top, ptr_mode, bot, ptr_mode);
    5840          204 :   return ret;
    5841              : }
    5842              : 
    5843              : /* Expand a call to bswap builtin in EXP.
    5844              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5845              :    function in-line.  If convenient, the result should be placed in TARGET.
    5846              :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5847              : 
    5848              : static rtx
    5849         1276 : expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
    5850              :                       rtx subtarget)
    5851              : {
    5852         1276 :   tree arg;
    5853         1276 :   rtx op0;
    5854              : 
    5855         1276 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5856              :     return NULL_RTX;
    5857              : 
    5858         1276 :   arg = CALL_EXPR_ARG (exp, 0);
    5859         1276 :   op0 = expand_expr (arg,
    5860           56 :                      subtarget && GET_MODE (subtarget) == target_mode
    5861              :                      ? subtarget : NULL_RTX,
    5862              :                      target_mode, EXPAND_NORMAL);
    5863         1276 :   if (GET_MODE (op0) != target_mode)
    5864            0 :     op0 = convert_to_mode (target_mode, op0, 1);
    5865              : 
    5866         1276 :   target = expand_unop (target_mode, bswap_optab, op0, target, 1);
    5867              : 
    5868         1276 :   gcc_assert (target);
    5869              : 
    5870         1276 :   return convert_to_mode (target_mode, target, 1);
    5871              : }
    5872              : 
    5873              : /* Expand a call to a unary builtin in EXP.
    5874              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5875              :    function in-line.  If convenient, the result should be placed in TARGET.
    5876              :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5877              : 
    5878              : static rtx
    5879          862 : expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
    5880              :                      rtx subtarget, optab op_optab)
    5881              : {
    5882          862 :   rtx op0;
    5883              : 
    5884          862 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5885              :     return NULL_RTX;
    5886              : 
    5887              :   /* Compute the argument.  */
    5888         1724 :   op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
    5889              :                      (subtarget
    5890          106 :                       && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
    5891          106 :                           == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
    5892              :                      VOIDmode, EXPAND_NORMAL);
    5893              :   /* Compute op, into TARGET if possible.
    5894              :      Set TARGET to wherever the result comes back.  */
    5895          862 :   target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
    5896              :                         op_optab, op0, target, op_optab != clrsb_optab);
    5897          862 :   gcc_assert (target);
    5898              : 
    5899          862 :   return convert_to_mode (target_mode, target, 0);
    5900              : }
    5901              : 
    5902              : /* Expand a call to __builtin_expect.  We just return our argument
    5903              :    as the builtin_expect semantic should've been already executed by
    5904              :    tree branch prediction pass. */
    5905              : 
    5906              : static rtx
    5907         1407 : expand_builtin_expect (tree exp, rtx target)
    5908              : {
    5909         1407 :   tree arg;
    5910              : 
    5911         1407 :   if (call_expr_nargs (exp) < 2)
    5912            0 :     return const0_rtx;
    5913         1407 :   arg = CALL_EXPR_ARG (exp, 0);
    5914              : 
    5915         1407 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5916              :   /* When guessing was done, the hints should be already stripped away.  */
    5917         1407 :   gcc_assert (!flag_guess_branch_prob
    5918              :               || optimize == 0 || seen_error ());
    5919              :   return target;
    5920              : }
    5921              : 
    5922              : /* Expand a call to __builtin_expect_with_probability.  We just return our
    5923              :    argument as the builtin_expect semantic should've been already executed by
    5924              :    tree branch prediction pass.  */
    5925              : 
    5926              : static rtx
    5927            5 : expand_builtin_expect_with_probability (tree exp, rtx target)
    5928              : {
    5929            5 :   tree arg;
    5930              : 
    5931            5 :   if (call_expr_nargs (exp) < 3)
    5932            0 :     return const0_rtx;
    5933            5 :   arg = CALL_EXPR_ARG (exp, 0);
    5934              : 
    5935            5 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5936              :   /* When guessing was done, the hints should be already stripped away.  */
    5937            5 :   gcc_assert (!flag_guess_branch_prob
    5938              :               || optimize == 0 || seen_error ());
    5939              :   return target;
    5940              : }
    5941              : 
    5942              : 
    5943              : /* Expand a call to __builtin_assume_aligned.  We just return our first
    5944              :    argument as the builtin_assume_aligned semantic should've been already
    5945              :    executed by CCP.  */
    5946              : 
    5947              : static rtx
    5948          662 : expand_builtin_assume_aligned (tree exp, rtx target)
    5949              : {
    5950          662 :   if (call_expr_nargs (exp) < 2)
    5951            0 :     return const0_rtx;
    5952          662 :   target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
    5953              :                         EXPAND_NORMAL);
    5954          662 :   gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
    5955              :               && (call_expr_nargs (exp) < 3
    5956              :                   || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
    5957              :   return target;
    5958              : }
    5959              : 
    5960              : void
    5961        38761 : expand_builtin_trap (void)
    5962              : {
    5963        38761 :   if (targetm.have_trap ())
    5964              :     {
    5965        38761 :       rtx_insn *insn = emit_insn (targetm.gen_trap ());
    5966              :       /* For trap insns when not accumulating outgoing args force
    5967              :          REG_ARGS_SIZE note to prevent crossjumping of calls with
    5968              :          different args sizes.  */
    5969        38761 :       if (!ACCUMULATE_OUTGOING_ARGS)
    5970        38759 :         add_args_size_note (insn, stack_pointer_delta);
    5971              :     }
    5972              :   else
    5973              :     {
    5974            0 :       tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
    5975            0 :       tree call_expr = build_call_expr (fn, 0);
    5976            0 :       expand_call (call_expr, NULL_RTX, false);
    5977              :     }
    5978              : 
    5979        38761 :   emit_barrier ();
    5980        38761 : }
    5981              : 
    5982              : /* Expand a call to __builtin_unreachable.  We do nothing except emit
    5983              :    a barrier saying that control flow will not pass here.
    5984              : 
    5985              :    It is the responsibility of the program being compiled to ensure
    5986              :    that control flow does never reach __builtin_unreachable.  */
    5987              : static void
    5988         2641 : expand_builtin_unreachable (void)
    5989              : {
    5990              :   /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable
    5991              :      to avoid this.  */
    5992         2641 :   gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE));
    5993         2641 :   emit_barrier ();
    5994         2641 : }
    5995              : 
    5996              : /* Expand EXP, a call to fabs, fabsf or fabsl.
    5997              :    Return NULL_RTX if a normal call should be emitted rather than expanding
    5998              :    the function inline.  If convenient, the result should be placed
    5999              :    in TARGET.  SUBTARGET may be used as the target for computing
    6000              :    the operand.  */
    6001              : 
    6002              : static rtx
    6003            4 : expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
    6004              : {
    6005            4 :   machine_mode mode;
    6006            4 :   tree arg;
    6007            4 :   rtx op0;
    6008              : 
    6009            4 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    6010              :     return NULL_RTX;
    6011              : 
    6012            0 :   arg = CALL_EXPR_ARG (exp, 0);
    6013            0 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    6014            0 :   mode = TYPE_MODE (TREE_TYPE (arg));
    6015            0 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6016            0 :   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
    6017              : }
    6018              : 
    6019              : /* Expand EXP, a call to copysign, copysignf, or copysignl.
    6020              :    Return NULL is a normal call should be emitted rather than expanding the
    6021              :    function inline.  If convenient, the result should be placed in TARGET.
    6022              :    SUBTARGET may be used as the target for computing the operand.  */
    6023              : 
    6024              : static rtx
    6025        11677 : expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
    6026              : {
    6027        11677 :   rtx op0, op1;
    6028        11677 :   tree arg;
    6029              : 
    6030        11677 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    6031              :     return NULL_RTX;
    6032              : 
    6033        11676 :   arg = CALL_EXPR_ARG (exp, 0);
    6034        11676 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6035              : 
    6036        11676 :   arg = CALL_EXPR_ARG (exp, 1);
    6037        11676 :   op1 = expand_normal (arg);
    6038              : 
    6039        11676 :   return expand_copysign (op0, op1, target);
    6040              : }
    6041              : 
    6042              : /* Emit a call to __builtin___clear_cache.  */
    6043              : 
    6044              : void
    6045            0 : default_emit_call_builtin___clear_cache (rtx begin, rtx end)
    6046              : {
    6047            0 :   rtx callee = gen_rtx_SYMBOL_REF (Pmode,
    6048              :                                    BUILTIN_ASM_NAME_PTR
    6049              :                                    (BUILT_IN_CLEAR_CACHE));
    6050              : 
    6051            0 :   emit_library_call (callee,
    6052              :                      LCT_NORMAL, VOIDmode,
    6053              :                      convert_memory_address (ptr_mode, begin), ptr_mode,
    6054              :                      convert_memory_address (ptr_mode, end), ptr_mode);
    6055            0 : }
    6056              : 
    6057              : /* Emit a call to __builtin___clear_cache, unless the target specifies
    6058              :    it as do-nothing.  This function can be used by trampoline
    6059              :    finalizers to duplicate the effects of expanding a call to the
    6060              :    clear_cache builtin.  */
    6061              : 
    6062              : void
    6063           28 : maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
    6064              : {
    6065           28 :   gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
    6066              :                || CONST_INT_P (begin))
    6067              :               && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
    6068              :                   || CONST_INT_P (end)));
    6069              : 
    6070           28 :   if (targetm.have_clear_cache ())
    6071              :     {
    6072              :       /* We have a "clear_cache" insn, and it will handle everything.  */
    6073            0 :       class expand_operand ops[2];
    6074              : 
    6075            0 :       create_address_operand (&ops[0], begin);
    6076            0 :       create_address_operand (&ops[1], end);
    6077              : 
    6078            0 :       if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
    6079            0 :         return;
    6080              :     }
    6081              :   else
    6082              :     {
    6083              : #ifndef CLEAR_INSN_CACHE
    6084              :       /* There is no "clear_cache" insn, and __clear_cache() in libgcc
    6085              :          does nothing.  There is no need to call it.  Do nothing.  */
    6086              :       return;
    6087              : #endif /* CLEAR_INSN_CACHE */
    6088              :     }
    6089              : 
    6090            0 :   targetm.calls.emit_call_builtin___clear_cache (begin, end);
    6091              : }
    6092              : 
    6093              : /* Expand a call to __builtin___clear_cache.  */
    6094              : 
    6095              : static void
    6096           28 : expand_builtin___clear_cache (tree exp)
    6097              : {
    6098           28 :   tree begin, end;
    6099           28 :   rtx begin_rtx, end_rtx;
    6100              : 
    6101              :   /* We must not expand to a library call.  If we did, any
    6102              :      fallback library function in libgcc that might contain a call to
    6103              :      __builtin___clear_cache() would recurse infinitely.  */
    6104           28 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    6105              :     {
    6106            0 :       error ("both arguments to %<__builtin___clear_cache%> must be pointers");
    6107            0 :       return;
    6108              :     }
    6109              : 
    6110           28 :   begin = CALL_EXPR_ARG (exp, 0);
    6111           30 :   begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
    6112              : 
    6113           28 :   end = CALL_EXPR_ARG (exp, 1);
    6114           30 :   end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
    6115              : 
    6116           28 :   maybe_emit_call_builtin___clear_cache (begin_rtx, end_rtx);
    6117              : }
    6118              : 
    6119              : /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
    6120              : 
    6121              : static rtx
    6122          659 : round_trampoline_addr (rtx tramp)
    6123              : {
    6124          659 :   rtx temp, addend, mask;
    6125              : 
    6126              :   /* If we don't need too much alignment, we'll have been guaranteed
    6127              :      proper alignment by get_trampoline_type.  */
    6128          659 :   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
    6129              :     return tramp;
    6130              : 
    6131              :   /* Round address up to desired boundary.  */
    6132            0 :   temp = gen_reg_rtx (Pmode);
    6133            0 :   addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
    6134            0 :   mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
    6135              : 
    6136            0 :   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
    6137              :                                temp, 0, OPTAB_LIB_WIDEN);
    6138            0 :   tramp = expand_simple_binop (Pmode, AND, temp, mask,
    6139              :                                temp, 0, OPTAB_LIB_WIDEN);
    6140              : 
    6141            0 :   return tramp;
    6142              : }
    6143              : 
    6144              : static rtx
    6145          306 : expand_builtin_init_trampoline (tree exp, bool onstack)
    6146              : {
    6147          306 :   tree t_tramp, t_func, t_chain;
    6148          306 :   rtx m_tramp, r_tramp, r_chain, tmp;
    6149              : 
    6150          306 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
    6151              :                          POINTER_TYPE, VOID_TYPE))
    6152              :     return NULL_RTX;
    6153              : 
    6154          306 :   t_tramp = CALL_EXPR_ARG (exp, 0);
    6155          306 :   t_func = CALL_EXPR_ARG (exp, 1);
    6156          306 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6157              : 
    6158          306 :   r_tramp = expand_normal (t_tramp);
    6159          306 :   m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
    6160          306 :   MEM_NOTRAP_P (m_tramp) = 1;
    6161              : 
    6162              :   /* If ONSTACK, the TRAMP argument should be the address of a field
    6163              :      within the local function's FRAME decl.  Either way, let's see if
    6164              :      we can fill in the MEM_ATTRs for this memory.  */
    6165          306 :   if (TREE_CODE (t_tramp) == ADDR_EXPR)
    6166          306 :     set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
    6167              : 
    6168              :   /* Creator of a heap trampoline is responsible for making sure the
    6169              :      address is aligned to at least STACK_BOUNDARY.  Normally malloc
    6170              :      will ensure this anyhow.  */
    6171          306 :   tmp = round_trampoline_addr (r_tramp);
    6172          306 :   if (tmp != r_tramp)
    6173              :     {
    6174            0 :       m_tramp = change_address (m_tramp, BLKmode, tmp);
    6175            0 :       set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
    6176            0 :       set_mem_size (m_tramp, TRAMPOLINE_SIZE);
    6177              :     }
    6178              : 
    6179              :   /* The FUNC argument should be the address of the nested function.
    6180              :      Extract the actual function decl to pass to the hook.  */
    6181          306 :   gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
    6182          306 :   t_func = TREE_OPERAND (t_func, 0);
    6183          306 :   gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
    6184              : 
    6185          306 :   r_chain = expand_normal (t_chain);
    6186              : 
    6187              :   /* Generate insns to initialize the trampoline.  */
    6188          306 :   targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
    6189              : 
    6190          306 :   if (onstack)
    6191              :     {
    6192          306 :       trampolines_created = 1;
    6193              : 
    6194          306 :       if (targetm.calls.custom_function_descriptors != 0)
    6195          306 :         warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
    6196              :                     "trampoline generated for nested function %qD", t_func);
    6197              :     }
    6198              : 
    6199          306 :   return const0_rtx;
    6200              : }
    6201              : 
    6202              : static rtx
    6203          353 : expand_builtin_adjust_trampoline (tree exp)
    6204              : {
    6205          353 :   rtx tramp;
    6206              : 
    6207          353 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6208              :     return NULL_RTX;
    6209              : 
    6210          353 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6211          353 :   tramp = round_trampoline_addr (tramp);
    6212          353 :   if (targetm.calls.trampoline_adjust_address)
    6213            0 :     tramp = targetm.calls.trampoline_adjust_address (tramp);
    6214              : 
    6215              :   return tramp;
    6216              : }
    6217              : 
    6218              : /* Expand a call to the builtin descriptor initialization routine.
    6219              :    A descriptor is made up of a couple of pointers to the static
    6220              :    chain and the code entry in this order.  */
    6221              : 
    6222              : static rtx
    6223            0 : expand_builtin_init_descriptor (tree exp)
    6224              : {
    6225            0 :   tree t_descr, t_func, t_chain;
    6226            0 :   rtx m_descr, r_descr, r_func, r_chain;
    6227              : 
    6228            0 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
    6229              :                          VOID_TYPE))
    6230              :     return NULL_RTX;
    6231              : 
    6232            0 :   t_descr = CALL_EXPR_ARG (exp, 0);
    6233            0 :   t_func = CALL_EXPR_ARG (exp, 1);
    6234            0 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6235              : 
    6236            0 :   r_descr = expand_normal (t_descr);
    6237            0 :   m_descr = gen_rtx_MEM (BLKmode, r_descr);
    6238            0 :   MEM_NOTRAP_P (m_descr) = 1;
    6239            0 :   set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
    6240              : 
    6241            0 :   r_func = expand_normal (t_func);
    6242            0 :   r_chain = expand_normal (t_chain);
    6243              : 
    6244              :   /* Generate insns to initialize the descriptor.  */
    6245            0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
    6246            0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
    6247              :                                      POINTER_SIZE / BITS_PER_UNIT), r_func);
    6248              : 
    6249            0 :   return const0_rtx;
    6250              : }
    6251              : 
    6252              : /* Expand a call to the builtin descriptor adjustment routine.  */
    6253              : 
    6254              : static rtx
    6255            0 : expand_builtin_adjust_descriptor (tree exp)
    6256              : {
    6257            0 :   rtx tramp;
    6258              : 
    6259            0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6260              :     return NULL_RTX;
    6261              : 
    6262            0 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6263              : 
    6264              :   /* Unalign the descriptor to allow runtime identification.  */
    6265            0 :   tramp = plus_constant (ptr_mode, tramp,
    6266            0 :                          targetm.calls.custom_function_descriptors);
    6267              : 
    6268            0 :   return force_operand (tramp, NULL_RTX);
    6269              : }
    6270              : 
    6271              : /* Expand the call EXP to the built-in signbit, signbitf or signbitl
    6272              :    function.  The function first checks whether the back end provides
    6273              :    an insn to implement signbit for the respective mode.  If not, it
    6274              :    checks whether the floating point format of the value is such that
    6275              :    the sign bit can be extracted.  If that is not the case, error out.
    6276              :    EXP is the expression that is a call to the builtin function; if
    6277              :    convenient, the result should be placed in TARGET.  */
    6278              : static rtx
    6279         1380 : expand_builtin_signbit (tree exp, rtx target)
    6280              : {
    6281         1380 :   const struct real_format *fmt;
    6282         1380 :   scalar_float_mode fmode;
    6283         1380 :   scalar_int_mode rmode, imode;
    6284         1380 :   tree arg;
    6285         1380 :   int word, bitpos;
    6286         1380 :   enum insn_code icode;
    6287         1380 :   rtx temp;
    6288         1380 :   location_t loc = EXPR_LOCATION (exp);
    6289              : 
    6290         1380 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    6291              :     return NULL_RTX;
    6292              : 
    6293         1380 :   arg = CALL_EXPR_ARG (exp, 0);
    6294         1380 :   fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
    6295         1380 :   rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
    6296         1380 :   fmt = REAL_MODE_FORMAT (fmode);
    6297              : 
    6298         1380 :   arg = builtin_save_expr (arg);
    6299              : 
    6300              :   /* Expand the argument yielding a RTX expression. */
    6301         1380 :   temp = expand_normal (arg);
    6302              : 
    6303              :   /* Check if the back end provides an insn that handles signbit for the
    6304              :      argument's mode. */
    6305         1380 :   icode = optab_handler (signbit_optab, fmode);
    6306         1380 :   if (icode != CODE_FOR_nothing)
    6307              :     {
    6308           10 :       rtx_insn *last = get_last_insn ();
    6309           10 :       rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    6310           10 :       if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
    6311              :         return this_target;
    6312            0 :       delete_insns_since (last);
    6313              :     }
    6314              : 
    6315              :   /* For floating point formats without a sign bit, implement signbit
    6316              :      as "ARG < 0.0".  */
    6317         1370 :   bitpos = fmt->signbit_ro;
    6318         1370 :   if (bitpos < 0)
    6319              :   {
    6320              :     /* But we can't do this if the format supports signed zero.  */
    6321            0 :     gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
    6322              : 
    6323            0 :     arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
    6324            0 :                        build_real (TREE_TYPE (arg), dconst0));
    6325            0 :     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    6326              :   }
    6327              : 
    6328         2744 :   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
    6329              :     {
    6330         1266 :       imode = int_mode_for_mode (fmode).require ();
    6331         1266 :       temp = gen_lowpart (imode, temp);
    6332              :     }
    6333              :   else
    6334              :     {
    6335          104 :       imode = word_mode;
    6336              :       /* Handle targets with different FP word orders.  */
    6337          104 :       if (FLOAT_WORDS_BIG_ENDIAN)
    6338              :         word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
    6339              :       else
    6340          104 :         word = bitpos / BITS_PER_WORD;
    6341          104 :       temp = operand_subword_force (temp, word, fmode);
    6342          104 :       bitpos = bitpos % BITS_PER_WORD;
    6343              :     }
    6344              : 
    6345              :   /* Force the intermediate word_mode (or narrower) result into a
    6346              :      register.  This avoids attempting to create paradoxical SUBREGs
    6347              :      of floating point modes below.  */
    6348         1370 :   temp = force_reg (imode, temp);
    6349              : 
    6350              :   /* If the bitpos is within the "result mode" lowpart, the operation
    6351              :      can be implement with a single bitwise AND.  Otherwise, we need
    6352              :      a right shift and an AND.  */
    6353              : 
    6354         2740 :   if (bitpos < GET_MODE_BITSIZE (rmode))
    6355              :     {
    6356         1162 :       wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
    6357              : 
    6358         3486 :       if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
    6359            0 :         temp = gen_lowpart (rmode, temp);
    6360         2324 :       temp = expand_binop (rmode, and_optab, temp,
    6361         2324 :                            immed_wide_int_const (mask, rmode),
    6362              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6363         1162 :     }
    6364              :   else
    6365              :     {
    6366              :       /* Perform a logical right shift to place the signbit in the least
    6367              :          significant bit, then truncate the result to the desired mode
    6368              :          and mask just this bit.  */
    6369          208 :       temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
    6370          208 :       temp = gen_lowpart (rmode, temp);
    6371          208 :       temp = expand_binop (rmode, and_optab, temp, const1_rtx,
    6372              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6373              :     }
    6374              : 
    6375              :   return temp;
    6376              : }
    6377              : 
    6378              : /* Expand fork or exec calls.  TARGET is the desired target of the
    6379              :    call.  EXP is the call. FN is the
    6380              :    identificator of the actual function.  IGNORE is nonzero if the
    6381              :    value is to be ignored.  */
    6382              : 
    6383              : static rtx
    6384          109 : expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
    6385              : {
    6386          109 :   tree id, decl;
    6387          109 :   tree call;
    6388              : 
    6389              :   /* If we are not profiling, just call the function.  */
    6390          109 :   if (!coverage_instrumentation_p ())
    6391              :     return NULL_RTX;
    6392              : 
    6393              :   /* Otherwise call the wrapper.  This should be equivalent for the rest of
    6394              :      compiler, so the code does not diverge, and the wrapper may run the
    6395              :      code necessary for keeping the profiling sane.  */
    6396              : 
    6397            4 :   switch (DECL_FUNCTION_CODE (fn))
    6398              :     {
    6399            4 :     case BUILT_IN_FORK:
    6400            4 :       id = get_identifier ("__gcov_fork");
    6401            4 :       break;
    6402              : 
    6403            0 :     case BUILT_IN_EXECL:
    6404            0 :       id = get_identifier ("__gcov_execl");
    6405            0 :       break;
    6406              : 
    6407            0 :     case BUILT_IN_EXECV:
    6408            0 :       id = get_identifier ("__gcov_execv");
    6409            0 :       break;
    6410              : 
    6411            0 :     case BUILT_IN_EXECLP:
    6412            0 :       id = get_identifier ("__gcov_execlp");
    6413            0 :       break;
    6414              : 
    6415            0 :     case BUILT_IN_EXECLE:
    6416            0 :       id = get_identifier ("__gcov_execle");
    6417            0 :       break;
    6418              : 
    6419            0 :     case BUILT_IN_EXECVP:
    6420            0 :       id = get_identifier ("__gcov_execvp");
    6421            0 :       break;
    6422              : 
    6423            0 :     case BUILT_IN_EXECVE:
    6424            0 :       id = get_identifier ("__gcov_execve");
    6425            0 :       break;
    6426              : 
    6427            0 :     default:
    6428            0 :       gcc_unreachable ();
    6429              :     }
    6430              : 
    6431            4 :   decl = build_decl (DECL_SOURCE_LOCATION (fn),
    6432            4 :                      FUNCTION_DECL, id, TREE_TYPE (fn));
    6433            4 :   DECL_EXTERNAL (decl) = 1;
    6434            4 :   TREE_PUBLIC (decl) = 1;
    6435            4 :   DECL_ARTIFICIAL (decl) = 1;
    6436            4 :   TREE_NOTHROW (decl) = 1;
    6437            4 :   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
    6438            4 :   DECL_VISIBILITY_SPECIFIED (decl) = 1;
    6439            4 :   call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
    6440            4 :   return expand_call (call, target, ignore);
    6441              :  }
    6442              : 
    6443              : 
    6444              : 
    6445              : /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
    6446              :    the pointer in these functions is void*, the tree optimizers may remove
    6447              :    casts.  The mode computed in expand_builtin isn't reliable either, due
    6448              :    to __sync_bool_compare_and_swap.
    6449              : 
    6450              :    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
    6451              :    group of builtins.  This gives us log2 of the mode size.  */
    6452              : 
    6453              : static inline machine_mode
    6454       134548 : get_builtin_sync_mode (int fcode_diff)
    6455              : {
    6456              :   /* The size is not negotiable, so ask not to get BLKmode in return
    6457              :      if the target indicates that a smaller size would be better.  */
    6458       134548 :   return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
    6459              : }
    6460              : 
    6461              : /* Expand the memory expression LOC and return the appropriate memory operand
    6462              :    for the builtin_sync operations.  */
    6463              : 
    6464              : static rtx
    6465       151188 : get_builtin_sync_mem (tree loc, machine_mode mode)
    6466              : {
    6467       151188 :   rtx addr, mem;
    6468       151188 :   int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
    6469              :                                     ? TREE_TYPE (TREE_TYPE (loc))
    6470              :                                     : TREE_TYPE (loc));
    6471       151188 :   scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
    6472              : 
    6473       151188 :   addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
    6474       151188 :   addr = convert_memory_address (addr_mode, addr);
    6475              : 
    6476              :   /* Note that we explicitly do not want any alias information for this
    6477              :      memory, so that we kill all other live memories.  Otherwise we don't
    6478              :      satisfy the full barrier semantics of the intrinsic.  */
    6479       151188 :   mem = gen_rtx_MEM (mode, addr);
    6480              : 
    6481       151188 :   set_mem_addr_space (mem, addr_space);
    6482              : 
    6483       151188 :   mem = validize_mem (mem);
    6484              : 
    6485              :   /* The alignment needs to be at least according to that of the mode.  */
    6486       151188 :   set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
    6487              :                            get_pointer_alignment (loc)));
    6488       151188 :   set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
    6489       151188 :   MEM_VOLATILE_P (mem) = 1;
    6490              : 
    6491       151188 :   return mem;
    6492              : }
    6493              : 
    6494              : /* Make sure an argument is in the right mode.
    6495              :    EXP is the tree argument.
    6496              :    MODE is the mode it should be in.  */
    6497              : 
    6498              : static rtx
    6499        94213 : expand_expr_force_mode (tree exp, machine_mode mode)
    6500              : {
    6501        94213 :   rtx val;
    6502        94213 :   machine_mode old_mode;
    6503              : 
    6504        94213 :   if (TREE_CODE (exp) == SSA_NAME
    6505        94213 :       && TYPE_MODE (TREE_TYPE (exp)) != mode)
    6506              :     {
    6507              :       /* Undo argument promotion if possible, as combine might not
    6508              :          be able to do it later due to MEM_VOLATILE_P uses in the
    6509              :          patterns.  */
    6510           25 :       gimple *g = get_gimple_for_ssa_name (exp);
    6511           25 :       if (g && gimple_assign_cast_p (g))
    6512              :         {
    6513            0 :           tree rhs = gimple_assign_rhs1 (g);
    6514            0 :           tree_code code = gimple_assign_rhs_code (g);
    6515            0 :           if (CONVERT_EXPR_CODE_P (code)
    6516            0 :               && TYPE_MODE (TREE_TYPE (rhs)) == mode
    6517            0 :               && INTEGRAL_TYPE_P (TREE_TYPE (exp))
    6518            0 :               && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
    6519            0 :               && (TYPE_PRECISION (TREE_TYPE (exp))
    6520            0 :                   > TYPE_PRECISION (TREE_TYPE (rhs))))
    6521              :             exp = rhs;
    6522              :         }
    6523              :     }
    6524              : 
    6525        94213 :   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
    6526              :   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
    6527              :      of CONST_INTs, where we know the old_mode only from the call argument.  */
    6528              : 
    6529        94213 :   old_mode = GET_MODE (val);
    6530        94213 :   if (old_mode == VOIDmode)
    6531        44280 :     old_mode = TYPE_MODE (TREE_TYPE (exp));
    6532        94213 :   val = convert_modes (mode, old_mode, val, 1);
    6533        94213 :   return val;
    6534              : }
    6535              : 
    6536              : 
    6537              : /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
    6538              :    EXP is the CALL_EXPR.  CODE is the rtx code
    6539              :    that corresponds to the arithmetic or logical operation from the name;
    6540              :    an exception here is that NOT actually means NAND.  TARGET is an optional
    6541              :    place for us to store the results; AFTER is true if this is the
    6542              :    fetch_and_xxx form.  */
    6543              : 
    6544              : static rtx
    6545         4028 : expand_builtin_sync_operation (machine_mode mode, tree exp,
    6546              :                                enum rtx_code code, bool after,
    6547              :                                rtx target)
    6548              : {
    6549         4028 :   rtx val, mem;
    6550         4028 :   location_t loc = EXPR_LOCATION (exp);
    6551              : 
    6552         4028 :   if (code == NOT && warn_sync_nand)
    6553              :     {
    6554          523 :       tree fndecl = get_callee_fndecl (exp);
    6555          523 :       enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    6556              : 
    6557          523 :       static bool warned_f_a_n, warned_n_a_f;
    6558              : 
    6559          523 :       switch (fcode)
    6560              :         {
    6561          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    6562          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    6563          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    6564          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    6565          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    6566          434 :           if (warned_f_a_n)
    6567              :             break;
    6568              : 
    6569           30 :           fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
    6570           30 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6571           30 :           warned_f_a_n = true;
    6572           30 :           break;
    6573              : 
    6574           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    6575           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    6576           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    6577           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    6578           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    6579           89 :           if (warned_n_a_f)
    6580              :             break;
    6581              : 
    6582           22 :          fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
    6583           22 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6584           22 :           warned_n_a_f = true;
    6585           22 :           break;
    6586              : 
    6587            0 :         default:
    6588            0 :           gcc_unreachable ();
    6589              :         }
    6590              :     }
    6591              : 
    6592              :   /* Expand the operands.  */
    6593         4028 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6594         4028 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6595              : 
    6596         4028 :   return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
    6597         4028 :                                  after);
    6598              : }
    6599              : 
    6600              : /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
    6601              :    intrinsics. EXP is the CALL_EXPR.  IS_BOOL is
    6602              :    true if this is the boolean form.  TARGET is a place for us to store the
    6603              :    results; this is NOT optional if IS_BOOL is true.  */
    6604              : 
    6605              : static rtx
    6606          460 : expand_builtin_compare_and_swap (machine_mode mode, tree exp,
    6607              :                                  bool is_bool, rtx target)
    6608              : {
    6609          460 :   rtx old_val, new_val, mem;
    6610          460 :   rtx *pbool, *poval;
    6611              : 
    6612              :   /* Expand the operands.  */
    6613          460 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6614          460 :   old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6615          460 :   new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6616              : 
    6617          460 :   pbool = poval = NULL;
    6618          460 :   if (target != const0_rtx)
    6619              :     {
    6620          434 :       if (is_bool)
    6621              :         pbool = &target;
    6622              :       else
    6623          230 :         poval = &target;
    6624              :     }
    6625          460 :   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
    6626              :                                        false, MEMMODEL_SYNC_SEQ_CST,
    6627              :                                        MEMMODEL_SYNC_SEQ_CST))
    6628              :     return NULL_RTX;
    6629              : 
    6630          458 :   return target;
    6631              : }
    6632              : 
    6633              : /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
    6634              :    general form is actually an atomic exchange, and some targets only
    6635              :    support a reduced form with the second argument being a constant 1.
    6636              :    EXP is the CALL_EXPR; TARGET is an optional place for us to store
    6637              :    the results.  */
    6638              : 
    6639              : static rtx
    6640          326 : expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
    6641              :                                        rtx target)
    6642              : {
    6643          326 :   rtx val, mem;
    6644              : 
    6645              :   /* Expand the operands.  */
    6646          326 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6647          326 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6648              : 
    6649          326 :   return expand_sync_lock_test_and_set (target, mem, val);
    6650              : }
    6651              : 
    6652              : /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
    6653              : 
    6654              : static rtx
    6655          146 : expand_builtin_sync_lock_release (machine_mode mode, tree exp)
    6656              : {
    6657          146 :   rtx mem;
    6658              : 
    6659              :   /* Expand the operands.  */
    6660          146 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6661              : 
    6662          146 :   return expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
    6663              : }
    6664              : 
    6665              : /* Given an integer representing an ``enum memmodel'', verify its
    6666              :    correctness and return the memory model enum.  */
    6667              : 
    6668              : static enum memmodel
    6669       169708 : get_memmodel (tree exp)
    6670              : {
    6671              :   /* If the parameter is not a constant, it's a run time value so we'll just
    6672              :      convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking.  */
    6673       169708 :   if (TREE_CODE (exp) != INTEGER_CST)
    6674              :     return MEMMODEL_SEQ_CST;
    6675              : 
    6676       168881 :   rtx op = expand_normal (exp);
    6677              : 
    6678       168881 :   unsigned HOST_WIDE_INT val = INTVAL (op);
    6679       168881 :   if (targetm.memmodel_check)
    6680       168881 :     val = targetm.memmodel_check (val);
    6681            0 :   else if (val & ~MEMMODEL_MASK)
    6682              :     return MEMMODEL_SEQ_CST;
    6683              : 
    6684              :   /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
    6685       168881 :   if (memmodel_base (val) >= MEMMODEL_LAST)
    6686              :     return MEMMODEL_SEQ_CST;
    6687              : 
    6688              :   /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
    6689              :      be conservative and promote consume to acquire.  */
    6690       168878 :   if (val == MEMMODEL_CONSUME)
    6691          755 :     val = MEMMODEL_ACQUIRE;
    6692              : 
    6693       168878 :   return (enum memmodel) val;
    6694              : }
    6695              : 
    6696              : /* Expand the __atomic_exchange intrinsic:
    6697              :         TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
    6698              :    EXP is the CALL_EXPR.
    6699              :    TARGET is an optional place for us to store the results.  */
    6700              : 
    6701              : static rtx
    6702         2937 : expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
    6703              : {
    6704         2937 :   rtx val, mem;
    6705         2937 :   enum memmodel model;
    6706              : 
    6707         2937 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6708              : 
    6709         2937 :   if (!flag_inline_atomics)
    6710              :     return NULL_RTX;
    6711              : 
    6712              :   /* Expand the operands.  */
    6713         2886 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6714         2886 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6715              : 
    6716         2886 :   return expand_atomic_exchange (target, mem, val, model);
    6717              : }
    6718              : 
    6719              : /* Expand the __atomic_compare_exchange intrinsic:
    6720              :         bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
    6721              :                                         TYPE desired, BOOL weak,
    6722              :                                         enum memmodel success,
    6723              :                                         enum memmodel failure)
    6724              :    EXP is the CALL_EXPR.
    6725              :    TARGET is an optional place for us to store the results.  */
    6726              : 
    6727              : static rtx
    6728         9131 : expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
    6729              :                                         rtx target)
    6730              : {
    6731         9131 :   rtx expect, desired, mem, oldval;
    6732         9131 :   rtx_code_label *label;
    6733         9131 :   tree weak;
    6734         9131 :   bool is_weak;
    6735              : 
    6736         9131 :   memmodel success = get_memmodel (CALL_EXPR_ARG (exp, 4));
    6737         9131 :   memmodel failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
    6738              : 
    6739         9131 :   if (failure > success)
    6740           22 :     success = MEMMODEL_SEQ_CST;
    6741              : 
    6742         9131 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6743              :     {
    6744              :       failure = MEMMODEL_SEQ_CST;
    6745              :       success = MEMMODEL_SEQ_CST;
    6746              :     }
    6747              : 
    6748              : 
    6749         9131 :   if (!flag_inline_atomics)
    6750              :     return NULL_RTX;
    6751              : 
    6752              :   /* Expand the operands.  */
    6753         9080 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6754              : 
    6755         9080 :   expect = expand_normal (CALL_EXPR_ARG (exp, 1));
    6756         9116 :   expect = convert_memory_address (Pmode, expect);
    6757         9080 :   expect = gen_rtx_MEM (mode, expect);
    6758         9080 :   desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6759              : 
    6760         9080 :   weak = CALL_EXPR_ARG (exp, 3);
    6761         9080 :   is_weak = false;
    6762         9080 :   if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
    6763         9080 :     is_weak = true;
    6764              : 
    6765         9080 :   if (target == const0_rtx)
    6766          289 :     target = NULL;
    6767              : 
    6768              :   /* Lest the rtl backend create a race condition with an imporoper store
    6769              :      to memory, always create a new pseudo for OLDVAL.  */
    6770         9080 :   oldval = NULL;
    6771              : 
    6772         9080 :   if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
    6773              :                                        is_weak, success, failure))
    6774              :     return NULL_RTX;
    6775              : 
    6776              :   /* Conditionally store back to EXPECT, lest we create a race condition
    6777              :      with an improper store to memory.  */
    6778              :   /* ??? With a rearrangement of atomics at the gimple level, we can handle
    6779              :      the normal case where EXPECT is totally private, i.e. a register.  At
    6780              :      which point the store can be unconditional.  */
    6781         7331 :   label = gen_label_rtx ();
    6782         7331 :   emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
    6783         7331 :                            GET_MODE (target), 1, label);
    6784         7331 :   emit_move_insn (expect, oldval);
    6785         7331 :   emit_label (label);
    6786              : 
    6787         7331 :   return target;
    6788              : }
    6789              : 
    6790              : /* Helper function for expand_ifn_atomic_compare_exchange - expand
    6791              :    internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
    6792              :    call.  The weak parameter must be dropped to match the expected parameter
    6793              :    list and the expected argument changed from value to pointer to memory
    6794              :    slot.  */
    6795              : 
    6796              : static void
    6797            0 : expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
    6798              : {
    6799            0 :   unsigned int z;
    6800            0 :   vec<tree, va_gc> *vec;
    6801              : 
    6802            0 :   vec_alloc (vec, 5);
    6803            0 :   vec->quick_push (gimple_call_arg (call, 0));
    6804            0 :   tree expected = gimple_call_arg (call, 1);
    6805            0 :   rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
    6806            0 :                                       TREE_TYPE (expected));
    6807            0 :   rtx expd = expand_expr (expected, x, mode, EXPAND_NORMAL);
    6808            0 :   if (expd != x)
    6809            0 :     emit_move_insn (x, expd);
    6810            0 :   tree v = make_tree (TREE_TYPE (expected), x);
    6811            0 :   vec->quick_push (build1 (ADDR_EXPR,
    6812            0 :                            build_pointer_type (TREE_TYPE (expected)), v));
    6813            0 :   vec->quick_push (gimple_call_arg (call, 2));
    6814              :   /* Skip the boolean weak parameter.  */
    6815            0 :   for (z = 4; z < 6; z++)
    6816            0 :     vec->quick_push (gimple_call_arg (call, z));
    6817              :   /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}.  */
    6818            0 :   unsigned int bytes_log2 = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
    6819            0 :   gcc_assert (bytes_log2 < 5);
    6820            0 :   built_in_function fncode
    6821              :     = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
    6822              :                            + bytes_log2);
    6823            0 :   tree fndecl = builtin_decl_explicit (fncode);
    6824            0 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
    6825              :                     fndecl);
    6826            0 :   tree exp = build_call_vec (boolean_type_node, fn, vec);
    6827            0 :   tree lhs = gimple_call_lhs (call);
    6828            0 :   rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
    6829            0 :   if (lhs)
    6830              :     {
    6831            0 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6832            0 :       if (GET_MODE (boolret) != mode)
    6833            0 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6834            0 :       x = force_reg (mode, x);
    6835            0 :       write_complex_part (target, boolret, true, true);
    6836            0 :       write_complex_part (target, x, false, false);
    6837              :     }
    6838            0 : }
    6839              : 
    6840              : /* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function.  */
    6841              : 
    6842              : void
    6843        13951 : expand_ifn_atomic_compare_exchange (gcall *call)
    6844              : {
    6845        13951 :   int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
    6846        13951 :   gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
    6847        13951 :   machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
    6848              : 
    6849        13951 :   memmodel success = get_memmodel (gimple_call_arg (call, 4));
    6850        13951 :   memmodel failure = get_memmodel (gimple_call_arg (call, 5));
    6851              : 
    6852        13951 :   if (failure > success)
    6853            0 :     success = MEMMODEL_SEQ_CST;
    6854              : 
    6855        13951 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6856              :     {
    6857              :       failure = MEMMODEL_SEQ_CST;
    6858              :       success = MEMMODEL_SEQ_CST;
    6859              :     }
    6860              : 
    6861        13951 :   if (!flag_inline_atomics)
    6862              :     {
    6863            0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6864            0 :       return;
    6865              :     }
    6866              : 
    6867              :   /* Expand the operands.  */
    6868        13951 :   rtx mem = get_builtin_sync_mem (gimple_call_arg (call, 0), mode);
    6869              : 
    6870        13951 :   rtx expect = expand_expr_force_mode (gimple_call_arg (call, 1), mode);
    6871        13951 :   rtx desired = expand_expr_force_mode (gimple_call_arg (call, 2), mode);
    6872              : 
    6873        13951 :   bool is_weak = (tree_to_shwi (gimple_call_arg (call, 3)) & 256) != 0;
    6874              : 
    6875        13951 :   rtx boolret = NULL;
    6876        13951 :   rtx oldval = NULL;
    6877              : 
    6878        13951 :   if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
    6879              :                                        is_weak, success, failure))
    6880              :     {
    6881            0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6882            0 :       return;
    6883              :     }
    6884              : 
    6885        13951 :   tree lhs = gimple_call_lhs (call);
    6886        13951 :   if (lhs)
    6887              :     {
    6888        13742 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6889        13742 :       if (GET_MODE (boolret) != mode)
    6890        12294 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6891        13742 :       write_complex_part (target, boolret, true, true);
    6892        13742 :       write_complex_part (target, oldval, false, false);
    6893              :     }
    6894              : }
    6895              : 
    6896              : /* Expand the __atomic_load intrinsic:
    6897              :         TYPE __atomic_load (TYPE *object, enum memmodel)
    6898              :    EXP is the CALL_EXPR.
    6899              :    TARGET is an optional place for us to store the results.  */
    6900              : 
    6901              : static rtx
    6902        70962 : expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
    6903              : {
    6904        70962 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    6905        70962 :   if (is_mm_release (model) || is_mm_acq_rel (model))
    6906              :     model = MEMMODEL_SEQ_CST;
    6907              : 
    6908        70962 :   if (!flag_inline_atomics)
    6909              :     return NULL_RTX;
    6910              : 
    6911              :   /* Expand the operand.  */
    6912        70921 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6913              : 
    6914        70921 :   return expand_atomic_load (target, mem, model);
    6915              : }
    6916              : 
    6917              : 
    6918              : /* Expand the __atomic_store intrinsic:
    6919              :         void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
    6920              :    EXP is the CALL_EXPR.
    6921              :    TARGET is an optional place for us to store the results.  */
    6922              : 
    6923              : static rtx
    6924        17481 : expand_builtin_atomic_store (machine_mode mode, tree exp)
    6925              : {
    6926        17481 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6927        17481 :   if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
    6928         1599 :         || is_mm_release (model)))
    6929              :     model = MEMMODEL_SEQ_CST;
    6930              : 
    6931        17481 :   if (!flag_inline_atomics)
    6932              :     return NULL_RTX;
    6933              : 
    6934              :   /* Expand the operands.  */
    6935        17450 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6936        17450 :   rtx val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6937              : 
    6938        17450 :   return expand_atomic_store (mem, val, model, false);
    6939              : }
    6940              : 
    6941              : /* Expand the __atomic_fetch_XXX intrinsic:
    6942              :         TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
    6943              :    EXP is the CALL_EXPR.
    6944              :    TARGET is an optional place for us to store the results.
    6945              :    CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
    6946              :    FETCH_AFTER is true if returning the result of the operation.
    6947              :    FETCH_AFTER is false if returning the value before the operation.
    6948              :    IGNORE is true if the result is not used.
    6949              :    EXT_CALL is the correct builtin for an external call if this cannot be
    6950              :    resolved to an instruction sequence.  */
    6951              : 
    6952              : static rtx
    6953        29046 : expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
    6954              :                                 enum rtx_code code, bool fetch_after,
    6955              :                                 bool ignore, enum built_in_function ext_call)
    6956              : {
    6957        29046 :   rtx val, mem, ret;
    6958        29046 :   enum memmodel model;
    6959        29046 :   tree fndecl, addr, oldval;
    6960              : 
    6961        29046 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6962              : 
    6963              :   /* Expand the operands.  */
    6964        29046 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6965        29046 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6966              : 
    6967              :   /* Only try generating instructions if inlining is turned on.  */
    6968        29046 :   if (flag_inline_atomics)
    6969              :     {
    6970        28503 :       ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
    6971        28503 :       if (ret)
    6972              :         return ret;
    6973              :     }
    6974              : 
    6975              :   /* Return if a different routine isn't needed for the library call.  */
    6976         1159 :   if (ext_call == BUILT_IN_NONE)
    6977              :     return NULL_RTX;
    6978              : 
    6979              :   /* Change the call to the specified function.  */
    6980          288 :   fndecl = get_callee_fndecl (exp);
    6981          288 :   addr = CALL_EXPR_FN (exp);
    6982          288 :   STRIP_NOPS (addr);
    6983              : 
    6984          288 :   gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
    6985          288 :   TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
    6986          288 :   oldval = CALL_EXPR_ARG (exp, 1);
    6987              : 
    6988          288 :   if (!ignore && reg_overlap_mentioned_p (mem, val))
    6989              :     {
    6990            1 :       val = force_reg (mode, val);
    6991            1 :       CALL_EXPR_ARG (exp, 1) = make_tree (TREE_TYPE (oldval), val);
    6992              :     }
    6993              : 
    6994              :   /* If we will emit code after the call, the call cannot be a tail call.
    6995              :      If it is emitted as a tail call, a barrier is emitted after it, and
    6996              :      then all trailing code is removed.  */
    6997          288 :   if (!ignore)
    6998          191 :     CALL_EXPR_TAILCALL (exp) = 0;
    6999              : 
    7000              :   /* Expand the call here so we can emit trailing code.  */
    7001          288 :   ret = expand_call (exp, target, ignore);
    7002              : 
    7003              :   /* Replace the original function just in case it matters.  */
    7004          288 :   TREE_OPERAND (addr, 0) = fndecl;
    7005              : 
    7006              :   /* Then issue the arithmetic correction to return the right result.  */
    7007          288 :   if (!ignore)
    7008              :     {
    7009          191 :       CALL_EXPR_ARG (exp, 1) = oldval;
    7010          191 :       if (code == NOT)
    7011              :         {
    7012           33 :           ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
    7013              :                                      OPTAB_LIB_WIDEN);
    7014           33 :           ret = expand_simple_unop (mode, NOT, ret, target, true);
    7015              :         }
    7016              :       else
    7017          158 :         ret = expand_simple_binop (mode, code, ret, val, target, true,
    7018              :                                    OPTAB_LIB_WIDEN);
    7019              :     }
    7020              :   return ret;
    7021              : }
    7022              : 
    7023              : /* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function.  */
    7024              : 
    7025              : void
    7026          427 : expand_ifn_atomic_bit_test_and (gcall *call)
    7027              : {
    7028          427 :   tree ptr = gimple_call_arg (call, 0);
    7029          427 :   tree bit = gimple_call_arg (call, 1);
    7030          427 :   tree flag = gimple_call_arg (call, 2);
    7031          427 :   tree lhs = gimple_call_lhs (call);
    7032          427 :   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
    7033          427 :   machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
    7034          427 :   enum rtx_code code;
    7035          427 :   optab optab;
    7036          427 :   class expand_operand ops[5];
    7037              : 
    7038          427 :   gcc_assert (flag_inline_atomics);
    7039              : 
    7040          427 :   if (gimple_call_num_args (call) == 5)
    7041          296 :     model = get_memmodel (gimple_call_arg (call, 3));
    7042              : 
    7043          427 :   rtx mem = get_builtin_sync_mem (ptr, mode);
    7044          427 :   rtx val = expand_expr_force_mode (bit, mode);
    7045              : 
    7046          427 :   switch (gimple_call_internal_fn (call))
    7047              :     {
    7048              :     case IFN_ATOMIC_BIT_TEST_AND_SET:
    7049              :       code = IOR;
    7050              :       optab = atomic_bit_test_and_set_optab;
    7051              :       break;
    7052              :     case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
    7053              :       code = XOR;
    7054              :       optab = atomic_bit_test_and_complement_optab;
    7055              :       break;
    7056              :     case IFN_ATOMIC_BIT_TEST_AND_RESET:
    7057              :       code = AND;
    7058              :       optab = atomic_bit_test_and_reset_optab;
    7059              :       break;
    7060            0 :     default:
    7061            0 :       gcc_unreachable ();
    7062              :     }
    7063              : 
    7064          427 :   if (lhs == NULL_TREE)
    7065              :     {
    7066            0 :       rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7067              :                                       val, NULL_RTX, true, OPTAB_DIRECT);
    7068            0 :       if (code == AND)
    7069            0 :         val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
    7070            0 :       if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
    7071          427 :         return;
    7072              :     }
    7073              : 
    7074            0 :   rtx target;
    7075            0 :   if (lhs)
    7076          427 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    7077              :   else
    7078            0 :     target = gen_reg_rtx (mode);
    7079          427 :   enum insn_code icode = direct_optab_handler (optab, mode);
    7080          427 :   gcc_assert (icode != CODE_FOR_nothing);
    7081          427 :   create_output_operand (&ops[0], target, mode);
    7082          427 :   create_fixed_operand (&ops[1], mem);
    7083          427 :   create_convert_operand_to (&ops[2], val, mode, true);
    7084          427 :   create_integer_operand (&ops[3], model);
    7085          427 :   create_integer_operand (&ops[4], integer_onep (flag));
    7086          427 :   if (maybe_expand_insn (icode, 5, ops))
    7087              :     return;
    7088              : 
    7089            0 :   if (reg_overlap_mentioned_p (mem, val))
    7090            0 :     val = force_reg (mode, val);
    7091              : 
    7092            0 :   rtx bitval = val;
    7093            0 :   val = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7094              :                              val, NULL_RTX, true, OPTAB_DIRECT);
    7095            0 :   rtx maskval = val;
    7096            0 :   if (code == AND)
    7097            0 :     val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
    7098            0 :   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
    7099              :                                        code, model, false);
    7100            0 :   if (!result)
    7101              :     {
    7102            0 :       bool is_atomic = gimple_call_num_args (call) == 5;
    7103            0 :       tree tcall = gimple_call_arg (call, 3 + is_atomic);
    7104            0 :       tree fndecl = gimple_call_addr_fndecl (tcall);
    7105            0 :       tree type = TREE_TYPE (TREE_TYPE (fndecl));
    7106            0 :       tree exp;
    7107            0 :       if (is_atomic)
    7108            0 :         exp = build_call_nary (type, tcall, 3,
    7109              :                                ptr, make_tree (type, val),
    7110              :                                gimple_call_arg (call, 3));
    7111              :       else
    7112            0 :         exp = build_call_nary (type, tcall, 2, ptr, make_tree (type, val));
    7113            0 :       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
    7114              :                                mode, !lhs);
    7115              :     }
    7116            0 :   if (!lhs)
    7117              :     return;
    7118            0 :   if (integer_onep (flag))
    7119              :     {
    7120            0 :       result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
    7121              :                                     NULL_RTX, true, OPTAB_DIRECT);
    7122            0 :       result = expand_simple_binop (mode, AND, result, const1_rtx, target,
    7123              :                                     true, OPTAB_DIRECT);
    7124              :     }
    7125              :   else
    7126            0 :     result = expand_simple_binop (mode, AND, result, maskval, target, true,
    7127              :                                   OPTAB_DIRECT);
    7128            0 :   if (result != target)
    7129            0 :     emit_move_insn (target, result);
    7130              : }
    7131              : 
    7132              : /* Expand IFN_ATOMIC_*_FETCH_CMP_0 internal function.  */
    7133              : 
    7134              : void
    7135         2148 : expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
    7136              : {
    7137         2148 :   tree cmp = gimple_call_arg (call, 0);
    7138         2148 :   tree ptr = gimple_call_arg (call, 1);
    7139         2148 :   tree arg = gimple_call_arg (call, 2);
    7140         2148 :   tree lhs = gimple_call_lhs (call);
    7141         2148 :   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
    7142         2148 :   machine_mode mode = TYPE_MODE (TREE_TYPE (cmp));
    7143         2148 :   optab optab;
    7144         2148 :   rtx_code code;
    7145         2148 :   class expand_operand ops[5];
    7146              : 
    7147         2148 :   gcc_assert (flag_inline_atomics);
    7148              : 
    7149         2148 :   if (gimple_call_num_args (call) == 5)
    7150         1740 :     model = get_memmodel (gimple_call_arg (call, 3));
    7151              : 
    7152         2148 :   rtx mem = get_builtin_sync_mem (ptr, mode);
    7153         2148 :   rtx op = expand_expr_force_mode (arg, mode);
    7154              : 
    7155         2148 :   switch (gimple_call_internal_fn (call))
    7156              :     {
    7157              :     case IFN_ATOMIC_ADD_FETCH_CMP_0:
    7158              :       code = PLUS;
    7159              :       optab = atomic_add_fetch_cmp_0_optab;
    7160              :       break;
    7161              :     case IFN_ATOMIC_SUB_FETCH_CMP_0:
    7162              :       code = MINUS;
    7163              :       optab = atomic_sub_fetch_cmp_0_optab;
    7164              :       break;
    7165              :     case IFN_ATOMIC_AND_FETCH_CMP_0:
    7166              :       code = AND;
    7167              :       optab = atomic_and_fetch_cmp_0_optab;
    7168              :       break;
    7169              :     case IFN_ATOMIC_OR_FETCH_CMP_0:
    7170              :       code = IOR;
    7171              :       optab = atomic_or_fetch_cmp_0_optab;
    7172              :       break;
    7173              :     case IFN_ATOMIC_XOR_FETCH_CMP_0:
    7174              :       code = XOR;
    7175              :       optab = atomic_xor_fetch_cmp_0_optab;
    7176              :       break;
    7177            0 :     default:
    7178            0 :       gcc_unreachable ();
    7179              :     }
    7180              : 
    7181         2148 :   enum rtx_code comp = UNKNOWN;
    7182         2148 :   switch (tree_to_uhwi (cmp))
    7183              :     {
    7184              :     case ATOMIC_OP_FETCH_CMP_0_EQ: comp = EQ; break;
    7185              :     case ATOMIC_OP_FETCH_CMP_0_NE: comp = NE; break;
    7186              :     case ATOMIC_OP_FETCH_CMP_0_GT: comp = GT; break;
    7187              :     case ATOMIC_OP_FETCH_CMP_0_GE: comp = GE; break;
    7188              :     case ATOMIC_OP_FETCH_CMP_0_LT: comp = LT; break;
    7189              :     case ATOMIC_OP_FETCH_CMP_0_LE: comp = LE; break;
    7190            0 :     default: gcc_unreachable ();
    7191              :     }
    7192              : 
    7193         2148 :   rtx target;
    7194         2148 :   if (lhs == NULL_TREE)
    7195            0 :     target = gen_reg_rtx (TYPE_MODE (boolean_type_node));
    7196              :   else
    7197         2148 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    7198         2148 :   enum insn_code icode = direct_optab_handler (optab, mode);
    7199         2148 :   gcc_assert (icode != CODE_FOR_nothing);
    7200         2148 :   create_output_operand (&ops[0], target, TYPE_MODE (boolean_type_node));
    7201         2148 :   create_fixed_operand (&ops[1], mem);
    7202         2148 :   create_convert_operand_to (&ops[2], op, mode, true);
    7203         2148 :   create_integer_operand (&ops[3], model);
    7204         2148 :   create_integer_operand (&ops[4], comp);
    7205         2148 :   if (maybe_expand_insn (icode, 5, ops))
    7206         2116 :     return;
    7207              : 
    7208           32 :   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
    7209              :                                        code, model, true);
    7210           32 :   if (!result)
    7211              :     {
    7212            0 :       bool is_atomic = gimple_call_num_args (call) == 5;
    7213            0 :       tree tcall = gimple_call_arg (call, 3 + is_atomic);
    7214            0 :       tree fndecl = gimple_call_addr_fndecl (tcall);
    7215            0 :       tree type = TREE_TYPE (TREE_TYPE (fndecl));
    7216            0 :       tree exp;
    7217            0 :       if (is_atomic)
    7218            0 :         exp = build_call_nary (type, tcall, 3,
    7219              :                                ptr, arg,
    7220              :                                gimple_call_arg (call, 3));
    7221              :       else
    7222            0 :         exp = build_call_nary (type, tcall, 2, ptr, arg);
    7223            0 :       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
    7224              :                                mode, !lhs);
    7225              :     }
    7226              : 
    7227           32 :   if (lhs)
    7228              :     {
    7229           32 :       result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
    7230              :                                       0, 1);
    7231           32 :       if (result != target)
    7232           32 :         emit_move_insn (target, result);
    7233              :     }
    7234              : }
    7235              : 
    7236              : /* Expand an atomic clear operation.
    7237              :         void _atomic_clear (BOOL *obj, enum memmodel)
    7238              :    EXP is the call expression.  */
    7239              : 
    7240              : static rtx
    7241           53 : expand_builtin_atomic_clear (tree exp)
    7242              : {
    7243           53 :   machine_mode mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7244           53 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7245           53 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7246              : 
    7247           53 :   if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
    7248              :     model = MEMMODEL_SEQ_CST;
    7249              : 
    7250              :   /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
    7251              :      Failing that, a store is issued by __atomic_store.  The only way this can
    7252              :      fail is if the bool type is larger than a word size.  Unlikely, but
    7253              :      handle it anyway for completeness.  Assume a single threaded model since
    7254              :      there is no atomic support in this case, and no barriers are required.  */
    7255           53 :   rtx ret = expand_atomic_store (mem, const0_rtx, model, true);
    7256           53 :   if (!ret)
    7257            0 :     emit_move_insn (mem, const0_rtx);
    7258           53 :   return const0_rtx;
    7259              : }
    7260              : 
    7261              : /* Expand an atomic test_and_set operation.
    7262              :         bool _atomic_test_and_set (BOOL *obj, enum memmodel)
    7263              :    EXP is the call expression.  */
    7264              : 
    7265              : static rtx
    7266          266 : expand_builtin_atomic_test_and_set (tree exp, rtx target)
    7267              : {
    7268          266 :   rtx mem;
    7269          266 :   enum memmodel model;
    7270          266 :   machine_mode mode;
    7271              : 
    7272          266 :   mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7273          266 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7274          266 :   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7275              : 
    7276          266 :   return expand_atomic_test_and_set (target, mem, model);
    7277              : }
    7278              : 
    7279              : 
    7280              : /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
    7281              :    this architecture.  If ARG1 is NULL, use typical alignment for size ARG0.  */
    7282              : 
    7283              : static tree
    7284       144806 : fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
    7285              : {
    7286       144806 :   HOST_WIDE_INT size;
    7287       144806 :   machine_mode mode;
    7288       144806 :   unsigned int mode_align, type_align;
    7289              : 
    7290       144806 :   if (!tree_fits_shwi_p (arg0))
    7291              :     return NULL_TREE;
    7292              : 
    7293              :   /* We need a corresponding integer mode for the access to be lock-free.  */
    7294       144653 :   size = tree_to_shwi (arg0) * BITS_PER_UNIT;
    7295       144653 :   if (!int_mode_for_size (size, 0).exists (&mode))
    7296            9 :     return boolean_false_node;
    7297              : 
    7298       144644 :   mode_align = GET_MODE_ALIGNMENT (mode);
    7299              : 
    7300       144644 :   if (tree_fits_uhwi_p (arg1))
    7301              :     {
    7302       124838 :       unsigned HOST_WIDE_INT val = tree_to_uhwi (arg1);
    7303              : 
    7304              :       /* Either this argument is null, or it's a fake pointer encoding
    7305              :          the alignment of the object.  */
    7306       124838 :       val = least_bit_hwi (val);
    7307       124838 :       val *= BITS_PER_UNIT;
    7308              : 
    7309       124838 :       if (val == 0 || mode_align < val)
    7310              :         type_align = mode_align;
    7311              :       else
    7312        19049 :         type_align = val;
    7313              :     }
    7314              :   else
    7315              :     {
    7316        19806 :       tree ttype = TREE_TYPE (arg1);
    7317              : 
    7318              :       /* This function is usually invoked and folded immediately by the front
    7319              :          end before anything else has a chance to look at it.  The pointer
    7320              :          parameter at this point is usually cast to a void *, so check for that
    7321              :          and look past the cast.  */
    7322          195 :       if (CONVERT_EXPR_P (arg1)
    7323        19642 :           && POINTER_TYPE_P (ttype)
    7324        19642 :           && VOID_TYPE_P (TREE_TYPE (ttype))
    7325        39448 :           && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
    7326        19611 :         arg1 = TREE_OPERAND (arg1, 0);
    7327              : 
    7328        19806 :       ttype = TREE_TYPE (arg1);
    7329        19806 :       gcc_assert (POINTER_TYPE_P (ttype));
    7330              : 
    7331              :       /* Get the underlying type of the object.  */
    7332        19806 :       ttype = TREE_TYPE (ttype);
    7333        19806 :       type_align = TYPE_ALIGN (ttype);
    7334              :     }
    7335              : 
    7336              :   /* If the object has smaller alignment, the lock free routines cannot
    7337              :      be used.  */
    7338       144644 :   if (type_align < mode_align)
    7339          247 :     return boolean_false_node;
    7340              : 
    7341              :   /* Check if a compare_and_swap pattern exists for the mode which represents
    7342              :      the required size.  The pattern is not allowed to fail, so the existence
    7343              :      of the pattern indicates support is present.  Also require that an
    7344              :      atomic load exists for the required size.  */
    7345       144397 :   if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
    7346       144355 :     return boolean_true_node;
    7347              :   else
    7348           42 :     return boolean_false_node;
    7349              : }
    7350              : 
    7351              : /* Return true if the parameters to call EXP represent an object which will
    7352              :    always generate lock free instructions.  The first argument represents the
    7353              :    size of the object, and the second parameter is a pointer to the object
    7354              :    itself.  If NULL is passed for the object, then the result is based on
    7355              :    typical alignment for an object of the specified size.  Otherwise return
    7356              :    false.  */
    7357              : 
    7358              : static rtx
    7359            1 : expand_builtin_atomic_always_lock_free (tree exp)
    7360              : {
    7361            1 :   tree size;
    7362            1 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7363            1 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7364              : 
    7365            1 :   if (TREE_CODE (arg0) != INTEGER_CST)
    7366              :     {
    7367            1 :       error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
    7368            1 :       return const0_rtx;
    7369              :     }
    7370              : 
    7371            0 :   size = fold_builtin_atomic_always_lock_free (arg0, arg1);
    7372            0 :   if (size == boolean_true_node)
    7373            0 :     return const1_rtx;
    7374            0 :   return const0_rtx;
    7375              : }
    7376              : 
    7377              : /* Return a one or zero if it can be determined that object ARG1 of size ARG
    7378              :    is lock free on this architecture.  */
    7379              : 
    7380              : static tree
    7381        38954 : fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
    7382              : {
    7383        38954 :   if (!flag_inline_atomics)
    7384              :     return NULL_TREE;
    7385              : 
    7386              :   /* If it isn't always lock free, don't generate a result.  */
    7387        38945 :   if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
    7388        38586 :     return boolean_true_node;
    7389              : 
    7390              :   return NULL_TREE;
    7391              : }
    7392              : 
    7393              : /* Return true if the parameters to call EXP represent an object which will
    7394              :    always generate lock free instructions.  The first argument represents the
    7395              :    size of the object, and the second parameter is a pointer to the object
    7396              :    itself.  If NULL is passed for the object, then the result is based on
    7397              :    typical alignment for an object of the specified size.  Otherwise return
    7398              :    NULL*/
    7399              : 
    7400              : static rtx
    7401           10 : expand_builtin_atomic_is_lock_free (tree exp)
    7402              : {
    7403           10 :   tree size;
    7404           10 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7405           10 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7406              : 
    7407           10 :   if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
    7408              :     {
    7409            0 :       error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
    7410            0 :       return NULL_RTX;
    7411              :     }
    7412              : 
    7413           10 :   if (!flag_inline_atomics)
    7414              :     return NULL_RTX;
    7415              : 
    7416              :   /* If the value is known at compile time, return the RTX for it.  */
    7417            9 :   size = fold_builtin_atomic_is_lock_free (arg0, arg1);
    7418            9 :   if (size == boolean_true_node)
    7419            0 :     return const1_rtx;
    7420              : 
    7421              :   return NULL_RTX;
    7422              : }
    7423              : 
    7424              : /* Expand the __atomic_thread_fence intrinsic:
    7425              :         void __atomic_thread_fence (enum memmodel)
    7426              :    EXP is the CALL_EXPR.  */
    7427              : 
    7428              : static void
    7429          703 : expand_builtin_atomic_thread_fence (tree exp)
    7430              : {
    7431          703 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7432          703 :   expand_mem_thread_fence (model);
    7433          703 : }
    7434              : 
    7435              : /* Expand the __atomic_signal_fence intrinsic:
    7436              :         void __atomic_signal_fence (enum memmodel)
    7437              :    EXP is the CALL_EXPR.  */
    7438              : 
    7439              : static void
    7440           60 : expand_builtin_atomic_signal_fence (tree exp)
    7441              : {
    7442           60 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7443           60 :   expand_mem_signal_fence (model);
    7444           60 : }
    7445              : 
    7446              : /* Expand the __sync_synchronize intrinsic.  */
    7447              : 
    7448              : static void
    7449          275 : expand_builtin_sync_synchronize (void)
    7450              : {
    7451            0 :   expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
    7452            0 : }
    7453              : 
    7454              : static rtx
    7455            3 : expand_builtin_thread_pointer (tree exp, rtx target)
    7456              : {
    7457            3 :   enum insn_code icode;
    7458            3 :   if (!validate_arglist (exp, VOID_TYPE))
    7459            0 :     return const0_rtx;
    7460            3 :   icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
    7461            3 :   if (icode != CODE_FOR_nothing)
    7462              :     {
    7463            3 :       class expand_operand op;
    7464              :       /* If the target is not sutitable then create a new target. */
    7465            3 :       if (target == NULL_RTX
    7466            3 :           || !REG_P (target)
    7467            6 :           || GET_MODE (target) != Pmode)
    7468            0 :         target = gen_reg_rtx (Pmode);
    7469            3 :       create_output_operand (&op, target, Pmode);
    7470            3 :       expand_insn (icode, 1, &op);
    7471            3 :       return target;
    7472              :     }
    7473            0 :   error ("%<__builtin_thread_pointer%> is not supported on this target");
    7474            0 :   return const0_rtx;
    7475              : }
    7476              : 
    7477              : static void
    7478            0 : expand_builtin_set_thread_pointer (tree exp)
    7479              : {
    7480            0 :   enum insn_code icode;
    7481            0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    7482              :     return;
    7483            0 :   icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
    7484            0 :   if (icode != CODE_FOR_nothing)
    7485              :     {
    7486            0 :       class expand_operand op;
    7487            0 :       rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
    7488            0 :                              Pmode, EXPAND_NORMAL);
    7489            0 :       create_input_operand (&op, val, Pmode);
    7490            0 :       expand_insn (icode, 1, &op);
    7491            0 :       return;
    7492              :     }
    7493            0 :   error ("%<__builtin_set_thread_pointer%> is not supported on this target");
    7494              : }
    7495              : 
    7496              : 
    7497              : /* Emit code to restore the current value of stack.  */
    7498              : 
    7499              : static void
    7500         1755 : expand_stack_restore (tree var)
    7501              : {
    7502         1755 :   rtx_insn *prev;
    7503         1755 :   rtx sa = expand_normal (var);
    7504              : 
    7505         1811 :   sa = convert_memory_address (Pmode, sa);
    7506              : 
    7507         1755 :   prev = get_last_insn ();
    7508         1755 :   emit_stack_restore (SAVE_BLOCK, sa);
    7509              : 
    7510         1755 :   record_new_stack_level ();
    7511              : 
    7512         1755 :   fixup_args_size_notes (prev, get_last_insn (), 0);
    7513         1755 : }
    7514              : 
    7515              : /* Emit code to save the current value of stack.  */
    7516              : 
    7517              : static rtx
    7518         1856 : expand_stack_save (void)
    7519              : {
    7520         1856 :   rtx ret = NULL_RTX;
    7521              : 
    7522            0 :   emit_stack_save (SAVE_BLOCK, &ret);
    7523         1856 :   return ret;
    7524              : }
    7525              : 
    7526              : /* Emit code to get the openacc gang, worker or vector id or size.  */
    7527              : 
    7528              : static rtx
    7529          356 : expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
    7530              : {
    7531          356 :   const char *name;
    7532          356 :   rtx fallback_retval;
    7533          356 :   rtx_insn *(*gen_fn) (rtx, rtx);
    7534          356 :   switch (DECL_FUNCTION_CODE (get_callee_fndecl (exp)))
    7535              :     {
    7536          244 :     case BUILT_IN_GOACC_PARLEVEL_ID:
    7537          244 :       name = "__builtin_goacc_parlevel_id";
    7538          244 :       fallback_retval = const0_rtx;
    7539          244 :       gen_fn = targetm.gen_oacc_dim_pos;
    7540          244 :       break;
    7541          112 :     case BUILT_IN_GOACC_PARLEVEL_SIZE:
    7542          112 :       name = "__builtin_goacc_parlevel_size";
    7543          112 :       fallback_retval = const1_rtx;
    7544          112 :       gen_fn = targetm.gen_oacc_dim_size;
    7545          112 :       break;
    7546            0 :     default:
    7547            0 :       gcc_unreachable ();
    7548              :     }
    7549              : 
    7550          356 :   if (oacc_get_fn_attrib (current_function_decl) == NULL_TREE)
    7551              :     {
    7552            8 :       error ("%qs only supported in OpenACC code", name);
    7553            8 :       return const0_rtx;
    7554              :     }
    7555              : 
    7556          348 :   tree arg = CALL_EXPR_ARG (exp, 0);
    7557          348 :   if (TREE_CODE (arg) != INTEGER_CST)
    7558              :     {
    7559            8 :       error ("non-constant argument 0 to %qs", name);
    7560            8 :       return const0_rtx;
    7561              :     }
    7562              : 
    7563          340 :   int dim = TREE_INT_CST_LOW (arg);
    7564          340 :   switch (dim)
    7565              :     {
    7566          324 :     case GOMP_DIM_GANG:
    7567          324 :     case GOMP_DIM_WORKER:
    7568          324 :     case GOMP_DIM_VECTOR:
    7569          324 :       break;
    7570           16 :     default:
    7571           16 :       error ("illegal argument 0 to %qs", name);
    7572           16 :       return const0_rtx;
    7573              :     }
    7574              : 
    7575          324 :   if (ignore)
    7576              :     return target;
    7577              : 
    7578          180 :   if (target == NULL_RTX)
    7579            0 :     target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    7580              : 
    7581          180 :   if (!targetm.have_oacc_dim_size ())
    7582              :     {
    7583          180 :       emit_move_insn (target, fallback_retval);
    7584          180 :       return target;
    7585              :     }
    7586              : 
    7587            0 :   rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
    7588            0 :   emit_insn (gen_fn (reg, GEN_INT (dim)));
    7589            0 :   if (reg != target)
    7590            0 :     emit_move_insn (target, reg);
    7591              : 
    7592              :   return target;
    7593              : }
    7594              : 
    7595              : /* Expand a string compare operation using a sequence of char comparison
    7596              :    to get rid of the calling overhead, with result going to TARGET if
    7597              :    that's convenient.
    7598              : 
    7599              :    VAR_STR is the variable string source;
    7600              :    CONST_STR is the constant string source;
    7601              :    LENGTH is the number of chars to compare;
    7602              :    CONST_STR_N indicates which source string is the constant string;
    7603              :    IS_MEMCMP indicates whether it's a memcmp or strcmp.
    7604              : 
    7605              :    to: (assume const_str_n is 2, i.e., arg2 is a constant string)
    7606              : 
    7607              :    target = (int) (unsigned char) var_str[0]
    7608              :             - (int) (unsigned char) const_str[0];
    7609              :    if (target != 0)
    7610              :      goto ne_label;
    7611              :      ...
    7612              :    target = (int) (unsigned char) var_str[length - 2]
    7613              :             - (int) (unsigned char) const_str[length - 2];
    7614              :    if (target != 0)
    7615              :      goto ne_label;
    7616              :    target = (int) (unsigned char) var_str[length - 1]
    7617              :             - (int) (unsigned char) const_str[length - 1];
    7618              :    ne_label:
    7619              :   */
    7620              : 
    7621              : static rtx
    7622          635 : inline_string_cmp (rtx target, tree var_str, const char *const_str,
    7623              :                    unsigned HOST_WIDE_INT length,
    7624              :                    int const_str_n, machine_mode mode)
    7625              : {
    7626          635 :   HOST_WIDE_INT offset = 0;
    7627          635 :   rtx var_rtx_array
    7628          635 :     = get_memory_rtx (var_str, build_int_cst (unsigned_type_node, length),
    7629              :                       false);
    7630          635 :   rtx var_rtx = NULL_RTX;
    7631          635 :   rtx const_rtx = NULL_RTX;
    7632          635 :   rtx result = target ? target : gen_reg_rtx (mode);
    7633          635 :   rtx_code_label *ne_label = gen_label_rtx ();
    7634          635 :   tree unit_type_node = unsigned_char_type_node;
    7635          635 :   scalar_int_mode unit_mode
    7636          635 :     = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
    7637              : 
    7638          635 :   start_sequence ();
    7639              : 
    7640         2964 :   for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
    7641              :     {
    7642         1694 :       var_rtx
    7643         1694 :         = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
    7644         1694 :       const_rtx = c_readstr (const_str + offset, unit_mode);
    7645         1694 :       rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
    7646         1544 :       rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
    7647              : 
    7648         1694 :       op0 = convert_modes (mode, unit_mode, op0, 1);
    7649         1694 :       op1 = convert_modes (mode, unit_mode, op1, 1);
    7650         1694 :       rtx diff = expand_simple_binop (mode, MINUS, op0, op1,
    7651              :                                       result, 1, OPTAB_WIDEN);
    7652              : 
    7653              :       /* Force the difference into result register.  We cannot reassign
    7654              :          result here ("result = diff") or we may end up returning
    7655              :          uninitialized result when expand_simple_binop allocates a new
    7656              :          pseudo-register for returning.  */
    7657         1694 :       if (diff != result)
    7658            0 :         emit_move_insn (result, diff);
    7659              : 
    7660         1694 :       if (i < length - 1)
    7661         1059 :         emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
    7662              :                                  mode, true, ne_label);
    7663         3388 :       offset += GET_MODE_SIZE (unit_mode);
    7664              :     }
    7665              : 
    7666          635 :   emit_label (ne_label);
    7667          635 :   rtx_insn *insns = end_sequence ();
    7668          635 :   emit_insn (insns);
    7669              : 
    7670          635 :   return result;
    7671              : }
    7672              : 
    7673              : /* Inline expansion of a call to str(n)cmp and memcmp, with result going
    7674              :    to TARGET if that's convenient.
    7675              :    If the call is not been inlined, return NULL_RTX.  */
    7676              : 
    7677              : static rtx
    7678       145281 : inline_expand_builtin_bytecmp (tree exp, rtx target)
    7679              : {
    7680       145281 :   tree fndecl = get_callee_fndecl (exp);
    7681       145281 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7682       145281 :   bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
    7683              : 
    7684              :   /* Do NOT apply this inlining expansion when optimizing for size or
    7685              :      optimization level below 2 or if unused *cmp hasn't been DCEd.  */
    7686       145281 :   if (optimize < 2 || optimize_insn_for_size_p () || target == const0_rtx)
    7687              :     return NULL_RTX;
    7688              : 
    7689        23144 :   gcc_checking_assert (fcode == BUILT_IN_STRCMP
    7690              :                        || fcode == BUILT_IN_STRNCMP
    7691              :                        || fcode == BUILT_IN_MEMCMP);
    7692              : 
    7693              :   /* On a target where the type of the call (int) has same or narrower precision
    7694              :      than unsigned char, give up the inlining expansion.  */
    7695        23144 :   if (TYPE_PRECISION (unsigned_char_type_node)
    7696        23144 :       >= TYPE_PRECISION (TREE_TYPE (exp)))
    7697              :     return NULL_RTX;
    7698              : 
    7699        23144 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    7700        23144 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    7701        23144 :   tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
    7702              : 
    7703        23144 :   unsigned HOST_WIDE_INT len1 = 0;
    7704        23144 :   unsigned HOST_WIDE_INT len2 = 0;
    7705        23144 :   unsigned HOST_WIDE_INT len3 = 0;
    7706              : 
    7707              :   /* Get the object representation of the initializers of ARG1 and ARG2
    7708              :      as strings, provided they refer to constant objects, with their byte
    7709              :      sizes in LEN1 and LEN2, respectively.  */
    7710        23144 :   const char *bytes1 = getbyterep (arg1, &len1);
    7711        23144 :   const char *bytes2 = getbyterep (arg2, &len2);
    7712              : 
    7713              :   /* Fail if neither argument refers to an initialized constant.  */
    7714        23144 :   if (!bytes1 && !bytes2)
    7715              :     return NULL_RTX;
    7716              : 
    7717        18501 :   if (is_ncmp)
    7718              :     {
    7719              :       /* Fail if the memcmp/strncmp bound is not a constant.  */
    7720         1384 :       if (!tree_fits_uhwi_p (len3_tree))
    7721              :         return NULL_RTX;
    7722              : 
    7723          962 :       len3 = tree_to_uhwi (len3_tree);
    7724              : 
    7725          962 :       if (fcode == BUILT_IN_MEMCMP)
    7726              :         {
    7727              :           /* Fail if the memcmp bound is greater than the size of either
    7728              :              of the two constant objects.  */
    7729          462 :           if ((bytes1 && len1 < len3)
    7730          462 :               || (bytes2 && len2 < len3))
    7731              :             return NULL_RTX;
    7732              :         }
    7733              :     }
    7734              : 
    7735              :   if (fcode != BUILT_IN_MEMCMP)
    7736              :     {
    7737              :       /* For string functions (i.e., strcmp and strncmp) reduce LEN1
    7738              :          and LEN2 to the length of the nul-terminated string stored
    7739              :          in each.  */
    7740        17617 :       if (bytes1 != NULL)
    7741          236 :         len1 = strnlen (bytes1, len1) + 1;
    7742        17617 :       if (bytes2 != NULL)
    7743        17384 :         len2 = strnlen (bytes2, len2) + 1;
    7744              :     }
    7745              : 
    7746              :   /* See inline_string_cmp.  */
    7747        18075 :   int const_str_n;
    7748        18075 :   if (!len1)
    7749              :     const_str_n = 2;
    7750          241 :   else if (!len2)
    7751              :     const_str_n = 1;
    7752            3 :   else if (len2 > len1)
    7753              :     const_str_n = 1;
    7754              :   else
    7755              :     const_str_n = 2;
    7756              : 
    7757              :   /* For strncmp only, compute the new bound as the smallest of
    7758              :      the lengths of the two strings (plus 1) and the bound provided
    7759              :      to the function.  */
    7760        17836 :   unsigned HOST_WIDE_INT bound = (const_str_n == 1) ? len1 : len2;
    7761        18075 :   if (is_ncmp && len3 < bound)
    7762          534 :     bound = len3;
    7763              : 
    7764              :   /* If the bound of the comparison is larger than the threshold,
    7765              :      do nothing.  */
    7766        18075 :   if (bound > (unsigned HOST_WIDE_INT) param_builtin_string_cmp_inline_length)
    7767              :     return NULL_RTX;
    7768              : 
    7769          635 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    7770              : 
    7771              :   /* Now, start inline expansion the call.  */
    7772         1213 :   return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
    7773              :                             (const_str_n == 1) ? bytes1 : bytes2, bound,
    7774          635 :                             const_str_n, mode);
    7775              : }
    7776              : 
    7777              : /* Expand a call to __builtin_speculation_safe_value_<N>.  MODE
    7778              :    represents the size of the first argument to that call, or VOIDmode
    7779              :    if the argument is a pointer.  IGNORE will be true if the result
    7780              :    isn't used.  */
    7781              : static rtx
    7782           35 : expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
    7783              :                                bool ignore)
    7784              : {
    7785           35 :   rtx val, failsafe;
    7786           35 :   unsigned nargs = call_expr_nargs (exp);
    7787              : 
    7788           35 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7789              : 
    7790           35 :   if (mode == VOIDmode)
    7791              :     {
    7792            4 :       mode = TYPE_MODE (TREE_TYPE (arg0));
    7793            4 :       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
    7794              :     }
    7795              : 
    7796           35 :   val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    7797              : 
    7798              :   /* An optional second argument can be used as a failsafe value on
    7799              :      some machines.  If it isn't present, then the failsafe value is
    7800              :      assumed to be 0.  */
    7801           35 :   if (nargs > 1)
    7802              :     {
    7803            4 :       tree arg1 = CALL_EXPR_ARG (exp, 1);
    7804            4 :       failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
    7805              :     }
    7806              :   else
    7807           31 :     failsafe = const0_rtx;
    7808              : 
    7809              :   /* If the result isn't used, the behavior is undefined.  It would be
    7810              :      nice to emit a warning here, but path splitting means this might
    7811              :      happen with legitimate code.  So simply drop the builtin
    7812              :      expansion in that case; we've handled any side-effects above.  */
    7813           35 :   if (ignore)
    7814            0 :     return const0_rtx;
    7815              : 
    7816              :   /* If we don't have a suitable target, create one to hold the result.  */
    7817           35 :   if (target == NULL || GET_MODE (target) != mode)
    7818            0 :     target = gen_reg_rtx (mode);
    7819              : 
    7820           35 :   if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
    7821            0 :     val = convert_modes (mode, VOIDmode, val, false);
    7822              : 
    7823           35 :   return targetm.speculation_safe_value (mode, target, val, failsafe);
    7824              : }
    7825              : 
    7826              : /* Expand CRC* or REV_CRC* built-ins.  */
    7827              : 
    7828              : rtx
    7829           45 : expand_builtin_crc_table_based (internal_fn fn, scalar_mode crc_mode,
    7830              :                                 scalar_mode data_mode, machine_mode mode,
    7831              :                                 tree exp, rtx target)
    7832              : {
    7833           45 :   tree rhs1 = CALL_EXPR_ARG (exp, 0); // crc
    7834           45 :   tree rhs2 = CALL_EXPR_ARG (exp, 1); // data
    7835           45 :   tree rhs3 = CALL_EXPR_ARG (exp, 2); // polynomial
    7836              : 
    7837           45 :   if (!target || mode == VOIDmode)
    7838            0 :     target = gen_reg_rtx (crc_mode);
    7839              : 
    7840           45 :   rtx op1 = expand_normal (rhs1);
    7841           45 :   rtx op2 = expand_normal (rhs2);
    7842           45 :   rtx op3;
    7843           45 :   if (TREE_CODE (rhs3) != INTEGER_CST)
    7844              :     {
    7845            1 :       error ("third argument to %<crc%> builtins must be a constant");
    7846            1 :       op3 = const0_rtx;
    7847              :     }
    7848              :   else
    7849           44 :     op3 = convert_to_mode (crc_mode, expand_normal (rhs3), 0);
    7850              : 
    7851           45 :   if (CONST_INT_P (op2))
    7852           32 :     op2 = convert_to_mode (crc_mode, op2, 0);
    7853              : 
    7854           45 :   if (fn == IFN_CRC)
    7855           28 :     expand_crc_table_based (target, op1, op2, op3, data_mode);
    7856              :   else
    7857              :     /* If it's IFN_CRC_REV generate bit-reversed CRC.  */
    7858           17 :     expand_reversed_crc_table_based (target, op1, op2, op3,
    7859              :                                      data_mode);
    7860           45 :   return target;
    7861              : }
    7862              : 
    7863              : /* Expand an expression EXP that calls a built-in function,
    7864              :    with result going to TARGET if that's convenient
    7865              :    (and in mode MODE if that's convenient).
    7866              :    SUBTARGET may be used as the target for computing one of EXP's operands.
    7867              :    IGNORE is nonzero if the value is to be ignored.  */
    7868              : 
    7869              : rtx
    7870      2036546 : expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
    7871              :                 int ignore)
    7872              : {
    7873      2036546 :   tree fndecl = get_callee_fndecl (exp);
    7874      2036546 :   machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
    7875      2036546 :   int flags;
    7876              : 
    7877      2036546 :   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
    7878       177332 :     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
    7879              : 
    7880              :   /* When ASan is enabled, we don't want to expand some memory/string
    7881              :      builtins and rely on libsanitizer's hooks.  This allows us to avoid
    7882              :      redundant checks and be sure, that possible overflow will be detected
    7883              :      by ASan.  */
    7884              : 
    7885      1859214 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7886      1859214 :   if (param_asan_kernel_mem_intrinsic_prefix
    7887      1859214 :       && sanitize_flags_p (SANITIZE_KERNEL_ADDRESS
    7888              :                            | SANITIZE_KERNEL_HWADDRESS))
    7889           42 :     switch (fcode)
    7890              :       {
    7891           42 :         rtx save_decl_rtl, ret;
    7892           42 :       case BUILT_IN_MEMCPY:
    7893           42 :       case BUILT_IN_MEMMOVE:
    7894           42 :       case BUILT_IN_MEMSET:
    7895           42 :         save_decl_rtl = DECL_RTL (fndecl);
    7896           42 :         DECL_RTL (fndecl) = asan_memfn_rtl (fndecl);
    7897           42 :         ret = expand_call (exp, target, ignore);
    7898           42 :         DECL_RTL (fndecl) = save_decl_rtl;
    7899           42 :         return ret;
    7900              :       default:
    7901              :         break;
    7902              :       }
    7903      1859172 :   if (sanitize_flags_p (SANITIZE_ADDRESS | SANITIZE_HWADDRESS)
    7904      1859172 :                   && asan_intercepted_p (fcode))
    7905          938 :     return expand_call (exp, target, ignore);
    7906              : 
    7907              :   /* When not optimizing, generate calls to library functions for a certain
    7908              :      set of builtins.  */
    7909      1858234 :   if (!optimize
    7910       430486 :       && !called_as_built_in (fndecl)
    7911       145806 :       && fcode != BUILT_IN_FORK
    7912       145806 :       && fcode != BUILT_IN_EXECL
    7913       145793 :       && fcode != BUILT_IN_EXECV
    7914       145793 :       && fcode != BUILT_IN_EXECLP
    7915       145791 :       && fcode != BUILT_IN_EXECLE
    7916       145791 :       && fcode != BUILT_IN_EXECVP
    7917       145790 :       && fcode != BUILT_IN_EXECVE
    7918       145790 :       && fcode != BUILT_IN_CLEAR_CACHE
    7919       145787 :       && !ALLOCA_FUNCTION_CODE_P (fcode)
    7920       145733 :       && fcode != BUILT_IN_FREE
    7921       143590 :       && (fcode != BUILT_IN_MEMSET
    7922        55891 :           || !(flag_inline_stringops & ILSOP_MEMSET))
    7923       143587 :       && (fcode != BUILT_IN_MEMCPY
    7924          918 :           || !(flag_inline_stringops & ILSOP_MEMCPY))
    7925       143451 :       && (fcode != BUILT_IN_MEMMOVE
    7926          348 :           || !(flag_inline_stringops & ILSOP_MEMMOVE))
    7927      2001685 :       && (fcode != BUILT_IN_MEMCMP
    7928         2529 :           || !(flag_inline_stringops & ILSOP_MEMCMP)))
    7929       143403 :     return expand_call (exp, target, ignore);
    7930              : 
    7931              :   /* The built-in function expanders test for target == const0_rtx
    7932              :      to determine whether the function's result will be ignored.  */
    7933      1714831 :   if (ignore)
    7934      1016882 :     target = const0_rtx;
    7935              : 
    7936              :   /* If the result of a pure or const built-in function is ignored, and
    7937              :      none of its arguments are volatile, we can avoid expanding the
    7938              :      built-in call and just evaluate the arguments for side-effects.  */
    7939      1714831 :   if (target == const0_rtx
    7940      1016882 :       && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
    7941      1718578 :       && !(flags & ECF_LOOPING_CONST_OR_PURE))
    7942              :     {
    7943            6 :       bool volatilep = false;
    7944            6 :       tree arg;
    7945            6 :       call_expr_arg_iterator iter;
    7946              : 
    7947           20 :       FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
    7948            8 :         if (TREE_THIS_VOLATILE (arg))
    7949              :           {
    7950              :             volatilep = true;
    7951              :             break;
    7952              :           }
    7953              : 
    7954            6 :       if (! volatilep)
    7955              :         {
    7956           20 :           FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
    7957            8 :             expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
    7958            6 :           return const0_rtx;
    7959              :         }
    7960              :     }
    7961              : 
    7962      1714825 :   switch (fcode)
    7963              :     {
    7964            4 :     CASE_FLT_FN (BUILT_IN_FABS):
    7965            4 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
    7966            4 :     case BUILT_IN_FABSD32:
    7967            4 :     case BUILT_IN_FABSD64:
    7968            4 :     case BUILT_IN_FABSD128:
    7969            4 :     case BUILT_IN_FABSD64X:
    7970            4 :       target = expand_builtin_fabs (exp, target, subtarget);
    7971            4 :       if (target)
    7972       856841 :         return target;
    7973       857984 :       break;
    7974              : 
    7975        11677 :     CASE_FLT_FN (BUILT_IN_COPYSIGN):
    7976        11677 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
    7977        11677 :       target = expand_builtin_copysign (exp, target, subtarget);
    7978        11677 :       if (target)
    7979              :         return target;
    7980              :       break;
    7981              : 
    7982              :       /* Just do a normal library call if we were unable to fold
    7983              :          the values.  */
    7984              :     CASE_FLT_FN (BUILT_IN_CABS):
    7985              :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_CABS):
    7986              :       break;
    7987              : 
    7988          368 :     CASE_FLT_FN (BUILT_IN_FMA):
    7989          368 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
    7990          368 :       target = expand_builtin_mathfn_ternary (exp, target, subtarget);
    7991          368 :       if (target)
    7992              :         return target;
    7993              :       break;
    7994              : 
    7995          232 :     CASE_FLT_FN (BUILT_IN_ILOGB):
    7996          232 :       if (! flag_unsafe_math_optimizations)
    7997              :         break;
    7998            4 :       gcc_fallthrough ();
    7999            4 :     CASE_FLT_FN (BUILT_IN_ISINF):
    8000            4 :     CASE_FLT_FN (BUILT_IN_FINITE):
    8001            4 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    8002            4 :     case BUILT_IN_ISFINITE:
    8003            4 :     case BUILT_IN_ISNORMAL:
    8004            4 :       target = expand_builtin_interclass_mathfn (exp, target);
    8005            4 :       if (target)
    8006              :         return target;
    8007              :       break;
    8008              : 
    8009          784 :     case BUILT_IN_ISSIGNALING:
    8010          784 :       target = expand_builtin_issignaling (exp, target);
    8011          784 :       if (target)
    8012              :         return target;
    8013              :       break;
    8014              : 
    8015          223 :     CASE_FLT_FN (BUILT_IN_ICEIL):
    8016          223 :     CASE_FLT_FN (BUILT_IN_LCEIL):
    8017          223 :     CASE_FLT_FN (BUILT_IN_LLCEIL):
    8018          223 :     CASE_FLT_FN (BUILT_IN_LFLOOR):
    8019          223 :     CASE_FLT_FN (BUILT_IN_IFLOOR):
    8020          223 :     CASE_FLT_FN (BUILT_IN_LLFLOOR):
    8021          223 :       target = expand_builtin_int_roundingfn (exp, target);
    8022          223 :       if (target)
    8023              :         return target;
    8024              :       break;
    8025              : 
    8026          588 :     CASE_FLT_FN (BUILT_IN_IRINT):
    8027          588 :     CASE_FLT_FN (BUILT_IN_LRINT):
    8028          588 :     CASE_FLT_FN (BUILT_IN_LLRINT):
    8029          588 :     CASE_FLT_FN (BUILT_IN_IROUND):
    8030          588 :     CASE_FLT_FN (BUILT_IN_LROUND):
    8031          588 :     CASE_FLT_FN (BUILT_IN_LLROUND):
    8032          588 :       target = expand_builtin_int_roundingfn_2 (exp, target);
    8033          588 :       if (target)
    8034              :         return target;
    8035              :       break;
    8036              : 
    8037          292 :     CASE_FLT_FN (BUILT_IN_POWI):
    8038          292 :       target = expand_builtin_powi (exp, target);
    8039          292 :       if (target)
    8040              :         return target;
    8041              :       break;
    8042              : 
    8043          170 :     CASE_FLT_FN (BUILT_IN_CEXPI):
    8044          170 :       target = expand_builtin_cexpi (exp, target);
    8045          170 :       gcc_assert (target);
    8046              :       return target;
    8047              : 
    8048         1017 :     CASE_FLT_FN (BUILT_IN_SIN):
    8049         1017 :     CASE_FLT_FN (BUILT_IN_COS):
    8050         1017 :       if (! flag_unsafe_math_optimizations)
    8051              :         break;
    8052           47 :       target = expand_builtin_mathfn_3 (exp, target, subtarget);
    8053           47 :       if (target)
    8054              :         return target;
    8055              :       break;
    8056              : 
    8057          164 :     CASE_FLT_FN (BUILT_IN_SINCOS):
    8058          164 :       if (! flag_unsafe_math_optimizations)
    8059              :         break;
    8060            3 :       target = expand_builtin_sincos (exp);
    8061            3 :       if (target)
    8062              :         return target;
    8063              :       break;
    8064              : 
    8065           60 :     case BUILT_IN_FEGETROUND:
    8066           60 :       target = expand_builtin_fegetround (exp, target, target_mode);
    8067           60 :       if (target)
    8068              :         return target;
    8069              :       break;
    8070              : 
    8071         1065 :     case BUILT_IN_FECLEAREXCEPT:
    8072         1065 :       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
    8073              :                                                       feclearexcept_optab);
    8074         1065 :       if (target)
    8075              :         return target;
    8076              :       break;
    8077              : 
    8078          831 :     case BUILT_IN_FERAISEEXCEPT:
    8079          831 :       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
    8080              :                                                       feraiseexcept_optab);
    8081          831 :       if (target)
    8082              :         return target;
    8083              :       break;
    8084              : 
    8085          464 :     case BUILT_IN_APPLY_ARGS:
    8086          464 :       return expand_builtin_apply_args ();
    8087              : 
    8088              :       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
    8089              :          FUNCTION with a copy of the parameters described by
    8090              :          ARGUMENTS, and ARGSIZE.  It returns a block of memory
    8091              :          allocated on the stack into which is stored all the registers
    8092              :          that might possibly be used for returning the result of a
    8093              :          function.  ARGUMENTS is the value returned by
    8094              :          __builtin_apply_args.  ARGSIZE is the number of bytes of
    8095              :          arguments that must be copied.  ??? How should this value be
    8096              :          computed?  We'll also need a safe worst case value for varargs
    8097              :          functions.  */
    8098          483 :     case BUILT_IN_APPLY:
    8099          483 :       if (!validate_arglist (exp, POINTER_TYPE,
    8100              :                              POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
    8101          483 :           && !validate_arglist (exp, REFERENCE_TYPE,
    8102              :                                 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    8103            0 :         return const0_rtx;
    8104              :       else
    8105              :         {
    8106          483 :           rtx ops[3];
    8107              : 
    8108          483 :           ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
    8109          483 :           ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
    8110          483 :           ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
    8111              : 
    8112          483 :           return expand_builtin_apply (ops[0], ops[1], ops[2]);
    8113              :         }
    8114              : 
    8115              :       /* __builtin_return (RESULT) causes the function to return the
    8116              :          value described by RESULT.  RESULT is address of the block of
    8117              :          memory returned by __builtin_apply.  */
    8118          379 :     case BUILT_IN_RETURN:
    8119          379 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8120          379 :         expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
    8121          379 :       return const0_rtx;
    8122              : 
    8123            0 :     case BUILT_IN_CALL_CODE_ADDRESS:
    8124              :       /* All valid uses of __builtin_call_code_address () are removed in
    8125              :          in tree-nested.cc or gimple-fold.cc.  */
    8126            0 :       error ("argument to %<__builtin_call_code_address%> must be a function");
    8127            0 :       return const0_rtx;
    8128              : 
    8129            0 :     case BUILT_IN_CALL_STATIC_CHAIN:
    8130              :        /* All valid uses of __builtin_call_static_chain () are removed in
    8131              :           in tree-nested.cc or gimple-fold.cc.  */
    8132            0 :       error ("argument to %<__builtin_call_static_chain%> must be a function");
    8133            0 :       return const0_rtx;
    8134              : 
    8135            0 :     case BUILT_IN_SAVEREGS:
    8136            0 :       return expand_builtin_saveregs ();
    8137              : 
    8138           16 :     case BUILT_IN_VA_ARG_PACK:
    8139              :       /* All valid uses of __builtin_va_arg_pack () are removed during
    8140              :          inlining.  */
    8141           16 :       error ("invalid use of %<__builtin_va_arg_pack ()%>");
    8142           16 :       return const0_rtx;
    8143              : 
    8144            0 :     case BUILT_IN_VA_ARG_PACK_LEN:
    8145              :       /* All valid uses of __builtin_va_arg_pack_len () are removed during
    8146              :          inlining.  */
    8147            0 :       error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
    8148            0 :       return const0_rtx;
    8149              : 
    8150              :       /* Return the address of the first anonymous stack arg.  */
    8151          158 :     case BUILT_IN_NEXT_ARG:
    8152          158 :       if (fold_builtin_next_arg (exp, false))
    8153            0 :         return const0_rtx;
    8154          158 :       return expand_builtin_next_arg ();
    8155              : 
    8156           28 :     case BUILT_IN_CLEAR_CACHE:
    8157           28 :       expand_builtin___clear_cache (exp);
    8158           28 :       return const0_rtx;
    8159              : 
    8160            0 :     case BUILT_IN_CLASSIFY_TYPE:
    8161            0 :       return expand_builtin_classify_type (exp);
    8162              : 
    8163            0 :     case BUILT_IN_CONSTANT_P:
    8164            0 :       return const0_rtx;
    8165              : 
    8166        15936 :     case BUILT_IN_FRAME_ADDRESS:
    8167        15936 :     case BUILT_IN_RETURN_ADDRESS:
    8168        15936 :       return expand_builtin_frame_address (fndecl, exp);
    8169              : 
    8170          540 :     case BUILT_IN_STACK_ADDRESS:
    8171          540 :       return expand_builtin_stack_address ();
    8172              : 
    8173         2170 :     case BUILT_IN___STRUB_ENTER:
    8174         2170 :       target = expand_builtin_strub_enter (exp);
    8175         2170 :       if (target)
    8176              :         return target;
    8177              :       break;
    8178              : 
    8179         1084 :     case BUILT_IN___STRUB_UPDATE:
    8180         1084 :       target = expand_builtin_strub_update (exp);
    8181         1084 :       if (target)
    8182              :         return target;
    8183              :       break;
    8184              : 
    8185         2740 :     case BUILT_IN___STRUB_LEAVE:
    8186         2740 :       target = expand_builtin_strub_leave (exp);
    8187         2740 :       if (target)
    8188              :         return target;
    8189              :       break;
    8190              : 
    8191              :     /* Returns the address of the area where the structure is returned.
    8192              :        0 otherwise.  */
    8193            0 :     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
    8194            0 :       if (call_expr_nargs (exp) != 0
    8195            0 :           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
    8196            0 :           || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
    8197            0 :         return const0_rtx;
    8198              :       else
    8199            0 :         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
    8200              : 
    8201        27543 :     CASE_BUILT_IN_ALLOCA:
    8202        27543 :       target = expand_builtin_alloca (exp);
    8203        27543 :       if (target)
    8204              :         return target;
    8205              :       break;
    8206              : 
    8207          204 :     case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
    8208          204 :       return expand_asan_emit_allocas_unpoison (exp);
    8209              : 
    8210         1856 :     case BUILT_IN_STACK_SAVE:
    8211         1856 :       return expand_stack_save ();
    8212              : 
    8213         1755 :     case BUILT_IN_STACK_RESTORE:
    8214         1755 :       expand_stack_restore (CALL_EXPR_ARG (exp, 0));
    8215         1755 :       return const0_rtx;
    8216              : 
    8217         1276 :     case BUILT_IN_BSWAP16:
    8218         1276 :     case BUILT_IN_BSWAP32:
    8219         1276 :     case BUILT_IN_BSWAP64:
    8220         1276 :     case BUILT_IN_BSWAP128:
    8221         1276 :       target = expand_builtin_bswap (target_mode, exp, target, subtarget);
    8222         1276 :       if (target)
    8223              :         return target;
    8224              :       break;
    8225              : 
    8226           54 :     case BUILT_IN_BITREVERSE8:
    8227           54 :     case BUILT_IN_BITREVERSE16:
    8228           54 :     case BUILT_IN_BITREVERSE32:
    8229           54 :     case BUILT_IN_BITREVERSE64:
    8230           54 :     case BUILT_IN_BITREVERSE128:
    8231           54 :       target = expand_builtin_unop (target_mode, exp, target, subtarget,
    8232              :                                     bitreverse_optab);
    8233           54 :       if (target)
    8234              :         return target;
    8235              :       break;
    8236              : 
    8237            0 :     CASE_INT_FN (BUILT_IN_FFS):
    8238            0 :       target = expand_builtin_unop (target_mode, exp, target,
    8239              :                                     subtarget, ffs_optab);
    8240            0 :       if (target)
    8241              :         return target;
    8242              :       break;
    8243              : 
    8244          205 :     CASE_INT_FN (BUILT_IN_CLZ):
    8245          205 :       target = expand_builtin_unop (target_mode, exp, target,
    8246              :                                     subtarget, clz_optab);
    8247          205 :       if (target)
    8248              :         return target;
    8249              :       break;
    8250              : 
    8251           48 :     CASE_INT_FN (BUILT_IN_CTZ):
    8252           48 :       target = expand_builtin_unop (target_mode, exp, target,
    8253              :                                     subtarget, ctz_optab);
    8254           48 :       if (target)
    8255              :         return target;
    8256              :       break;
    8257              : 
    8258           91 :     CASE_INT_FN (BUILT_IN_CLRSB):
    8259           91 :       target = expand_builtin_unop (target_mode, exp, target,
    8260              :                                     subtarget, clrsb_optab);
    8261           91 :       if (target)
    8262              :         return target;
    8263              :       break;
    8264              : 
    8265          453 :     CASE_INT_FN (BUILT_IN_POPCOUNT):
    8266          453 :       target = expand_builtin_unop (target_mode, exp, target,
    8267              :                                     subtarget, popcount_optab);
    8268          453 :       if (target)
    8269              :         return target;
    8270              :       break;
    8271              : 
    8272           11 :     CASE_INT_FN (BUILT_IN_PARITY):
    8273           11 :       target = expand_builtin_unop (target_mode, exp, target,
    8274              :                                     subtarget, parity_optab);
    8275           11 :       if (target)
    8276              :         return target;
    8277              :       break;
    8278              : 
    8279        14752 :     case BUILT_IN_STRLEN:
    8280        14752 :       target = expand_builtin_strlen (exp, target, target_mode);
    8281        14752 :       if (target)
    8282              :         return target;
    8283              :       break;
    8284              : 
    8285          580 :     case BUILT_IN_STRNLEN:
    8286          580 :       target = expand_builtin_strnlen (exp, target, target_mode);
    8287          580 :       if (target)
    8288              :         return target;
    8289              :       break;
    8290              : 
    8291         1860 :     case BUILT_IN_STRCPY:
    8292         1860 :       target = expand_builtin_strcpy (exp, target);
    8293         1860 :       if (target)
    8294              :         return target;
    8295              :       break;
    8296              : 
    8297         2177 :     case BUILT_IN_STRNCPY:
    8298         2177 :       target = expand_builtin_strncpy (exp, target);
    8299         2177 :       if (target)
    8300              :         return target;
    8301              :       break;
    8302              : 
    8303          454 :     case BUILT_IN_STPCPY:
    8304          454 :       target = expand_builtin_stpcpy (exp, target, mode);
    8305          454 :       if (target)
    8306              :         return target;
    8307              :       break;
    8308              : 
    8309       110102 :     case BUILT_IN_MEMCPY:
    8310       110102 :       target = expand_builtin_memcpy (exp, target);
    8311       110102 :       if (target)
    8312              :         return target;
    8313              :       break;
    8314              : 
    8315        17646 :     case BUILT_IN_MEMMOVE:
    8316        17646 :       target = expand_builtin_memmove (exp, target);
    8317        17646 :       if (target)
    8318              :         return target;
    8319              :       break;
    8320              : 
    8321         1395 :     case BUILT_IN_MEMPCPY:
    8322         1395 :       target = expand_builtin_mempcpy (exp, target);
    8323         1395 :       if (target)
    8324              :         return target;
    8325              :       break;
    8326              : 
    8327        36908 :     case BUILT_IN_MEMSET:
    8328        36908 :       target = expand_builtin_memset (exp, target, mode);
    8329        36908 :       if (target)
    8330              :         return target;
    8331              :       break;
    8332              : 
    8333            0 :     case BUILT_IN_BZERO:
    8334            0 :       target = expand_builtin_bzero (exp);
    8335            0 :       if (target)
    8336              :         return target;
    8337              :       break;
    8338              : 
    8339              :     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
    8340              :        back to a BUILT_IN_STRCMP. Remember to delete the 3rd parameter
    8341              :        when changing it to a strcmp call.  */
    8342          371 :     case BUILT_IN_STRCMP_EQ:
    8343          371 :       target = expand_builtin_memcmp (exp, target, true);
    8344          371 :       if (target)
    8345              :         return target;
    8346              : 
    8347              :       /* Change this call back to a BUILT_IN_STRCMP.  */
    8348           25 :       TREE_OPERAND (exp, 1)
    8349           25 :         = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
    8350              : 
    8351              :       /* Delete the last parameter.  */
    8352           25 :       unsigned int i;
    8353           25 :       vec<tree, va_gc> *arg_vec;
    8354           25 :       vec_alloc (arg_vec, 2);
    8355          100 :       for (i = 0; i < 2; i++)
    8356           50 :         arg_vec->quick_push (CALL_EXPR_ARG (exp, i));
    8357           25 :       exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), arg_vec);
    8358              :       /* FALLTHROUGH */
    8359              : 
    8360       127960 :     case BUILT_IN_STRCMP:
    8361       127960 :       target = expand_builtin_strcmp (exp, target);
    8362       127960 :       if (target)
    8363              :         return target;
    8364              :       break;
    8365              : 
    8366              :     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
    8367              :        back to a BUILT_IN_STRNCMP.  */
    8368           38 :     case BUILT_IN_STRNCMP_EQ:
    8369           38 :       target = expand_builtin_memcmp (exp, target, true);
    8370           38 :       if (target)
    8371              :         return target;
    8372              : 
    8373              :       /* Change it back to a BUILT_IN_STRNCMP.  */
    8374            0 :       TREE_OPERAND (exp, 1)
    8375            0 :         = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
    8376              :       /* FALLTHROUGH */
    8377              : 
    8378         2027 :     case BUILT_IN_STRNCMP:
    8379         2027 :       target = expand_builtin_strncmp (exp, target, mode);
    8380         2027 :       if (target)
    8381              :         return target;
    8382              :       break;
    8383              : 
    8384       106850 :     case BUILT_IN_BCMP:
    8385       106850 :     case BUILT_IN_MEMCMP:
    8386       106850 :     case BUILT_IN_MEMCMP_EQ:
    8387       106850 :       target = expand_builtin_memcmp (exp, target, fcode == BUILT_IN_MEMCMP_EQ);
    8388       106850 :       if (target)
    8389              :         return target;
    8390        38214 :       if (fcode == BUILT_IN_MEMCMP_EQ)
    8391              :         {
    8392        23286 :           tree newdecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
    8393        23286 :           TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
    8394              :         }
    8395              :       break;
    8396              : 
    8397            0 :     case BUILT_IN_SETJMP:
    8398              :       /* This should have been lowered to the builtins below.  */
    8399            0 :       gcc_unreachable ();
    8400              : 
    8401          842 :     case BUILT_IN_SETJMP_SETUP:
    8402              :       /* __builtin_setjmp_setup is passed a pointer to an array of five words
    8403              :           and the receiver label.  */
    8404          842 :       if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    8405              :         {
    8406          842 :           rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
    8407              :                                       VOIDmode, EXPAND_NORMAL);
    8408          842 :           tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
    8409          842 :           rtx_insn *label_r = label_rtx (label);
    8410              : 
    8411          842 :           expand_builtin_setjmp_setup (buf_addr, label_r);
    8412          842 :           return const0_rtx;
    8413              :         }
    8414              :       break;
    8415              : 
    8416          842 :     case BUILT_IN_SETJMP_RECEIVER:
    8417              :        /* __builtin_setjmp_receiver is passed the receiver label.  */
    8418          842 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8419              :         {
    8420          842 :           tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
    8421          842 :           rtx_insn *label_r = label_rtx (label);
    8422              : 
    8423          842 :           expand_builtin_setjmp_receiver (label_r);
    8424          842 :           nonlocal_goto_handler_labels
    8425         1684 :             = gen_rtx_INSN_LIST (VOIDmode, label_r,
    8426          842 :                                  nonlocal_goto_handler_labels);
    8427              :           /* ??? Do not let expand_label treat us as such since we would
    8428              :              not want to be both on the list of non-local labels and on
    8429              :              the list of forced labels.  */
    8430          842 :           FORCED_LABEL (label) = 0;
    8431          842 :           return const0_rtx;
    8432              :         }
    8433              :       break;
    8434              : 
    8435              :       /* __builtin_longjmp is passed a pointer to an array of five words.
    8436              :          It's similar to the C library longjmp function but works with
    8437              :          __builtin_setjmp above.  */
    8438          392 :     case BUILT_IN_LONGJMP:
    8439          392 :       if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    8440              :         {
    8441          392 :           rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
    8442              :                                       VOIDmode, EXPAND_NORMAL);
    8443          392 :           rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
    8444              : 
    8445          392 :           if (value != const1_rtx)
    8446              :             {
    8447            0 :               error ("%<__builtin_longjmp%> second argument must be 1");
    8448            0 :               return const0_rtx;
    8449              :             }
    8450              : 
    8451          392 :           expand_builtin_longjmp (buf_addr, value);
    8452          392 :           return const0_rtx;
    8453              :         }
    8454              :       break;
    8455              : 
    8456          512 :     case BUILT_IN_NONLOCAL_GOTO:
    8457          512 :       target = expand_builtin_nonlocal_goto (exp);
    8458          512 :       if (target)
    8459              :         return target;
    8460              :       break;
    8461              : 
    8462              :       /* This updates the setjmp buffer that is its argument with the value
    8463              :          of the current stack pointer.  */
    8464            0 :     case BUILT_IN_UPDATE_SETJMP_BUF:
    8465            0 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8466              :         {
    8467            0 :           rtx buf_addr
    8468            0 :             = expand_normal (CALL_EXPR_ARG (exp, 0));
    8469              : 
    8470            0 :           expand_builtin_update_setjmp_buf (buf_addr);
    8471            0 :           return const0_rtx;
    8472              :         }
    8473              :       break;
    8474              : 
    8475        38759 :     case BUILT_IN_TRAP:
    8476        38759 :     case BUILT_IN_UNREACHABLE_TRAP:
    8477        38759 :       expand_builtin_trap ();
    8478        38759 :       return const0_rtx;
    8479              : 
    8480         2641 :     case BUILT_IN_UNREACHABLE:
    8481         2641 :       expand_builtin_unreachable ();
    8482         2641 :       return const0_rtx;
    8483              : 
    8484          408 :     case BUILT_IN_OBSERVABLE_CHKPT:
    8485              :       /* Generate no code.  */
    8486          408 :       return const0_rtx;
    8487              : 
    8488         1380 :     CASE_FLT_FN (BUILT_IN_SIGNBIT):
    8489         1380 :     case BUILT_IN_SIGNBITD32:
    8490         1380 :     case BUILT_IN_SIGNBITD64:
    8491         1380 :     case BUILT_IN_SIGNBITD128:
    8492         1380 :       target = expand_builtin_signbit (exp, target);
    8493         1380 :       if (target)
    8494              :         return target;
    8495              :       break;
    8496              : 
    8497              :       /* Various hooks for the DWARF 2 __throw routine.  */
    8498           34 :     case BUILT_IN_UNWIND_INIT:
    8499           34 :       expand_builtin_unwind_init ();
    8500           34 :       return const0_rtx;
    8501         1224 :     case BUILT_IN_DWARF_CFA:
    8502         1224 :       return virtual_cfa_rtx;
    8503              : #ifdef DWARF2_UNWIND_INFO
    8504           48 :     case BUILT_IN_DWARF_SP_COLUMN:
    8505           48 :       return expand_builtin_dwarf_sp_column ();
    8506            8 :     case BUILT_IN_INIT_DWARF_REG_SIZES:
    8507            8 :       expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
    8508            8 :       return const0_rtx;
    8509              : #endif
    8510           19 :     case BUILT_IN_FROB_RETURN_ADDR:
    8511           19 :       return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
    8512         2352 :     case BUILT_IN_EXTRACT_RETURN_ADDR:
    8513         2352 :       return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
    8514           29 :     case BUILT_IN_EH_RETURN:
    8515           58 :       expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
    8516           29 :                                 CALL_EXPR_ARG (exp, 1));
    8517           29 :       return const0_rtx;
    8518           21 :     case BUILT_IN_EH_RETURN_DATA_REGNO:
    8519           21 :       return expand_builtin_eh_return_data_regno (exp);
    8520            2 :     case BUILT_IN_EXTEND_POINTER:
    8521            2 :       return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
    8522       106012 :     case BUILT_IN_EH_POINTER:
    8523       106012 :       return expand_builtin_eh_pointer (exp);
    8524         6187 :     case BUILT_IN_EH_FILTER:
    8525         6187 :       return expand_builtin_eh_filter (exp);
    8526       107596 :     case BUILT_IN_EH_COPY_VALUES:
    8527       107596 :       return expand_builtin_eh_copy_values (exp);
    8528              : 
    8529        21087 :     case BUILT_IN_VA_START:
    8530        21087 :       return expand_builtin_va_start (exp);
    8531        12162 :     case BUILT_IN_VA_END:
    8532        12162 :       return expand_builtin_va_end (exp);
    8533          240 :     case BUILT_IN_VA_COPY:
    8534          240 :       return expand_builtin_va_copy (exp);
    8535         1407 :     case BUILT_IN_EXPECT:
    8536         1407 :       return expand_builtin_expect (exp, target);
    8537            5 :     case BUILT_IN_EXPECT_WITH_PROBABILITY:
    8538            5 :       return expand_builtin_expect_with_probability (exp, target);
    8539          662 :     case BUILT_IN_ASSUME_ALIGNED:
    8540          662 :       return expand_builtin_assume_aligned (exp, target);
    8541         2058 :     case BUILT_IN_PREFETCH:
    8542         2058 :       expand_builtin_prefetch (exp);
    8543         2058 :       return const0_rtx;
    8544              : 
    8545          306 :     case BUILT_IN_INIT_TRAMPOLINE:
    8546          306 :       return expand_builtin_init_trampoline (exp, true);
    8547            0 :     case BUILT_IN_INIT_HEAP_TRAMPOLINE:
    8548            0 :       return expand_builtin_init_trampoline (exp, false);
    8549          353 :     case BUILT_IN_ADJUST_TRAMPOLINE:
    8550          353 :       return expand_builtin_adjust_trampoline (exp);
    8551              : 
    8552            0 :     case BUILT_IN_INIT_DESCRIPTOR:
    8553            0 :       return expand_builtin_init_descriptor (exp);
    8554            0 :     case BUILT_IN_ADJUST_DESCRIPTOR:
    8555            0 :       return expand_builtin_adjust_descriptor (exp);
    8556              : 
    8557              :     case BUILT_IN_GCC_NESTED_PTR_CREATED:
    8558              :     case BUILT_IN_GCC_NESTED_PTR_DELETED:
    8559              :       break; /* At present, no expansion, just call the function.  */
    8560              : 
    8561          109 :     case BUILT_IN_FORK:
    8562          109 :     case BUILT_IN_EXECL:
    8563          109 :     case BUILT_IN_EXECV:
    8564          109 :     case BUILT_IN_EXECLP:
    8565          109 :     case BUILT_IN_EXECLE:
    8566          109 :     case BUILT_IN_EXECVP:
    8567          109 :     case BUILT_IN_EXECVE:
    8568          109 :       target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
    8569          109 :       if (target)
    8570              :         return target;
    8571              :       break;
    8572              : 
    8573          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_1:
    8574          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_2:
    8575          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_4:
    8576          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_8:
    8577          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_16:
    8578          712 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
    8579          712 :       target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
    8580          712 :       if (target)
    8581              :         return target;
    8582              :       break;
    8583              : 
    8584          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_1:
    8585          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_2:
    8586          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_4:
    8587          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_8:
    8588          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_16:
    8589          585 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
    8590          585 :       target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
    8591          585 :       if (target)
    8592              :         return target;
    8593              :       break;
    8594              : 
    8595          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_1:
    8596          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_2:
    8597          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_4:
    8598          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_8:
    8599          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_16:
    8600          512 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
    8601          512 :       target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
    8602          512 :       if (target)
    8603              :         return target;
    8604              :       break;
    8605              : 
    8606          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_1:
    8607          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_2:
    8608          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_4:
    8609          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_8:
    8610          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_16:
    8611          488 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
    8612          488 :       target = expand_builtin_sync_operation (mode, exp, AND, false, target);
    8613          488 :       if (target)
    8614              :         return target;
    8615              :       break;
    8616              : 
    8617          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_1:
    8618          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_2:
    8619          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_4:
    8620          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_8:
    8621          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_16:
    8622          581 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
    8623          581 :       target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
    8624          581 :       if (target)
    8625              :         return target;
    8626              :       break;
    8627              : 
    8628          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    8629          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    8630          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    8631          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    8632          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    8633          434 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
    8634          434 :       target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
    8635          434 :       if (target)
    8636              :         return target;
    8637              :       break;
    8638              : 
    8639          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_1:
    8640          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_2:
    8641          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_4:
    8642          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_8:
    8643          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_16:
    8644          161 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
    8645          161 :       target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
    8646          161 :       if (target)
    8647              :         return target;
    8648              :       break;
    8649              : 
    8650          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_1:
    8651          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_2:
    8652          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_4:
    8653          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_8:
    8654          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_16:
    8655          121 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
    8656          121 :       target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
    8657          121 :       if (target)
    8658              :         return target;
    8659              :       break;
    8660              : 
    8661          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_1:
    8662          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_2:
    8663          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_4:
    8664          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_8:
    8665          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_16:
    8666          115 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
    8667          115 :       target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
    8668          115 :       if (target)
    8669              :         return target;
    8670              :       break;
    8671              : 
    8672          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_1:
    8673          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_2:
    8674          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_4:
    8675          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_8:
    8676          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_16:
    8677          116 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
    8678          116 :       target = expand_builtin_sync_operation (mode, exp, AND, true, target);
    8679          116 :       if (target)
    8680              :         return target;
    8681              :       break;
    8682              : 
    8683          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_1:
    8684          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_2:
    8685          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_4:
    8686          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_8:
    8687          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_16:
    8688          114 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
    8689          114 :       target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
    8690          114 :       if (target)
    8691              :         return target;
    8692              :       break;
    8693              : 
    8694           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    8695           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    8696           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    8697           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    8698           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    8699           89 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
    8700           89 :       target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
    8701           89 :       if (target)
    8702              :         return target;
    8703              :       break;
    8704              : 
    8705          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
    8706          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
    8707          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
    8708          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
    8709          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
    8710          204 :       if (mode == VOIDmode)
    8711           40 :         mode = TYPE_MODE (boolean_type_node);
    8712          204 :       if (!target || !register_operand (target, mode))
    8713           40 :         target = gen_reg_rtx (mode);
    8714              : 
    8715          204 :       mode = get_builtin_sync_mode
    8716          204 :                                 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
    8717          204 :       target = expand_builtin_compare_and_swap (mode, exp, true, target);
    8718          204 :       if (target)
    8719              :         return target;
    8720              :       break;
    8721              : 
    8722          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
    8723          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
    8724          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
    8725          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
    8726          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
    8727          256 :       mode = get_builtin_sync_mode
    8728          256 :                                 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
    8729          256 :       target = expand_builtin_compare_and_swap (mode, exp, false, target);
    8730          256 :       if (target)
    8731              :         return target;
    8732              :       break;
    8733              : 
    8734          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
    8735          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
    8736          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
    8737          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
    8738          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
    8739          326 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
    8740          326 :       target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
    8741          326 :       if (target)
    8742              :         return target;
    8743              :       break;
    8744              : 
    8745          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_1:
    8746          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_2:
    8747          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_4:
    8748          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_8:
    8749          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_16:
    8750          146 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
    8751          146 :       if (expand_builtin_sync_lock_release (mode, exp))
    8752          144 :         return const0_rtx;
    8753              :       break;
    8754              : 
    8755          275 :     case BUILT_IN_SYNC_SYNCHRONIZE:
    8756          275 :       expand_builtin_sync_synchronize ();
    8757          275 :       return const0_rtx;
    8758              : 
    8759         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_1:
    8760         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_2:
    8761         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_4:
    8762         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_8:
    8763         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_16:
    8764         2937 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
    8765         2937 :       target = expand_builtin_atomic_exchange (mode, exp, target);
    8766         2937 :       if (target)
    8767              :         return target;
    8768              :       break;
    8769              : 
    8770         9131 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
    8771         9131 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
    8772         9131 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
    8773         9131 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
    8774         9131 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
    8775         9131 :       {
    8776         9131 :         unsigned int nargs, z;
    8777         9131 :         vec<tree, va_gc> *vec;
    8778              : 
    8779         9131 :         mode =
    8780         9131 :             get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
    8781         9131 :         target = expand_builtin_atomic_compare_exchange (mode, exp, target);
    8782         9131 :         if (target)
    8783         7331 :           return target;
    8784              : 
    8785              :         /* If this is turned into an external library call, the weak parameter
    8786              :            must be dropped to match the expected parameter list.  */
    8787         1800 :         nargs = call_expr_nargs (exp);
    8788         1800 :         vec_alloc (vec, nargs - 1);
    8789         9000 :         for (z = 0; z < 3; z++)
    8790         5400 :           vec->quick_push (CALL_EXPR_ARG (exp, z));
    8791              :         /* Skip the boolean weak parameter.  */
    8792         5400 :         for (z = 4; z < 6; z++)
    8793         3600 :           vec->quick_push (CALL_EXPR_ARG (exp, z));
    8794         1800 :         exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
    8795         1800 :         break;
    8796              :       }
    8797              : 
    8798        70962 :     case BUILT_IN_ATOMIC_LOAD_1:
    8799        70962 :     case BUILT_IN_ATOMIC_LOAD_2:
    8800        70962 :     case BUILT_IN_ATOMIC_LOAD_4:
    8801        70962 :     case BUILT_IN_ATOMIC_LOAD_8:
    8802        70962 :     case BUILT_IN_ATOMIC_LOAD_16:
    8803        70962 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
    8804        70962 :       target = expand_builtin_atomic_load (mode, exp, target);
    8805        70962 :       if (target)
    8806              :         return target;
    8807              :       break;
    8808              : 
    8809        17481 :     case BUILT_IN_ATOMIC_STORE_1:
    8810        17481 :     case BUILT_IN_ATOMIC_STORE_2:
    8811        17481 :     case BUILT_IN_ATOMIC_STORE_4:
    8812        17481 :     case BUILT_IN_ATOMIC_STORE_8:
    8813        17481 :     case BUILT_IN_ATOMIC_STORE_16:
    8814        17481 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
    8815        17481 :       target = expand_builtin_atomic_store (mode, exp);
    8816        17481 :       if (target)
    8817        15849 :         return const0_rtx;
    8818              :       break;
    8819              : 
    8820         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_1:
    8821         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_2:
    8822         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_4:
    8823         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_8:
    8824         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_16:
    8825         4394 :       {
    8826         4394 :         enum built_in_function lib;
    8827         4394 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
    8828         4394 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
    8829              :                                        (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
    8830         4394 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
    8831              :                                                  ignore, lib);
    8832         4394 :         if (target)
    8833              :           return target;
    8834              :         break;
    8835              :       }
    8836         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_1:
    8837         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_2:
    8838         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_4:
    8839         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_8:
    8840         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_16:
    8841         2172 :       {
    8842         2172 :         enum built_in_function lib;
    8843         2172 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
    8844         2172 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
    8845              :                                        (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
    8846         2172 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
    8847              :                                                  ignore, lib);
    8848         2172 :         if (target)
    8849              :           return target;
    8850              :         break;
    8851              :       }
    8852          902 :     case BUILT_IN_ATOMIC_AND_FETCH_1:
    8853          902 :     case BUILT_IN_ATOMIC_AND_FETCH_2:
    8854          902 :     case BUILT_IN_ATOMIC_AND_FETCH_4:
    8855          902 :     case BUILT_IN_ATOMIC_AND_FETCH_8:
    8856          902 :     case BUILT_IN_ATOMIC_AND_FETCH_16:
    8857          902 :       {
    8858          902 :         enum built_in_function lib;
    8859          902 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
    8860          902 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
    8861              :                                        (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
    8862          902 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
    8863              :                                                  ignore, lib);
    8864          902 :         if (target)
    8865              :           return target;
    8866              :         break;
    8867              :       }
    8868          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_1:
    8869          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_2:
    8870          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_4:
    8871          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_8:
    8872          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_16:
    8873          162 :       {
    8874          162 :         enum built_in_function lib;
    8875          162 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
    8876          162 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
    8877              :                                        (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
    8878          162 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
    8879              :                                                  ignore, lib);
    8880          162 :         if (target)
    8881              :           return target;
    8882              :         break;
    8883              :       }
    8884          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_1:
    8885          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_2:
    8886          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_4:
    8887          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_8:
    8888          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_16:
    8889          847 :       {
    8890          847 :         enum built_in_function lib;
    8891          847 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
    8892          847 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
    8893              :                                        (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
    8894          847 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
    8895              :                                                  ignore, lib);
    8896          847 :         if (target)
    8897              :           return target;
    8898              :         break;
    8899              :       }
    8900          965 :     case BUILT_IN_ATOMIC_OR_FETCH_1:
    8901          965 :     case BUILT_IN_ATOMIC_OR_FETCH_2:
    8902          965 :     case BUILT_IN_ATOMIC_OR_FETCH_4:
    8903          965 :     case BUILT_IN_ATOMIC_OR_FETCH_8:
    8904          965 :     case BUILT_IN_ATOMIC_OR_FETCH_16:
    8905          965 :       {
    8906          965 :         enum built_in_function lib;
    8907          965 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
    8908          965 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
    8909              :                                        (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
    8910          965 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
    8911              :                                                  ignore, lib);
    8912          965 :         if (target)
    8913              :           return target;
    8914              :         break;
    8915              :       }
    8916        14572 :     case BUILT_IN_ATOMIC_FETCH_ADD_1:
    8917        14572 :     case BUILT_IN_ATOMIC_FETCH_ADD_2:
    8918        14572 :     case BUILT_IN_ATOMIC_FETCH_ADD_4:
    8919        14572 :     case BUILT_IN_ATOMIC_FETCH_ADD_8:
    8920        14572 :     case BUILT_IN_ATOMIC_FETCH_ADD_16:
    8921        14572 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
    8922        14572 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
    8923              :                                                ignore, BUILT_IN_NONE);
    8924        14572 :       if (target)
    8925              :         return target;
    8926              :       break;
    8927              : 
    8928         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_1:
    8929         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_2:
    8930         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_4:
    8931         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_8:
    8932         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_16:
    8933         2107 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
    8934         2107 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
    8935              :                                                ignore, BUILT_IN_NONE);
    8936         2107 :       if (target)
    8937              :         return target;
    8938              :       break;
    8939              : 
    8940          785 :     case BUILT_IN_ATOMIC_FETCH_AND_1:
    8941          785 :     case BUILT_IN_ATOMIC_FETCH_AND_2:
    8942          785 :     case BUILT_IN_ATOMIC_FETCH_AND_4:
    8943          785 :     case BUILT_IN_ATOMIC_FETCH_AND_8:
    8944          785 :     case BUILT_IN_ATOMIC_FETCH_AND_16:
    8945          785 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
    8946          785 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
    8947              :                                                ignore, BUILT_IN_NONE);
    8948          785 :       if (target)
    8949              :         return target;
    8950              :       break;
    8951              : 
    8952          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_1:
    8953          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_2:
    8954          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_4:
    8955          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_8:
    8956          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_16:
    8957          125 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
    8958          125 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
    8959              :                                                ignore, BUILT_IN_NONE);
    8960          125 :       if (target)
    8961              :         return target;
    8962              :       break;
    8963              : 
    8964          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_1:
    8965          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_2:
    8966          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_4:
    8967          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_8:
    8968          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_16:
    8969          875 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
    8970          875 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
    8971              :                                                ignore, BUILT_IN_NONE);
    8972          875 :       if (target)
    8973              :         return target;
    8974              :       break;
    8975              : 
    8976         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_1:
    8977         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_2:
    8978         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_4:
    8979         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_8:
    8980         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_16:
    8981         1140 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
    8982         1140 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
    8983              :                                                ignore, BUILT_IN_NONE);
    8984         1140 :       if (target)
    8985              :         return target;
    8986              :       break;
    8987              : 
    8988          266 :     case BUILT_IN_ATOMIC_TEST_AND_SET:
    8989          266 :       target = expand_builtin_atomic_test_and_set (exp, target);
    8990          266 :       if (target)
    8991              :         return target;
    8992              :       break;
    8993              : 
    8994           53 :     case BUILT_IN_ATOMIC_CLEAR:
    8995           53 :       return expand_builtin_atomic_clear (exp);
    8996              : 
    8997            1 :     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
    8998            1 :       return expand_builtin_atomic_always_lock_free (exp);
    8999              : 
    9000           10 :     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
    9001           10 :       target = expand_builtin_atomic_is_lock_free (exp);
    9002           10 :       if (target)
    9003              :         return target;
    9004              :       break;
    9005              : 
    9006          703 :     case BUILT_IN_ATOMIC_THREAD_FENCE:
    9007          703 :       expand_builtin_atomic_thread_fence (exp);
    9008          703 :       return const0_rtx;
    9009              : 
    9010           60 :     case BUILT_IN_ATOMIC_SIGNAL_FENCE:
    9011           60 :       expand_builtin_atomic_signal_fence (exp);
    9012           60 :       return const0_rtx;
    9013              : 
    9014          620 :     case BUILT_IN_OBJECT_SIZE:
    9015          620 :     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
    9016          620 :       return expand_builtin_object_size (exp);
    9017              : 
    9018          837 :     case BUILT_IN_MEMCPY_CHK:
    9019          837 :     case BUILT_IN_MEMPCPY_CHK:
    9020          837 :     case BUILT_IN_MEMMOVE_CHK:
    9021          837 :     case BUILT_IN_MEMSET_CHK:
    9022          837 :       target = expand_builtin_memory_chk (exp, target, mode, fcode);
    9023          837 :       if (target)
    9024              :         return target;
    9025              :       break;
    9026              : 
    9027         1086 :     case BUILT_IN_STRCPY_CHK:
    9028         1086 :     case BUILT_IN_STPCPY_CHK:
    9029         1086 :     case BUILT_IN_STRNCPY_CHK:
    9030         1086 :     case BUILT_IN_STPNCPY_CHK:
    9031         1086 :     case BUILT_IN_STRCAT_CHK:
    9032         1086 :     case BUILT_IN_STRNCAT_CHK:
    9033         1086 :     case BUILT_IN_SNPRINTF_CHK:
    9034         1086 :     case BUILT_IN_VSNPRINTF_CHK:
    9035         1086 :       maybe_emit_chk_warning (exp, fcode);
    9036         1086 :       break;
    9037              : 
    9038         1328 :     case BUILT_IN_SPRINTF_CHK:
    9039         1328 :     case BUILT_IN_VSPRINTF_CHK:
    9040         1328 :       maybe_emit_sprintf_chk_warning (exp, fcode);
    9041         1328 :       break;
    9042              : 
    9043            3 :     case BUILT_IN_THREAD_POINTER:
    9044            3 :       return expand_builtin_thread_pointer (exp, target);
    9045              : 
    9046            0 :     case BUILT_IN_SET_THREAD_POINTER:
    9047            0 :       expand_builtin_set_thread_pointer (exp);
    9048            0 :       return const0_rtx;
    9049              : 
    9050              :     case BUILT_IN_ACC_ON_DEVICE:
    9051              :       /* Do library call, if we failed to expand the builtin when
    9052              :          folding.  */
    9053              :       break;
    9054              : 
    9055          356 :     case BUILT_IN_GOACC_PARLEVEL_ID:
    9056          356 :     case BUILT_IN_GOACC_PARLEVEL_SIZE:
    9057          356 :       return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
    9058              : 
    9059            4 :     case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
    9060            4 :       return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
    9061              : 
    9062           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_1:
    9063           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_2:
    9064           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_4:
    9065           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_8:
    9066           31 :     case BUILT_IN_SPECULATION_SAFE_VALUE_16:
    9067           31 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
    9068           31 :       return expand_speculation_safe_value (mode, exp, target, ignore);
    9069              : 
    9070            2 :     case BUILT_IN_CRC8_DATA8:
    9071            2 :       return expand_builtin_crc_table_based (IFN_CRC, QImode, QImode, mode,
    9072              :                                                exp, target);
    9073            2 :     case BUILT_IN_CRC16_DATA8:
    9074            2 :       return expand_builtin_crc_table_based (IFN_CRC, HImode, QImode, mode,
    9075              :                                                exp, target);
    9076            2 :     case BUILT_IN_CRC16_DATA16:
    9077            2 :       return expand_builtin_crc_table_based (IFN_CRC, HImode, HImode, mode,
    9078              :                                                exp, target);
    9079            2 :     case BUILT_IN_CRC32_DATA8:
    9080            2 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, QImode, mode,
    9081              :                                                exp, target);
    9082            2 :     case BUILT_IN_CRC32_DATA16:
    9083            2 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, HImode, mode,
    9084              :                                                exp, target);
    9085           14 :     case BUILT_IN_CRC32_DATA32:
    9086           14 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, SImode, mode,
    9087              :                                                exp, target);
    9088            1 :     case BUILT_IN_CRC64_DATA8:
    9089            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, QImode, mode,
    9090              :                                                exp, target);
    9091            1 :     case BUILT_IN_CRC64_DATA16:
    9092            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, HImode, mode,
    9093              :                                                exp, target);
    9094            1 :     case BUILT_IN_CRC64_DATA32:
    9095            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, SImode, mode,
    9096              :                                                exp, target);
    9097            1 :     case BUILT_IN_CRC64_DATA64:
    9098            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, DImode, mode,
    9099              :                                                exp, target);
    9100            2 :     case BUILT_IN_REV_CRC8_DATA8:
    9101            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, QImode, QImode,
    9102              :                                                mode, exp, target);
    9103            2 :     case BUILT_IN_REV_CRC16_DATA8:
    9104            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, QImode,
    9105              :                                                mode, exp, target);
    9106            2 :     case BUILT_IN_REV_CRC16_DATA16:
    9107            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, HImode,
    9108              :                                                mode, exp, target);
    9109            3 :     case BUILT_IN_REV_CRC32_DATA8:
    9110            3 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, QImode,
    9111              :                                                mode, exp, target);
    9112            2 :     case BUILT_IN_REV_CRC32_DATA16:
    9113            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, HImode,
    9114              :                                                mode, exp, target);
    9115            2 :     case BUILT_IN_REV_CRC32_DATA32:
    9116            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, SImode,
    9117              :                                                mode, exp, target);
    9118            1 :     case BUILT_IN_REV_CRC64_DATA8:
    9119            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, QImode,
    9120              :                                                mode, exp, target);
    9121            1 :     case BUILT_IN_REV_CRC64_DATA16:
    9122            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, HImode,
    9123              :                                                mode, exp, target);
    9124            1 :     case BUILT_IN_REV_CRC64_DATA32:
    9125            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, SImode,
    9126              :                                                mode, exp, target);
    9127            1 :     case BUILT_IN_REV_CRC64_DATA64:
    9128            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, DImode,
    9129              :                                                mode, exp, target);
    9130              :     default:    /* just do library call, if unknown builtin */
    9131              :       break;
    9132              :     }
    9133              : 
    9134              :   /* The switch statement above can drop through to cause the function
    9135              :      to be called normally.  */
    9136       857984 :   return expand_call (exp, target, ignore);
    9137              : }
    9138              : 
    9139              : /* Determine whether a tree node represents a call to a built-in
    9140              :    function.  If the tree T is a call to a built-in function with
    9141              :    the right number of arguments of the appropriate types, return
    9142              :    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
    9143              :    Otherwise the return value is END_BUILTINS.  */
    9144              : 
    9145              : enum built_in_function
    9146    109709140 : builtin_mathfn_code (const_tree t)
    9147              : {
    9148    109709140 :   const_tree fndecl, arg, parmlist;
    9149    109709140 :   const_tree argtype, parmtype;
    9150    109709140 :   const_call_expr_arg_iterator iter;
    9151              : 
    9152    109709140 :   if (TREE_CODE (t) != CALL_EXPR)
    9153              :     return END_BUILTINS;
    9154              : 
    9155      1467308 :   fndecl = get_callee_fndecl (t);
    9156      1467308 :   if (fndecl == NULL_TREE || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
    9157              :       return END_BUILTINS;
    9158              : 
    9159       661068 :   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
    9160       661068 :   init_const_call_expr_arg_iterator (t, &iter);
    9161      2133358 :   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
    9162              :     {
    9163              :       /* If a function doesn't take a variable number of arguments,
    9164              :          the last element in the list will have type `void'.  */
    9165      1452629 :       parmtype = TREE_VALUE (parmlist);
    9166      1452629 :       if (VOID_TYPE_P (parmtype))
    9167              :         {
    9168       641393 :           if (more_const_call_expr_args_p (&iter))
    9169              :             return END_BUILTINS;
    9170       641393 :           return DECL_FUNCTION_CODE (fndecl);
    9171              :         }
    9172              : 
    9173       811236 :       if (! more_const_call_expr_args_p (&iter))
    9174              :         return END_BUILTINS;
    9175              : 
    9176       811236 :       arg = next_const_call_expr_arg (&iter);
    9177       811236 :       argtype = TREE_TYPE (arg);
    9178              : 
    9179       811236 :       if (SCALAR_FLOAT_TYPE_P (parmtype))
    9180              :         {
    9181       549379 :           if (! SCALAR_FLOAT_TYPE_P (argtype))
    9182              :             return END_BUILTINS;
    9183              :         }
    9184       261857 :       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
    9185              :         {
    9186         7777 :           if (! COMPLEX_FLOAT_TYPE_P (argtype))
    9187              :             return END_BUILTINS;
    9188              :         }
    9189       254080 :       else if (POINTER_TYPE_P (parmtype))
    9190              :         {
    9191        75931 :           if (! POINTER_TYPE_P (argtype))
    9192              :             return END_BUILTINS;
    9193              :         }
    9194       178149 :       else if (INTEGRAL_TYPE_P (parmtype))
    9195              :         {
    9196       178149 :           if (! INTEGRAL_TYPE_P (argtype))
    9197              :             return END_BUILTINS;
    9198              :         }
    9199              :       else
    9200              :         return END_BUILTINS;
    9201              :     }
    9202              : 
    9203              :   /* Variable-length argument list.  */
    9204        19661 :   return DECL_FUNCTION_CODE (fndecl);
    9205              : }
    9206              : 
    9207              : /* Fold a call to __builtin_constant_p, if we know its argument ARG will
    9208              :    evaluate to a constant.  */
    9209              : 
    9210              : tree
    9211      3291894 : fold_builtin_constant_p (tree arg)
    9212              : {
    9213              :   /* We return 1 for a numeric type that's known to be a constant
    9214              :      value at compile-time or for an aggregate type that's a
    9215              :      literal constant.  */
    9216      3291894 :   STRIP_NOPS (arg);
    9217              : 
    9218              :   /* If we know this is a constant, emit the constant of one.  */
    9219      3291894 :   if (CONSTANT_CLASS_P (arg)
    9220      3291894 :       || (TREE_CODE (arg) == CONSTRUCTOR
    9221            6 :           && TREE_CONSTANT (arg)))
    9222      1835733 :     return integer_one_node;
    9223      1456161 :   if (TREE_CODE (arg) == ADDR_EXPR)
    9224              :     {
    9225          110 :        tree op = TREE_OPERAND (arg, 0);
    9226          110 :        if (TREE_CODE (op) == STRING_CST
    9227          110 :            || (TREE_CODE (op) == ARRAY_REF
    9228           57 :                && integer_zerop (TREE_OPERAND (op, 1))
    9229           57 :                && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
    9230           87 :          return integer_one_node;
    9231              :     }
    9232              : 
    9233              :   /* If this expression has side effects, show we don't know it to be a
    9234              :      constant.  Likewise if it's a pointer or aggregate type since in
    9235              :      those case we only want literals, since those are only optimized
    9236              :      when generating RTL, not later.
    9237              :      And finally, if we are compiling an initializer, not code, we
    9238              :      need to return a definite result now; there's not going to be any
    9239              :      more optimization done.  */
    9240      1456074 :   if (TREE_SIDE_EFFECTS (arg)
    9241      1455949 :       || AGGREGATE_TYPE_P (TREE_TYPE (arg))
    9242      1455943 :       || POINTER_TYPE_P (TREE_TYPE (arg))
    9243      1455772 :       || cfun == 0
    9244      1455679 :       || folding_initializer
    9245      2911746 :       || force_folding_builtin_constant_p)
    9246          497 :     return integer_zero_node;
    9247              : 
    9248              :   return NULL_TREE;
    9249              : }
    9250              : 
    9251              : /* Create builtin_expect or builtin_expect_with_probability
    9252              :    with PRED and EXPECTED as its arguments and return it as a truthvalue.
    9253              :    Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
    9254              :    builtin_expect_with_probability instead uses third argument as PROBABILITY
    9255              :    value.  */
    9256              : 
    9257              : static tree
    9258       226100 : build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
    9259              :                                 tree predictor, tree probability)
    9260              : {
    9261       226100 :   tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
    9262              : 
    9263       226100 :   fn = builtin_decl_explicit (probability == NULL_TREE ? BUILT_IN_EXPECT
    9264              :                               : BUILT_IN_EXPECT_WITH_PROBABILITY);
    9265       226100 :   arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
    9266       226100 :   ret_type = TREE_TYPE (TREE_TYPE (fn));
    9267       226100 :   pred_type = TREE_VALUE (arg_types);
    9268       226100 :   expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
    9269              : 
    9270       226100 :   pred = fold_convert_loc (loc, pred_type, pred);
    9271       226100 :   expected = fold_convert_loc (loc, expected_type, expected);
    9272              : 
    9273       226100 :   if (probability)
    9274            0 :     call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
    9275              :   else
    9276       452200 :     call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
    9277              :                                      predictor);
    9278              : 
    9279       226100 :   return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
    9280       226100 :                  build_int_cst (ret_type, 0));
    9281              : }
    9282              : 
    9283              : /* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3.  Return
    9284              :    NULL_TREE if no simplification is possible.  */
    9285              : 
    9286              : tree
    9287      7461664 : fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
    9288              :                      tree arg3)
    9289              : {
    9290      7461664 :   tree inner, fndecl, inner_arg0;
    9291      7461664 :   enum tree_code code;
    9292              : 
    9293              :   /* Distribute the expected value over short-circuiting operators.
    9294              :      See through the cast from truthvalue_type_node to long.  */
    9295      7461664 :   inner_arg0 = arg0;
    9296     15237794 :   while (CONVERT_EXPR_P (inner_arg0)
    9297      1071701 :          && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
    9298      9605065 :          && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
    9299      1071700 :     inner_arg0 = TREE_OPERAND (inner_arg0, 0);
    9300              : 
    9301              :   /* If this is a builtin_expect within a builtin_expect keep the
    9302              :      inner one.  See through a comparison against a constant.  It
    9303              :      might have been added to create a thruthvalue.  */
    9304      7461664 :   inner = inner_arg0;
    9305              : 
    9306      7461664 :   if (COMPARISON_CLASS_P (inner)
    9307      7461664 :       && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
    9308      1433512 :     inner = TREE_OPERAND (inner, 0);
    9309              : 
    9310      7461664 :   if (TREE_CODE (inner) == CALL_EXPR
    9311       177099 :       && (fndecl = get_callee_fndecl (inner))
    9312      7638763 :       && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT,
    9313              :                             BUILT_IN_EXPECT_WITH_PROBABILITY))
    9314              :     return arg0;
    9315              : 
    9316      7461656 :   inner = inner_arg0;
    9317      7461656 :   code = TREE_CODE (inner);
    9318      7461656 :   if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
    9319              :     {
    9320       113050 :       tree op0 = TREE_OPERAND (inner, 0);
    9321       113050 :       tree op1 = TREE_OPERAND (inner, 1);
    9322       113050 :       arg1 = save_expr (arg1);
    9323              : 
    9324       113050 :       op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2, arg3);
    9325       113050 :       op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2, arg3);
    9326       113050 :       inner = build2 (code, TREE_TYPE (inner), op0, op1);
    9327              : 
    9328       113050 :       return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
    9329              :     }
    9330              : 
    9331              :   /* If the argument isn't invariant then there's nothing else we can do.  */
    9332      7348606 :   if (!TREE_CONSTANT (inner_arg0))
    9333              :     return NULL_TREE;
    9334              : 
    9335              :   /* If we expect that a comparison against the argument will fold to
    9336              :      a constant return the constant.  In practice, this means a true
    9337              :      constant or the address of a non-weak symbol.  */
    9338       253917 :   inner = inner_arg0;
    9339       253917 :   STRIP_NOPS (inner);
    9340       253917 :   if (TREE_CODE (inner) == ADDR_EXPR)
    9341              :     {
    9342            1 :       do
    9343              :         {
    9344            1 :           inner = TREE_OPERAND (inner, 0);
    9345              :         }
    9346            1 :       while (TREE_CODE (inner) == COMPONENT_REF
    9347            1 :              || TREE_CODE (inner) == ARRAY_REF);
    9348            1 :       if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner))
    9349            0 :         return NULL_TREE;
    9350              :     }
    9351              : 
    9352              :   /* Otherwise, ARG0 already has the proper type for the return value.  */
    9353              :   return arg0;
    9354              : }
    9355              : 
    9356              : /* Fold a call to __builtin_classify_type with argument ARG.  */
    9357              : 
    9358              : static tree
    9359         2068 : fold_builtin_classify_type (tree arg)
    9360              : {
    9361         2068 :   if (arg == 0)
    9362            0 :     return build_int_cst (integer_type_node, no_type_class);
    9363              : 
    9364         2068 :   return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
    9365              : }
    9366              : 
    9367              : /* Fold a call EXPR (which may be null) to __builtin_strlen with argument
    9368              :    ARG.  */
    9369              : 
    9370              : static tree
    9371       478331 : fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg)
    9372              : {
    9373       478331 :   if (!validate_arg (arg, POINTER_TYPE))
    9374              :     return NULL_TREE;
    9375              :   else
    9376              :     {
    9377       478328 :       c_strlen_data lendata = { };
    9378       478328 :       tree len = c_strlen (arg, 0, &lendata);
    9379              : 
    9380       478328 :       if (len)
    9381         2223 :         return fold_convert_loc (loc, type, len);
    9382              : 
    9383              :       /* TODO: Move this to gimple-ssa-warn-access once the pass runs
    9384              :          also early enough to detect invalid reads in multimensional
    9385              :          arrays and struct members.  */
    9386       476105 :       if (!lendata.decl)
    9387       468927 :          c_strlen (arg, 1, &lendata);
    9388              : 
    9389       476105 :       if (lendata.decl)
    9390              :         {
    9391         7192 :           if (EXPR_HAS_LOCATION (arg))
    9392         2800 :             loc = EXPR_LOCATION (arg);
    9393         4392 :           else if (loc == UNKNOWN_LOCATION)
    9394            0 :             loc = input_location;
    9395         7192 :           warn_string_no_nul (loc, expr, "strlen", arg, lendata.decl);
    9396              :         }
    9397              : 
    9398              :       return NULL_TREE;
    9399              :     }
    9400              : }
    9401              : 
    9402              : /* Fold a call to __builtin_inf or __builtin_huge_val.  */
    9403              : 
    9404              : static tree
    9405       264547 : fold_builtin_inf (location_t loc, tree type, int warn)
    9406              : {
    9407              :   /* __builtin_inff is intended to be usable to define INFINITY on all
    9408              :      targets.  If an infinity is not available, INFINITY expands "to a
    9409              :      positive constant of type float that overflows at translation
    9410              :      time", footnote "In this case, using INFINITY will violate the
    9411              :      constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
    9412              :      Thus we pedwarn to ensure this constraint violation is
    9413              :      diagnosed.  */
    9414      1057379 :   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
    9415            0 :     pedwarn (loc, 0, "target format does not support infinity");
    9416              : 
    9417       264547 :   return build_real (type, dconstinf);
    9418              : }
    9419              : 
    9420              : /* Fold function call to builtin sincos, sincosf, or sincosl.  Return
    9421              :    NULL_TREE if no simplification can be made.  */
    9422              : 
    9423              : static tree
    9424          145 : fold_builtin_sincos (location_t loc,
    9425              :                      tree arg0, tree arg1, tree arg2)
    9426              : {
    9427          145 :   tree type;
    9428          145 :   tree fndecl, call = NULL_TREE;
    9429              : 
    9430          145 :   if (!validate_arg (arg0, REAL_TYPE)
    9431          145 :       || !validate_arg (arg1, POINTER_TYPE)
    9432          290 :       || !validate_arg (arg2, POINTER_TYPE))
    9433              :     return NULL_TREE;
    9434              : 
    9435          145 :   type = TREE_TYPE (arg0);
    9436              : 
    9437              :   /* Calculate the result when the argument is a constant.  */
    9438          145 :   built_in_function fn = mathfn_built_in_2 (type, CFN_BUILT_IN_CEXPI);
    9439          145 :   if (fn == END_BUILTINS)
    9440              :     return NULL_TREE;
    9441              : 
    9442              :   /* Canonicalize sincos to cexpi.  */
    9443          145 :   if (TREE_CODE (arg0) == REAL_CST)
    9444              :     {
    9445           86 :       tree complex_type = build_complex_type (type);
    9446           86 :       call = fold_const_call (as_combined_fn (fn), complex_type, arg0);
    9447              :     }
    9448           86 :   if (!call)
    9449              :     {
    9450           59 :       if (!targetm.libc_has_function (function_c99_math_complex, type)
    9451           59 :           || !builtin_decl_implicit_p (fn))
    9452              :         return NULL_TREE;
    9453           59 :       fndecl = builtin_decl_explicit (fn);
    9454           59 :       call = build_call_expr_loc (loc, fndecl, 1, arg0);
    9455           59 :       call = builtin_save_expr (call);
    9456              :     }
    9457              : 
    9458          145 :   tree ptype = build_pointer_type (type);
    9459          145 :   arg1 = fold_convert (ptype, arg1);
    9460          145 :   arg2 = fold_convert (ptype, arg2);
    9461          145 :   return build2 (COMPOUND_EXPR, void_type_node,
    9462              :                  build2 (MODIFY_EXPR, void_type_node,
    9463              :                          build_fold_indirect_ref_loc (loc, arg1),
    9464              :                          fold_build1_loc (loc, IMAGPART_EXPR, type, call)),
    9465              :                  build2 (MODIFY_EXPR, void_type_node,
    9466              :                          build_fold_indirect_ref_loc (loc, arg2),
    9467          145 :                          fold_build1_loc (loc, REALPART_EXPR, type, call)));
    9468              : }
    9469              : 
    9470              : /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
    9471              :    Return NULL_TREE if no simplification can be made.  */
    9472              : 
    9473              : static tree
    9474      2580962 : fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
    9475              : {
    9476      2580962 :   if (!validate_arg (arg1, POINTER_TYPE)
    9477      2580962 :       || !validate_arg (arg2, POINTER_TYPE)
    9478      5161924 :       || !validate_arg (len, INTEGER_TYPE))
    9479              :     return NULL_TREE;
    9480              : 
    9481              :   /* If the LEN parameter is zero, return zero.  */
    9482      2580962 :   if (integer_zerop (len))
    9483            0 :     return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
    9484            0 :                               arg1, arg2);
    9485              : 
    9486              :   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
    9487      2580962 :   if (operand_equal_p (arg1, arg2, 0))
    9488          705 :     return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
    9489              : 
    9490              :   /* If len parameter is one, return an expression corresponding to
    9491              :      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
    9492      2580257 :   if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
    9493              :     {
    9494        55287 :       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
    9495        55287 :       tree cst_uchar_ptr_node
    9496        55287 :         = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
    9497              : 
    9498        55287 :       tree ind1
    9499        55287 :         = fold_convert_loc (loc, integer_type_node,
    9500              :                             build1 (INDIRECT_REF, cst_uchar_node,
    9501              :                                     fold_convert_loc (loc,
    9502              :                                                       cst_uchar_ptr_node,
    9503              :                                                       arg1)));
    9504        55287 :       tree ind2
    9505        55287 :         = fold_convert_loc (loc, integer_type_node,
    9506              :                             build1 (INDIRECT_REF, cst_uchar_node,
    9507              :                                     fold_convert_loc (loc,
    9508              :                                                       cst_uchar_ptr_node,
    9509              :                                                       arg2)));
    9510        55287 :       return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
    9511              :     }
    9512              : 
    9513              :   return NULL_TREE;
    9514              : }
    9515              : 
    9516              : /* Fold a call to builtin isascii with argument ARG.  */
    9517              : 
    9518              : static tree
    9519          211 : fold_builtin_isascii (location_t loc, tree arg)
    9520              : {
    9521          211 :   if (!validate_arg (arg, INTEGER_TYPE))
    9522              :     return NULL_TREE;
    9523              :   else
    9524              :     {
    9525              :       /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
    9526          211 :       arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
    9527              :                          build_int_cst (integer_type_node,
    9528              :                                         ~ HOST_WIDE_INT_UC (0x7f)));
    9529          211 :       return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
    9530          211 :                               arg, integer_zero_node);
    9531              :     }
    9532              : }
    9533              : 
    9534              : /* Fold a call to builtin toascii with argument ARG.  */
    9535              : 
    9536              : static tree
    9537          168 : fold_builtin_toascii (location_t loc, tree arg)
    9538              : {
    9539          168 :   if (!validate_arg (arg, INTEGER_TYPE))
    9540              :     return NULL_TREE;
    9541              : 
    9542              :   /* Transform toascii(c) -> (c & 0x7f).  */
    9543          168 :   return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
    9544              :                           build_int_cst (integer_type_node, 0x7f));
    9545              : }
    9546              : 
    9547              : /* Fold a call to builtin isdigit with argument ARG.  */
    9548              : 
    9549              : static tree
    9550          325 : fold_builtin_isdigit (location_t loc, tree arg)
    9551              : {
    9552          325 :   if (!validate_arg (arg, INTEGER_TYPE))
    9553              :     return NULL_TREE;
    9554              :   else
    9555              :     {
    9556              :       /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
    9557              :       /* According to the C standard, isdigit is unaffected by locale.
    9558              :          However, it definitely is affected by the target character set.  */
    9559          313 :       unsigned HOST_WIDE_INT target_digit0
    9560          313 :         = lang_hooks.to_target_charset ('0');
    9561              : 
    9562          313 :       if (target_digit0 == 0)
    9563              :         return NULL_TREE;
    9564              : 
    9565          313 :       arg = fold_convert_loc (loc, unsigned_type_node, arg);
    9566          313 :       arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
    9567              :                          build_int_cst (unsigned_type_node, target_digit0));
    9568          313 :       return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
    9569              :                           build_int_cst (unsigned_type_node, 9));
    9570              :     }
    9571              : }
    9572              : 
    9573              : /* Fold a call to fabs, fabsf or fabsl with argument ARG.  */
    9574              : 
    9575              : static tree
    9576       379580 : fold_builtin_fabs (location_t loc, tree arg, tree type)
    9577              : {
    9578       379580 :   if (!validate_arg (arg, REAL_TYPE))
    9579              :     return NULL_TREE;
    9580              : 
    9581       379495 :   arg = fold_convert_loc (loc, type, arg);
    9582       379495 :   return fold_build1_loc (loc, ABS_EXPR, type, arg);
    9583              : }
    9584              : 
    9585              : /* Fold a call to abs, labs, llabs, imaxabs, uabs, ulabs, ullabs or uimaxabs
    9586              :    with argument ARG.  */
    9587              : 
    9588              : static tree
    9589       101470 : fold_builtin_abs (location_t loc, tree arg, tree type)
    9590              : {
    9591       101470 :   if (!validate_arg (arg, INTEGER_TYPE) || !INTEGRAL_TYPE_P (type))
    9592              :     return NULL_TREE;
    9593              : 
    9594       101422 :   if (TYPE_UNSIGNED (type))
    9595              :     {
    9596         1168 :       if (TYPE_PRECISION (TREE_TYPE (arg))
    9597         1168 :           != TYPE_PRECISION (type)
    9598         1168 :           || TYPE_UNSIGNED (TREE_TYPE (arg)))
    9599              :         return NULL_TREE;
    9600         1168 :       return fold_build1_loc (loc, ABSU_EXPR, type, arg);
    9601              :     }
    9602       100254 :   arg = fold_convert_loc (loc, type, arg);
    9603       100254 :   return fold_build1_loc (loc, ABS_EXPR, type, arg);
    9604              : }
    9605              : 
    9606              : /* Fold a call to builtin carg(a+bi) -> atan2(b,a).  */
    9607              : 
    9608              : static tree
    9609       104839 : fold_builtin_carg (location_t loc, tree arg, tree type)
    9610              : {
    9611       104839 :   if (validate_arg (arg, COMPLEX_TYPE)
    9612       104839 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
    9613              :     {
    9614       104839 :       tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
    9615              : 
    9616       104839 :       if (atan2_fn)
    9617              :         {
    9618       100935 :           tree new_arg = builtin_save_expr (arg);
    9619       100935 :           tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
    9620       100935 :           tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
    9621       100935 :           return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
    9622              :         }
    9623              :     }
    9624              : 
    9625              :   return NULL_TREE;
    9626              : }
    9627              : 
    9628              : /* Fold a call to builtin frexp, we can assume the base is 2.  */
    9629              : 
    9630              : static tree
    9631       116489 : fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
    9632              : {
    9633       116489 :   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
    9634              :     return NULL_TREE;
    9635              : 
    9636       116489 :   STRIP_NOPS (arg0);
    9637              : 
    9638       116489 :   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
    9639              :     return NULL_TREE;
    9640              : 
    9641         2210 :   arg1 = build_fold_indirect_ref_loc (loc, arg1);
    9642              : 
    9643              :   /* Proceed if a valid pointer type was passed in.  */
    9644         2210 :   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
    9645              :     {
    9646         2210 :       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
    9647         2210 :       tree frac, exp, res;
    9648              : 
    9649         2210 :       switch (value->cl)
    9650              :       {
    9651          276 :       case rvc_zero:
    9652          276 :       case rvc_nan:
    9653          276 :       case rvc_inf:
    9654              :         /* For +-0, return (*exp = 0, +-0).  */
    9655              :         /* For +-NaN or +-Inf, *exp is unspecified, but something should
    9656              :            be stored there so that it isn't read from uninitialized object.
    9657              :            As glibc and newlib store *exp = 0 for +-Inf/NaN, storing
    9658              :            0 here as well is easiest.  */
    9659          276 :         exp = integer_zero_node;
    9660          276 :         frac = arg0;
    9661          276 :         break;
    9662         1934 :       case rvc_normal:
    9663         1934 :         {
    9664              :           /* Since the frexp function always expects base 2, and in
    9665              :              GCC normalized significands are already in the range
    9666              :              [0.5, 1.0), we have exactly what frexp wants.  */
    9667         1934 :           REAL_VALUE_TYPE frac_rvt = *value;
    9668         1934 :           SET_REAL_EXP (&frac_rvt, 0);
    9669         1934 :           frac = build_real (rettype, frac_rvt);
    9670         1934 :           exp = build_int_cst (integer_type_node, REAL_EXP (value));
    9671              :         }
    9672         1934 :         break;
    9673            0 :       default:
    9674            0 :         gcc_unreachable ();
    9675              :       }
    9676              : 
    9677              :       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
    9678         2210 :       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
    9679         2210 :       TREE_SIDE_EFFECTS (arg1) = 1;
    9680         2210 :       res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
    9681         2210 :       suppress_warning (res, OPT_Wunused_value);
    9682         2210 :       return res;
    9683              :     }
    9684              : 
    9685              :   return NULL_TREE;
    9686              : }
    9687              : 
    9688              : /* Fold a call to builtin modf.  */
    9689              : 
    9690              : static tree
    9691        93230 : fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
    9692              : {
    9693        93230 :   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
    9694              :     return NULL_TREE;
    9695              : 
    9696        93230 :   STRIP_NOPS (arg0);
    9697              : 
    9698        93230 :   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
    9699              :     return NULL_TREE;
    9700              : 
    9701         2474 :   arg1 = build_fold_indirect_ref_loc (loc, arg1);
    9702              : 
    9703              :   /* Proceed if a valid pointer type was passed in.  */
    9704         2474 :   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
    9705              :     {
    9706         2474 :       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
    9707         2474 :       REAL_VALUE_TYPE trunc, frac;
    9708         2474 :       tree res;
    9709              : 
    9710         2474 :       switch (value->cl)
    9711              :       {
    9712          228 :       case rvc_nan:
    9713          228 :       case rvc_zero:
    9714              :         /* For +-NaN or +-0, return (*arg1 = arg0, arg0).  */
    9715          228 :         trunc = frac = *value;
    9716          228 :         break;
    9717           96 :       case rvc_inf:
    9718              :         /* For +-Inf, return (*arg1 = arg0, +-0).  */
    9719           96 :         frac = dconst0;
    9720           96 :         frac.sign = value->sign;
    9721           96 :         trunc = *value;
    9722           96 :         break;
    9723         2150 :       case rvc_normal:
    9724              :         /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)).  */
    9725         2150 :         real_trunc (&trunc, VOIDmode, value);
    9726         2150 :         real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
    9727              :         /* If the original number was negative and already
    9728              :            integral, then the fractional part is -0.0.  */
    9729         2150 :         if (value->sign && frac.cl == rvc_zero)
    9730           69 :           frac.sign = value->sign;
    9731              :         break;
    9732              :       }
    9733              : 
    9734              :       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
    9735         2474 :       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
    9736              :                           build_real (rettype, trunc));
    9737         2474 :       TREE_SIDE_EFFECTS (arg1) = 1;
    9738         2474 :       res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
    9739              :                              build_real (rettype, frac));
    9740         2474 :       suppress_warning (res, OPT_Wunused_value);
    9741         2474 :       return res;
    9742              :     }
    9743              : 
    9744              :   return NULL_TREE;
    9745              : }
    9746              : 
    9747              : /* Given a location LOC, an interclass builtin function decl FNDECL
    9748              :    and its single argument ARG, return an folded expression computing
    9749              :    the same, or NULL_TREE if we either couldn't or didn't want to fold
    9750              :    (the latter happen if there's an RTL instruction available).  */
    9751              : 
    9752              : static tree
    9753      1826615 : fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
    9754              : {
    9755      1826615 :   machine_mode mode;
    9756              : 
    9757      1826615 :   if (!validate_arg (arg, REAL_TYPE))
    9758              :     return NULL_TREE;
    9759              : 
    9760      1826615 :   if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
    9761              :     return NULL_TREE;
    9762              : 
    9763      1826615 :   mode = TYPE_MODE (TREE_TYPE (arg));
    9764              : 
    9765     12782463 :   bool is_ibm_extended = MODE_COMPOSITE_P (mode);
    9766              : 
    9767              :   /* If there is no optab, try generic code.  */
    9768      1826615 :   switch (DECL_FUNCTION_CODE (fndecl))
    9769              :     {
    9770       711704 :       tree result;
    9771              : 
    9772       711704 :     CASE_FLT_FN (BUILT_IN_ISINF):
    9773       711704 :       {
    9774              :         /* isinf(x) -> isgreater(fabs(x),DBL_MAX).  */
    9775       711704 :         tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
    9776       711704 :         tree type = TREE_TYPE (arg);
    9777       711704 :         REAL_VALUE_TYPE r;
    9778       711704 :         char buf[128];
    9779              : 
    9780       711704 :         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       711704 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9789       711704 :         real_from_string3 (&r, buf, mode);
    9790       711704 :         result = build_call_expr (isgr_fn, 2,
    9791              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9792              :                                   build_real (type, r));
    9793       711704 :         return result;
    9794              :       }
    9795       628395 :     CASE_FLT_FN (BUILT_IN_FINITE):
    9796       628395 :     case BUILT_IN_ISFINITE:
    9797       628395 :       {
    9798              :         /* isfinite(x) -> islessequal(fabs(x),DBL_MAX).  */
    9799       628395 :         tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
    9800       628395 :         tree type = TREE_TYPE (arg);
    9801       628395 :         REAL_VALUE_TYPE r;
    9802       628395 :         char buf[128];
    9803              : 
    9804       628395 :         if (is_ibm_extended)
    9805              :           {
    9806              :             /* NaN and Inf are encoded in the high-order double value
    9807              :                only.  The low-order value is not significant.  */
    9808            0 :             type = double_type_node;
    9809            0 :             mode = DFmode;
    9810            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9811              :           }
    9812       628395 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9813       628395 :         real_from_string3 (&r, buf, mode);
    9814       628395 :         result = build_call_expr (isle_fn, 2,
    9815              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9816              :                                   build_real (type, r));
    9817              :         /*result = fold_build2_loc (loc, UNGT_EXPR,
    9818              :                                   TREE_TYPE (TREE_TYPE (fndecl)),
    9819              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9820              :                                   build_real (type, r));
    9821              :         result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
    9822              :                                   TREE_TYPE (TREE_TYPE (fndecl)),
    9823              :                                   result);*/
    9824       628395 :         return result;
    9825              :       }
    9826       240988 :     case BUILT_IN_ISNORMAL:
    9827       240988 :       {
    9828              :         /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
    9829              :            islessequal(fabs(x),DBL_MAX).  */
    9830       240988 :         tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
    9831       240988 :         tree type = TREE_TYPE (arg);
    9832       240988 :         tree orig_arg, max_exp, min_exp;
    9833       240988 :         machine_mode orig_mode = mode;
    9834       240988 :         REAL_VALUE_TYPE rmax, rmin;
    9835       240988 :         char buf[128];
    9836              : 
    9837       240988 :         orig_arg = arg = builtin_save_expr (arg);
    9838       240988 :         if (is_ibm_extended)
    9839              :           {
    9840              :             /* Use double to test the normal range of IBM extended
    9841              :                precision.  Emin for IBM extended precision is
    9842              :                different to emin for IEEE double, being 53 higher
    9843              :                since the low double exponent is at least 53 lower
    9844              :                than the high double exponent.  */
    9845            0 :             type = double_type_node;
    9846            0 :             mode = DFmode;
    9847            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9848              :           }
    9849       240988 :         arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
    9850              : 
    9851       240988 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9852       240988 :         real_from_string3 (&rmax, buf, mode);
    9853       240988 :         if (DECIMAL_FLOAT_MODE_P (mode))
    9854            1 :           sprintf (buf, "1E%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
    9855              :         else
    9856       240987 :           sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
    9857       240988 :         real_from_string3 (&rmin, buf, orig_mode);
    9858       240988 :         max_exp = build_real (type, rmax);
    9859       240988 :         min_exp = build_real (type, rmin);
    9860              : 
    9861       240988 :         max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
    9862       240988 :         if (is_ibm_extended)
    9863              :           {
    9864              :             /* Testing the high end of the range is done just using
    9865              :                the high double, using the same test as isfinite().
    9866              :                For the subnormal end of the range we first test the
    9867              :                high double, then if its magnitude is equal to the
    9868              :                limit of 0x1p-969, we test whether the low double is
    9869              :                non-zero and opposite sign to the high double.  */
    9870            0 :             tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS);
    9871            0 :             tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
    9872            0 :             tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
    9873            0 :             tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
    9874              :                                        arg, min_exp);
    9875            0 :             tree as_complex = build1 (VIEW_CONVERT_EXPR,
    9876              :                                       complex_double_type_node, orig_arg);
    9877            0 :             tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
    9878            0 :             tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
    9879            0 :             tree zero = build_real (type, dconst0);
    9880            0 :             tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
    9881            0 :             tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
    9882            0 :             tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
    9883            0 :             tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
    9884              :                                       fold_build3 (COND_EXPR,
    9885              :                                                    integer_type_node,
    9886              :                                                    hilt, logt, lolt));
    9887            0 :             eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
    9888              :                                   eq_min, ok_lo);
    9889            0 :             min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
    9890              :                                    gt_min, eq_min);
    9891              :           }
    9892              :         else
    9893              :           {
    9894       240988 :             tree const isge_fn
    9895       240988 :               = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
    9896       240988 :             min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
    9897              :           }
    9898       240988 :         result = fold_build2 (BIT_AND_EXPR, integer_type_node,
    9899              :                               max_exp, min_exp);
    9900       240988 :         return result;
    9901              :       }
    9902       243994 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    9903       243994 :     case BUILT_IN_ISNAND32:
    9904       243994 :     case BUILT_IN_ISNAND64:
    9905       243994 :     case BUILT_IN_ISNAND128:
    9906       243994 :       {
    9907              :         /* In IBM extended NaN and Inf are encoded in the high-order double
    9908              :            value only.  The low-order value is not significant.  */
    9909       243994 :         if (is_ibm_extended)
    9910            0 :           arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
    9911       243994 :         arg = builtin_save_expr (arg);
    9912       243994 :         tree type = TREE_TYPE (TREE_TYPE (fndecl));
    9913       243994 :         return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
    9914              :       }
    9915              :     default:
    9916              :       break;
    9917              :     }
    9918              : 
    9919              :   return NULL_TREE;
    9920              : }
    9921              : 
    9922              : /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
    9923              :    ARG is the argument for the call.  */
    9924              : 
    9925              : static tree
    9926      1614857 : fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
    9927              : {
    9928      1614857 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
    9929              : 
    9930      1614857 :   if (!validate_arg (arg, REAL_TYPE))
    9931              :     return NULL_TREE;
    9932              : 
    9933      1614857 :   switch (builtin_index)
    9934              :     {
    9935       713489 :     case BUILT_IN_ISINF:
    9936       713489 :       if (tree_expr_infinite_p (arg))
    9937            0 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9938       713489 :       if (!tree_expr_maybe_infinite_p (arg))
    9939          251 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9940              :       return NULL_TREE;
    9941              : 
    9942          708 :     case BUILT_IN_ISINF_SIGN:
    9943          708 :       {
    9944              :         /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
    9945              :         /* In a boolean context, GCC will fold the inner COND_EXPR to
    9946              :            1.  So e.g. "if (isinf_sign(x))" would be folded to just
    9947              :            "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
    9948          708 :         tree signbit_fn = builtin_decl_explicit (BUILT_IN_SIGNBIT);
    9949          708 :         tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
    9950          708 :         tree tmp = NULL_TREE;
    9951              : 
    9952          708 :         arg = builtin_save_expr (arg);
    9953              : 
    9954          708 :         if (signbit_fn && isinf_fn)
    9955              :           {
    9956          708 :             tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
    9957          708 :             tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
    9958              : 
    9959          708 :             signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
    9960              :                                         signbit_call, integer_zero_node);
    9961          708 :             isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
    9962              :                                       isinf_call, integer_zero_node);
    9963              : 
    9964          708 :             tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
    9965              :                                integer_minus_one_node, integer_one_node);
    9966          708 :             tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
    9967              :                                isinf_call, tmp,
    9968              :                                integer_zero_node);
    9969              :           }
    9970              : 
    9971              :         return tmp;
    9972              :       }
    9973              : 
    9974       628727 :     case BUILT_IN_ISFINITE:
    9975       628727 :       if (tree_expr_finite_p (arg))
    9976          332 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9977       628395 :       if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
    9978            0 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9979              :       return NULL_TREE;
    9980              : 
    9981       244118 :     case BUILT_IN_ISNAN:
    9982       244118 :       if (tree_expr_nan_p (arg))
    9983            0 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9984       244118 :       if (!tree_expr_maybe_nan_p (arg))
    9985          124 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9986              :       return NULL_TREE;
    9987              : 
    9988        27815 :     case BUILT_IN_ISSIGNALING:
    9989              :       /* Folding to true for REAL_CST is done in fold_const_call_ss.
    9990              :          Don't use tree_expr_signaling_nan_p (arg) -> integer_one_node
    9991              :          and !tree_expr_maybe_signaling_nan_p (arg) -> integer_zero_node
    9992              :          here, so there is some possibility of __builtin_issignaling working
    9993              :          without -fsignaling-nans.  Especially when -fno-signaling-nans is
    9994              :          the default.  */
    9995        27815 :       if (!tree_expr_maybe_nan_p (arg))
    9996            0 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9997              :       return NULL_TREE;
    9998              : 
    9999            0 :     default:
   10000            0 :       gcc_unreachable ();
   10001              :     }
   10002              : }
   10003              : 
   10004              : /* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
   10005              :    This builtin will generate code to return the appropriate floating
   10006              :    point classification depending on the value of the floating point
   10007              :    number passed in.  The possible return values must be supplied as
   10008              :    int arguments to the call in the following order: FP_NAN, FP_INFINITE,
   10009              :    FP_NORMAL, FP_SUBNORMAL and FP_ZERO.  The ellipses is for exactly
   10010              :    one floating point argument which is "type generic".  */
   10011              : 
   10012              : static tree
   10013       104982 : fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
   10014              : {
   10015       104982 :   tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
   10016              :     arg, type, res, tmp;
   10017       104982 :   machine_mode mode;
   10018       104982 :   REAL_VALUE_TYPE r;
   10019       104982 :   char buf[128];
   10020              : 
   10021              :   /* Verify the required arguments in the original call.  */
   10022       104982 :   if (nargs != 6
   10023       104982 :       || !validate_arg (args[0], INTEGER_TYPE)
   10024       104982 :       || !validate_arg (args[1], INTEGER_TYPE)
   10025       104982 :       || !validate_arg (args[2], INTEGER_TYPE)
   10026       104982 :       || !validate_arg (args[3], INTEGER_TYPE)
   10027       104982 :       || !validate_arg (args[4], INTEGER_TYPE)
   10028       209964 :       || !validate_arg (args[5], REAL_TYPE))
   10029              :     return NULL_TREE;
   10030              : 
   10031       104982 :   fp_nan = args[0];
   10032       104982 :   fp_infinite = args[1];
   10033       104982 :   fp_normal = args[2];
   10034       104982 :   fp_subnormal = args[3];
   10035       104982 :   fp_zero = args[4];
   10036       104982 :   arg = args[5];
   10037       104982 :   type = TREE_TYPE (arg);
   10038       104982 :   mode = TYPE_MODE (type);
   10039              : 
   10040              :   /* A target defines the classification optabs when FP comparisons are
   10041              :      unsuitable for classification, for instance because they raise
   10042              :      FE_INVALID for a signaling NaN (PR middle-end/66462).  Build on the
   10043              :      built-ins in that case rather than on comparisons.  */
   10044       104982 :   if (optab_handler (isnan_optab, mode) != CODE_FOR_nothing
   10045            0 :       && optab_handler (isinf_optab, mode) != CODE_FOR_nothing
   10046       104982 :       && optab_handler (isnormal_optab, mode) != CODE_FOR_nothing)
   10047              :     {
   10048            0 :       tree isnan_fn = builtin_decl_explicit (BUILT_IN_ISNAN);
   10049            0 :       tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
   10050            0 :       tree isnormal_fn = builtin_decl_explicit (BUILT_IN_ISNORMAL);
   10051            0 :       const struct real_format *fmt = REAL_MODE_FORMAT (mode);
   10052            0 :       tree itype = NULL_TREE;
   10053            0 :       scalar_int_mode imode;
   10054              : 
   10055              :       /* The remaining zero versus subnormal test must not use a comparison
   10056              :          either.  Testing the magnitude of the encoding for zero works
   10057              :          whenever the format is binary, has a matching integer mode and
   10058              :          stores its sign in the high bit of it; that excludes e.g. XFmode,
   10059              :          whose encoding is narrower than its integer mode, and the composite
   10060              :          formats, whose sign is not a single bit that can be shifted out.  */
   10061            0 :       if (fmt->b == 2
   10062            0 :           && int_mode_for_mode (mode).exists (&imode)
   10063            0 :           && fmt->signbit_rw == fmt->signbit_ro
   10064            0 :           && fmt->signbit_rw == (int) GET_MODE_PRECISION (imode) - 1)
   10065              :         {
   10066            0 :           itype = lang_hooks.types.type_for_mode (imode, 1);
   10067            0 :           if (itype && TYPE_PRECISION (itype) != GET_MODE_PRECISION (imode))
   10068              :             itype = NULL_TREE;
   10069              :         }
   10070              : 
   10071            0 :       if (isnan_fn && isinf_fn && isnormal_fn && itype)
   10072              :         {
   10073            0 :           arg = builtin_save_expr (arg);
   10074              : 
   10075              :           /* Shifting the sign bit out leaves zero iff ARG is +-0.  */
   10076            0 :           tmp = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, arg);
   10077            0 :           tmp = fold_build2_loc (loc, LSHIFT_EXPR, itype, tmp,
   10078              :                                  build_int_cst (integer_type_node, 1));
   10079            0 :           tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, tmp,
   10080              :                                  build_int_cst (itype, 0));
   10081            0 :           res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
   10082              :                                  tmp, fp_zero, fp_subnormal);
   10083              : 
   10084            0 :           tmp = build_call_expr_loc (loc, isnormal_fn, 1, arg);
   10085            0 :           tmp = fold_build2_loc (loc, NE_EXPR, integer_type_node, tmp,
   10086              :                                  integer_zero_node);
   10087            0 :           res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10088              :                                  fp_normal, res);
   10089              : 
   10090            0 :           if (tree_expr_maybe_infinite_p (arg))
   10091              :             {
   10092            0 :               tmp = build_call_expr_loc (loc, isinf_fn, 1, arg);
   10093            0 :               tmp = fold_build2_loc (loc, NE_EXPR, integer_type_node, tmp,
   10094              :                                      integer_zero_node);
   10095            0 :               res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10096              :                                      fp_infinite, res);
   10097              :             }
   10098              : 
   10099            0 :           if (tree_expr_maybe_nan_p (arg))
   10100              :             {
   10101            0 :               tmp = build_call_expr_loc (loc, isnan_fn, 1, arg);
   10102            0 :               tmp = fold_build2_loc (loc, NE_EXPR, integer_type_node, tmp,
   10103              :                                      integer_zero_node);
   10104            0 :               res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10105              :                                      fp_nan, res);
   10106              :             }
   10107              : 
   10108       104982 :           return res;
   10109              :         }
   10110              :     }
   10111              : 
   10112       104982 :   arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
   10113              : 
   10114              :   /* fpclassify(x) ->
   10115              :        isnan(x) ? FP_NAN :
   10116              :          (fabs(x) == Inf ? FP_INFINITE :
   10117              :            (fabs(x) >= DBL_MIN ? FP_NORMAL :
   10118              :              (x == 0 ? FP_ZERO : FP_SUBNORMAL))).  */
   10119              : 
   10120       104982 :   tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   10121              :                          build_real (type, dconst0));
   10122       104982 :   res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
   10123              :                          tmp, fp_zero, fp_subnormal);
   10124              : 
   10125       104982 :   if (DECIMAL_FLOAT_MODE_P (mode))
   10126            3 :     sprintf (buf, "1E%d", REAL_MODE_FORMAT (mode)->emin - 1);
   10127              :   else
   10128       104979 :     sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
   10129       104982 :   real_from_string3 (&r, buf, mode);
   10130       104982 :   tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
   10131              :                          arg, build_real (type, r));
   10132       104982 :   res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10133              :                          fp_normal, res);
   10134              : 
   10135       104982 :   if (tree_expr_maybe_infinite_p (arg))
   10136              :     {
   10137       104894 :       tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   10138              :                              build_real (type, dconstinf));
   10139       104894 :       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10140              :                              fp_infinite, res);
   10141              :     }
   10142              : 
   10143       104982 :   if (tree_expr_maybe_nan_p (arg))
   10144              :     {
   10145       104892 :       tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
   10146       104892 :       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10147              :                              res, fp_nan);
   10148              :     }
   10149              : 
   10150              :   return res;
   10151              : }
   10152              : 
   10153              : /* Fold a call to an unordered comparison function such as
   10154              :    __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
   10155              :    being called and ARG0 and ARG1 are the arguments for the call.
   10156              :    UNORDERED_CODE and ORDERED_CODE are comparison codes that give
   10157              :    the opposite of the desired result.  UNORDERED_CODE is used
   10158              :    for modes that can hold NaNs and ORDERED_CODE is used for
   10159              :    the rest.  */
   10160              : 
   10161              : static tree
   10162      3272361 : fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
   10163              :                             enum tree_code unordered_code,
   10164              :                             enum tree_code ordered_code)
   10165              : {
   10166      3272361 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10167      3272361 :   enum tree_code code;
   10168      3272361 :   tree type0, type1;
   10169      3272361 :   enum tree_code code0, code1;
   10170      3272361 :   tree cmp_type = NULL_TREE;
   10171              : 
   10172      3272361 :   type0 = TREE_TYPE (arg0);
   10173      3272361 :   type1 = TREE_TYPE (arg1);
   10174              : 
   10175      3272361 :   code0 = TREE_CODE (type0);
   10176      3272361 :   code1 = TREE_CODE (type1);
   10177              : 
   10178      3272361 :   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
   10179              :     /* Choose the wider of two real types.  */
   10180      3272181 :     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   10181      3272181 :       ? type0 : type1;
   10182          180 :   else if (code0 == REAL_TYPE
   10183           91 :            && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
   10184              :     cmp_type = type0;
   10185           89 :   else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
   10186           89 :            && code1 == REAL_TYPE)
   10187          135 :     cmp_type = type1;
   10188              : 
   10189      3272361 :   arg0 = fold_convert_loc (loc, cmp_type, arg0);
   10190      3272361 :   arg1 = fold_convert_loc (loc, cmp_type, arg1);
   10191              : 
   10192      3272361 :   if (unordered_code == UNORDERED_EXPR)
   10193              :     {
   10194       241975 :       if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
   10195           16 :         return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
   10196       241959 :       if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
   10197          141 :         return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
   10198       241818 :       return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
   10199              :     }
   10200              : 
   10201      3033237 :   code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
   10202      3030386 :          ? unordered_code : ordered_code;
   10203      3030386 :   return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
   10204      3030386 :                       fold_build2_loc (loc, code, type, arg0, arg1));
   10205              : }
   10206              : 
   10207              : /* Fold a call to __builtin_iseqsig().  ARG0 and ARG1 are the arguments.
   10208              :    After choosing the wider floating-point type for the comparison,
   10209              :    the code is folded to:
   10210              :      SAVE_EXPR<ARG0> >= SAVE_EXPR<ARG1> && SAVE_EXPR<ARG0> <= SAVE_EXPR<ARG1>  */
   10211              : 
   10212              : static tree
   10213          709 : fold_builtin_iseqsig (location_t loc, tree arg0, tree arg1)
   10214              : {
   10215          709 :   tree type0, type1;
   10216          709 :   enum tree_code code0, code1;
   10217          709 :   tree cmp1, cmp2, cmp_type = NULL_TREE;
   10218              : 
   10219          709 :   type0 = TREE_TYPE (arg0);
   10220          709 :   type1 = TREE_TYPE (arg1);
   10221              : 
   10222          709 :   code0 = TREE_CODE (type0);
   10223          709 :   code1 = TREE_CODE (type1);
   10224              : 
   10225          709 :   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
   10226              :     /* Choose the wider of two real types.  */
   10227          690 :     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   10228          690 :       ? type0 : type1;
   10229           19 :   else if (code0 == REAL_TYPE
   10230            6 :            && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
   10231              :     cmp_type = type0;
   10232           13 :   else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
   10233           13 :            && code1 == REAL_TYPE)
   10234           13 :     cmp_type = type1;
   10235              : 
   10236          709 :   arg0 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg0));
   10237          709 :   arg1 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg1));
   10238              : 
   10239          709 :   cmp1 = fold_build2_loc (loc, GE_EXPR, integer_type_node, arg0, arg1);
   10240          709 :   cmp2 = fold_build2_loc (loc, LE_EXPR, integer_type_node, arg0, arg1);
   10241              : 
   10242          709 :   return fold_build2_loc (loc, TRUTH_AND_EXPR, integer_type_node, cmp1, cmp2);
   10243              : }
   10244              : 
   10245              : /* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
   10246              :    arithmetics if it can never overflow, or into internal functions that
   10247              :    return both result of arithmetics and overflowed boolean flag in
   10248              :    a complex integer result, or some other check for overflow.
   10249              :    Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
   10250              :    checking part of that.  */
   10251              : 
   10252              : static tree
   10253       511299 : fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
   10254              :                              tree arg0, tree arg1, tree arg2)
   10255              : {
   10256       511299 :   enum internal_fn ifn = IFN_LAST;
   10257              :   /* The code of the expression corresponding to the built-in.  */
   10258       511299 :   enum tree_code opcode = ERROR_MARK;
   10259       511299 :   bool ovf_only = false;
   10260              : 
   10261       511299 :   switch (fcode)
   10262              :     {
   10263              :     case BUILT_IN_ADD_OVERFLOW_P:
   10264              :       ovf_only = true;
   10265              :       /* FALLTHRU */
   10266              :     case BUILT_IN_ADD_OVERFLOW:
   10267              :     case BUILT_IN_SADD_OVERFLOW:
   10268              :     case BUILT_IN_SADDL_OVERFLOW:
   10269              :     case BUILT_IN_SADDLL_OVERFLOW:
   10270              :     case BUILT_IN_UADD_OVERFLOW:
   10271              :     case BUILT_IN_UADDL_OVERFLOW:
   10272              :     case BUILT_IN_UADDLL_OVERFLOW:
   10273              :       opcode = PLUS_EXPR;
   10274              :       ifn = IFN_ADD_OVERFLOW;
   10275              :       break;
   10276        15577 :     case BUILT_IN_SUB_OVERFLOW_P:
   10277        15577 :       ovf_only = true;
   10278              :       /* FALLTHRU */
   10279        37597 :     case BUILT_IN_SUB_OVERFLOW:
   10280        37597 :     case BUILT_IN_SSUB_OVERFLOW:
   10281        37597 :     case BUILT_IN_SSUBL_OVERFLOW:
   10282        37597 :     case BUILT_IN_SSUBLL_OVERFLOW:
   10283        37597 :     case BUILT_IN_USUB_OVERFLOW:
   10284        37597 :     case BUILT_IN_USUBL_OVERFLOW:
   10285        37597 :     case BUILT_IN_USUBLL_OVERFLOW:
   10286        37597 :       opcode = MINUS_EXPR;
   10287        37597 :       ifn = IFN_SUB_OVERFLOW;
   10288        37597 :       break;
   10289        15878 :     case BUILT_IN_MUL_OVERFLOW_P:
   10290        15878 :       ovf_only = true;
   10291              :       /* FALLTHRU */
   10292       434159 :     case BUILT_IN_MUL_OVERFLOW:
   10293       434159 :     case BUILT_IN_SMUL_OVERFLOW:
   10294       434159 :     case BUILT_IN_SMULL_OVERFLOW:
   10295       434159 :     case BUILT_IN_SMULLL_OVERFLOW:
   10296       434159 :     case BUILT_IN_UMUL_OVERFLOW:
   10297       434159 :     case BUILT_IN_UMULL_OVERFLOW:
   10298       434159 :     case BUILT_IN_UMULLL_OVERFLOW:
   10299       434159 :       opcode = MULT_EXPR;
   10300       434159 :       ifn = IFN_MUL_OVERFLOW;
   10301       434159 :       break;
   10302            0 :     default:
   10303            0 :       gcc_unreachable ();
   10304              :     }
   10305              : 
   10306              :   /* For the "generic" overloads, the first two arguments can have different
   10307              :      types and the last argument determines the target type to use to check
   10308              :      for overflow.  The arguments of the other overloads all have the same
   10309              :      type.  */
   10310       511299 :   tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
   10311              : 
   10312              :   /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
   10313              :      arguments are constant, attempt to fold the built-in call into a constant
   10314              :      expression indicating whether or not it detected an overflow.  */
   10315       511299 :   if (ovf_only
   10316        43265 :       && TREE_CODE (arg0) == INTEGER_CST
   10317        13131 :       && TREE_CODE (arg1) == INTEGER_CST)
   10318              :     /* Perform the computation in the target type and check for overflow.  */
   10319         7347 :     return omit_one_operand_loc (loc, boolean_type_node,
   10320         7347 :                                  arith_overflowed_p (opcode, type, arg0, arg1)
   10321              :                                  ? boolean_true_node : boolean_false_node,
   10322         7347 :                                  arg2);
   10323              : 
   10324       503952 :   tree intres, ovfres;
   10325       503952 :   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
   10326              :     {
   10327        88954 :       intres = fold_binary_loc (loc, opcode, type,
   10328              :                                 fold_convert_loc (loc, type, arg0),
   10329              :                                 fold_convert_loc (loc, type, arg1));
   10330        88954 :       if (TREE_OVERFLOW (intres))
   10331         1629 :         intres = drop_tree_overflow (intres);
   10332       177908 :       ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
   10333        88954 :                 ? boolean_true_node : boolean_false_node);
   10334              :     }
   10335              :   else
   10336              :     {
   10337       414998 :       tree ctype = build_complex_type (type);
   10338       414998 :       tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10339              :                                                 arg0, arg1);
   10340       414998 :       tree tgt;
   10341       414998 :       if (ovf_only)
   10342              :         {
   10343              :           tgt = call;
   10344       414998 :           intres = NULL_TREE;
   10345              :         }
   10346              :       else
   10347              :         {
   10348              :           /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
   10349              :              as while the call itself is const, the REALPART_EXPR store is
   10350              :              certainly not.  And in any case, we want just one call,
   10351              :              not multiple and trying to CSE them later.  */
   10352       379080 :           TREE_SIDE_EFFECTS (call) = 1;
   10353       379080 :           tgt = save_expr (call);
   10354              :         }
   10355       414998 :       intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10356       414998 :       ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10357       414998 :       ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
   10358              :     }
   10359              : 
   10360       503952 :   if (ovf_only)
   10361        35918 :     return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
   10362              : 
   10363       468034 :   tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
   10364       468034 :   tree store
   10365       468034 :     = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
   10366       468034 :   return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
   10367              : }
   10368              : 
   10369              : /* Fold __builtin_{clz,ctz,clrsb,ffs,parity,popcount}g into corresponding
   10370              :    internal function.  */
   10371              : 
   10372              : static tree
   10373       267151 : fold_builtin_bit_query (location_t loc, enum built_in_function fcode,
   10374              :                         tree arg0, tree arg1)
   10375              : {
   10376       267151 :   enum internal_fn ifn;
   10377       267151 :   enum built_in_function fcodei, fcodel, fcodell;
   10378       267151 :   tree arg0_type = TREE_TYPE (arg0);
   10379       267151 :   tree cast_type = NULL_TREE;
   10380       267151 :   int addend = 0;
   10381              : 
   10382       267151 :   switch (fcode)
   10383              :     {
   10384       188435 :     case BUILT_IN_CLZG:
   10385       188435 :       if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
   10386              :         return NULL_TREE;
   10387              :       ifn = IFN_CLZ;
   10388              :       fcodei = BUILT_IN_CLZ;
   10389              :       fcodel = BUILT_IN_CLZL;
   10390              :       fcodell = BUILT_IN_CLZLL;
   10391              :       break;
   10392        67237 :     case BUILT_IN_CTZG:
   10393        67237 :       if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
   10394              :         return NULL_TREE;
   10395              :       ifn = IFN_CTZ;
   10396              :       fcodei = BUILT_IN_CTZ;
   10397              :       fcodel = BUILT_IN_CTZL;
   10398              :       fcodell = BUILT_IN_CTZLL;
   10399              :       break;
   10400              :     case BUILT_IN_CLRSBG:
   10401              :       ifn = IFN_CLRSB;
   10402              :       fcodei = BUILT_IN_CLRSB;
   10403              :       fcodel = BUILT_IN_CLRSBL;
   10404              :       fcodell = BUILT_IN_CLRSBLL;
   10405              :       break;
   10406           84 :     case BUILT_IN_FFSG:
   10407           84 :       ifn = IFN_FFS;
   10408           84 :       fcodei = BUILT_IN_FFS;
   10409           84 :       fcodel = BUILT_IN_FFSL;
   10410           84 :       fcodell = BUILT_IN_FFSLL;
   10411           84 :       break;
   10412           82 :     case BUILT_IN_PARITYG:
   10413           82 :       ifn = IFN_PARITY;
   10414           82 :       fcodei = BUILT_IN_PARITY;
   10415           82 :       fcodel = BUILT_IN_PARITYL;
   10416           82 :       fcodell = BUILT_IN_PARITYLL;
   10417           82 :       break;
   10418        11231 :     case BUILT_IN_POPCOUNTG:
   10419        11231 :       ifn = IFN_POPCOUNT;
   10420        11231 :       fcodei = BUILT_IN_POPCOUNT;
   10421        11231 :       fcodel = BUILT_IN_POPCOUNTL;
   10422        11231 :       fcodell = BUILT_IN_POPCOUNTLL;
   10423        11231 :       break;
   10424            0 :     default:
   10425            0 :       gcc_unreachable ();
   10426              :     }
   10427              : 
   10428       266948 :   if (TYPE_PRECISION (arg0_type)
   10429       266948 :       <= TYPE_PRECISION (long_long_unsigned_type_node))
   10430              :     {
   10431       227681 :       if (TYPE_PRECISION (arg0_type) <= TYPE_PRECISION (unsigned_type_node))
   10432              : 
   10433        79774 :         cast_type = (TYPE_UNSIGNED (arg0_type)
   10434        79720 :                      ? unsigned_type_node : integer_type_node);
   10435       147961 :       else if (TYPE_PRECISION (arg0_type)
   10436       147961 :                <= TYPE_PRECISION (long_unsigned_type_node))
   10437              :         {
   10438       147910 :           cast_type = (TYPE_UNSIGNED (arg0_type)
   10439       147838 :                        ? long_unsigned_type_node : long_integer_type_node);
   10440              :           fcodei = fcodel;
   10441              :         }
   10442              :       else
   10443              :         {
   10444          123 :           cast_type = (TYPE_UNSIGNED (arg0_type)
   10445          123 :                        ? long_long_unsigned_type_node
   10446              :                        : long_long_integer_type_node);
   10447              :           fcodei = fcodell;
   10448              :         }
   10449              :     }
   10450        78534 :   else if (TYPE_PRECISION (arg0_type) <= MAX_FIXED_MODE_SIZE)
   10451              :     {
   10452        39157 :       cast_type
   10453        39157 :         = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
   10454        39157 :                                           TYPE_UNSIGNED (arg0_type));
   10455        39157 :       gcc_assert (TYPE_PRECISION (cast_type)
   10456              :                   == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
   10457              :       fcodei = END_BUILTINS;
   10458              :     }
   10459              :   else
   10460              :     fcodei = END_BUILTINS;
   10461       266838 :   if (cast_type)
   10462              :     {
   10463       266838 :       switch (fcode)
   10464              :         {
   10465       188384 :         case BUILT_IN_CLZG:
   10466       188384 :         case BUILT_IN_CLRSBG:
   10467       188384 :           addend = TYPE_PRECISION (arg0_type) - TYPE_PRECISION (cast_type);
   10468       188384 :           break;
   10469              :         default:
   10470              :           break;
   10471              :         }
   10472       266838 :       arg0 = fold_convert (cast_type, arg0);
   10473       266838 :       arg0_type = cast_type;
   10474              :     }
   10475              : 
   10476       266948 :   if (arg1)
   10477       177049 :     arg1 = fold_convert (integer_type_node, arg1);
   10478              : 
   10479       266948 :   tree arg2 = arg1;
   10480       266948 :   if (fcode == BUILT_IN_CLZG && addend)
   10481              :     {
   10482         4389 :       if (arg1)
   10483         4356 :         arg0 = save_expr (arg0);
   10484              :       arg2 = NULL_TREE;
   10485              :     }
   10486       266948 :   tree call = NULL_TREE, tem;
   10487       266948 :   if (TYPE_PRECISION (arg0_type) == MAX_FIXED_MODE_SIZE
   10488        39280 :       && (TYPE_PRECISION (arg0_type)
   10489        39280 :           == 2 * TYPE_PRECISION (long_long_unsigned_type_node))
   10490              :       /* If the target supports the optab, then don't do the expansion. */
   10491       306105 :       && !direct_internal_fn_supported_p (ifn, arg0_type, OPTIMIZE_FOR_BOTH))
   10492              :     {
   10493              :       /* __int128 expansions using up to 2 long long builtins.  */
   10494        39157 :       arg0 = save_expr (arg0);
   10495        39157 :       tree type = (TYPE_UNSIGNED (arg0_type)
   10496        39157 :                    ? long_long_unsigned_type_node
   10497        39157 :                    : long_long_integer_type_node);
   10498        78314 :       tree hi = fold_build2 (RSHIFT_EXPR, arg0_type, arg0,
   10499              :                              build_int_cst (integer_type_node,
   10500              :                                             MAX_FIXED_MODE_SIZE / 2));
   10501        39157 :       hi = fold_convert (type, hi);
   10502        39157 :       tree lo = fold_convert (type, arg0);
   10503        39157 :       switch (fcode)
   10504              :         {
   10505        39068 :         case BUILT_IN_CLZG:
   10506        39068 :           call = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
   10507        78136 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10508              :                               build_int_cst (integer_type_node,
   10509              :                                              MAX_FIXED_MODE_SIZE / 2));
   10510        39068 :           if (arg2)
   10511        39048 :             call = fold_build3 (COND_EXPR, integer_type_node,
   10512              :                                 fold_build2 (NE_EXPR, boolean_type_node,
   10513              :                                              lo, build_zero_cst (type)),
   10514              :                                 call, arg2);
   10515        39068 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10516              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10517              :                                            hi, build_zero_cst (type)),
   10518              :                               fold_builtin_bit_query (loc, fcode, hi,
   10519              :                                                       NULL_TREE),
   10520              :                               call);
   10521        39068 :           break;
   10522           27 :         case BUILT_IN_CTZG:
   10523           27 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10524           54 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10525              :                               build_int_cst (integer_type_node,
   10526              :                                              MAX_FIXED_MODE_SIZE / 2));
   10527           27 :           if (arg2)
   10528           18 :             call = fold_build3 (COND_EXPR, integer_type_node,
   10529              :                                 fold_build2 (NE_EXPR, boolean_type_node,
   10530              :                                              hi, build_zero_cst (type)),
   10531              :                                 call, arg2);
   10532           27 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10533              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10534              :                                            lo, build_zero_cst (type)),
   10535              :                               fold_builtin_bit_query (loc, fcode, lo,
   10536              :                                                       NULL_TREE),
   10537              :                               call);
   10538           27 :           break;
   10539            9 :         case BUILT_IN_CLRSBG:
   10540            9 :           tem = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
   10541           18 :           tem = fold_build2 (PLUS_EXPR, integer_type_node, tem,
   10542              :                              build_int_cst (integer_type_node,
   10543              :                                             MAX_FIXED_MODE_SIZE / 2));
   10544           18 :           tem = fold_build3 (COND_EXPR, integer_type_node,
   10545              :                              fold_build2 (LT_EXPR, boolean_type_node,
   10546              :                                           fold_build2 (BIT_XOR_EXPR, type,
   10547              :                                                        lo, hi),
   10548              :                                           build_zero_cst (type)),
   10549              :                              build_int_cst (integer_type_node,
   10550              :                                             MAX_FIXED_MODE_SIZE / 2 - 1),
   10551              :                              tem);
   10552            9 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10553            9 :           call = save_expr (call);
   10554           18 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10555              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10556              :                                            call,
   10557              :                                            build_int_cst (integer_type_node,
   10558              :                                                           MAX_FIXED_MODE_SIZE
   10559              :                                                           / 2 - 1)),
   10560              :                               call, tem);
   10561            9 :           break;
   10562            9 :         case BUILT_IN_FFSG:
   10563            9 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10564           18 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10565              :                               build_int_cst (integer_type_node,
   10566              :                                              MAX_FIXED_MODE_SIZE / 2));
   10567            9 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10568              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10569              :                                            hi, build_zero_cst (type)),
   10570              :                               call, integer_zero_node);
   10571            9 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10572              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10573              :                                            lo, build_zero_cst (type)),
   10574              :                               fold_builtin_bit_query (loc, fcode, lo,
   10575              :                                                       NULL_TREE),
   10576              :                               call);
   10577            9 :           break;
   10578            9 :         case BUILT_IN_PARITYG:
   10579            9 :           call = fold_builtin_bit_query (loc, fcode,
   10580              :                                          fold_build2 (BIT_XOR_EXPR, type,
   10581              :                                                       lo, hi), NULL_TREE);
   10582            9 :           break;
   10583           35 :         case BUILT_IN_POPCOUNTG:
   10584           35 :           call = fold_build2 (PLUS_EXPR, integer_type_node,
   10585              :                               fold_builtin_bit_query (loc, fcode, hi,
   10586              :                                                       NULL_TREE),
   10587              :                               fold_builtin_bit_query (loc, fcode, lo,
   10588              :                                                       NULL_TREE));
   10589           35 :           break;
   10590              :         default:
   10591              :           gcc_unreachable ();
   10592              :         }
   10593              :     }
   10594              :   else
   10595              :     {
   10596              :       /* Only keep second argument to IFN_CLZ/IFN_CTZ if it is the
   10597              :          value defined at zero during GIMPLE, or for large/huge _BitInt
   10598              :          (which are then lowered during bitint lowering).  */
   10599       227791 :       if (arg2 && !BITINT_TYPE_P (TREE_TYPE (arg0)))
   10600              :         {
   10601       133607 :           int val;
   10602       133607 :           if (fcode == BUILT_IN_CLZG)
   10603              :             {
   10604        66664 :               if (CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
   10605              :                                              val) != 2
   10606        66664 :                   || wi::to_widest (arg2) != val)
   10607              :                 arg2 = NULL_TREE;
   10608              :             }
   10609        66943 :           else if (CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
   10610              :                                               val) != 2
   10611        66943 :                    || wi::to_widest (arg2) != val)
   10612              :             arg2 = NULL_TREE;
   10613       133607 :           if (!direct_internal_fn_supported_p (ifn, arg0_type,
   10614              :                                                OPTIMIZE_FOR_BOTH))
   10615              :             arg2 = NULL_TREE;
   10616       133496 :           if (arg2 == NULL_TREE)
   10617       133560 :             arg0 = save_expr (arg0);
   10618              :         }
   10619       227791 :       if (fcodei == END_BUILTINS || arg2)
   10620          247 :         call = build_call_expr_internal_loc (loc, ifn, integer_type_node,
   10621              :                                              arg2 ? 2 : 1, arg0, arg2);
   10622              :       else
   10623       227634 :         call = build_call_expr_loc (loc, builtin_decl_explicit (fcodei), 1,
   10624              :                                     arg0);
   10625              :     }
   10626       266948 :   if (addend)
   10627         4407 :     call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10628              :                         build_int_cst (integer_type_node, addend));
   10629       266948 :   if (arg1 && arg2 == NULL_TREE)
   10630       137916 :     call = fold_build3 (COND_EXPR, integer_type_node,
   10631              :                         fold_build2 (NE_EXPR, boolean_type_node,
   10632              :                                      arg0, build_zero_cst (arg0_type)),
   10633              :                         call, arg1);
   10634              : 
   10635              :   return call;
   10636              : }
   10637              : 
   10638              : /* Fold or build a __builtin_bswapg (ARG) (if IFN is IFN_BSWAP) or
   10639              :    __builtin_bitreverseg (ARG (otherwise) call.  The FE should have
   10640              :    verified earlier that the argument type is unsigned INTEGER_TYPE
   10641              :    or BITINT_TYPE, for __builtin_bswapg with precision divisible by 8.  */
   10642              : 
   10643              : tree
   10644          218 : fold_build_builtin_bswapg_bitreverseg (location_t loc, enum internal_fn ifn,
   10645              :                                        tree arg)
   10646              : {
   10647          218 :   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
   10648          218 :   if (ifn == IFN_BSWAP && TYPE_PRECISION (type) == 8)
   10649           11 :     return fold_convert_loc (loc, type, arg);
   10650          207 :   struct { tree type; built_in_function bswap, bitreverse; } fns[]
   10651          207 :     = { { unsigned_char_type_node, END_BUILTINS, BUILT_IN_BITREVERSE8 },
   10652          207 :         { uint16_type_node, BUILT_IN_BSWAP16, BUILT_IN_BITREVERSE16 },
   10653          207 :         { uint32_type_node, BUILT_IN_BSWAP32, BUILT_IN_BITREVERSE32 },
   10654          207 :         { uint64_type_node, BUILT_IN_BSWAP64, BUILT_IN_BITREVERSE64 },
   10655          207 :         { uint128_type_node, BUILT_IN_BSWAP128, BUILT_IN_BITREVERSE128 } };
   10656          207 :   if (TREE_CODE (arg) == INTEGER_CST)
   10657              :     {
   10658          127 :       wide_int res;
   10659          127 :       if (ifn == IFN_BSWAP)
   10660           37 :         res = wi::bswap (wi::to_wide (arg));
   10661              :       else
   10662           96 :         res = wi::bitreverse (wi::to_wide (arg));
   10663          127 :       return wide_int_to_tree (type, res);
   10664          127 :     }
   10665          346 :   for (unsigned i = 0; i < ARRAY_SIZE (fns); ++i)
   10666          314 :     if (fns[i].type
   10667          314 :         && TYPE_PRECISION (fns[i].type) >= TYPE_PRECISION (type))
   10668              :       {
   10669           48 :         arg = fold_convert_loc (loc, fns[i].type, arg);
   10670           48 :         tree fndecl
   10671           48 :           = builtin_decl_explicit (ifn == IFN_BSWAP
   10672              :                                    ? fns[i].bswap : fns[i].bitreverse);
   10673           48 :         tree ret = build_call_expr_loc (loc, fndecl, 1, arg);
   10674           48 :         if (TYPE_PRECISION (type) != TYPE_PRECISION (fns[i].type))
   10675            4 :           ret = fold_build2_loc (loc, RSHIFT_EXPR, fns[i].type, ret,
   10676              :                                  build_int_cst (unsigned_type_node,
   10677            4 :                                                 TYPE_PRECISION (fns[i].type)
   10678            4 :                                                 - TYPE_PRECISION (type)));
   10679           48 :         return fold_convert_loc (loc, type, ret);
   10680              :       }
   10681           32 :   gcc_assert (TREE_CODE (type) == BITINT_TYPE);
   10682           32 :   return build_call_expr_internal_loc (loc, ifn, type, 1, arg);
   10683              : }
   10684              : 
   10685              : /* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
   10686              :    that return both result of arithmetics and overflowed boolean
   10687              :    flag in a complex integer result.  */
   10688              : 
   10689              : static tree
   10690           55 : fold_builtin_addc_subc (location_t loc, enum built_in_function fcode,
   10691              :                         tree *args)
   10692              : {
   10693           55 :   enum internal_fn ifn;
   10694              : 
   10695           55 :   switch (fcode)
   10696              :     {
   10697              :     case BUILT_IN_ADDC:
   10698              :     case BUILT_IN_ADDCL:
   10699              :     case BUILT_IN_ADDCLL:
   10700              :       ifn = IFN_ADD_OVERFLOW;
   10701              :       break;
   10702           29 :     case BUILT_IN_SUBC:
   10703           29 :     case BUILT_IN_SUBCL:
   10704           29 :     case BUILT_IN_SUBCLL:
   10705           29 :       ifn = IFN_SUB_OVERFLOW;
   10706           29 :       break;
   10707            0 :     default:
   10708            0 :       gcc_unreachable ();
   10709              :     }
   10710              : 
   10711           55 :   tree type = TREE_TYPE (args[0]);
   10712           55 :   tree ctype = build_complex_type (type);
   10713           55 :   tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10714              :                                             args[0], args[1]);
   10715              :   /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
   10716              :      as while the call itself is const, the REALPART_EXPR store is
   10717              :      certainly not.  And in any case, we want just one call,
   10718              :      not multiple and trying to CSE them later.  */
   10719           55 :   TREE_SIDE_EFFECTS (call) = 1;
   10720           55 :   tree tgt = save_expr (call);
   10721           55 :   tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10722           55 :   tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10723           55 :   call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10724              :                                        intres, args[2]);
   10725           55 :   TREE_SIDE_EFFECTS (call) = 1;
   10726           55 :   tgt = save_expr (call);
   10727           55 :   intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10728           55 :   tree ovfres2 = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10729           55 :   ovfres = build2_loc (loc, BIT_IOR_EXPR, type, ovfres, ovfres2);
   10730           55 :   tree mem_arg3 = build_fold_indirect_ref_loc (loc, args[3]);
   10731           55 :   tree store
   10732           55 :     = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg3, ovfres);
   10733           55 :   return build2_loc (loc, COMPOUND_EXPR, type, store, intres);
   10734              : }
   10735              : 
   10736              : /* Fold a call to __builtin_FILE to a constant string.  */
   10737              : 
   10738              : static inline tree
   10739         5939 : fold_builtin_FILE (location_t loc)
   10740              : {
   10741         5939 :   if (const char *fname = LOCATION_FILE (loc))
   10742              :     {
   10743              :       /* The documentation says this builtin is equivalent to the preprocessor
   10744              :          __FILE__ macro so it appears appropriate to use the same file prefix
   10745              :          mappings.  */
   10746         5939 :       fname = remap_macro_filename (fname);
   10747         5939 :       return build_string_literal (fname);
   10748              :     }
   10749              : 
   10750            0 :   return build_string_literal ("");
   10751              : }
   10752              : 
   10753              : /* Fold a call to __builtin_FUNCTION to a constant string.  */
   10754              : 
   10755              : static inline tree
   10756           68 : fold_builtin_FUNCTION ()
   10757              : {
   10758           68 :   const char *name = "";
   10759              : 
   10760           68 :   if (current_function_decl)
   10761           43 :     name = lang_hooks.decl_printable_name (current_function_decl, 0);
   10762              : 
   10763           68 :   return build_string_literal (name);
   10764              : }
   10765              : 
   10766              : /* Fold a call to __builtin_LINE to an integer constant.  */
   10767              : 
   10768              : static inline tree
   10769        11845 : fold_builtin_LINE (location_t loc, tree type)
   10770              : {
   10771        11845 :   return build_int_cst (type, LOCATION_LINE (loc));
   10772              : }
   10773              : 
   10774              : /* Fold a call to built-in function FNDECL with 0 arguments.
   10775              :    This function returns NULL_TREE if no simplification was possible.  */
   10776              : 
   10777              : static tree
   10778     24135509 : fold_builtin_0 (location_t loc, tree fndecl)
   10779              : {
   10780     24135509 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10781     24135509 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10782     24135509 :   switch (fcode)
   10783              :     {
   10784         5939 :     case BUILT_IN_FILE:
   10785         5939 :       return fold_builtin_FILE (loc);
   10786              : 
   10787           68 :     case BUILT_IN_FUNCTION:
   10788           68 :       return fold_builtin_FUNCTION ();
   10789              : 
   10790        11845 :     case BUILT_IN_LINE:
   10791        11845 :       return fold_builtin_LINE (loc, type);
   10792              : 
   10793        33954 :     CASE_FLT_FN (BUILT_IN_INF):
   10794        33954 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
   10795        33954 :     case BUILT_IN_INFD32:
   10796        33954 :     case BUILT_IN_INFD64:
   10797        33954 :     case BUILT_IN_INFD128:
   10798        33954 :     case BUILT_IN_INFD64X:
   10799        33954 :       return fold_builtin_inf (loc, type, true);
   10800              : 
   10801       230593 :     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
   10802       230593 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
   10803       230593 :       return fold_builtin_inf (loc, type, false);
   10804              : 
   10805            0 :     case BUILT_IN_CLASSIFY_TYPE:
   10806            0 :       return fold_builtin_classify_type (NULL_TREE);
   10807              : 
   10808     20661913 :     case BUILT_IN_UNREACHABLE:
   10809              :       /* Rewrite any explicit calls to __builtin_unreachable.  */
   10810     20661913 :       if (sanitize_flags_p (SANITIZE_UNREACHABLE))
   10811           91 :         return build_builtin_unreachable (loc);
   10812              :       break;
   10813              : 
   10814              :     default:
   10815              :       break;
   10816              :     }
   10817              :   return NULL_TREE;
   10818              : }
   10819              : 
   10820              : /* Fold a call to built-in function FNDECL with 1 argument, ARG0.
   10821              :    This function returns NULL_TREE if no simplification was possible.  */
   10822              : 
   10823              : static tree
   10824     20330621 : fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
   10825              : {
   10826     20330621 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10827     20330621 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10828              : 
   10829     20330621 :   if (error_operand_p (arg0))
   10830              :     return NULL_TREE;
   10831              : 
   10832     20330621 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0))
   10833              :     return ret;
   10834              : 
   10835     19700707 :   switch (fcode)
   10836              :     {
   10837      3120931 :     case BUILT_IN_CONSTANT_P:
   10838      3120931 :       {
   10839      3120931 :         tree val = fold_builtin_constant_p (arg0);
   10840              : 
   10841              :         /* Gimplification will pull the CALL_EXPR for the builtin out of
   10842              :            an if condition.  When not optimizing, we'll not CSE it back.
   10843              :            To avoid link error types of regressions, return false now.  */
   10844      3120931 :         if (!val && !optimize)
   10845         1558 :           val = integer_zero_node;
   10846              : 
   10847              :         return val;
   10848              :       }
   10849              : 
   10850         2068 :     case BUILT_IN_CLASSIFY_TYPE:
   10851         2068 :       return fold_builtin_classify_type (arg0);
   10852              : 
   10853       478331 :     case BUILT_IN_STRLEN:
   10854       478331 :       return fold_builtin_strlen (loc, expr, type, arg0);
   10855              : 
   10856       379580 :     CASE_FLT_FN (BUILT_IN_FABS):
   10857       379580 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   10858       379580 :     case BUILT_IN_FABSD32:
   10859       379580 :     case BUILT_IN_FABSD64:
   10860       379580 :     case BUILT_IN_FABSD128:
   10861       379580 :     case BUILT_IN_FABSD64X:
   10862       379580 :       return fold_builtin_fabs (loc, arg0, type);
   10863              : 
   10864       101470 :     case BUILT_IN_ABS:
   10865       101470 :     case BUILT_IN_LABS:
   10866       101470 :     case BUILT_IN_LLABS:
   10867       101470 :     case BUILT_IN_IMAXABS:
   10868       101470 :     case BUILT_IN_UABS:
   10869       101470 :     case BUILT_IN_ULABS:
   10870       101470 :     case BUILT_IN_ULLABS:
   10871       101470 :     case BUILT_IN_UMAXABS:
   10872       101470 :       return fold_builtin_abs (loc, arg0, type);
   10873              : 
   10874        25461 :     CASE_FLT_FN (BUILT_IN_CONJ):
   10875        25461 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10876        25461 :         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10877        25461 :         return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
   10878              :     break;
   10879              : 
   10880          764 :     CASE_FLT_FN (BUILT_IN_CREAL):
   10881          764 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10882          764 :         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10883          764 :         return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
   10884              :     break;
   10885              : 
   10886         1884 :     CASE_FLT_FN (BUILT_IN_CIMAG):
   10887         1884 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10888         1884 :           && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10889         1884 :         return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
   10890              :     break;
   10891              : 
   10892       104839 :     CASE_FLT_FN (BUILT_IN_CARG):
   10893       104839 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_CARG):
   10894       104839 :       return fold_builtin_carg (loc, arg0, type);
   10895              : 
   10896          211 :     case BUILT_IN_ISASCII:
   10897          211 :       return fold_builtin_isascii (loc, arg0);
   10898              : 
   10899          168 :     case BUILT_IN_TOASCII:
   10900          168 :       return fold_builtin_toascii (loc, arg0);
   10901              : 
   10902          325 :     case BUILT_IN_ISDIGIT:
   10903          325 :       return fold_builtin_isdigit (loc, arg0);
   10904              : 
   10905       628727 :     CASE_FLT_FN (BUILT_IN_FINITE):
   10906       628727 :     case BUILT_IN_FINITED32:
   10907       628727 :     case BUILT_IN_FINITED64:
   10908       628727 :     case BUILT_IN_FINITED128:
   10909       628727 :     case BUILT_IN_ISFINITE:
   10910       628727 :       {
   10911       628727 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
   10912       628727 :         if (ret)
   10913              :           return ret;
   10914       628395 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10915              :       }
   10916              : 
   10917       713489 :     CASE_FLT_FN (BUILT_IN_ISINF):
   10918       713489 :     case BUILT_IN_ISINFD32:
   10919       713489 :     case BUILT_IN_ISINFD64:
   10920       713489 :     case BUILT_IN_ISINFD128:
   10921       713489 :       {
   10922       713489 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
   10923       713489 :         if (ret)
   10924              :           return ret;
   10925       713238 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10926              :       }
   10927              : 
   10928       240988 :     case BUILT_IN_ISNORMAL:
   10929       240988 :       return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10930              : 
   10931          708 :     case BUILT_IN_ISINF_SIGN:
   10932          708 :       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
   10933              : 
   10934       244118 :     CASE_FLT_FN (BUILT_IN_ISNAN):
   10935       244118 :     case BUILT_IN_ISNAND32:
   10936       244118 :     case BUILT_IN_ISNAND64:
   10937       244118 :     case BUILT_IN_ISNAND128:
   10938       244118 :       {
   10939       244118 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
   10940       244118 :         if (ret)
   10941              :           return ret;
   10942       243994 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10943              :       }
   10944              : 
   10945        27815 :     case BUILT_IN_ISSIGNALING:
   10946        27815 :       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISSIGNALING);
   10947              : 
   10948       638871 :     case BUILT_IN_FREE:
   10949       638871 :       if (integer_zerop (arg0))
   10950         1082 :         return build_empty_stmt (loc);
   10951              :       break;
   10952              : 
   10953        11594 :     case BUILT_IN_CLZG:
   10954        11594 :     case BUILT_IN_CTZG:
   10955        11594 :     case BUILT_IN_CLRSBG:
   10956        11594 :     case BUILT_IN_FFSG:
   10957        11594 :     case BUILT_IN_PARITYG:
   10958        11594 :     case BUILT_IN_POPCOUNTG:
   10959        11594 :       return fold_builtin_bit_query (loc, fcode, arg0, NULL_TREE);
   10960              : 
   10961              :     default:
   10962              :       break;
   10963              :     }
   10964              : 
   10965              :   return NULL_TREE;
   10966              : 
   10967              : }
   10968              : 
   10969              : /* Folds a call EXPR (which may be null) to built-in function FNDECL
   10970              :    with 2 arguments, ARG0 and ARG1.  This function returns NULL_TREE
   10971              :    if no simplification was possible.  */
   10972              : 
   10973              : static tree
   10974     19543824 : fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
   10975              : {
   10976     19543824 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10977     19543824 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10978              : 
   10979     19543824 :   if (error_operand_p (arg0)
   10980     19543824 :       || error_operand_p (arg1))
   10981              :     return NULL_TREE;
   10982              : 
   10983     19543820 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0, arg1))
   10984              :     return ret;
   10985              : 
   10986     19326967 :   switch (fcode)
   10987              :     {
   10988         6504 :     CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
   10989         6504 :     CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
   10990         6504 :       if (validate_arg (arg0, REAL_TYPE)
   10991         6504 :           && validate_arg (arg1, POINTER_TYPE))
   10992         6504 :         return do_mpfr_lgamma_r (arg0, arg1, type);
   10993              :     break;
   10994              : 
   10995       116489 :     CASE_FLT_FN (BUILT_IN_FREXP):
   10996       116489 :       return fold_builtin_frexp (loc, arg0, arg1, type);
   10997              : 
   10998        93230 :     CASE_FLT_FN (BUILT_IN_MODF):
   10999        93230 :       return fold_builtin_modf (loc, arg0, arg1, type);
   11000              : 
   11001         2560 :     case BUILT_IN_STRSPN:
   11002         2560 :       return fold_builtin_strspn (loc, expr, arg0, arg1, type);
   11003              : 
   11004         2465 :     case BUILT_IN_STRCSPN:
   11005         2465 :       return fold_builtin_strcspn (loc, expr, arg0, arg1, type);
   11006              : 
   11007       100567 :     case BUILT_IN_STRPBRK:
   11008       100567 :       return fold_builtin_strpbrk (loc, expr, arg0, arg1, type);
   11009              : 
   11010      6774165 :     case BUILT_IN_EXPECT:
   11011      6774165 :       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
   11012              : 
   11013       954385 :     case BUILT_IN_ISGREATER:
   11014       954385 :       return fold_builtin_unordered_cmp (loc, fndecl,
   11015       954385 :                                          arg0, arg1, UNLE_EXPR, LE_EXPR);
   11016       482070 :     case BUILT_IN_ISGREATEREQUAL:
   11017       482070 :       return fold_builtin_unordered_cmp (loc, fndecl,
   11018       482070 :                                          arg0, arg1, UNLT_EXPR, LT_EXPR);
   11019       242651 :     case BUILT_IN_ISLESS:
   11020       242651 :       return fold_builtin_unordered_cmp (loc, fndecl,
   11021       242651 :                                          arg0, arg1, UNGE_EXPR, GE_EXPR);
   11022      1110495 :     case BUILT_IN_ISLESSEQUAL:
   11023      1110495 :       return fold_builtin_unordered_cmp (loc, fndecl,
   11024      1110495 :                                          arg0, arg1, UNGT_EXPR, GT_EXPR);
   11025       240785 :     case BUILT_IN_ISLESSGREATER:
   11026       240785 :       return fold_builtin_unordered_cmp (loc, fndecl,
   11027       240785 :                                          arg0, arg1, UNEQ_EXPR, EQ_EXPR);
   11028       241975 :     case BUILT_IN_ISUNORDERED:
   11029       241975 :       return fold_builtin_unordered_cmp (loc, fndecl,
   11030              :                                          arg0, arg1, UNORDERED_EXPR,
   11031       241975 :                                          NOP_EXPR);
   11032              : 
   11033          709 :     case BUILT_IN_ISEQSIG:
   11034          709 :       return fold_builtin_iseqsig (loc, arg0, arg1);
   11035              : 
   11036              :       /* We do the folding for va_start in the expander.  */
   11037              :     case BUILT_IN_VA_START:
   11038              :       break;
   11039              : 
   11040       201103 :     case BUILT_IN_OBJECT_SIZE:
   11041       201103 :     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
   11042       201103 :       return fold_builtin_object_size (arg0, arg1, fcode);
   11043              : 
   11044       105861 :     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
   11045       105861 :       return fold_builtin_atomic_always_lock_free (arg0, arg1);
   11046              : 
   11047        38945 :     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
   11048        38945 :       return fold_builtin_atomic_is_lock_free (arg0, arg1);
   11049              : 
   11050       177252 :     case BUILT_IN_CLZG:
   11051       177252 :     case BUILT_IN_CTZG:
   11052       177252 :       return fold_builtin_bit_query (loc, fcode, arg0, arg1);
   11053              : 
   11054              :     default:
   11055              :       break;
   11056              :     }
   11057              :   return NULL_TREE;
   11058              : }
   11059              : 
   11060              : /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
   11061              :    and ARG2.
   11062              :    This function returns NULL_TREE if no simplification was possible.  */
   11063              : 
   11064              : static tree
   11065      7447587 : fold_builtin_3 (location_t loc, tree fndecl,
   11066              :                 tree arg0, tree arg1, tree arg2)
   11067              : {
   11068      7447587 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   11069      7447587 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   11070              : 
   11071      7447587 :   if (error_operand_p (arg0)
   11072      7447587 :       || error_operand_p (arg1)
   11073     14895174 :       || error_operand_p (arg2))
   11074              :     return NULL_TREE;
   11075              : 
   11076      7447585 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type,
   11077              :                                   arg0, arg1, arg2))
   11078              :     return ret;
   11079              : 
   11080      7430462 :   switch (fcode)
   11081              :     {
   11082              : 
   11083          145 :     CASE_FLT_FN (BUILT_IN_SINCOS):
   11084          145 :       return fold_builtin_sincos (loc, arg0, arg1, arg2);
   11085              : 
   11086       100416 :     CASE_FLT_FN (BUILT_IN_REMQUO):
   11087       100416 :       if (validate_arg (arg0, REAL_TYPE)
   11088       100416 :           && validate_arg (arg1, REAL_TYPE)
   11089       200832 :           && validate_arg (arg2, POINTER_TYPE))
   11090       100416 :         return do_mpfr_remquo (arg0, arg1, arg2);
   11091              :     break;
   11092              : 
   11093      2580962 :     case BUILT_IN_MEMCMP:
   11094      2580962 :       return fold_builtin_memcmp (loc, arg0, arg1, arg2);
   11095              : 
   11096       520371 :     case BUILT_IN_EXPECT:
   11097       520371 :       return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
   11098              : 
   11099          395 :     case BUILT_IN_EXPECT_WITH_PROBABILITY:
   11100          395 :       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg2);
   11101              : 
   11102       511299 :     case BUILT_IN_ADD_OVERFLOW:
   11103       511299 :     case BUILT_IN_SUB_OVERFLOW:
   11104       511299 :     case BUILT_IN_MUL_OVERFLOW:
   11105       511299 :     case BUILT_IN_ADD_OVERFLOW_P:
   11106       511299 :     case BUILT_IN_SUB_OVERFLOW_P:
   11107       511299 :     case BUILT_IN_MUL_OVERFLOW_P:
   11108       511299 :     case BUILT_IN_SADD_OVERFLOW:
   11109       511299 :     case BUILT_IN_SADDL_OVERFLOW:
   11110       511299 :     case BUILT_IN_SADDLL_OVERFLOW:
   11111       511299 :     case BUILT_IN_SSUB_OVERFLOW:
   11112       511299 :     case BUILT_IN_SSUBL_OVERFLOW:
   11113       511299 :     case BUILT_IN_SSUBLL_OVERFLOW:
   11114       511299 :     case BUILT_IN_SMUL_OVERFLOW:
   11115       511299 :     case BUILT_IN_SMULL_OVERFLOW:
   11116       511299 :     case BUILT_IN_SMULLL_OVERFLOW:
   11117       511299 :     case BUILT_IN_UADD_OVERFLOW:
   11118       511299 :     case BUILT_IN_UADDL_OVERFLOW:
   11119       511299 :     case BUILT_IN_UADDLL_OVERFLOW:
   11120       511299 :     case BUILT_IN_USUB_OVERFLOW:
   11121       511299 :     case BUILT_IN_USUBL_OVERFLOW:
   11122       511299 :     case BUILT_IN_USUBLL_OVERFLOW:
   11123       511299 :     case BUILT_IN_UMUL_OVERFLOW:
   11124       511299 :     case BUILT_IN_UMULL_OVERFLOW:
   11125       511299 :     case BUILT_IN_UMULLL_OVERFLOW:
   11126       511299 :       return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
   11127              : 
   11128              :     default:
   11129              :       break;
   11130              :     }
   11131              :   return NULL_TREE;
   11132              : }
   11133              : 
   11134              : /* Folds a call EXPR (which may be null) to built-in function FNDECL.
   11135              :    ARGS is an array of NARGS arguments.  IGNORE is true if the result
   11136              :    of the function call is ignored.  This function returns NULL_TREE
   11137              :    if no simplification was possible.  */
   11138              : 
   11139              : static tree
   11140     74079571 : fold_builtin_n (location_t loc, tree expr, tree fndecl, tree *args,
   11141              :                 int nargs, bool)
   11142              : {
   11143     74079571 :   tree ret = NULL_TREE;
   11144              : 
   11145     74079571 :   switch (nargs)
   11146              :     {
   11147     24135509 :     case 0:
   11148     24135509 :       ret = fold_builtin_0 (loc, fndecl);
   11149     24135509 :       break;
   11150     20330621 :     case 1:
   11151     20330621 :       ret = fold_builtin_1 (loc, expr, fndecl, args[0]);
   11152     20330621 :       break;
   11153     19543824 :     case 2:
   11154     19543824 :       ret = fold_builtin_2 (loc, expr, fndecl, args[0], args[1]);
   11155     19543824 :       break;
   11156      7447587 :     case 3:
   11157      7447587 :       ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]);
   11158      7447587 :       break;
   11159      2622030 :     default:
   11160      2622030 :       ret = fold_builtin_varargs (loc, fndecl, args, nargs);
   11161      2622030 :       break;
   11162              :     }
   11163     74079571 :   if (ret)
   11164              :     {
   11165     10092864 :       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   11166     10092864 :       SET_EXPR_LOCATION (ret, loc);
   11167     10092864 :       return ret;
   11168              :     }
   11169              :   return NULL_TREE;
   11170              : }
   11171              : 
   11172              : /* Construct a new CALL_EXPR to FNDECL using the tail of the argument
   11173              :    list ARGS along with N new arguments in NEWARGS.  SKIP is the number
   11174              :    of arguments in ARGS to be omitted.  OLDNARGS is the number of
   11175              :    elements in ARGS.  */
   11176              : 
   11177              : static tree
   11178            4 : rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
   11179              :                           int skip, tree fndecl, int n, va_list newargs)
   11180              : {
   11181            4 :   int nargs = oldnargs - skip + n;
   11182            4 :   tree *buffer;
   11183              : 
   11184            4 :   if (n > 0)
   11185              :     {
   11186            0 :       int i, j;
   11187              : 
   11188            0 :       buffer = XALLOCAVEC (tree, nargs);
   11189            0 :       for (i = 0; i < n; i++)
   11190            0 :         buffer[i] = va_arg (newargs, tree);
   11191            0 :       for (j = skip; j < oldnargs; j++, i++)
   11192            0 :         buffer[i] = args[j];
   11193              :     }
   11194              :   else
   11195            4 :     buffer = args + skip;
   11196              : 
   11197            4 :   return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
   11198              : }
   11199              : 
   11200              : /* Return true if FNDECL shouldn't be folded right now.
   11201              :    If a built-in function has an inline attribute always_inline
   11202              :    wrapper, defer folding it after always_inline functions have
   11203              :    been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
   11204              :    might not be performed.  */
   11205              : 
   11206              : bool
   11207    154920669 : avoid_folding_inline_builtin (tree fndecl)
   11208              : {
   11209    154920669 :   return (DECL_DECLARED_INLINE_P (fndecl)
   11210        13300 :           && DECL_DISREGARD_INLINE_LIMITS (fndecl)
   11211        13258 :           && cfun
   11212        13258 :           && !cfun->always_inline_functions_inlined
   11213    154933927 :           && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
   11214              : }
   11215              : 
   11216              : /* A wrapper function for builtin folding that prevents warnings for
   11217              :    "statement without effect" and the like, caused by removing the
   11218              :    call node earlier than the warning is generated.  */
   11219              : 
   11220              : tree
   11221    204420939 : fold_call_expr (location_t loc, tree exp, bool ignore)
   11222              : {
   11223    204420939 :   tree ret = NULL_TREE;
   11224    204420939 :   tree fndecl = get_callee_fndecl (exp);
   11225    202637364 :   if (fndecl && fndecl_built_in_p (fndecl)
   11226              :       /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
   11227              :          yet.  Defer folding until we see all the arguments
   11228              :          (after inlining).  */
   11229    264493647 :       && !CALL_EXPR_VA_ARG_PACK (exp))
   11230              :     {
   11231     60072677 :       int nargs = call_expr_nargs (exp);
   11232              : 
   11233              :       /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
   11234              :          instead last argument is __builtin_va_arg_pack ().  Defer folding
   11235              :          even in that case, until arguments are finalized.  */
   11236     60072677 :       if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
   11237              :         {
   11238       223586 :           tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
   11239       223586 :           if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   11240              :             return NULL_TREE;
   11241              :         }
   11242              : 
   11243     60072608 :       if (avoid_folding_inline_builtin (fndecl))
   11244              :         return NULL_TREE;
   11245              : 
   11246     60069070 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   11247     71916262 :         return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
   11248     71916262 :                                      CALL_EXPR_ARGP (exp), ignore);
   11249              :       else
   11250              :         {
   11251     24110939 :           tree *args = CALL_EXPR_ARGP (exp);
   11252     24110939 :           ret = fold_builtin_n (loc, exp, fndecl, args, nargs, ignore);
   11253     24110939 :           if (ret)
   11254              :             return ret;
   11255              :         }
   11256              :     }
   11257              :   return NULL_TREE;
   11258              : }
   11259              : 
   11260              : /* Fold a CALL_EXPR with type TYPE with FN as the function expression.
   11261              :    N arguments are passed in the array ARGARRAY.  Return a folded
   11262              :    expression or NULL_TREE if no simplification was possible.  */
   11263              : 
   11264              : tree
   11265     79604911 : fold_builtin_call_array (location_t loc, tree,
   11266              :                          tree fn,
   11267              :                          int n,
   11268              :                          tree *argarray)
   11269              : {
   11270     79604911 :   if (TREE_CODE (fn) != ADDR_EXPR)
   11271              :     return NULL_TREE;
   11272              : 
   11273     79604911 :   tree fndecl = TREE_OPERAND (fn, 0);
   11274     79604911 :   if (TREE_CODE (fndecl) == FUNCTION_DECL
   11275     79604911 :       && fndecl_built_in_p (fndecl))
   11276              :     {
   11277              :       /* If last argument is __builtin_va_arg_pack (), arguments to this
   11278              :          function are not finalized yet.  Defer folding until they are.  */
   11279     78992279 :       if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
   11280              :         {
   11281       137702 :           tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
   11282       137702 :           if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   11283              :             return NULL_TREE;
   11284              :         }
   11285     78992240 :       if (avoid_folding_inline_builtin (fndecl))
   11286              :         return NULL_TREE;
   11287     78992240 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   11288     35191971 :         return targetm.fold_builtin (fndecl, n, argarray, false);
   11289              :       else
   11290     43800269 :         return fold_builtin_n (loc, NULL_TREE, fndecl, argarray, n, false);
   11291              :     }
   11292              : 
   11293              :   return NULL_TREE;
   11294              : }
   11295              : 
   11296              : /* Construct a new CALL_EXPR using the tail of the argument list of EXP
   11297              :    along with N new arguments specified as the "..." parameters.  SKIP
   11298              :    is the number of arguments in EXP to be omitted.  This function is used
   11299              :    to do varargs-to-varargs transformations.  */
   11300              : 
   11301              : static tree
   11302            4 : rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
   11303              : {
   11304            4 :   va_list ap;
   11305            4 :   tree t;
   11306              : 
   11307            4 :   va_start (ap, n);
   11308            8 :   t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
   11309            4 :                                 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
   11310            4 :   va_end (ap);
   11311              : 
   11312            4 :   return t;
   11313              : }
   11314              : 
   11315              : /* Validate a single argument ARG against a tree code CODE representing
   11316              :    a type.  Return true when argument is valid.  */
   11317              : 
   11318              : static bool
   11319     15525520 : validate_arg (const_tree arg, enum tree_code code)
   11320              : {
   11321     15525520 :   if (!arg)
   11322              :     return false;
   11323     15525497 :   else if (code == POINTER_TYPE)
   11324      7206153 :     return POINTER_TYPE_P (TREE_TYPE (arg));
   11325      8319344 :   else if (code == INTEGER_TYPE)
   11326      3815211 :     return INTEGRAL_TYPE_P (TREE_TYPE (arg));
   11327      4504133 :   return code == TREE_CODE (TREE_TYPE (arg));
   11328              : }
   11329              : 
   11330              : /* This function validates the types of a function call argument list
   11331              :    against a specified list of tree_codes.  If the last specifier is a 0,
   11332              :    that represents an ellipses, otherwise the last specifier must be a
   11333              :    VOID_TYPE.
   11334              : 
   11335              :    This is the GIMPLE version of validate_arglist.  Eventually we want to
   11336              :    completely convert builtins.cc to work from GIMPLEs and the tree based
   11337              :    validate_arglist will then be removed.  */
   11338              : 
   11339              : bool
   11340          136 : validate_gimple_arglist (const gcall *call, ...)
   11341              : {
   11342          136 :   enum tree_code code;
   11343          136 :   bool res = 0;
   11344          136 :   va_list ap;
   11345          136 :   const_tree arg;
   11346          136 :   size_t i;
   11347              : 
   11348          136 :   va_start (ap, call);
   11349          136 :   i = 0;
   11350              : 
   11351          544 :   do
   11352              :     {
   11353          544 :       code = (enum tree_code) va_arg (ap, int);
   11354          544 :       switch (code)
   11355              :         {
   11356            0 :         case 0:
   11357              :           /* This signifies an ellipses, any further arguments are all ok.  */
   11358            0 :           res = true;
   11359            0 :           goto end;
   11360          136 :         case VOID_TYPE:
   11361              :           /* This signifies an endlink, if no arguments remain, return
   11362              :              true, otherwise return false.  */
   11363          136 :           res = (i == gimple_call_num_args (call));
   11364          136 :           goto end;
   11365          408 :         default:
   11366              :           /* If no parameters remain or the parameter's code does not
   11367              :              match the specified code, return false.  Otherwise continue
   11368              :              checking any remaining arguments.  */
   11369          408 :           arg = gimple_call_arg (call, i++);
   11370          408 :           if (!validate_arg (arg, code))
   11371            0 :             goto end;
   11372              :           break;
   11373              :         }
   11374              :     }
   11375              :   while (1);
   11376              : 
   11377              :   /* We need gotos here since we can only have one VA_CLOSE in a
   11378              :      function.  */
   11379          136 :  end: ;
   11380          136 :   va_end (ap);
   11381              : 
   11382          136 :   return res;
   11383              : }
   11384              : 
   11385              : /* Default target-specific builtin expander that does nothing.  */
   11386              : 
   11387              : rtx
   11388            0 : default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
   11389              :                         rtx target ATTRIBUTE_UNUSED,
   11390              :                         rtx subtarget ATTRIBUTE_UNUSED,
   11391              :                         machine_mode mode ATTRIBUTE_UNUSED,
   11392              :                         int ignore ATTRIBUTE_UNUSED)
   11393              : {
   11394            0 :   return NULL_RTX;
   11395              : }
   11396              : 
   11397              : /* Returns true is EXP represents data that would potentially reside
   11398              :    in a readonly section.  */
   11399              : 
   11400              : bool
   11401       211730 : readonly_data_expr (tree exp)
   11402              : {
   11403       211730 :   STRIP_NOPS (exp);
   11404              : 
   11405       211730 :   if (TREE_CODE (exp) != ADDR_EXPR)
   11406              :     return false;
   11407              : 
   11408        26811 :   exp = get_base_address (TREE_OPERAND (exp, 0));
   11409        26811 :   if (!exp)
   11410              :     return false;
   11411              : 
   11412              :   /* Make sure we call decl_readonly_section only for trees it
   11413              :      can handle (since it returns true for everything it doesn't
   11414              :      understand).  */
   11415        26811 :   if (TREE_CODE (exp) == STRING_CST
   11416         5775 :       || TREE_CODE (exp) == CONSTRUCTOR
   11417         5775 :       || (VAR_P (exp) && TREE_STATIC (exp)))
   11418        23655 :     return decl_readonly_section (exp, 0);
   11419              :   else
   11420              :     return false;
   11421              : }
   11422              : 
   11423              : /* Simplify a call to the strpbrk builtin.  S1 and S2 are the arguments
   11424              :    to the call, and TYPE is its return type.
   11425              : 
   11426              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11427              :    simplified form of the call as a tree.
   11428              : 
   11429              :    The simplified form may be a constant or other expression which
   11430              :    computes the same value, but in a more efficient manner (including
   11431              :    calls to other builtin functions).
   11432              : 
   11433              :    The call may contain arguments which need to be evaluated, but
   11434              :    which are not useful to determine the result of the call.  In
   11435              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11436              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11437              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11438              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11439              :    form of the builtin function call.  */
   11440              : 
   11441              : static tree
   11442       100567 : fold_builtin_strpbrk (location_t loc, tree, tree s1, tree s2, tree type)
   11443              : {
   11444       100567 :   if (!validate_arg (s1, POINTER_TYPE)
   11445       100567 :       || !validate_arg (s2, POINTER_TYPE))
   11446              :     return NULL_TREE;
   11447              : 
   11448       100567 :   tree fn;
   11449       100567 :   const char *p1, *p2;
   11450              : 
   11451       100567 :   p2 = c_getstr (s2);
   11452       100567 :   if (p2 == NULL)
   11453              :     return NULL_TREE;
   11454              : 
   11455           92 :   p1 = c_getstr (s1);
   11456           92 :   if (p1 != NULL)
   11457              :     {
   11458           22 :       const char *r = strpbrk (p1, p2);
   11459           22 :       tree tem;
   11460              : 
   11461           22 :       if (r == NULL)
   11462            0 :         return build_int_cst (TREE_TYPE (s1), 0);
   11463              : 
   11464              :       /* Return an offset into the constant string argument.  */
   11465           22 :       tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
   11466           22 :       return fold_convert_loc (loc, type, tem);
   11467              :     }
   11468              : 
   11469           70 :   if (p2[0] == '\0')
   11470              :     /* strpbrk(x, "") == NULL.
   11471              :        Evaluate and ignore s1 in case it had side-effects.  */
   11472           26 :     return omit_one_operand_loc (loc, type, integer_zero_node, s1);
   11473              : 
   11474           44 :   if (p2[1] != '\0')
   11475              :     return NULL_TREE;  /* Really call strpbrk.  */
   11476              : 
   11477           41 :   fn = builtin_decl_implicit (BUILT_IN_STRCHR);
   11478           41 :   if (!fn)
   11479              :     return NULL_TREE;
   11480              : 
   11481              :   /* New argument list transforming strpbrk(s1, s2) to
   11482              :      strchr(s1, s2[0]).  */
   11483           41 :   return build_call_expr_loc (loc, fn, 2, s1,
   11484           41 :                               build_int_cst (integer_type_node, p2[0]));
   11485              : }
   11486              : 
   11487              : /* Simplify a call to the strspn builtin.  S1 and S2 are the arguments
   11488              :    to the call.
   11489              : 
   11490              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11491              :    simplified form of the call as a tree.
   11492              : 
   11493              :    The simplified form may be a constant or other expression which
   11494              :    computes the same value, but in a more efficient manner (including
   11495              :    calls to other builtin functions).
   11496              : 
   11497              :    The call may contain arguments which need to be evaluated, but
   11498              :    which are not useful to determine the result of the call.  In
   11499              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11500              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11501              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11502              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11503              :    form of the builtin function call.  */
   11504              : 
   11505              : static tree
   11506         2560 : fold_builtin_strspn (location_t loc, tree expr, tree s1, tree s2, tree type)
   11507              : {
   11508         2560 :   if (!validate_arg (s1, POINTER_TYPE)
   11509         2560 :       || !validate_arg (s2, POINTER_TYPE))
   11510              :     return NULL_TREE;
   11511              : 
   11512         2560 :   if (!check_nul_terminated_array (expr, s1)
   11513         2560 :       || !check_nul_terminated_array (expr, s2))
   11514              :     return NULL_TREE;
   11515              : 
   11516         2502 :   const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
   11517              : 
   11518              :   /* If either argument is "", return NULL_TREE.  */
   11519         2502 :   if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
   11520              :     /* Evaluate and ignore both arguments in case either one has
   11521              :        side-effects.  */
   11522          147 :     return omit_two_operands_loc (loc, type, size_zero_node, s1, s2);
   11523              :   return NULL_TREE;
   11524              : }
   11525              : 
   11526              : /* Simplify a call to the strcspn builtin.  S1 and S2 are the arguments
   11527              :    to the call.
   11528              : 
   11529              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11530              :    simplified form of the call as a tree.
   11531              : 
   11532              :    The simplified form may be a constant or other expression which
   11533              :    computes the same value, but in a more efficient manner (including
   11534              :    calls to other builtin functions).
   11535              : 
   11536              :    The call may contain arguments which need to be evaluated, but
   11537              :    which are not useful to determine the result of the call.  In
   11538              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11539              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11540              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11541              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11542              :    form of the builtin function call.  */
   11543              : 
   11544              : static tree
   11545         2465 : fold_builtin_strcspn (location_t loc, tree expr, tree s1, tree s2, tree type)
   11546              : {
   11547         2465 :   if (!validate_arg (s1, POINTER_TYPE)
   11548         2465 :       || !validate_arg (s2, POINTER_TYPE))
   11549              :     return NULL_TREE;
   11550              : 
   11551         2465 :   if (!check_nul_terminated_array (expr, s1)
   11552         2465 :       || !check_nul_terminated_array (expr, s2))
   11553              :     return NULL_TREE;
   11554              : 
   11555              :   /* If the first argument is "", return NULL_TREE.  */
   11556         2407 :   const char *p1 = c_getstr (s1);
   11557         2407 :   if (p1 && *p1 == '\0')
   11558              :     {
   11559              :       /* Evaluate and ignore argument s2 in case it has
   11560              :          side-effects.  */
   11561           65 :       return omit_one_operand_loc (loc, type, size_zero_node, s2);
   11562              :     }
   11563              : 
   11564              :   /* If the second argument is "", return __builtin_strlen(s1).  */
   11565         2342 :   const char *p2 = c_getstr (s2);
   11566         2342 :   if (p2 && *p2 == '\0')
   11567              :     {
   11568           81 :       tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
   11569              : 
   11570              :       /* If the replacement _DECL isn't initialized, don't do the
   11571              :          transformation.  */
   11572           81 :       if (!fn)
   11573              :         return NULL_TREE;
   11574              : 
   11575           81 :       return fold_convert_loc (loc, type,
   11576           81 :                                build_call_expr_loc (loc, fn, 1, s1));
   11577              :     }
   11578              :   return NULL_TREE;
   11579              : }
   11580              : 
   11581              : /* Fold the next_arg or va_start call EXP. Returns true if there was an error
   11582              :    produced.  False otherwise.  This is done so that we don't output the error
   11583              :    or warning twice or three times.  */
   11584              : 
   11585              : bool
   11586        42141 : fold_builtin_next_arg (tree exp, bool va_start_p)
   11587              : {
   11588        42141 :   tree fntype = TREE_TYPE (current_function_decl);
   11589        42141 :   int nargs = call_expr_nargs (exp);
   11590        42141 :   tree arg;
   11591              :   /* There is good chance the current input_location points inside the
   11592              :      definition of the va_start macro (perhaps on the token for
   11593              :      builtin) in a system header, so warnings will not be emitted.
   11594              :      Use the location in real source code.  */
   11595        42141 :   location_t current_location =
   11596        42141 :     linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
   11597              :                                               NULL);
   11598              : 
   11599        42141 :   if (!stdarg_p (fntype))
   11600              :     {
   11601            8 :       error ("%<va_start%> used in function with fixed arguments");
   11602            8 :       return true;
   11603              :     }
   11604              : 
   11605        42133 :   if (va_start_p)
   11606              :     {
   11607        41975 :       if (va_start_p && (nargs != 2))
   11608              :         {
   11609            0 :           error ("wrong number of arguments to function %<va_start%>");
   11610            0 :           return true;
   11611              :         }
   11612        41975 :       arg = CALL_EXPR_ARG (exp, 1);
   11613              :     }
   11614              :   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
   11615              :      when we checked the arguments and if needed issued a warning.  */
   11616              :   else
   11617              :     {
   11618          158 :       if (nargs == 0)
   11619              :         {
   11620              :           /* Evidently an out of date version of <stdarg.h>; can't validate
   11621              :              va_start's second argument, but can still work as intended.  */
   11622            0 :           warning_at (current_location,
   11623            0 :                       OPT_Wvarargs,
   11624              :                    "%<__builtin_next_arg%> called without an argument");
   11625            0 :           return true;
   11626              :         }
   11627          158 :       else if (nargs > 1)
   11628              :         {
   11629            0 :           error ("wrong number of arguments to function %<__builtin_next_arg%>");
   11630            0 :           return true;
   11631              :         }
   11632          158 :       arg = CALL_EXPR_ARG (exp, 0);
   11633              :     }
   11634              : 
   11635        42133 :   if (TREE_CODE (arg) == SSA_NAME
   11636        42133 :       && SSA_NAME_VAR (arg))
   11637              :     arg = SSA_NAME_VAR (arg);
   11638              : 
   11639              :   /* We destructively modify the call to be __builtin_va_start (ap, 0)
   11640              :      or __builtin_next_arg (0) the first time we see it, after checking
   11641              :      the arguments and if needed issuing a warning.  */
   11642        42133 :   if (!integer_zerop (arg))
   11643              :     {
   11644         7031 :       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
   11645              : 
   11646              :       /* Strip off all nops for the sake of the comparison.  This
   11647              :          is not quite the same as STRIP_NOPS.  It does more.
   11648              :          We must also strip off INDIRECT_EXPR for C++ reference
   11649              :          parameters.  */
   11650        14064 :       while (CONVERT_EXPR_P (arg)
   11651        14075 :              || INDIRECT_REF_P (arg))
   11652           11 :         arg = TREE_OPERAND (arg, 0);
   11653         7031 :       if (arg != last_parm)
   11654              :         {
   11655              :           /* FIXME: Sometimes with the tree optimizers we can get the
   11656              :              not the last argument even though the user used the last
   11657              :              argument.  We just warn and set the arg to be the last
   11658              :              argument so that we will get wrong-code because of
   11659              :              it.  */
   11660           12 :           warning_at (current_location,
   11661           12 :                       OPT_Wvarargs,
   11662              :                       "second parameter of %<va_start%> not last named argument");
   11663              :         }
   11664              : 
   11665              :       /* Undefined by C99 7.15.1.4p4 (va_start):
   11666              :          "If the parameter parmN is declared with the register storage
   11667              :          class, with a function or array type, or with a type that is
   11668              :          not compatible with the type that results after application of
   11669              :          the default argument promotions, the behavior is undefined."
   11670              :       */
   11671         7019 :       else if (DECL_REGISTER (arg))
   11672              :         {
   11673           12 :           warning_at (current_location,
   11674           12 :                       OPT_Wvarargs,
   11675              :                       "undefined behavior when second parameter of "
   11676              :                       "%<va_start%> is declared with %<register%> storage");
   11677              :         }
   11678              : 
   11679              :       /* We want to verify the second parameter just once before the tree
   11680              :          optimizers are run and then avoid keeping it in the tree,
   11681              :          as otherwise we could warn even for correct code like:
   11682              :          void foo (int i, ...)
   11683              :          { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
   11684         7031 :       if (va_start_p)
   11685         7029 :         CALL_EXPR_ARG (exp, 1) = integer_zero_node;
   11686              :       else
   11687            2 :         CALL_EXPR_ARG (exp, 0) = integer_zero_node;
   11688              :     }
   11689              :   return false;
   11690              : }
   11691              : 
   11692              : 
   11693              : /* Expand a call EXP to __builtin_object_size.  */
   11694              : 
   11695              : static rtx
   11696          620 : expand_builtin_object_size (tree exp)
   11697              : {
   11698          620 :   tree ost;
   11699          620 :   int object_size_type;
   11700          620 :   tree fndecl = get_callee_fndecl (exp);
   11701              : 
   11702          620 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   11703              :     {
   11704            0 :       error ("first argument of %qD must be a pointer, second integer constant",
   11705              :              fndecl);
   11706            0 :       expand_builtin_trap ();
   11707            0 :       return const0_rtx;
   11708              :     }
   11709              : 
   11710          620 :   ost = CALL_EXPR_ARG (exp, 1);
   11711          620 :   STRIP_NOPS (ost);
   11712              : 
   11713          620 :   if (TREE_CODE (ost) != INTEGER_CST
   11714          620 :       || tree_int_cst_sgn (ost) < 0
   11715         1240 :       || compare_tree_int (ost, 3) > 0)
   11716              :     {
   11717            0 :       error ("last argument of %qD is not integer constant between 0 and 3",
   11718              :               fndecl);
   11719            0 :       expand_builtin_trap ();
   11720            0 :       return const0_rtx;
   11721              :     }
   11722              : 
   11723          620 :   object_size_type = tree_to_shwi (ost);
   11724              : 
   11725          620 :   return object_size_type < 2 ? constm1_rtx : const0_rtx;
   11726              : }
   11727              : 
   11728              : /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
   11729              :    FCODE is the BUILT_IN_* to use.
   11730              :    Return NULL_RTX if we failed; the caller should emit a normal call,
   11731              :    otherwise try to get the result in TARGET, if convenient (and in
   11732              :    mode MODE if that's convenient).  */
   11733              : 
   11734              : static rtx
   11735          837 : expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
   11736              :                            enum built_in_function fcode)
   11737              : {
   11738         1410 :   if (!validate_arglist (exp,
   11739              :                          POINTER_TYPE,
   11740              :                          fcode == BUILT_IN_MEMSET_CHK
   11741              :                          ? INTEGER_TYPE : POINTER_TYPE,
   11742              :                          INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
   11743              :     return NULL_RTX;
   11744              : 
   11745          837 :   tree dest = CALL_EXPR_ARG (exp, 0);
   11746          837 :   tree src = CALL_EXPR_ARG (exp, 1);
   11747          837 :   tree len = CALL_EXPR_ARG (exp, 2);
   11748          837 :   tree size = CALL_EXPR_ARG (exp, 3);
   11749              : 
   11750              :   /* FIXME: Set access mode to write only for memset et al.  */
   11751          837 :   bool sizes_ok = check_access (exp, len, /*maxread=*/NULL_TREE,
   11752              :                                 /*srcstr=*/NULL_TREE, size, access_read_write);
   11753              : 
   11754          837 :   if (!tree_fits_uhwi_p (size))
   11755              :     return NULL_RTX;
   11756              : 
   11757          627 :   if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
   11758              :     {
   11759              :       /* Avoid transforming the checking call to an ordinary one when
   11760              :          an overflow has been detected or when the call couldn't be
   11761              :          validated because the size is not constant.  */
   11762          186 :       if (!sizes_ok && !integer_all_onesp (size) && tree_int_cst_lt (size, len))
   11763              :         return NULL_RTX;
   11764              : 
   11765            0 :       tree fn = NULL_TREE;
   11766              :       /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
   11767              :          mem{cpy,pcpy,move,set} is available.  */
   11768            0 :       switch (fcode)
   11769              :         {
   11770            0 :         case BUILT_IN_MEMCPY_CHK:
   11771            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
   11772            0 :           break;
   11773            0 :         case BUILT_IN_MEMPCPY_CHK:
   11774            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
   11775            0 :           break;
   11776            0 :         case BUILT_IN_MEMMOVE_CHK:
   11777            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
   11778            0 :           break;
   11779            0 :         case BUILT_IN_MEMSET_CHK:
   11780            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMSET);
   11781            0 :           break;
   11782              :         default:
   11783              :           break;
   11784              :         }
   11785              : 
   11786            0 :       if (! fn)
   11787              :         return NULL_RTX;
   11788              : 
   11789            0 :       fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
   11790            0 :       gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   11791            0 :       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   11792            0 :       return expand_expr (fn, target, mode, EXPAND_NORMAL);
   11793              :     }
   11794          441 :   else if (fcode == BUILT_IN_MEMSET_CHK)
   11795              :     return NULL_RTX;
   11796              :   else
   11797              :     {
   11798          293 :       unsigned int dest_align = get_pointer_alignment (dest);
   11799              : 
   11800              :       /* If DEST is not a pointer type, call the normal function.  */
   11801          293 :       if (dest_align == 0)
   11802              :         return NULL_RTX;
   11803              : 
   11804              :       /* If SRC and DEST are the same (and not volatile), do nothing.  */
   11805          293 :       if (operand_equal_p (src, dest, 0))
   11806              :         {
   11807            0 :           tree expr;
   11808              : 
   11809            0 :           if (fcode != BUILT_IN_MEMPCPY_CHK)
   11810              :             {
   11811              :               /* Evaluate and ignore LEN in case it has side-effects.  */
   11812            0 :               expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
   11813            0 :               return expand_expr (dest, target, mode, EXPAND_NORMAL);
   11814              :             }
   11815              : 
   11816            0 :           expr = fold_build_pointer_plus (dest, len);
   11817            0 :           return expand_expr (expr, target, mode, EXPAND_NORMAL);
   11818              :         }
   11819              : 
   11820              :       /* __memmove_chk special case.  */
   11821          293 :       if (fcode == BUILT_IN_MEMMOVE_CHK)
   11822              :         {
   11823           79 :           unsigned int src_align = get_pointer_alignment (src);
   11824              : 
   11825           79 :           if (src_align == 0)
   11826              :             return NULL_RTX;
   11827              : 
   11828              :           /* If src is categorized for a readonly section we can use
   11829              :              normal __memcpy_chk.  */
   11830           79 :           if (readonly_data_expr (src))
   11831              :             {
   11832           15 :               tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
   11833           15 :               if (!fn)
   11834              :                 return NULL_RTX;
   11835           15 :               fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
   11836              :                                           dest, src, len, size);
   11837           15 :               gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   11838           15 :               CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   11839           15 :               return expand_expr (fn, target, mode, EXPAND_NORMAL);
   11840              :             }
   11841              :         }
   11842              :       return NULL_RTX;
   11843              :     }
   11844              : }
   11845              : 
   11846              : /* Emit warning if a buffer overflow is detected at compile time.  */
   11847              : 
   11848              : static void
   11849         1086 : maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
   11850              : {
   11851              :   /* The source string.  */
   11852         1086 :   tree srcstr = NULL_TREE;
   11853              :   /* The size of the destination object returned by __builtin_object_size.  */
   11854         1086 :   tree objsize = NULL_TREE;
   11855              :   /* The string that is being concatenated with (as in __strcat_chk)
   11856              :      or null if it isn't.  */
   11857         1086 :   tree catstr = NULL_TREE;
   11858              :   /* The maximum length of the source sequence in a bounded operation
   11859              :      (such as __strncat_chk) or null if the operation isn't bounded
   11860              :      (such as __strcat_chk).  */
   11861         1086 :   tree maxread = NULL_TREE;
   11862              :   /* The exact size of the access (such as in __strncpy_chk).  */
   11863         1086 :   tree size = NULL_TREE;
   11864              :   /* The access by the function that's checked.  Except for snprintf
   11865              :      both writing and reading is checked.  */
   11866         1086 :   access_mode mode = access_read_write;
   11867              : 
   11868         1086 :   switch (fcode)
   11869              :     {
   11870          275 :     case BUILT_IN_STRCPY_CHK:
   11871          275 :     case BUILT_IN_STPCPY_CHK:
   11872          275 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11873          275 :       objsize = CALL_EXPR_ARG (exp, 2);
   11874          275 :       break;
   11875              : 
   11876          151 :     case BUILT_IN_STRCAT_CHK:
   11877              :       /* For __strcat_chk the warning will be emitted only if overflowing
   11878              :          by at least strlen (dest) + 1 bytes.  */
   11879          151 :       catstr = CALL_EXPR_ARG (exp, 0);
   11880          151 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11881          151 :       objsize = CALL_EXPR_ARG (exp, 2);
   11882          151 :       break;
   11883              : 
   11884          108 :     case BUILT_IN_STRNCAT_CHK:
   11885          108 :       catstr = CALL_EXPR_ARG (exp, 0);
   11886          108 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11887          108 :       maxread = CALL_EXPR_ARG (exp, 2);
   11888          108 :       objsize = CALL_EXPR_ARG (exp, 3);
   11889          108 :       break;
   11890              : 
   11891          243 :     case BUILT_IN_STRNCPY_CHK:
   11892          243 :     case BUILT_IN_STPNCPY_CHK:
   11893          243 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11894          243 :       size = CALL_EXPR_ARG (exp, 2);
   11895          243 :       objsize = CALL_EXPR_ARG (exp, 3);
   11896          243 :       break;
   11897              : 
   11898          309 :     case BUILT_IN_SNPRINTF_CHK:
   11899          309 :     case BUILT_IN_VSNPRINTF_CHK:
   11900          309 :       maxread = CALL_EXPR_ARG (exp, 1);
   11901          309 :       objsize = CALL_EXPR_ARG (exp, 3);
   11902              :       /* The only checked access the write to the destination.  */
   11903          309 :       mode = access_write_only;
   11904          309 :       break;
   11905            0 :     default:
   11906            0 :       gcc_unreachable ();
   11907              :     }
   11908              : 
   11909         1086 :   if (catstr && maxread)
   11910              :     {
   11911              :       /* Check __strncat_chk.  There is no way to determine the length
   11912              :          of the string to which the source string is being appended so
   11913              :          just warn when the length of the source string is not known.  */
   11914          108 :       check_strncat_sizes (exp, objsize);
   11915          108 :       return;
   11916              :     }
   11917              : 
   11918          978 :   check_access (exp, size, maxread, srcstr, objsize, mode);
   11919              : }
   11920              : 
   11921              : /* Emit warning if a buffer overflow is detected at compile time
   11922              :    in __sprintf_chk/__vsprintf_chk calls.  */
   11923              : 
   11924              : static void
   11925         1328 : maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
   11926              : {
   11927         1328 :   tree size, len, fmt;
   11928         1328 :   const char *fmt_str;
   11929         1328 :   int nargs = call_expr_nargs (exp);
   11930              : 
   11931              :   /* Verify the required arguments in the original call.  */
   11932              : 
   11933         1328 :   if (nargs < 4)
   11934              :     return;
   11935         1328 :   size = CALL_EXPR_ARG (exp, 2);
   11936         1328 :   fmt = CALL_EXPR_ARG (exp, 3);
   11937              : 
   11938         1328 :   if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
   11939              :     return;
   11940              : 
   11941              :   /* Check whether the format is a literal string constant.  */
   11942         1307 :   fmt_str = c_getstr (fmt);
   11943         1307 :   if (fmt_str == NULL)
   11944              :     return;
   11945              : 
   11946         1271 :   if (!init_target_chars ())
   11947              :     return;
   11948              : 
   11949              :   /* If the format doesn't contain % args or %%, we know its size.  */
   11950         1271 :   if (strchr (fmt_str, target_percent) == 0)
   11951           22 :     len = build_int_cstu (size_type_node, strlen (fmt_str));
   11952              :   /* If the format is "%s" and first ... argument is a string literal,
   11953              :      we know it too.  */
   11954         1249 :   else if (fcode == BUILT_IN_SPRINTF_CHK
   11955         1095 :            && strcmp (fmt_str, target_percent_s) == 0)
   11956              :     {
   11957           49 :       tree arg;
   11958              : 
   11959           49 :       if (nargs < 5)
   11960              :         return;
   11961           49 :       arg = CALL_EXPR_ARG (exp, 4);
   11962           49 :       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
   11963              :         return;
   11964              : 
   11965           45 :       len = c_strlen (arg, 1);
   11966           45 :       if (!len || ! tree_fits_uhwi_p (len))
   11967              :         return;
   11968              :     }
   11969              :   else
   11970              :     return;
   11971              : 
   11972              :   /* Add one for the terminating nul.  */
   11973           34 :   len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
   11974              : 
   11975           34 :   check_access (exp, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, len, size,
   11976              :                 access_write_only);
   11977              : }
   11978              : 
   11979              : /* Fold a call to __builtin_object_size with arguments PTR and OST,
   11980              :    if possible.  */
   11981              : 
   11982              : static tree
   11983       201103 : fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode)
   11984              : {
   11985       201103 :   tree bytes;
   11986       201103 :   int object_size_type;
   11987              : 
   11988       201103 :   if (!validate_arg (ptr, POINTER_TYPE)
   11989       201103 :       || !validate_arg (ost, INTEGER_TYPE))
   11990              :     return NULL_TREE;
   11991              : 
   11992       201103 :   STRIP_NOPS (ost);
   11993              : 
   11994       201103 :   if (TREE_CODE (ost) != INTEGER_CST
   11995       201103 :       || tree_int_cst_sgn (ost) < 0
   11996       402206 :       || compare_tree_int (ost, 3) > 0)
   11997              :     return NULL_TREE;
   11998              : 
   11999       201103 :   object_size_type = tree_to_shwi (ost);
   12000              : 
   12001              :   /* __builtin_object_size doesn't evaluate side-effects in its arguments;
   12002              :      if there are any side-effects, it returns (size_t) -1 for types 0 and 1
   12003              :      and (size_t) 0 for types 2 and 3.  */
   12004       201103 :   if (TREE_SIDE_EFFECTS (ptr))
   12005          603 :     return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
   12006              : 
   12007       200500 :   if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE)
   12008        67467 :     object_size_type |= OST_DYNAMIC;
   12009              : 
   12010       200500 :   if (TREE_CODE (ptr) == ADDR_EXPR)
   12011              :     {
   12012        12232 :       compute_builtin_object_size (ptr, object_size_type, &bytes);
   12013        12232 :       if ((object_size_type & OST_DYNAMIC)
   12014        10886 :           || int_fits_type_p (bytes, size_type_node))
   12015        12232 :         return fold_convert (size_type_node, bytes);
   12016              :     }
   12017       188268 :   else if (TREE_CODE (ptr) == SSA_NAME)
   12018              :     {
   12019              :       /* If object size is not known yet, delay folding until
   12020              :        later.  Maybe subsequent passes will help determining
   12021              :        it.  */
   12022       102230 :       if (compute_builtin_object_size (ptr, object_size_type, &bytes)
   12023       102230 :           && ((object_size_type & OST_DYNAMIC)
   12024         2538 :               || int_fits_type_p (bytes, size_type_node)))
   12025         4808 :         return fold_convert (size_type_node, bytes);
   12026              :     }
   12027              : 
   12028              :   return NULL_TREE;
   12029              : }
   12030              : 
   12031              : /* Builtins with folding operations that operate on "..." arguments
   12032              :    need special handling; we need to store the arguments in a convenient
   12033              :    data structure before attempting any folding.  Fortunately there are
   12034              :    only a few builtins that fall into this category.  FNDECL is the
   12035              :    function, EXP is the CALL_EXPR for the call.  */
   12036              : 
   12037              : static tree
   12038      2622030 : fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
   12039              : {
   12040      2622030 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   12041      2622030 :   tree ret = NULL_TREE;
   12042              : 
   12043      2622030 :   switch (fcode)
   12044              :     {
   12045       104982 :     case BUILT_IN_FPCLASSIFY:
   12046       104982 :       ret = fold_builtin_fpclassify (loc, args, nargs);
   12047       104982 :       break;
   12048              : 
   12049           55 :     case BUILT_IN_ADDC:
   12050           55 :     case BUILT_IN_ADDCL:
   12051           55 :     case BUILT_IN_ADDCLL:
   12052           55 :     case BUILT_IN_SUBC:
   12053           55 :     case BUILT_IN_SUBCL:
   12054           55 :     case BUILT_IN_SUBCLL:
   12055           55 :       return fold_builtin_addc_subc (loc, fcode, args);
   12056              : 
   12057              :     default:
   12058              :       break;
   12059              :     }
   12060       104982 :   if (ret)
   12061              :     {
   12062       104982 :       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   12063       104982 :       SET_EXPR_LOCATION (ret, loc);
   12064       104982 :       suppress_warning (ret);
   12065       104982 :       return ret;
   12066              :     }
   12067              :   return NULL_TREE;
   12068              : }
   12069              : 
   12070              : /* Initialize format string characters in the target charset.  */
   12071              : 
   12072              : bool
   12073       290956 : init_target_chars (void)
   12074              : {
   12075       290956 :   static bool init;
   12076       290956 :   if (!init)
   12077              :     {
   12078       115891 :       target_newline = lang_hooks.to_target_charset ('\n');
   12079       115891 :       target_percent = lang_hooks.to_target_charset ('%');
   12080       115891 :       target_c = lang_hooks.to_target_charset ('c');
   12081       115891 :       target_s = lang_hooks.to_target_charset ('s');
   12082       115891 :       if (target_newline == 0 || target_percent == 0 || target_c == 0
   12083       115891 :           || target_s == 0)
   12084              :         return false;
   12085              : 
   12086       115891 :       target_percent_c[0] = target_percent;
   12087       115891 :       target_percent_c[1] = target_c;
   12088       115891 :       target_percent_c[2] = '\0';
   12089              : 
   12090       115891 :       target_percent_s[0] = target_percent;
   12091       115891 :       target_percent_s[1] = target_s;
   12092       115891 :       target_percent_s[2] = '\0';
   12093              : 
   12094       115891 :       target_percent_s_newline[0] = target_percent;
   12095       115891 :       target_percent_s_newline[1] = target_s;
   12096       115891 :       target_percent_s_newline[2] = target_newline;
   12097       115891 :       target_percent_s_newline[3] = '\0';
   12098              : 
   12099       115891 :       init = true;
   12100              :     }
   12101              :   return true;
   12102              : }
   12103              : 
   12104              : /* Helper function for do_mpfr_arg*().  Ensure M is a normal number
   12105              :    and no overflow/underflow occurred.  INEXACT is true if M was not
   12106              :    exactly calculated.  TYPE is the tree type for the result.  This
   12107              :    function assumes that you cleared the MPFR flags and then
   12108              :    calculated M to see if anything subsequently set a flag prior to
   12109              :    entering this function.  Return NULL_TREE if any checks fail.  */
   12110              : 
   12111              : static tree
   12112         2979 : do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
   12113              : {
   12114              :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   12115              :      overflow/underflow occurred.  If -frounding-math, proceed iff the
   12116              :      result of calling FUNC was exact.  */
   12117         4832 :   if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
   12118         4832 :       && (!flag_rounding_math || !inexact))
   12119              :     {
   12120         1853 :       REAL_VALUE_TYPE rr;
   12121              : 
   12122         1853 :       real_from_mpfr (&rr, m, type, MPFR_RNDN);
   12123              :       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
   12124              :          check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   12125              :          but the mpfr_t is not, then we underflowed in the
   12126              :          conversion.  */
   12127         1853 :       if (real_isfinite (&rr)
   12128         1853 :           && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
   12129              :         {
   12130         1853 :           REAL_VALUE_TYPE rmode;
   12131              : 
   12132         1853 :           real_convert (&rmode, TYPE_MODE (type), &rr);
   12133              :           /* Proceed iff the specified mode can hold the value.  */
   12134         1853 :           if (real_identical (&rmode, &rr))
   12135         1853 :             return build_real (type, rmode);
   12136              :         }
   12137              :     }
   12138              :   return NULL_TREE;
   12139              : }
   12140              : 
   12141              : /* Helper function for do_mpc_arg*().  Ensure M is a normal complex
   12142              :    number and no overflow/underflow occurred.  INEXACT is true if M
   12143              :    was not exactly calculated.  TYPE is the tree type for the result.
   12144              :    This function assumes that you cleared the MPFR flags and then
   12145              :    calculated M to see if anything subsequently set a flag prior to
   12146              :    entering this function.  Return NULL_TREE if any checks fail, if
   12147              :    FORCE_CONVERT is true, then bypass the checks.  */
   12148              : 
   12149              : static tree
   12150         4171 : do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
   12151              : {
   12152              :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   12153              :      overflow/underflow occurred.  If -frounding-math, proceed iff the
   12154              :      result of calling FUNC was exact.  */
   12155         4171 :   if (force_convert
   12156         4171 :       || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
   12157         3852 :           && !mpfr_overflow_p () && !mpfr_underflow_p ()
   12158         3852 :           && (!flag_rounding_math || !inexact)))
   12159              :     {
   12160         3992 :       REAL_VALUE_TYPE re, im;
   12161              : 
   12162         3992 :       real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
   12163         3992 :       real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
   12164              :       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
   12165              :          check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   12166              :          but the mpfr_t is not, then we underflowed in the
   12167              :          conversion.  */
   12168         3992 :       if (force_convert
   12169         3992 :           || (real_isfinite (&re) && real_isfinite (&im)
   12170         3852 :               && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
   12171         3852 :               && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
   12172              :         {
   12173         3992 :           REAL_VALUE_TYPE re_mode, im_mode;
   12174              : 
   12175         3992 :           real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
   12176         3992 :           real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
   12177              :           /* Proceed iff the specified mode can hold the value.  */
   12178         3992 :           if (force_convert
   12179         3992 :               || (real_identical (&re_mode, &re)
   12180         3852 :                   && real_identical (&im_mode, &im)))
   12181         3992 :             return build_complex (type, build_real (TREE_TYPE (type), re_mode),
   12182         7984 :                                   build_real (TREE_TYPE (type), im_mode));
   12183              :         }
   12184              :     }
   12185              :   return NULL_TREE;
   12186              : }
   12187              : 
   12188              : /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
   12189              :    the pointer *(ARG_QUO) and return the result.  The type is taken
   12190              :    from the type of ARG0 and is used for setting the precision of the
   12191              :    calculation and results.  */
   12192              : 
   12193              : static tree
   12194       100416 : do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
   12195              : {
   12196       100416 :   tree const type = TREE_TYPE (arg0);
   12197       100416 :   tree result = NULL_TREE;
   12198              : 
   12199       100416 :   STRIP_NOPS (arg0);
   12200       100416 :   STRIP_NOPS (arg1);
   12201              : 
   12202              :   /* To proceed, MPFR must exactly represent the target floating point
   12203              :      format, which only happens when the target base equals two.  */
   12204       100416 :   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   12205       100416 :       && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
   12206       102721 :       && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
   12207              :     {
   12208         2305 :       const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
   12209         2305 :       const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
   12210              : 
   12211         2305 :       if (real_isfinite (ra0) && real_isfinite (ra1))
   12212              :         {
   12213         2305 :           const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   12214         2305 :           const int prec = fmt->p;
   12215         2305 :           const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   12216         2305 :           tree result_rem;
   12217         2305 :           long integer_quo;
   12218         2305 :           mpfr_t m0, m1;
   12219              : 
   12220         2305 :           mpfr_inits2 (prec, m0, m1, NULL);
   12221         2305 :           mpfr_from_real (m0, ra0, MPFR_RNDN);
   12222         2305 :           mpfr_from_real (m1, ra1, MPFR_RNDN);
   12223         2305 :           mpfr_clear_flags ();
   12224         2305 :           mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
   12225              :           /* Remquo is independent of the rounding mode, so pass
   12226              :              inexact=0 to do_mpfr_ckconv().  */
   12227         2305 :           result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
   12228         2305 :           mpfr_clears (m0, m1, NULL);
   12229         2305 :           if (result_rem)
   12230              :             {
   12231              :               /* MPFR calculates quo in the host's long so it may
   12232              :                  return more bits in quo than the target int can hold
   12233              :                  if sizeof(host long) > sizeof(target int).  This can
   12234              :                  happen even for native compilers in LP64 mode.  In
   12235              :                  these cases, modulo the quo value with the largest
   12236              :                  number that the target int can hold while leaving one
   12237              :                  bit for the sign.  */
   12238         1179 :               if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
   12239         1179 :                 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
   12240              : 
   12241              :               /* Dereference the quo pointer argument.  */
   12242         1179 :               arg_quo = build_fold_indirect_ref (arg_quo);
   12243              :               /* Proceed iff a valid pointer type was passed in.  */
   12244         1179 :               if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
   12245              :                 {
   12246              :                   /* Set the value. */
   12247         1179 :                   tree result_quo
   12248         1179 :                     = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
   12249              :                                    build_int_cst (TREE_TYPE (arg_quo),
   12250              :                                                   integer_quo));
   12251         1179 :                   TREE_SIDE_EFFECTS (result_quo) = 1;
   12252              :                   /* Combine the quo assignment with the rem.  */
   12253         1179 :                   result = fold_build2 (COMPOUND_EXPR, type,
   12254              :                                         result_quo, result_rem);
   12255         1179 :                   suppress_warning (result, OPT_Wunused_value);
   12256         1179 :                   result = non_lvalue (result);
   12257              :                 }
   12258              :             }
   12259              :         }
   12260              :     }
   12261       100416 :   return result;
   12262              : }
   12263              : 
   12264              : /* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
   12265              :    resulting value as a tree with type TYPE.  The mpfr precision is
   12266              :    set to the precision of TYPE.  We assume that this mpfr function
   12267              :    returns zero if the result could be calculated exactly within the
   12268              :    requested precision.  In addition, the integer pointer represented
   12269              :    by ARG_SG will be dereferenced and set to the appropriate signgam
   12270              :    (-1,1) value.  */
   12271              : 
   12272              : static tree
   12273         6504 : do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
   12274              : {
   12275         6504 :   tree result = NULL_TREE;
   12276              : 
   12277         6504 :   STRIP_NOPS (arg);
   12278              : 
   12279              :   /* To proceed, MPFR must exactly represent the target floating point
   12280              :      format, which only happens when the target base equals two.  Also
   12281              :      verify ARG is a constant and that ARG_SG is an int pointer.  */
   12282         6504 :   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   12283         6504 :       && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
   12284         6470 :       && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
   12285        12974 :       && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
   12286              :     {
   12287         6470 :       const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
   12288              : 
   12289              :       /* In addition to NaN and Inf, the argument cannot be zero or a
   12290              :          negative integer.  */
   12291         6470 :       if (real_isfinite (ra)
   12292         6470 :           && ra->cl != rvc_zero
   12293        12940 :           && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
   12294              :         {
   12295          674 :           const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   12296          674 :           const int prec = fmt->p;
   12297          674 :           const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   12298          674 :           int inexact, sg;
   12299          674 :           tree result_lg;
   12300              : 
   12301          674 :           auto_mpfr m (prec);
   12302          674 :           mpfr_from_real (m, ra, MPFR_RNDN);
   12303          674 :           mpfr_clear_flags ();
   12304          674 :           inexact = mpfr_lgamma (m, &sg, m, rnd);
   12305          674 :           result_lg = do_mpfr_ckconv (m, type, inexact);
   12306          674 :           if (result_lg)
   12307              :             {
   12308          674 :               tree result_sg;
   12309              : 
   12310              :               /* Dereference the arg_sg pointer argument.  */
   12311          674 :               arg_sg = build_fold_indirect_ref (arg_sg);
   12312              :               /* Assign the signgam value into *arg_sg. */
   12313          674 :               result_sg = fold_build2 (MODIFY_EXPR,
   12314              :                                        TREE_TYPE (arg_sg), arg_sg,
   12315              :                                        build_int_cst (TREE_TYPE (arg_sg), sg));
   12316          674 :               TREE_SIDE_EFFECTS (result_sg) = 1;
   12317              :               /* Combine the signgam assignment with the lgamma result.  */
   12318          674 :               result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
   12319              :                                                 result_sg, result_lg));
   12320              :             }
   12321          674 :         }
   12322              :     }
   12323              : 
   12324         6504 :   return result;
   12325              : }
   12326              : 
   12327              : /* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
   12328              :    mpc function FUNC on it and return the resulting value as a tree
   12329              :    with type TYPE.  The mpfr precision is set to the precision of
   12330              :    TYPE.  We assume that function FUNC returns zero if the result
   12331              :    could be calculated exactly within the requested precision.  If
   12332              :    DO_NONFINITE is true, then fold expressions containing Inf or NaN
   12333              :    in the arguments and/or results.  */
   12334              : 
   12335              : tree
   12336         4523 : do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
   12337              :              int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
   12338              : {
   12339         4523 :   tree result = NULL_TREE;
   12340              : 
   12341         4523 :   STRIP_NOPS (arg0);
   12342         4523 :   STRIP_NOPS (arg1);
   12343              : 
   12344              :   /* To proceed, MPFR must exactly represent the target floating point
   12345              :      format, which only happens when the target base equals two.  */
   12346         4523 :   if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
   12347         4523 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
   12348         4523 :       && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
   12349         4523 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))
   12350         9046 :       && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
   12351              :     {
   12352         4523 :       const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
   12353         4523 :       const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
   12354         4523 :       const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
   12355         4523 :       const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
   12356              : 
   12357         4523 :       if (do_nonfinite
   12358         4523 :           || (real_isfinite (re0) && real_isfinite (im0)
   12359         4059 :               && real_isfinite (re1) && real_isfinite (im1)))
   12360              :         {
   12361         4171 :           const struct real_format *const fmt =
   12362         4171 :             REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
   12363         4171 :           const int prec = fmt->p;
   12364         4171 :           const mpfr_rnd_t rnd = fmt->round_towards_zero
   12365         4171 :                                  ? MPFR_RNDZ : MPFR_RNDN;
   12366         4171 :           const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
   12367         4171 :           int inexact;
   12368         4171 :           mpc_t m0, m1;
   12369              : 
   12370         4171 :           mpc_init2 (m0, prec);
   12371         4171 :           mpc_init2 (m1, prec);
   12372         4171 :           mpfr_from_real (mpc_realref (m0), re0, rnd);
   12373         4171 :           mpfr_from_real (mpc_imagref (m0), im0, rnd);
   12374         4171 :           mpfr_from_real (mpc_realref (m1), re1, rnd);
   12375         4171 :           mpfr_from_real (mpc_imagref (m1), im1, rnd);
   12376         4171 :           mpfr_clear_flags ();
   12377         4171 :           inexact = func (m0, m0, m1, crnd);
   12378         4171 :           result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
   12379         4171 :           mpc_clear (m0);
   12380         4171 :           mpc_clear (m1);
   12381              :         }
   12382              :     }
   12383              : 
   12384         4523 :   return result;
   12385              : }
   12386              : 
   12387              : /* A wrapper function for builtin folding that prevents warnings for
   12388              :    "statement without effect" and the like, caused by removing the
   12389              :    call node earlier than the warning is generated.  */
   12390              : 
   12391              : tree
   12392      6168429 : fold_call_stmt (gcall *stmt, bool ignore)
   12393              : {
   12394      6168429 :   tree ret = NULL_TREE;
   12395      6168429 :   tree fndecl = gimple_call_fndecl (stmt);
   12396      6168429 :   location_t loc = gimple_location (stmt);
   12397      6168429 :   if (fndecl && fndecl_built_in_p (fndecl)
   12398     12336858 :       && !gimple_call_va_arg_pack_p (stmt))
   12399              :     {
   12400      6168363 :       int nargs = gimple_call_num_args (stmt);
   12401      6168363 :       tree *args = (nargs > 0
   12402      6168363 :                     ? gimple_call_arg_ptr (stmt, 0)
   12403              :                     : &error_mark_node);
   12404              : 
   12405      6168363 :       if (avoid_folding_inline_builtin (fndecl))
   12406              :         return NULL_TREE;
   12407      6168363 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   12408              :         {
   12409            0 :           return targetm.fold_builtin (fndecl, nargs, args, ignore);
   12410              :         }
   12411              :       else
   12412              :         {
   12413      6168363 :           ret = fold_builtin_n (loc, NULL_TREE, fndecl, args, nargs, ignore);
   12414      6168363 :           if (ret)
   12415              :             {
   12416              :               /* Propagate location information from original call to
   12417              :                  expansion of builtin.  Otherwise things like
   12418              :                  maybe_emit_chk_warning, that operate on the expansion
   12419              :                  of a builtin, will use the wrong location information.  */
   12420         5119 :               if (gimple_has_location (stmt))
   12421              :                 {
   12422         5118 :                   tree realret = ret;
   12423         5118 :                   if (TREE_CODE (ret) == NOP_EXPR)
   12424         5118 :                     realret = TREE_OPERAND (ret, 0);
   12425         5118 :                   if (CAN_HAVE_LOCATION_P (realret)
   12426         9366 :                       && !EXPR_HAS_LOCATION (realret))
   12427            6 :                     SET_EXPR_LOCATION (realret, loc);
   12428              :                   return realret;
   12429              :                 }
   12430              :               return ret;
   12431              :             }
   12432              :         }
   12433              :     }
   12434              :   return NULL_TREE;
   12435              : }
   12436              : 
   12437              : /* Look up the function in builtin_decl that corresponds to DECL
   12438              :    and set ASMSPEC as its user assembler name.  DECL must be a
   12439              :    function decl that declares a builtin.  */
   12440              : 
   12441              : void
   12442       156382 : set_builtin_user_assembler_name (tree decl, const char *asmspec)
   12443              : {
   12444       156382 :   gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
   12445              :               && asmspec != 0);
   12446              : 
   12447       156382 :   tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
   12448       156382 :   set_user_assembler_name (builtin, asmspec);
   12449              : 
   12450       156382 :   if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
   12451       156382 :       && INT_TYPE_SIZE < BITS_PER_WORD)
   12452              :     {
   12453            1 :       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
   12454            1 :       set_user_assembler_libfunc ("ffs", asmspec);
   12455            1 :       set_optab_libfunc (ffs_optab, mode, "ffs");
   12456              :     }
   12457       156382 : }
   12458              : 
   12459              : /* Return true if DECL is a builtin that expands to a constant or similarly
   12460              :    simple code.  */
   12461              : bool
   12462     32691432 : is_simple_builtin (tree decl)
   12463              : {
   12464     32691432 :   if (decl && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
   12465     31372316 :     switch (DECL_FUNCTION_CODE (decl))
   12466              :       {
   12467              :         /* Builtins that expand to constants.  */
   12468              :       case BUILT_IN_CONSTANT_P:
   12469              :       case BUILT_IN_EXPECT:
   12470              :       case BUILT_IN_OBJECT_SIZE:
   12471              :       case BUILT_IN_UNREACHABLE:
   12472              :         /* Simple register moves or loads from stack.  */
   12473              :       case BUILT_IN_ASSUME_ALIGNED:
   12474              :       case BUILT_IN_RETURN_ADDRESS:
   12475              :       case BUILT_IN_EXTRACT_RETURN_ADDR:
   12476              :       case BUILT_IN_FROB_RETURN_ADDR:
   12477              :       case BUILT_IN_RETURN:
   12478              :       case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
   12479              :       case BUILT_IN_FRAME_ADDRESS:
   12480              :       case BUILT_IN_VA_END:
   12481              :       case BUILT_IN_STACK_SAVE:
   12482              :       case BUILT_IN_STACK_RESTORE:
   12483              :       case BUILT_IN_DWARF_CFA:
   12484              :       case BUILT_IN_CALL_CODE_ADDRESS:
   12485              :       case BUILT_IN_CALL_STATIC_CHAIN:
   12486              :         /* Exception state returns or moves registers around.  */
   12487              :       case BUILT_IN_EH_FILTER:
   12488              :       case BUILT_IN_EH_POINTER:
   12489              :       case BUILT_IN_EH_COPY_VALUES:
   12490              :         return true;
   12491              : 
   12492     28123304 :       default:
   12493     28123304 :         return false;
   12494              :       }
   12495              : 
   12496              :   return false;
   12497              : }
   12498              : 
   12499              : /* Return true if DECL is a builtin that is not expensive, i.e., they are
   12500              :    most probably expanded inline into reasonably simple code.  This is a
   12501              :    superset of is_simple_builtin.  */
   12502              : bool
   12503     19669435 : is_inexpensive_builtin (tree decl)
   12504              : {
   12505     19669435 :   if (!decl)
   12506              :     return false;
   12507     19654844 :   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
   12508              :     return true;
   12509     18309335 :   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   12510     15242131 :     switch (DECL_FUNCTION_CODE (decl))
   12511              :       {
   12512              :       case BUILT_IN_ABS:
   12513              :       CASE_BUILT_IN_ALLOCA:
   12514              :       case BUILT_IN_BSWAP16:
   12515              :       case BUILT_IN_BSWAP32:
   12516              :       case BUILT_IN_BSWAP64:
   12517              :       case BUILT_IN_BSWAP128:
   12518              :       case BUILT_IN_BITREVERSE8:
   12519              :       case BUILT_IN_BITREVERSE16:
   12520              :       case BUILT_IN_BITREVERSE32:
   12521              :       case BUILT_IN_BITREVERSE64:
   12522              :       case BUILT_IN_BITREVERSE128:
   12523              :       case BUILT_IN_CLZ:
   12524              :       case BUILT_IN_CLZIMAX:
   12525              :       case BUILT_IN_CLZL:
   12526              :       case BUILT_IN_CLZLL:
   12527              :       case BUILT_IN_CTZ:
   12528              :       case BUILT_IN_CTZIMAX:
   12529              :       case BUILT_IN_CTZL:
   12530              :       case BUILT_IN_CTZLL:
   12531              :       case BUILT_IN_FFS:
   12532              :       case BUILT_IN_FFSIMAX:
   12533              :       case BUILT_IN_FFSL:
   12534              :       case BUILT_IN_FFSLL:
   12535              :       case BUILT_IN_IMAXABS:
   12536              :       case BUILT_IN_FINITE:
   12537              :       case BUILT_IN_FINITEF:
   12538              :       case BUILT_IN_FINITEL:
   12539              :       case BUILT_IN_FINITED32:
   12540              :       case BUILT_IN_FINITED64:
   12541              :       case BUILT_IN_FINITED128:
   12542              :       case BUILT_IN_FPCLASSIFY:
   12543              :       case BUILT_IN_ISFINITE:
   12544              :       case BUILT_IN_ISINF_SIGN:
   12545              :       case BUILT_IN_ISINF:
   12546              :       case BUILT_IN_ISINFF:
   12547              :       case BUILT_IN_ISINFL:
   12548              :       case BUILT_IN_ISINFD32:
   12549              :       case BUILT_IN_ISINFD64:
   12550              :       case BUILT_IN_ISINFD128:
   12551              :       case BUILT_IN_ISNAN:
   12552              :       case BUILT_IN_ISNANF:
   12553              :       case BUILT_IN_ISNANL:
   12554              :       case BUILT_IN_ISNAND32:
   12555              :       case BUILT_IN_ISNAND64:
   12556              :       case BUILT_IN_ISNAND128:
   12557              :       case BUILT_IN_ISNORMAL:
   12558              :       case BUILT_IN_ISGREATER:
   12559              :       case BUILT_IN_ISGREATEREQUAL:
   12560              :       case BUILT_IN_ISLESS:
   12561              :       case BUILT_IN_ISLESSEQUAL:
   12562              :       case BUILT_IN_ISLESSGREATER:
   12563              :       case BUILT_IN_ISUNORDERED:
   12564              :       case BUILT_IN_ISEQSIG:
   12565              :       case BUILT_IN_VA_ARG_PACK:
   12566              :       case BUILT_IN_VA_ARG_PACK_LEN:
   12567              :       case BUILT_IN_VA_COPY:
   12568              :       case BUILT_IN_TRAP:
   12569              :       case BUILT_IN_UNREACHABLE_TRAP:
   12570              :       case BUILT_IN_SAVEREGS:
   12571              :       case BUILT_IN_POPCOUNTL:
   12572              :       case BUILT_IN_POPCOUNTLL:
   12573              :       case BUILT_IN_POPCOUNTIMAX:
   12574              :       case BUILT_IN_POPCOUNT:
   12575              :       case BUILT_IN_PARITYL:
   12576              :       case BUILT_IN_PARITYLL:
   12577              :       case BUILT_IN_PARITYIMAX:
   12578              :       case BUILT_IN_PARITY:
   12579              :       case BUILT_IN_LABS:
   12580              :       case BUILT_IN_LLABS:
   12581              :       case BUILT_IN_PREFETCH:
   12582              :       case BUILT_IN_ACC_ON_DEVICE:
   12583              :         return true;
   12584              : 
   12585     14581859 :       default:
   12586     14581859 :         return is_simple_builtin (decl);
   12587              :       }
   12588              : 
   12589              :   return false;
   12590              : }
   12591              : 
   12592              : /* Return true if T is a constant and the value cast to a target char
   12593              :    can be represented by a host char.
   12594              :    Store the casted char constant in *P if so.  */
   12595              : 
   12596              : bool
   12597         3791 : target_char_cst_p (tree t, char *p)
   12598              : {
   12599         3791 :   if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
   12600              :     return false;
   12601              : 
   12602         2065 :   *p = (char)tree_to_uhwi (t);
   12603         2065 :   return true;
   12604              : }
   12605              : 
   12606              : /* Return true if the builtin DECL is implemented in a standard library.
   12607              :    Otherwise return false which doesn't guarantee it is not (thus the list
   12608              :    of handled builtins below may be incomplete).  */
   12609              : 
   12610              : bool
   12611        42460 : builtin_with_linkage_p (tree decl)
   12612              : {
   12613        42460 :   if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   12614        42176 :     switch (DECL_FUNCTION_CODE (decl))
   12615              :     {
   12616         1322 :       CASE_FLT_FN (BUILT_IN_ACOS):
   12617         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
   12618         1322 :       CASE_FLT_FN (BUILT_IN_ACOSH):
   12619         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
   12620         1322 :       CASE_FLT_FN (BUILT_IN_ACOSPI):
   12621         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSPI):
   12622         1322 :       CASE_FLT_FN (BUILT_IN_ASIN):
   12623         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
   12624         1322 :       CASE_FLT_FN (BUILT_IN_ASINH):
   12625         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINH):
   12626         1322 :       CASE_FLT_FN (BUILT_IN_ASINPI):
   12627         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINPI):
   12628         1322 :       CASE_FLT_FN (BUILT_IN_ATAN):
   12629         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN):
   12630         1322 :       CASE_FLT_FN (BUILT_IN_ATAN2):
   12631         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2):
   12632         1322 :       CASE_FLT_FN (BUILT_IN_ATAN2PI):
   12633         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2PI):
   12634         1322 :       CASE_FLT_FN (BUILT_IN_ATANH):
   12635         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
   12636         1322 :       CASE_FLT_FN (BUILT_IN_ATANPI):
   12637         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANPI):
   12638         1322 :       CASE_FLT_FN (BUILT_IN_CBRT):
   12639         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_CBRT):
   12640         1322 :       CASE_FLT_FN (BUILT_IN_CEIL):
   12641         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
   12642         1322 :       CASE_FLT_FN (BUILT_IN_COPYSIGN):
   12643         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
   12644         1322 :       CASE_FLT_FN (BUILT_IN_COS):
   12645         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS):
   12646         1322 :       CASE_FLT_FN (BUILT_IN_COSH):
   12647         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH):
   12648         1322 :       CASE_FLT_FN (BUILT_IN_COSPI):
   12649         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSPI):
   12650         1322 :       CASE_FLT_FN (BUILT_IN_ERF):
   12651         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERF):
   12652         1322 :       CASE_FLT_FN (BUILT_IN_ERFC):
   12653         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERFC):
   12654         1322 :       CASE_FLT_FN (BUILT_IN_EXP):
   12655         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP):
   12656         1322 :       CASE_FLT_FN (BUILT_IN_EXP2):
   12657         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2):
   12658         1322 :       CASE_FLT_FN (BUILT_IN_EXPM1):
   12659         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1):
   12660         1322 :       CASE_FLT_FN (BUILT_IN_FABS):
   12661         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   12662         1322 :       CASE_FLT_FN (BUILT_IN_FDIM):
   12663         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FDIM):
   12664         1322 :       CASE_FLT_FN (BUILT_IN_FLOOR):
   12665         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
   12666         1322 :       CASE_FLT_FN (BUILT_IN_FMA):
   12667         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
   12668         1322 :       CASE_FLT_FN (BUILT_IN_FMAX):
   12669         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMAX):
   12670         1322 :       CASE_FLT_FN (BUILT_IN_FMIN):
   12671         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN):
   12672         1322 :       CASE_FLT_FN (BUILT_IN_FMOD):
   12673         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD):
   12674         1322 :       CASE_FLT_FN (BUILT_IN_FREXP):
   12675         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FREXP):
   12676         1322 :       CASE_FLT_FN (BUILT_IN_HYPOT):
   12677         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_HYPOT):
   12678         1322 :       CASE_FLT_FN (BUILT_IN_ILOGB):
   12679         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ILOGB):
   12680         1322 :       CASE_FLT_FN (BUILT_IN_LDEXP):
   12681         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LDEXP):
   12682         1322 :       CASE_FLT_FN (BUILT_IN_LGAMMA):
   12683         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LGAMMA):
   12684         1322 :       CASE_FLT_FN (BUILT_IN_LLRINT):
   12685         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLRINT):
   12686         1322 :       CASE_FLT_FN (BUILT_IN_LLROUND):
   12687         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLROUND):
   12688         1322 :       CASE_FLT_FN (BUILT_IN_LOG):
   12689         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
   12690         1322 :       CASE_FLT_FN (BUILT_IN_LOG10):
   12691         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
   12692         1322 :       CASE_FLT_FN (BUILT_IN_LOG1P):
   12693         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
   12694         1322 :       CASE_FLT_FN (BUILT_IN_LOG2):
   12695         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
   12696         1322 :       CASE_FLT_FN (BUILT_IN_LOGB):
   12697         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOGB):
   12698         1322 :       CASE_FLT_FN (BUILT_IN_LRINT):
   12699         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LRINT):
   12700         1322 :       CASE_FLT_FN (BUILT_IN_LROUND):
   12701         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LROUND):
   12702         1322 :       CASE_FLT_FN (BUILT_IN_MODF):
   12703         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_MODF):
   12704         1322 :       CASE_FLT_FN (BUILT_IN_NAN):
   12705         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NAN):
   12706         1322 :       CASE_FLT_FN (BUILT_IN_NEARBYINT):
   12707         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT):
   12708         1322 :       CASE_FLT_FN (BUILT_IN_NEXTAFTER):
   12709         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEXTAFTER):
   12710         1322 :       CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
   12711         1322 :       CASE_FLT_FN (BUILT_IN_POW):
   12712         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_POW):
   12713         1322 :       CASE_FLT_FN (BUILT_IN_REMAINDER):
   12714         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER):
   12715         1322 :       CASE_FLT_FN (BUILT_IN_REMQUO):
   12716         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMQUO):
   12717         1322 :       CASE_FLT_FN (BUILT_IN_RINT):
   12718         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
   12719         1322 :       CASE_FLT_FN (BUILT_IN_ROUND):
   12720         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
   12721         1322 :       CASE_FLT_FN (BUILT_IN_SCALBLN):
   12722         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBLN):
   12723         1322 :       CASE_FLT_FN (BUILT_IN_SCALBN):
   12724         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBN):
   12725         1322 :       CASE_FLT_FN (BUILT_IN_SIN):
   12726         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN):
   12727         1322 :       CASE_FLT_FN (BUILT_IN_SINCOS):
   12728         1322 :       CASE_FLT_FN (BUILT_IN_SINH):
   12729         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH):
   12730         1322 :       CASE_FLT_FN (BUILT_IN_SINPI):
   12731         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINPI):
   12732         1322 :       CASE_FLT_FN (BUILT_IN_SQRT):
   12733         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
   12734         1322 :       CASE_FLT_FN (BUILT_IN_TAN):
   12735         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TAN):
   12736         1322 :       CASE_FLT_FN (BUILT_IN_TANH):
   12737         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANH):
   12738         1322 :       CASE_FLT_FN (BUILT_IN_TANPI):
   12739         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANPI):
   12740         1322 :       CASE_FLT_FN (BUILT_IN_TGAMMA):
   12741         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TGAMMA):
   12742         1322 :       CASE_FLT_FN (BUILT_IN_TRUNC):
   12743         1322 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC):
   12744         1322 :         return true;
   12745              : 
   12746           16 :       case BUILT_IN_STPCPY:
   12747           16 :       case BUILT_IN_STPNCPY:
   12748              :         /* stpcpy is both referenced in libiberty's pex-win32.c and provided
   12749              :            by libiberty's stpcpy.c for MinGW targets so we need to return true
   12750              :            in order to be able to build libiberty in LTO mode for them.  */
   12751           16 :         return true;
   12752              : 
   12753              :       default:
   12754              :         break;
   12755              :     }
   12756              :   return false;
   12757              : }
   12758              : 
   12759              : /* Return true if OFFRNG is bounded to a subrange of offset values
   12760              :    valid for the largest possible object.  */
   12761              : 
   12762              : bool
   12763          501 : access_ref::offset_bounded () const
   12764              : {
   12765          501 :   tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
   12766          501 :   tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
   12767          975 :   return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max);
   12768              : }
   12769              : 
   12770              : /* If CALLEE has known side effects, fill in INFO and return true.
   12771              :    See tree-ssa-structalias.cc:find_func_aliases
   12772              :    for the list of builtins we might need to handle here.  */
   12773              : 
   12774              : attr_fnspec
   12775    116196797 : builtin_fnspec (tree callee)
   12776              : {
   12777    116196797 :   built_in_function code = DECL_FUNCTION_CODE (callee);
   12778              : 
   12779    116196797 :   switch (code)
   12780              :     {
   12781              :       /* All the following functions read memory pointed to by
   12782              :          their second argument and write memory pointed to by first
   12783              :          argument.
   12784              :          strcat/strncat additionally reads memory pointed to by the first
   12785              :          argument.  */
   12786       133457 :       case BUILT_IN_STRCAT:
   12787       133457 :       case BUILT_IN_STRCAT_CHK:
   12788       133457 :         return "1cW 1 ";
   12789        42125 :       case BUILT_IN_STRNCAT:
   12790        42125 :       case BUILT_IN_STRNCAT_CHK:
   12791        42125 :         return "1cW 13";
   12792       263477 :       case BUILT_IN_STRCPY:
   12793       263477 :       case BUILT_IN_STRCPY_CHK:
   12794       263477 :         return "1cO 1 ";
   12795        32528 :       case BUILT_IN_STPCPY:
   12796        32528 :       case BUILT_IN_STPCPY_CHK:
   12797        32528 :         return ".cO 1 ";
   12798     19313281 :       case BUILT_IN_STRNCPY:
   12799     19313281 :       case BUILT_IN_MEMCPY:
   12800     19313281 :       case BUILT_IN_MEMMOVE:
   12801     19313281 :       case BUILT_IN_TM_MEMCPY:
   12802     19313281 :       case BUILT_IN_TM_MEMMOVE:
   12803     19313281 :       case BUILT_IN_STRNCPY_CHK:
   12804     19313281 :       case BUILT_IN_MEMCPY_CHK:
   12805     19313281 :       case BUILT_IN_MEMMOVE_CHK:
   12806     19313281 :         return "1cO313";
   12807       143964 :       case BUILT_IN_MEMPCPY:
   12808       143964 :       case BUILT_IN_MEMPCPY_CHK:
   12809       143964 :         return ".cO313";
   12810        58403 :       case BUILT_IN_STPNCPY:
   12811        58403 :       case BUILT_IN_STPNCPY_CHK:
   12812        58403 :         return ".cO313";
   12813            0 :       case BUILT_IN_BCOPY:
   12814            0 :         return ".c23O3";
   12815            0 :       case BUILT_IN_BZERO:
   12816            0 :         return ".cO2";
   12817     10074025 :       case BUILT_IN_MEMCMP:
   12818     10074025 :       case BUILT_IN_MEMCMP_EQ:
   12819     10074025 :       case BUILT_IN_BCMP:
   12820     10074025 :       case BUILT_IN_STRNCMP:
   12821     10074025 :       case BUILT_IN_STRNCMP_EQ:
   12822     10074025 :       case BUILT_IN_STRNCASECMP:
   12823     10074025 :         return ".cR3R3";
   12824              : 
   12825              :       /* The following functions read memory pointed to by their
   12826              :          first argument.  */
   12827          773 :       CASE_BUILT_IN_TM_LOAD (1):
   12828          773 :       CASE_BUILT_IN_TM_LOAD (2):
   12829          773 :       CASE_BUILT_IN_TM_LOAD (4):
   12830          773 :       CASE_BUILT_IN_TM_LOAD (8):
   12831          773 :       CASE_BUILT_IN_TM_LOAD (FLOAT):
   12832          773 :       CASE_BUILT_IN_TM_LOAD (DOUBLE):
   12833          773 :       CASE_BUILT_IN_TM_LOAD (LDOUBLE):
   12834          773 :       CASE_BUILT_IN_TM_LOAD (M64):
   12835          773 :       CASE_BUILT_IN_TM_LOAD (M128):
   12836          773 :       CASE_BUILT_IN_TM_LOAD (M256):
   12837          773 :       case BUILT_IN_TM_LOG:
   12838          773 :       case BUILT_IN_TM_LOG_1:
   12839          773 :       case BUILT_IN_TM_LOG_2:
   12840          773 :       case BUILT_IN_TM_LOG_4:
   12841          773 :       case BUILT_IN_TM_LOG_8:
   12842          773 :       case BUILT_IN_TM_LOG_FLOAT:
   12843          773 :       case BUILT_IN_TM_LOG_DOUBLE:
   12844          773 :       case BUILT_IN_TM_LOG_LDOUBLE:
   12845          773 :       case BUILT_IN_TM_LOG_M64:
   12846          773 :       case BUILT_IN_TM_LOG_M128:
   12847          773 :       case BUILT_IN_TM_LOG_M256:
   12848          773 :         return ".cR ";
   12849              : 
   12850       524045 :       case BUILT_IN_INDEX:
   12851       524045 :       case BUILT_IN_RINDEX:
   12852       524045 :       case BUILT_IN_STRCHR:
   12853       524045 :       case BUILT_IN_STRLEN:
   12854       524045 :       case BUILT_IN_STRRCHR:
   12855       524045 :         return ".cR ";
   12856        59118 :       case BUILT_IN_STRNLEN:
   12857        59118 :         return ".cR2";
   12858              : 
   12859              :       /* These read memory pointed to by the first argument.
   12860              :          Allocating memory does not have any side-effects apart from
   12861              :          being the definition point for the pointer.
   12862              :          Unix98 specifies that errno is set on allocation failure.  */
   12863        18629 :       case BUILT_IN_STRDUP:
   12864        18629 :         return "mCR ";
   12865        13316 :       case BUILT_IN_STRNDUP:
   12866        13316 :         return "mCR2";
   12867              :       /* Allocating memory does not have any side-effects apart from
   12868              :          being the definition point for the pointer.  */
   12869     11395171 :       case BUILT_IN_MALLOC:
   12870     11395171 :       case BUILT_IN_ALIGNED_ALLOC:
   12871     11395171 :       case BUILT_IN_CALLOC:
   12872     11395171 :       case BUILT_IN_GOMP_ALLOC:
   12873     11395171 :         return "mC";
   12874       852553 :       CASE_BUILT_IN_ALLOCA:
   12875       852553 :         return "mc";
   12876              :       /* These read memory pointed to by the first argument with size
   12877              :          in the third argument.  */
   12878       746530 :       case BUILT_IN_MEMCHR:
   12879       746530 :         return ".cR3";
   12880              :       /* These read memory pointed to by the first and second arguments.  */
   12881     12362599 :       case BUILT_IN_STRSTR:
   12882     12362599 :       case BUILT_IN_STRPBRK:
   12883     12362599 :       case BUILT_IN_STRCASECMP:
   12884     12362599 :       case BUILT_IN_STRCSPN:
   12885     12362599 :       case BUILT_IN_STRSPN:
   12886     12362599 :       case BUILT_IN_STRCMP:
   12887     12362599 :       case BUILT_IN_STRCMP_EQ:
   12888     12362599 :         return ".cR R ";
   12889              :       /* Freeing memory kills the pointed-to memory.  More importantly
   12890              :          the call has to serve as a barrier for moving loads and stores
   12891              :          across it.  */
   12892      6572268 :       case BUILT_IN_STACK_RESTORE:
   12893      6572268 :       case BUILT_IN_FREE:
   12894      6572268 :       case BUILT_IN_GOMP_FREE:
   12895      6572268 :         return ".co ";
   12896       108884 :       case BUILT_IN_VA_END:
   12897       108884 :         return ".cO ";
   12898              :       /* Realloc serves both as allocation point and deallocation point.  */
   12899      1116905 :       case BUILT_IN_REALLOC:
   12900      1116905 :       case BUILT_IN_GOMP_REALLOC:
   12901      1116905 :         return ".Cw ";
   12902        15732 :       case BUILT_IN_GAMMA_R:
   12903        15732 :       case BUILT_IN_GAMMAF_R:
   12904        15732 :       case BUILT_IN_GAMMAL_R:
   12905        15732 :       case BUILT_IN_LGAMMA_R:
   12906        15732 :       case BUILT_IN_LGAMMAF_R:
   12907        15732 :       case BUILT_IN_LGAMMAL_R:
   12908        15732 :         return ".C. Ot";
   12909        44420 :       case BUILT_IN_FREXP:
   12910        44420 :       case BUILT_IN_FREXPF:
   12911        44420 :       case BUILT_IN_FREXPL:
   12912        44420 :       case BUILT_IN_MODF:
   12913        44420 :       case BUILT_IN_MODFF:
   12914        44420 :       case BUILT_IN_MODFL:
   12915        44420 :         return ".c. Ot";
   12916         7586 :       case BUILT_IN_REMQUO:
   12917         7586 :       case BUILT_IN_REMQUOF:
   12918         7586 :       case BUILT_IN_REMQUOL:
   12919         7586 :         return ".c. . Ot";
   12920          164 :       case BUILT_IN_SINCOS:
   12921          164 :       case BUILT_IN_SINCOSF:
   12922          164 :       case BUILT_IN_SINCOSL:
   12923          164 :         return ".c. OtOt";
   12924      4366861 :       case BUILT_IN_MEMSET:
   12925      4366861 :       case BUILT_IN_MEMSET_CHK:
   12926      4366861 :       case BUILT_IN_TM_MEMSET:
   12927      4366861 :         return "1cO3";
   12928          366 :       CASE_BUILT_IN_TM_STORE (1):
   12929          366 :       CASE_BUILT_IN_TM_STORE (2):
   12930          366 :       CASE_BUILT_IN_TM_STORE (4):
   12931          366 :       CASE_BUILT_IN_TM_STORE (8):
   12932          366 :       CASE_BUILT_IN_TM_STORE (FLOAT):
   12933          366 :       CASE_BUILT_IN_TM_STORE (DOUBLE):
   12934          366 :       CASE_BUILT_IN_TM_STORE (LDOUBLE):
   12935          366 :       CASE_BUILT_IN_TM_STORE (M64):
   12936          366 :       CASE_BUILT_IN_TM_STORE (M128):
   12937          366 :       CASE_BUILT_IN_TM_STORE (M256):
   12938          366 :         return ".cO ";
   12939      2557172 :       case BUILT_IN_STACK_SAVE:
   12940      2557172 :       case BUILT_IN_RETURN:
   12941      2557172 :       case BUILT_IN_EH_POINTER:
   12942      2557172 :       case BUILT_IN_EH_FILTER:
   12943      2557172 :       case BUILT_IN_UNWIND_RESUME:
   12944      2557172 :       case BUILT_IN_CXA_END_CLEANUP:
   12945      2557172 :       case BUILT_IN_EH_COPY_VALUES:
   12946      2557172 :       case BUILT_IN_FRAME_ADDRESS:
   12947      2557172 :       case BUILT_IN_APPLY_ARGS:
   12948      2557172 :       case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
   12949      2557172 :       case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
   12950      2557172 :       case BUILT_IN_PREFETCH:
   12951      2557172 :       case BUILT_IN_DWARF_CFA:
   12952      2557172 :       case BUILT_IN_RETURN_ADDRESS:
   12953      2557172 :         return ".c";
   12954      2317424 :       case BUILT_IN_ASSUME_ALIGNED:
   12955      2317424 :       case BUILT_IN_EXPECT:
   12956      2317424 :       case BUILT_IN_EXPECT_WITH_PROBABILITY:
   12957      2317424 :         return "1cX ";
   12958              :       /* But posix_memalign stores a pointer into the memory pointed to
   12959              :          by its first argument.  */
   12960         6162 :       case BUILT_IN_POSIX_MEMALIGN:
   12961         6162 :         return ".cOt";
   12962         4438 :       case BUILT_IN_OMP_GET_MAPPED_PTR:
   12963         4438 :         return ". R ";
   12964              : 
   12965     43044421 :       default:
   12966     43044421 :         return "";
   12967              :     }
   12968              : }
        

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