LCOV - code coverage report
Current view: top level - gcc - builtins.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.2 % 5773 4979
Test Date: 2026-09-19 16:22:48 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       536032 : is_builtin_name (const char *name)
     203              : {
     204       536032 :   return (startswith (name, "__builtin_")
     205       194864 :           || startswith (name, "__sync_")
     206       730031 :           || 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       536032 : 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       536032 :   const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
     220       536032 :   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    112292746 : get_object_alignment_2 (tree exp, unsigned int *alignp,
     240              :                         unsigned HOST_WIDE_INT *bitposp, bool addr_p)
     241              : {
     242    112292746 :   poly_int64 bitsize, bitpos;
     243    112292746 :   tree offset;
     244    112292746 :   machine_mode mode;
     245    112292746 :   int unsignedp, reversep, volatilep;
     246    112292746 :   unsigned int align = BITS_PER_UNIT;
     247    112292746 :   bool known_alignment = false;
     248              : 
     249              :   /* Get the innermost object and the constant (bitpos) and possibly
     250              :      variable (offset) offset of the access.  */
     251    112292746 :   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    112292746 :   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    111831097 :   else if (TREE_CODE (exp) == LABEL_DECL)
     266              :     ;
     267    111794180 :   else if (TREE_CODE (exp) == CONST_DECL)
     268              :     {
     269              :       /* The alignment of a CONST_DECL is determined by its initializer.  */
     270        59675 :       exp = DECL_INITIAL (exp);
     271        59675 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     272        59675 :       if (CONSTANT_CLASS_P (exp))
     273        59674 :         align = targetm.constant_alignment (exp, align);
     274              : 
     275              :       known_alignment = true;
     276              :     }
     277    111734505 :   else if (DECL_P (exp))
     278              :     {
     279     67034072 :       align = DECL_ALIGN (exp);
     280              :       known_alignment = true;
     281              :     }
     282     44700433 :   else if (TREE_CODE (exp) == INDIRECT_REF
     283     44699377 :            || TREE_CODE (exp) == MEM_REF
     284      5384895 :            || TREE_CODE (exp) == TARGET_MEM_REF)
     285              :     {
     286     42997610 :       tree addr = TREE_OPERAND (exp, 0);
     287     42997610 :       unsigned ptr_align;
     288     42997610 :       unsigned HOST_WIDE_INT ptr_bitpos;
     289     42997610 :       unsigned HOST_WIDE_INT ptr_bitmask = ~0;
     290              : 
     291              :       /* If the address is explicitly aligned, handle that.  */
     292     42997610 :       if (TREE_CODE (addr) == BIT_AND_EXPR
     293     42997610 :           && 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     42997610 :       known_alignment
     302     42997610 :         = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
     303     42997610 :       align = MAX (ptr_align, align);
     304              : 
     305              :       /* Re-apply explicit alignment to the bitpos.  */
     306     42997610 :       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     42997610 :       if (TREE_CODE (exp) == TARGET_MEM_REF)
     311              :         {
     312      3682072 :           if (TMR_INDEX (exp))
     313              :             {
     314      1602275 :               unsigned HOST_WIDE_INT step = 1;
     315      1602275 :               if (TMR_STEP (exp))
     316      1468356 :                 step = TREE_INT_CST_LOW (TMR_STEP (exp));
     317      1602275 :               align = MIN (align, least_bit_hwi (step) * BITS_PER_UNIT);
     318              :             }
     319      3682072 :           if (TMR_INDEX2 (exp))
     320        42926 :             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     42997610 :       unsigned int talign;
     330     42997610 :       if (!addr_p && !known_alignment
     331     40560944 :           && (talign = min_align_of_type (TREE_TYPE (exp)) * BITS_PER_UNIT)
     332     83558548 :           && talign > align)
     333              :         align = talign;
     334              :       else
     335              :         {
     336              :           /* Else adjust bitpos accordingly.  */
     337     11701037 :           bitpos += ptr_bitpos;
     338     11701037 :           if (TREE_CODE (exp) == MEM_REF
     339     11701037 :               || TREE_CODE (exp) == TARGET_MEM_REF)
     340     11699981 :             bitpos += mem_ref_offset (exp).force_shwi () * BITS_PER_UNIT;
     341              :         }
     342     42997610 :     }
     343      1702823 :   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      1702203 :       align = TYPE_ALIGN (TREE_TYPE (exp));
     348      1702203 :       if (CONSTANT_CLASS_P (exp))
     349      1702203 :         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    112292746 :   if (offset)
     357              :     {
     358     10028092 :       unsigned int trailing_zeros = tree_ctz (offset);
     359     10028092 :       if (trailing_zeros < HOST_BITS_PER_INT)
     360              :         {
     361     10028014 :           unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     362     10028014 :           if (inner)
     363     10028014 :             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    112292746 :   unsigned int alt_align = ::known_alignment (bitpos - bitpos.coeffs[0]);
     370    112292746 :   if (alt_align != 0 && alt_align < align)
     371              :     {
     372              :       align = alt_align;
     373              :       known_alignment = false;
     374              :     }
     375              : 
     376    112292746 :   *alignp = align;
     377    112292746 :   *bitposp = bitpos.coeffs[0] & (align - 1);
     378    112292746 :   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     89086199 : 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     89086199 :   if (TREE_CODE (exp) == WITH_SIZE_EXPR)
     393            0 :     exp = TREE_OPERAND (exp, 0);
     394     89086199 :   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     36922046 : get_object_alignment (tree exp)
     401              : {
     402     36922046 :   unsigned HOST_WIDE_INT bitpos = 0;
     403     36922046 :   unsigned int align;
     404              : 
     405     36922046 :   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     36922046 :   if (bitpos != 0)
     411      2771791 :     align = least_bit_hwi (bitpos);
     412     36922046 :   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     85048619 : get_pointer_alignment_1 (tree exp, unsigned int *alignp,
     424              :                          unsigned HOST_WIDE_INT *bitposp)
     425              : {
     426     85048619 :   STRIP_NOPS (exp);
     427              : 
     428     85048619 :   if (TREE_CODE (exp) == ADDR_EXPR)
     429     23204916 :     return get_object_alignment_2 (TREE_OPERAND (exp, 0),
     430     23204916 :                                    alignp, bitposp, true);
     431     61843703 :   else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
     432              :     {
     433      1016499 :       unsigned int align;
     434      1016499 :       unsigned HOST_WIDE_INT bitpos;
     435      1016499 :       bool res = get_pointer_alignment_1 (TREE_OPERAND (exp, 0),
     436              :                                           &align, &bitpos);
     437      1016499 :       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      1012741 :           unsigned int trailing_zeros = tree_ctz (TREE_OPERAND (exp, 1));
     442      1012741 :           if (trailing_zeros < HOST_BITS_PER_INT)
     443              :             {
     444      1012733 :               unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
     445      1012733 :               if (inner)
     446      1012733 :                 align = MIN (align, inner);
     447              :             }
     448              :         }
     449      1016499 :       *alignp = align;
     450      1016499 :       *bitposp = bitpos & (align - 1);
     451      1016499 :       return res;
     452              :     }
     453     60827204 :   else if (TREE_CODE (exp) == SSA_NAME
     454     60827204 :            && POINTER_TYPE_P (TREE_TYPE (exp)))
     455              :     {
     456     58511827 :       unsigned int ptr_align, ptr_misalign;
     457     58511827 :       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
     458              : 
     459     58511827 :       if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
     460              :         {
     461      6480668 :           *bitposp = ptr_misalign * BITS_PER_UNIT;
     462      6480668 :           *alignp = ptr_align * BITS_PER_UNIT;
     463              :           /* Make sure to return a sensible alignment when the multiplication
     464              :              by BITS_PER_UNIT overflowed.  */
     465      6480668 :           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     52031159 :           *bitposp = 0;
     473     52031159 :           *alignp = BITS_PER_UNIT;
     474     52031159 :           return false;
     475              :         }
     476              :     }
     477      2315377 :   else if (TREE_CODE (exp) == INTEGER_CST)
     478              :     {
     479        17485 :       *alignp = BIGGEST_ALIGNMENT;
     480        17485 :       *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
     481        17485 :                   & (BIGGEST_ALIGNMENT - 1));
     482        17485 :       return true;
     483              :     }
     484              : 
     485      2297892 :   *bitposp = 0;
     486      2297892 :   *alignp = BITS_PER_UNIT;
     487      2297892 :   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     11598398 : get_pointer_alignment (tree exp)
     499              : {
     500     11598398 :   unsigned HOST_WIDE_INT bitpos = 0;
     501     11598398 :   unsigned int align;
     502              : 
     503     11598398 :   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     11598398 :   if (bitpos != 0)
     509        79554 :     align = least_bit_hwi (bitpos);
     510              : 
     511     11598398 :   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       774464 : string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
     520              : {
     521       774464 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     522              : 
     523       774464 :   unsigned n;
     524              : 
     525       774464 :   if (eltsize == 1)
     526              :     {
     527              :       /* Optimize the common case of plain char.  */
     528    244947658 :       for (n = 0; n < maxelts; n++)
     529              :         {
     530    244857660 :           const char *elt = (const char*) ptr + n;
     531    244857660 :           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       774464 :   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      2631627 : 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      2631627 :   c_strlen_data local_strlen_data = { };
     583      2631627 :   if (!data)
     584       604953 :     data = &local_strlen_data;
     585              : 
     586      2631627 :   gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
     587              : 
     588      2631627 :   tree src = STRIP_NOPS (arg);
     589      2631627 :   if (TREE_CODE (src) == COND_EXPR
     590      2631627 :       && (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      2631461 :   if (TREE_CODE (src) == COMPOUND_EXPR
     601      2631461 :       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
     602           45 :     return c_strlen (TREE_OPERAND (src, 1), only_value, data, eltsize);
     603              : 
     604      2631416 :   location_t loc = EXPR_LOC_OR_LOC (src, input_location);
     605              : 
     606              :   /* Offset from the beginning of the string in bytes.  */
     607      2631416 :   tree byteoff;
     608      2631416 :   tree memsize;
     609      2631416 :   tree decl;
     610      2631416 :   src = string_constant (src, &byteoff, &memsize, &decl);
     611      2631416 :   if (src == 0)
     612              :     return NULL_TREE;
     613              : 
     614              :   /* Determine the size of the string element.  */
     615       790710 :   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       778292 :   HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
     625       778292 :   strelts = strelts / eltsize;
     626              : 
     627       778292 :   if (!tree_fits_uhwi_p (memsize))
     628              :     return NULL_TREE;
     629              : 
     630       778292 :   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       778292 :   const char *ptr = TREE_STRING_POINTER (src);
     635              : 
     636       778292 :   if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
     637              :     {
     638              :       /* The code below works only for single byte character types.  */
     639         5058 :       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         5058 :       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         5058 :       if (len + 1 < strelts)
     652              :         return NULL_TREE;
     653         4488 :       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         3386 :       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         3347 :       tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
     671              :                                                  : byteoff;
     672         3347 :       offsave = fold_convert_loc (loc, sizetype, offsave);
     673         3347 :       tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
     674         3347 :                                       size_int (len));
     675         3347 :       tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
     676              :                                      offsave);
     677         3347 :       lenexp = fold_convert_loc (loc, ssizetype, lenexp);
     678         3347 :       return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
     679         3347 :                               build_zero_cst (ssizetype));
     680              :     }
     681              : 
     682              :   /* Offset from the beginning of the string in elements.  */
     683       773234 :   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       773234 :   if (byteoff == 0)
     688              :     eltoff = 0;
     689       773234 :   else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
     690              :     eltoff = -1;
     691              :   else
     692       772046 :     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       773234 :   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       769406 :   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       769406 :   unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
     724       769406 :                                 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       769406 :   if (len >= maxelts - eltoff)
     730              :     {
     731        84400 :       data->decl = decl;
     732        84400 :       data->off = byteoff;
     733        84400 :       data->minlen = ssize_int (len);
     734        84400 :       return NULL_TREE;
     735              :     }
     736              : 
     737       685006 :   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       291876 : c_readstr (const char *str, fixed_size_mode mode,
     748              :            bool null_terminated_p/*=true*/)
     749              : {
     750       291876 :   auto_vec<target_unit, MAX_BITSIZE_MODE_ANY_INT / BITS_PER_UNIT> bytes;
     751              : 
     752       583752 :   bytes.reserve (GET_MODE_SIZE (mode));
     753              : 
     754       291876 :   target_unit ch = 1;
     755      4753310 :   for (unsigned int i = 0; i < GET_MODE_SIZE (mode); ++i)
     756              :     {
     757      2084779 :       if (ch || !null_terminated_p)
     758      1996644 :         ch = (unsigned char) str[i];
     759      2084779 :       bytes.quick_push (ch);
     760              :     }
     761              : 
     762       291876 :   return native_decode_rtx (mode, bytes, 0);
     763       291876 : }
     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        60832 : target_char_cast (tree cst, char *p)
     771              : {
     772        60832 :   unsigned HOST_WIDE_INT val, hostval;
     773              : 
     774        60832 :   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        60832 :   val = TREE_INT_CST_LOW (cst);
     780              : 
     781        60832 :   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
     782        60832 :     val &= (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
     783              : 
     784        60832 :   hostval = val;
     785        60832 :   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
     786        60832 :     hostval &= (HOST_WIDE_INT_1U << HOST_BITS_PER_CHAR) - 1;
     787              : 
     788        60832 :   if (val != hostval)
     789              :     return 1;
     790              : 
     791        60832 :   *p = hostval;
     792        60832 :   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      1134609 : builtin_save_expr (tree exp)
     801              : {
     802      1134609 :   if (TREE_CODE (exp) == SSA_NAME
     803       970506 :       || (TREE_ADDRESSABLE (exp) == 0
     804       970314 :           && (TREE_CODE (exp) == PARM_DECL
     805       434259 :               || (VAR_P (exp) && !TREE_STATIC (exp)))))
     806              :     return exp;
     807              : 
     808       432450 :   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      1949651 : more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
    1080              : {
    1081      1949651 :   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       507441 : validate_arglist (const_tree callexpr, ...)
    1091              : {
    1092       507441 :   enum tree_code code;
    1093       507441 :   bool res = 0;
    1094       507441 :   va_list ap;
    1095       507441 :   const_call_expr_arg_iterator iter;
    1096       507441 :   const_tree arg;
    1097              : 
    1098       507441 :   va_start (ap, callexpr);
    1099       507441 :   init_const_call_expr_arg_iterator (callexpr, &iter);
    1100              : 
    1101              :   /* Get a bitmap of pointer argument numbers declared attribute nonnull.  */
    1102       507441 :   tree fn = CALL_EXPR_FN (callexpr);
    1103       507441 :   bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
    1104              : 
    1105      1770690 :   for (unsigned argno = 1; ; ++argno)
    1106              :     {
    1107      1770690 :       code = (enum tree_code) va_arg (ap, int);
    1108              : 
    1109      1770690 :       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       505151 :         case VOID_TYPE:
    1116              :           /* This signifies an endlink, if no arguments remain, return
    1117              :              true, otherwise return false.  */
    1118       505151 :           res = !more_const_call_expr_args_p (&iter);
    1119       505151 :           goto end;
    1120       832014 :         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       832014 :           if (argmap
    1125       832014 :               && (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
    1126              :             {
    1127       281820 :               arg = next_const_call_expr_arg (&iter);
    1128       281820 :               if (!validate_arg (arg, code) || integer_zerop (arg))
    1129           58 :                 goto end;
    1130              :               break;
    1131              :             }
    1132              :           /* FALLTHRU */
    1133       981661 :         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       981661 :           arg = next_const_call_expr_arg (&iter);
    1138       981661 :           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       507441 :  end: ;
    1147       507441 :   va_end (ap);
    1148              : 
    1149       507441 :   BITMAP_FREE (argmap);
    1150              : 
    1151       507441 :   if (res)
    1152       507209 :     for (tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_TYPE (fn)));
    1153       737489 :          (attrs = lookup_attribute ("nonnull_if_nonzero", attrs));
    1154       230280 :          attrs = TREE_CHAIN (attrs))
    1155              :       {
    1156       230302 :         tree args = TREE_VALUE (attrs);
    1157       230302 :         unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
    1158       230302 :         unsigned int idx2
    1159       230302 :           = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
    1160       230302 :         unsigned int idx3 = idx2;
    1161       230302 :         if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args)))
    1162            0 :           idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1;
    1163       230302 :         if (idx < (unsigned) call_expr_nargs (callexpr)
    1164       230302 :             && idx2 < (unsigned) call_expr_nargs (callexpr)
    1165       230302 :             && idx3 < (unsigned) call_expr_nargs (callexpr)
    1166       230302 :             && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx)))
    1167       230302 :             && integer_zerop (CALL_EXPR_ARG (callexpr, idx))
    1168           89 :             && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx2)))
    1169           89 :             && integer_nonzerop (CALL_EXPR_ARG (callexpr, idx2))
    1170           22 :             && INTEGRAL_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (callexpr, idx3)))
    1171       230324 :             && 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       761729 : get_memory_rtx (tree exp, tree len, bool store_p)
    1371              : {
    1372       761729 :   tree orig_exp = exp, base;
    1373       761729 :   rtx addr, mem;
    1374              : 
    1375       761729 :   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       761729 :   if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
    1381         1611 :     exp = TREE_OPERAND (exp, 0);
    1382              : 
    1383       761729 :   addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    1384       761729 :   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      1523458 :   while (CONVERT_EXPR_P (exp)
    1389       761732 :          && 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       761729 :   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       761729 :   if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
    1404       761717 :     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       761729 :   set_mem_alias_set (mem, 0);
    1424       761729 :   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         2365 : type_to_class (tree type)
    1886              : {
    1887         2365 :   switch (TREE_CODE (type))
    1888              :     {
    1889              :     case VOID_TYPE:        return void_type_class;
    1890          896 :     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          982 :     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       607244 : mathfn_built_in_2 (tree type, combined_fn fn)
    1958              : {
    1959       607244 :   tree mtype;
    1960       607244 :   built_in_function fcode, fcodef, fcodel;
    1961       607244 :   built_in_function fcodef16 = END_BUILTINS;
    1962       607244 :   built_in_function fcodef32 = END_BUILTINS;
    1963       607244 :   built_in_function fcodef64 = END_BUILTINS;
    1964       607244 :   built_in_function fcodef128 = END_BUILTINS;
    1965       607244 :   built_in_function fcodef32x = END_BUILTINS;
    1966       607244 :   built_in_function fcodef64x = END_BUILTINS;
    1967       607244 :   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       607244 :   switch (fn)
    1975              :     {
    1976              : #define SEQ_OF_CASE_MATHFN                      \
    1977              :     CASE_MATHFN_FLOATN (ACOS)                   \
    1978              :     CASE_MATHFN_FLOATN (ACOSH)                  \
    1979              :     CASE_MATHFN_FLOATN (ASIN)                   \
    1980              :     CASE_MATHFN_FLOATN (ASINH)                  \
    1981              :     CASE_MATHFN_FLOATN (ATAN)                   \
    1982              :     CASE_MATHFN_FLOATN (ATAN2)                  \
    1983              :     CASE_MATHFN_FLOATN (ATANH)                  \
    1984              :     CASE_MATHFN_FLOATN (CBRT)                   \
    1985              :     CASE_MATHFN_FLOATN (CEIL)                   \
    1986              :     CASE_MATHFN (CEXPI)                         \
    1987              :     CASE_MATHFN_FLOATN (COPYSIGN)               \
    1988              :     CASE_MATHFN_FLOATN (COS)                    \
    1989              :     CASE_MATHFN_FLOATN (COSH)                   \
    1990              :     CASE_MATHFN (DREM)                          \
    1991              :     CASE_MATHFN_FLOATN (ERF)                    \
    1992              :     CASE_MATHFN_FLOATN (ERFC)                   \
    1993              :     CASE_MATHFN_FLOATN (EXP)                    \
    1994              :     CASE_MATHFN (EXP10)                         \
    1995              :     CASE_MATHFN_FLOATN (EXP2)                   \
    1996              :     CASE_MATHFN_FLOATN (EXPM1)                  \
    1997              :     CASE_MATHFN_FLOATN (FABS)                   \
    1998              :     CASE_MATHFN_FLOATN (FDIM)                   \
    1999              :     CASE_MATHFN_FLOATN (FLOOR)                  \
    2000              :     CASE_MATHFN_FLOATN (FMA)                    \
    2001              :     CASE_MATHFN_FLOATN (FMAX)                   \
    2002              :     CASE_MATHFN_FLOATN (FMIN)                   \
    2003              :     CASE_MATHFN_FLOATN (FMOD)                   \
    2004              :     CASE_MATHFN_FLOATN (FREXP)                  \
    2005              :     CASE_MATHFN (GAMMA)                         \
    2006              :     CASE_MATHFN_REENT (GAMMA) /* GAMMA_R */     \
    2007              :     CASE_MATHFN_FLOATN (HUGE_VAL)               \
    2008              :     CASE_MATHFN_FLOATN (HYPOT)                  \
    2009              :     CASE_MATHFN_FLOATN (ILOGB)                  \
    2010              :     CASE_MATHFN (ICEIL)                         \
    2011              :     CASE_MATHFN (IFLOOR)                        \
    2012              :     CASE_MATHFN_FLOATN (INF)                    \
    2013              :     CASE_MATHFN (IRINT)                         \
    2014              :     CASE_MATHFN (IROUND)                        \
    2015              :     CASE_MATHFN (ISINF)                         \
    2016              :     CASE_MATHFN (J0)                            \
    2017              :     CASE_MATHFN (J1)                            \
    2018              :     CASE_MATHFN (JN)                            \
    2019              :     CASE_MATHFN (LCEIL)                         \
    2020              :     CASE_MATHFN_FLOATN (LDEXP)                  \
    2021              :     CASE_MATHFN (LFLOOR)                        \
    2022              :     CASE_MATHFN_FLOATN (LGAMMA)                 \
    2023              :     CASE_MATHFN_REENT (LGAMMA) /* LGAMMA_R */   \
    2024              :     CASE_MATHFN (LLCEIL)                        \
    2025              :     CASE_MATHFN (LLFLOOR)                       \
    2026              :     CASE_MATHFN_FLOATN (LLRINT)                 \
    2027              :     CASE_MATHFN_FLOATN (LLROUND)                \
    2028              :     CASE_MATHFN_FLOATN (LOG)                    \
    2029              :     CASE_MATHFN_FLOATN (LOG10)                  \
    2030              :     CASE_MATHFN_FLOATN (LOG1P)                  \
    2031              :     CASE_MATHFN_FLOATN (LOG2)                   \
    2032              :     CASE_MATHFN_FLOATN (LOGB)                   \
    2033              :     CASE_MATHFN_FLOATN (LRINT)                  \
    2034              :     CASE_MATHFN_FLOATN (LROUND)                 \
    2035              :     CASE_MATHFN_FLOATN (MODF)                   \
    2036              :     CASE_MATHFN_FLOATN (NAN)                    \
    2037              :     CASE_MATHFN_FLOATN (NANS)                   \
    2038              :     CASE_MATHFN_FLOATN (NEARBYINT)              \
    2039              :     CASE_MATHFN_FLOATN (NEXTAFTER)              \
    2040              :     CASE_MATHFN (NEXTTOWARD)                    \
    2041              :     CASE_MATHFN_FLOATN (POW)                    \
    2042              :     CASE_MATHFN (POWI)                          \
    2043              :     CASE_MATHFN (POW10)                         \
    2044              :     CASE_MATHFN_FLOATN (REMAINDER)              \
    2045              :     CASE_MATHFN_FLOATN (REMQUO)                 \
    2046              :     CASE_MATHFN_FLOATN (RINT)                   \
    2047              :     CASE_MATHFN_FLOATN (ROUND)                  \
    2048              :     CASE_MATHFN_FLOATN (ROUNDEVEN)              \
    2049              :     CASE_MATHFN (SCALB)                         \
    2050              :     CASE_MATHFN_FLOATN (SCALBLN)                \
    2051              :     CASE_MATHFN_FLOATN (SCALBN)                 \
    2052              :     CASE_MATHFN (SIGNBIT)                       \
    2053              :     CASE_MATHFN (SIGNIFICAND)                   \
    2054              :     CASE_MATHFN_FLOATN (SIN)                    \
    2055              :     CASE_MATHFN (SINCOS)                        \
    2056              :     CASE_MATHFN_FLOATN (SINH)                   \
    2057              :     CASE_MATHFN_FLOATN (SQRT)                   \
    2058              :     CASE_MATHFN_FLOATN (TAN)                    \
    2059              :     CASE_MATHFN_FLOATN (TANH)                   \
    2060              :     CASE_MATHFN_FLOATN (TGAMMA)                 \
    2061              :     CASE_MATHFN_FLOATN (TRUNC)                  \
    2062              :     CASE_MATHFN (Y0)                            \
    2063              :     CASE_MATHFN (Y1)                            \
    2064              :     CASE_MATHFN (YN)
    2065              : 
    2066       607180 :     SEQ_OF_CASE_MATHFN
    2067              : 
    2068              :     default:
    2069              :       return END_BUILTINS;
    2070              :     }
    2071              : 
    2072       607244 :   mtype = TYPE_MAIN_VARIANT (type);
    2073       607244 :   if (mtype == double_type_node)
    2074              :     return fcode;
    2075       567692 :   else if (mtype == float_type_node)
    2076              :     return fcodef;
    2077       522193 :   else if (mtype == long_double_type_node)
    2078              :     return fcodel;
    2079       489664 :   else if (mtype == float16_type_node)
    2080              :     return fcodef16;
    2081       489616 :   else if (mtype == float32_type_node)
    2082              :     return fcodef32;
    2083       489616 :   else if (mtype == float64_type_node)
    2084              :     return fcodef64;
    2085       489616 :   else if (mtype == float128_type_node)
    2086              :     return fcodef128;
    2087       482148 :   else if (mtype == float32x_type_node)
    2088              :     return fcodef32x;
    2089       482148 :   else if (mtype == float64x_type_node)
    2090              :     return fcodef64x;
    2091       482148 :   else if (mtype == float128x_type_node)
    2092              :     return fcodef128x;
    2093              :   else
    2094       482148 :     return END_BUILTINS;
    2095              : }
    2096              : 
    2097              : #undef CASE_MATHFN
    2098              : #undef CASE_MATHFN_FLOATN
    2099              : #undef CASE_MATHFN_REENT
    2100              : 
    2101              : /* Return mathematic function equivalent to FN but operating directly on TYPE,
    2102              :    if available.  If IMPLICIT_P is true use the implicit builtin declaration,
    2103              :    otherwise use the explicit declaration.  If we can't do the conversion,
    2104              :    return null.  */
    2105              : 
    2106              : static tree
    2107       607099 : mathfn_built_in_1 (tree type, combined_fn fn, bool implicit_p)
    2108              : {
    2109       607099 :   built_in_function fcode2 = mathfn_built_in_2 (type, fn);
    2110       607099 :   if (fcode2 == END_BUILTINS)
    2111              :     return NULL_TREE;
    2112              : 
    2113       121303 :   if (implicit_p && !builtin_decl_implicit_p (fcode2))
    2114              :     return NULL_TREE;
    2115              : 
    2116       117386 :   return builtin_decl_explicit (fcode2);
    2117              : }
    2118              : 
    2119              : /* Like mathfn_built_in_1, but always use the implicit array.  */
    2120              : 
    2121              : tree
    2122          276 : mathfn_built_in (tree type, combined_fn fn)
    2123              : {
    2124          276 :   return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
    2125              : }
    2126              : 
    2127              : /* Like mathfn_built_in_1, but always use the explicit array.  */
    2128              : 
    2129              : tree
    2130            0 : mathfn_built_in_explicit (tree type, combined_fn fn)
    2131              : {
    2132            0 :   return mathfn_built_in_1 (type, fn, /*implicit=*/ 0);
    2133              : }
    2134              : 
    2135              : /* Like mathfn_built_in_1, but take a built_in_function and
    2136              :    always use the implicit array.  */
    2137              : 
    2138              : tree
    2139       606600 : mathfn_built_in (tree type, enum built_in_function fn)
    2140              : {
    2141       606600 :   return mathfn_built_in_1 (type, as_combined_fn (fn), /*implicit=*/ 1);
    2142              : }
    2143              : 
    2144              : /* Return the type associated with a built in function, i.e., the one
    2145              :    to be passed to mathfn_built_in to get the type-specific
    2146              :    function.  */
    2147              : 
    2148              : tree
    2149         1290 : mathfn_built_in_type (combined_fn fn)
    2150              : {
    2151              : #define CASE_MATHFN(MATHFN)                     \
    2152              :   case CFN_BUILT_IN_##MATHFN:                   \
    2153              :     return double_type_node;                    \
    2154              :   case CFN_BUILT_IN_##MATHFN##F:                \
    2155              :     return float_type_node;                     \
    2156              :   case CFN_BUILT_IN_##MATHFN##L:                \
    2157              :     return long_double_type_node;
    2158              : 
    2159              : #define CASE_MATHFN_FLOATN(MATHFN)              \
    2160              :   CASE_MATHFN(MATHFN)                           \
    2161              :   case CFN_BUILT_IN_##MATHFN##F16:              \
    2162              :     return float16_type_node;                   \
    2163              :   case CFN_BUILT_IN_##MATHFN##F32:              \
    2164              :     return float32_type_node;                   \
    2165              :   case CFN_BUILT_IN_##MATHFN##F64:              \
    2166              :     return float64_type_node;                   \
    2167              :   case CFN_BUILT_IN_##MATHFN##F128:             \
    2168              :     return float128_type_node;                  \
    2169              :   case CFN_BUILT_IN_##MATHFN##F32X:             \
    2170              :     return float32x_type_node;                  \
    2171              :   case CFN_BUILT_IN_##MATHFN##F64X:             \
    2172              :     return float64x_type_node;                  \
    2173              :   case CFN_BUILT_IN_##MATHFN##F128X:            \
    2174              :     return float128x_type_node;
    2175              : 
    2176              : /* Similar to above, but appends _R after any F/L suffix.  */
    2177              : #define CASE_MATHFN_REENT(MATHFN) \
    2178              :   case CFN_BUILT_IN_##MATHFN##_R:               \
    2179              :     return double_type_node;                    \
    2180              :   case CFN_BUILT_IN_##MATHFN##F_R:              \
    2181              :     return float_type_node;                     \
    2182              :   case CFN_BUILT_IN_##MATHFN##L_R:              \
    2183              :     return long_double_type_node;
    2184              : 
    2185         1290 :   switch (fn)
    2186              :     {
    2187         1288 :     SEQ_OF_CASE_MATHFN
    2188              : 
    2189              :     default:
    2190              :       return NULL_TREE;
    2191              :     }
    2192              : 
    2193              : #undef CASE_MATHFN
    2194              : #undef CASE_MATHFN_FLOATN
    2195              : #undef CASE_MATHFN_REENT
    2196              : #undef SEQ_OF_CASE_MATHFN
    2197              : }
    2198              : 
    2199              : /* Check whether there is an internal function associated with function FN
    2200              :    and return type RETURN_TYPE.  Return the function if so, otherwise return
    2201              :    IFN_LAST.
    2202              : 
    2203              :    Note that this function only tests whether the function is defined in
    2204              :    internals.def, not whether it is actually available on the target.  */
    2205              : 
    2206              : static internal_fn
    2207     14089687 : associated_internal_fn (built_in_function fn, tree return_type)
    2208              : {
    2209     14089687 :   switch (fn)
    2210              :     {
    2211              : #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2212              :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2213              : #define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
    2214              :     CASE_FLT_FN (BUILT_IN_##NAME): return IFN_##NAME; \
    2215              :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_##NAME): return IFN_##NAME;
    2216              : #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
    2217              :     CASE_INT_FN (BUILT_IN_##NAME): return IFN_##NAME;
    2218              : #include "internal-fn.def"
    2219              : 
    2220              :     CASE_FLT_FN (BUILT_IN_POW10):
    2221              :       return IFN_EXP10;
    2222              : 
    2223              :     CASE_FLT_FN (BUILT_IN_DREM):
    2224              :       return IFN_REMAINDER;
    2225              : 
    2226        19587 :     CASE_FLT_FN (BUILT_IN_SCALBN):
    2227        19587 :     CASE_FLT_FN (BUILT_IN_SCALBLN):
    2228        19587 :       if (REAL_MODE_FORMAT (TYPE_MODE (return_type))->b == 2)
    2229              :         return IFN_LDEXP;
    2230              :       return IFN_LAST;
    2231          715 :     case BUILT_IN_CRC8_DATA8:
    2232          715 :     case BUILT_IN_CRC16_DATA8:
    2233          715 :     case BUILT_IN_CRC16_DATA16:
    2234          715 :     case BUILT_IN_CRC32_DATA8:
    2235          715 :     case BUILT_IN_CRC32_DATA16:
    2236          715 :     case BUILT_IN_CRC32_DATA32:
    2237          715 :     case BUILT_IN_CRC64_DATA8:
    2238          715 :     case BUILT_IN_CRC64_DATA16:
    2239          715 :     case BUILT_IN_CRC64_DATA32:
    2240          715 :     case BUILT_IN_CRC64_DATA64:
    2241          715 :       return IFN_CRC;
    2242          369 :     case BUILT_IN_REV_CRC8_DATA8:
    2243          369 :     case BUILT_IN_REV_CRC16_DATA8:
    2244          369 :     case BUILT_IN_REV_CRC16_DATA16:
    2245          369 :     case BUILT_IN_REV_CRC32_DATA8:
    2246          369 :     case BUILT_IN_REV_CRC32_DATA16:
    2247          369 :     case BUILT_IN_REV_CRC32_DATA32:
    2248          369 :     case BUILT_IN_REV_CRC64_DATA8:
    2249          369 :     case BUILT_IN_REV_CRC64_DATA16:
    2250          369 :     case BUILT_IN_REV_CRC64_DATA32:
    2251          369 :     case BUILT_IN_REV_CRC64_DATA64:
    2252          369 :       return IFN_CRC_REV;
    2253              :     default:
    2254              :       return IFN_LAST;
    2255              :     }
    2256              : }
    2257              : 
    2258              : /* If BUILT_IN_NORMAL function FNDECL has an associated internal function,
    2259              :    return its code, otherwise return IFN_LAST.  Note that this function
    2260              :    only tests whether the function is defined in internals.def, not whether
    2261              :    it is actually available on the target.  */
    2262              : 
    2263              : internal_fn
    2264       636165 : associated_internal_fn (tree fndecl)
    2265              : {
    2266       636165 :   gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
    2267       636165 :   return associated_internal_fn (DECL_FUNCTION_CODE (fndecl),
    2268       636165 :                                  TREE_TYPE (TREE_TYPE (fndecl)));
    2269              : }
    2270              : 
    2271              : /* Check whether there is an internal function associated with function CFN
    2272              :    and return type RETURN_TYPE.  Return the function if so, otherwise return
    2273              :    IFN_LAST.
    2274              : 
    2275              :    Note that this function only tests whether the function is defined in
    2276              :    internals.def, not whether it is actually available on the target.  */
    2277              : 
    2278              : internal_fn
    2279     34368183 : associated_internal_fn (combined_fn cfn, tree return_type)
    2280              : {
    2281     34368183 :   if (internal_fn_p (cfn))
    2282     20914661 :     return as_internal_fn (cfn);
    2283     13453522 :   return associated_internal_fn (as_builtin_fn (cfn), return_type);
    2284              : }
    2285              : 
    2286              : /* If CALL is a call to a BUILT_IN_NORMAL function that could be replaced
    2287              :    on the current target by a call to an internal function, return the
    2288              :    code of that internal function, otherwise return IFN_LAST.  The caller
    2289              :    is responsible for ensuring that any side-effects of the built-in
    2290              :    call are dealt with correctly.  E.g. if CALL sets errno, the caller
    2291              :    must decide that the errno result isn't needed or make it available
    2292              :    in some other way.  */
    2293              : 
    2294              : internal_fn
    2295       870514 : replacement_internal_fn (gcall *call)
    2296              : {
    2297       870514 :   if (gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    2298              :     {
    2299       633303 :       internal_fn ifn = associated_internal_fn (gimple_call_fndecl (call));
    2300       633303 :       if (ifn != IFN_LAST)
    2301              :         {
    2302        59152 :           tree_pair types = direct_internal_fn_types (ifn, call);
    2303        59152 :           optimization_type opt_type = bb_optimization_type (gimple_bb (call));
    2304        59152 :           if (direct_internal_fn_supported_p (ifn, types, opt_type))
    2305        37213 :             return ifn;
    2306              :         }
    2307              :     }
    2308              :   return IFN_LAST;
    2309              : }
    2310              : 
    2311              : /* Expand a call to the builtin trinary math functions (fma).
    2312              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2313              :    function in-line.  EXP is the expression that is a call to the builtin
    2314              :    function; if convenient, the result should be placed in TARGET.
    2315              :    SUBTARGET may be used as the target for computing one of EXP's
    2316              :    operands.  */
    2317              : 
    2318              : static rtx
    2319          368 : expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
    2320              : {
    2321          368 :   optab builtin_optab;
    2322          368 :   rtx op0, op1, op2, result;
    2323          368 :   rtx_insn *insns;
    2324          368 :   tree fndecl = get_callee_fndecl (exp);
    2325          368 :   tree arg0, arg1, arg2;
    2326          368 :   machine_mode mode;
    2327              : 
    2328          368 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    2329              :     return NULL_RTX;
    2330              : 
    2331          368 :   arg0 = CALL_EXPR_ARG (exp, 0);
    2332          368 :   arg1 = CALL_EXPR_ARG (exp, 1);
    2333          368 :   arg2 = CALL_EXPR_ARG (exp, 2);
    2334              : 
    2335          368 :   switch (DECL_FUNCTION_CODE (fndecl))
    2336              :     {
    2337          368 :     CASE_FLT_FN (BUILT_IN_FMA):
    2338          368 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
    2339          368 :       builtin_optab = fma_optab; break;
    2340            0 :     default:
    2341            0 :       gcc_unreachable ();
    2342              :     }
    2343              : 
    2344              :   /* Make a suitable register to place result in.  */
    2345          368 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2346              : 
    2347              :   /* Before working hard, check whether the instruction is available.  */
    2348          368 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2349              :     return NULL_RTX;
    2350              : 
    2351            0 :   result = gen_reg_rtx (mode);
    2352              : 
    2353              :   /* Always stabilize the argument list.  */
    2354            0 :   CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
    2355            0 :   CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
    2356            0 :   CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
    2357              : 
    2358            0 :   op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
    2359            0 :   op1 = expand_normal (arg1);
    2360            0 :   op2 = expand_normal (arg2);
    2361              : 
    2362            0 :   start_sequence ();
    2363              : 
    2364              :   /* Compute into RESULT.
    2365              :      Set RESULT to wherever the result comes back.  */
    2366            0 :   result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
    2367              :                               result, 0);
    2368              : 
    2369              :   /* If we were unable to expand via the builtin, stop the sequence
    2370              :      (without outputting the insns) and call to the library function
    2371              :      with the stabilized argument list.  */
    2372            0 :   if (result == 0)
    2373              :     {
    2374            0 :       end_sequence ();
    2375            0 :       return expand_call (exp, target, target == const0_rtx);
    2376              :     }
    2377              : 
    2378              :   /* Output the entire sequence.  */
    2379            0 :   insns = end_sequence ();
    2380            0 :   emit_insn (insns);
    2381              : 
    2382            0 :   return result;
    2383              : }
    2384              : 
    2385              : /* Expand a call to the builtin sin and cos math functions.
    2386              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2387              :    function in-line.  EXP is the expression that is a call to the builtin
    2388              :    function; if convenient, the result should be placed in TARGET.
    2389              :    SUBTARGET may be used as the target for computing one of EXP's
    2390              :    operands.  */
    2391              : 
    2392              : static rtx
    2393           47 : expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
    2394              : {
    2395           47 :   optab builtin_optab;
    2396           47 :   rtx op0;
    2397           47 :   rtx_insn *insns;
    2398           47 :   tree fndecl = get_callee_fndecl (exp);
    2399           47 :   machine_mode mode;
    2400           47 :   tree arg;
    2401              : 
    2402           47 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2403              :     return NULL_RTX;
    2404              : 
    2405           39 :   arg = CALL_EXPR_ARG (exp, 0);
    2406              : 
    2407           39 :   switch (DECL_FUNCTION_CODE (fndecl))
    2408              :     {
    2409           39 :     CASE_FLT_FN (BUILT_IN_SIN):
    2410           39 :     CASE_FLT_FN (BUILT_IN_COS):
    2411           39 :       builtin_optab = sincos_optab; break;
    2412            0 :     default:
    2413            0 :       gcc_unreachable ();
    2414              :     }
    2415              : 
    2416              :   /* Make a suitable register to place result in.  */
    2417           39 :   mode = TYPE_MODE (TREE_TYPE (exp));
    2418              : 
    2419              :   /* Check if sincos insn is available, otherwise fallback
    2420              :      to sin or cos insn.  */
    2421           39 :   if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
    2422           39 :     switch (DECL_FUNCTION_CODE (fndecl))
    2423              :       {
    2424              :       CASE_FLT_FN (BUILT_IN_SIN):
    2425              :         builtin_optab = sin_optab; break;
    2426           14 :       CASE_FLT_FN (BUILT_IN_COS):
    2427           14 :         builtin_optab = cos_optab; break;
    2428            0 :       default:
    2429            0 :         gcc_unreachable ();
    2430              :       }
    2431              : 
    2432              :   /* Before working hard, check whether the instruction is available.  */
    2433           39 :   if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
    2434              :     {
    2435            0 :       rtx result = gen_reg_rtx (mode);
    2436              : 
    2437              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2438              :          need to expand the argument again.  This way, we will not perform
    2439              :          side-effects more the once.  */
    2440            0 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2441              : 
    2442            0 :       op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    2443              : 
    2444            0 :       start_sequence ();
    2445              : 
    2446              :       /* Compute into RESULT.
    2447              :          Set RESULT to wherever the result comes back.  */
    2448            0 :       if (builtin_optab == sincos_optab)
    2449              :         {
    2450            0 :           int ok;
    2451              : 
    2452            0 :           switch (DECL_FUNCTION_CODE (fndecl))
    2453              :             {
    2454            0 :             CASE_FLT_FN (BUILT_IN_SIN):
    2455            0 :               ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
    2456            0 :               break;
    2457            0 :             CASE_FLT_FN (BUILT_IN_COS):
    2458            0 :               ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
    2459            0 :               break;
    2460            0 :             default:
    2461            0 :               gcc_unreachable ();
    2462              :             }
    2463            0 :           gcc_assert (ok);
    2464              :         }
    2465              :       else
    2466            0 :         result = expand_unop (mode, builtin_optab, op0, result, 0);
    2467              : 
    2468            0 :       if (result != 0)
    2469              :         {
    2470              :           /* Output the entire sequence.  */
    2471            0 :           insns = end_sequence ();
    2472            0 :           emit_insn (insns);
    2473            0 :           return result;
    2474              :         }
    2475              : 
    2476              :       /* If we were unable to expand via the builtin, stop the sequence
    2477              :          (without outputting the insns) and call to the library function
    2478              :          with the stabilized argument list.  */
    2479            0 :       end_sequence ();
    2480              :     }
    2481              : 
    2482           39 :   return expand_call (exp, target, target == const0_rtx);
    2483              : }
    2484              : 
    2485              : /* Given an interclass math builtin decl FNDECL and it's argument ARG
    2486              :    return an RTL instruction code that implements the functionality.
    2487              :    If that isn't possible or available return CODE_FOR_nothing.  */
    2488              : 
    2489              : static enum insn_code
    2490      1818519 : interclass_mathfn_icode (tree arg, tree fndecl)
    2491              : {
    2492      1818519 :   bool errno_set = false;
    2493      1818519 :   optab builtin_optab = unknown_optab;
    2494      1818519 :   machine_mode mode;
    2495              : 
    2496      1818519 :   switch (DECL_FUNCTION_CODE (fndecl))
    2497              :     {
    2498            4 :     CASE_FLT_FN (BUILT_IN_ILOGB):
    2499            4 :       errno_set = true;
    2500            4 :       builtin_optab = ilogb_optab;
    2501            4 :       break;
    2502       708836 :     CASE_FLT_FN (BUILT_IN_ISINF):
    2503       708836 :       builtin_optab = isinf_optab;
    2504       708836 :       break;
    2505       625191 :     case BUILT_IN_ISFINITE:
    2506       625191 :       builtin_optab = isfinite_optab;
    2507       625191 :       break;
    2508       239896 :     case BUILT_IN_ISNORMAL:
    2509       239896 :       builtin_optab = isnormal_optab;
    2510       239896 :       break;
    2511       242515 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    2512       242515 :       builtin_optab = isnan_optab;
    2513       242515 :       break;
    2514              :     CASE_FLT_FN (BUILT_IN_FINITE):
    2515              :     case BUILT_IN_FINITED32:
    2516              :     case BUILT_IN_FINITED64:
    2517              :     case BUILT_IN_FINITED128:
    2518              :     case BUILT_IN_ISINFD32:
    2519              :     case BUILT_IN_ISINFD64:
    2520              :     case BUILT_IN_ISINFD128:
    2521              :     case BUILT_IN_ISNAND32:
    2522              :     case BUILT_IN_ISNAND64:
    2523              :     case BUILT_IN_ISNAND128:
    2524              :       /* These builtins have no optabs (yet).  */
    2525              :       break;
    2526            0 :     default:
    2527            0 :       gcc_unreachable ();
    2528              :     }
    2529              : 
    2530              :   /* There's no easy way to detect the case we need to set EDOM.  */
    2531      1818519 :   if (flag_errno_math && errno_set)
    2532              :     return CODE_FOR_nothing;
    2533              : 
    2534              :   /* Optab mode depends on the mode of the input argument.  */
    2535      1818519 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2536              : 
    2537      1818519 :   if (builtin_optab)
    2538      1816442 :     return optab_handler (builtin_optab, mode);
    2539              :   return CODE_FOR_nothing;
    2540              : }
    2541              : 
    2542              : /* Expand a call to one of the builtin math functions that operate on
    2543              :    floating point argument and output an integer result (ilogb, isinf,
    2544              :    isnan, etc).
    2545              :    Return 0 if a normal call should be emitted rather than expanding the
    2546              :    function in-line.  EXP is the expression that is a call to the builtin
    2547              :    function; if convenient, the result should be placed in TARGET.  */
    2548              : 
    2549              : static rtx
    2550            4 : expand_builtin_interclass_mathfn (tree exp, rtx target)
    2551              : {
    2552            4 :   enum insn_code icode = CODE_FOR_nothing;
    2553            4 :   rtx op0;
    2554            4 :   tree fndecl = get_callee_fndecl (exp);
    2555            4 :   machine_mode mode;
    2556            4 :   tree arg;
    2557              : 
    2558            4 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2559              :     return NULL_RTX;
    2560              : 
    2561            4 :   arg = CALL_EXPR_ARG (exp, 0);
    2562            4 :   icode = interclass_mathfn_icode (arg, fndecl);
    2563            4 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2564              : 
    2565            4 :   if (icode != CODE_FOR_nothing)
    2566              :     {
    2567            2 :       class expand_operand ops[1];
    2568            2 :       rtx_insn *last = get_last_insn ();
    2569            2 :       tree orig_arg = arg;
    2570              : 
    2571              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    2572              :          need to expand the argument again.  This way, we will not perform
    2573              :          side-effects more the once.  */
    2574            2 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    2575              : 
    2576            2 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2577              : 
    2578            2 :       if (mode != GET_MODE (op0))
    2579            0 :         op0 = convert_to_mode (mode, op0, 0);
    2580              : 
    2581            2 :       create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
    2582            2 :       if (maybe_legitimize_operands (icode, 0, 1, ops)
    2583            2 :           && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
    2584            1 :         return ops[0].value;
    2585              : 
    2586            1 :       delete_insns_since (last);
    2587            1 :       CALL_EXPR_ARG (exp, 0) = orig_arg;
    2588              :     }
    2589              : 
    2590              :   return NULL_RTX;
    2591              : }
    2592              : 
    2593              : /* Expand a call to the builtin sincos math function.
    2594              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    2595              :    function in-line.  EXP is the expression that is a call to the builtin
    2596              :    function.  */
    2597              : 
    2598              : static rtx
    2599            3 : expand_builtin_sincos (tree exp)
    2600              : {
    2601            3 :   rtx op0, op1, op2, target1, target2;
    2602            3 :   machine_mode mode;
    2603            3 :   tree arg, sinp, cosp;
    2604            3 :   int result;
    2605            3 :   location_t loc = EXPR_LOCATION (exp);
    2606            3 :   tree alias_type, alias_off;
    2607              : 
    2608            3 :   if (!validate_arglist (exp, REAL_TYPE,
    2609              :                          POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    2610              :     return NULL_RTX;
    2611              : 
    2612            3 :   arg = CALL_EXPR_ARG (exp, 0);
    2613            3 :   sinp = CALL_EXPR_ARG (exp, 1);
    2614            3 :   cosp = CALL_EXPR_ARG (exp, 2);
    2615              : 
    2616              :   /* Make a suitable register to place result in.  */
    2617            3 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2618              : 
    2619              :   /* Check if sincos insn is available, otherwise emit the call.  */
    2620            3 :   if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
    2621              :     return NULL_RTX;
    2622              : 
    2623            0 :   target1 = gen_reg_rtx (mode);
    2624            0 :   target2 = gen_reg_rtx (mode);
    2625              : 
    2626            0 :   op0 = expand_normal (arg);
    2627            0 :   alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
    2628            0 :   alias_off = build_int_cst (alias_type, 0);
    2629            0 :   op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2630              :                                         sinp, alias_off));
    2631            0 :   op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
    2632              :                                         cosp, alias_off));
    2633              : 
    2634              :   /* Compute into target1 and target2.
    2635              :      Set TARGET to wherever the result comes back.  */
    2636            0 :   result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
    2637            0 :   gcc_assert (result);
    2638              : 
    2639              :   /* Move target1 and target2 to the memory locations indicated
    2640              :      by op1 and op2.  */
    2641            0 :   emit_move_insn (op1, target1);
    2642            0 :   emit_move_insn (op2, target2);
    2643              : 
    2644            0 :   return const0_rtx;
    2645              : }
    2646              : 
    2647              : /* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the
    2648              :    result and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
    2649              : static rtx
    2650           60 : expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode)
    2651              : {
    2652           60 :   if (!validate_arglist (exp, VOID_TYPE))
    2653              :     return NULL_RTX;
    2654              : 
    2655           60 :   insn_code icode = direct_optab_handler (fegetround_optab, SImode);
    2656           60 :   if (icode == CODE_FOR_nothing)
    2657              :     return NULL_RTX;
    2658              : 
    2659            0 :   if (target == 0
    2660            0 :       || GET_MODE (target) != target_mode
    2661            0 :       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
    2662            0 :     target = gen_reg_rtx (target_mode);
    2663              : 
    2664            0 :   rtx pat = GEN_FCN (icode) (target);
    2665            0 :   if (!pat)
    2666              :     return NULL_RTX;
    2667            0 :   emit_insn (pat);
    2668              : 
    2669            0 :   return target;
    2670              : }
    2671              : 
    2672              : /* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99
    2673              :    fenv.h), returning the result and setting it in TARGET.  Otherwise return
    2674              :    NULL_RTX on failure.  */
    2675              : static rtx
    2676         1895 : expand_builtin_feclear_feraise_except (tree exp, rtx target,
    2677              :                                        machine_mode target_mode, optab op_optab)
    2678              : {
    2679         1895 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    2680              :     return NULL_RTX;
    2681         1895 :   rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
    2682              : 
    2683         1895 :   insn_code icode = direct_optab_handler (op_optab, SImode);
    2684         1895 :   if (icode == CODE_FOR_nothing)
    2685              :     return NULL_RTX;
    2686              : 
    2687            0 :   if (!(*insn_data[icode].operand[1].predicate) (op0, GET_MODE (op0)))
    2688              :     return NULL_RTX;
    2689              : 
    2690            0 :   if (target == 0
    2691            0 :       || GET_MODE (target) != target_mode
    2692            0 :       || !(*insn_data[icode].operand[0].predicate) (target, target_mode))
    2693            0 :     target = gen_reg_rtx (target_mode);
    2694              : 
    2695            0 :   rtx pat = GEN_FCN (icode) (target, op0);
    2696            0 :   if (!pat)
    2697              :     return NULL_RTX;
    2698            0 :   emit_insn (pat);
    2699              : 
    2700            0 :   return target;
    2701              : }
    2702              : 
    2703              : /* Expand a call to the internal cexpi builtin to the sincos math function.
    2704              :    EXP is the expression that is a call to the builtin function; if convenient,
    2705              :    the result should be placed in TARGET.  */
    2706              : 
    2707              : static rtx
    2708          170 : expand_builtin_cexpi (tree exp, rtx target)
    2709              : {
    2710          170 :   tree fndecl = get_callee_fndecl (exp);
    2711          170 :   tree arg, type;
    2712          170 :   machine_mode mode;
    2713          170 :   rtx op0, op1, op2;
    2714          170 :   location_t loc = EXPR_LOCATION (exp);
    2715              : 
    2716          170 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2717              :     return NULL_RTX;
    2718              : 
    2719          170 :   arg = CALL_EXPR_ARG (exp, 0);
    2720          170 :   type = TREE_TYPE (arg);
    2721          170 :   mode = TYPE_MODE (TREE_TYPE (arg));
    2722              : 
    2723              :   /* Try expanding via a sincos optab, fall back to emitting a libcall
    2724              :      to sincos or cexp.  We are sure we have sincos or cexp because cexpi
    2725              :      is only generated from sincos, cexp or if we have either of them.  */
    2726          170 :   if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
    2727              :     {
    2728            6 :       op1 = gen_reg_rtx (mode);
    2729            6 :       op2 = gen_reg_rtx (mode);
    2730              : 
    2731            6 :       op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
    2732              : 
    2733              :       /* Compute into op1 and op2.  */
    2734            6 :       expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
    2735              :     }
    2736          164 :   else if (targetm.libc_has_function (function_sincos, type))
    2737              :     {
    2738          164 :       tree call, fn = NULL_TREE;
    2739          164 :       tree top1, top2;
    2740          164 :       rtx op1a, op2a;
    2741              : 
    2742          164 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2743           54 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
    2744          110 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2745           89 :         fn = builtin_decl_explicit (BUILT_IN_SINCOS);
    2746           21 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2747           21 :         fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
    2748              :       else
    2749            0 :         gcc_unreachable ();
    2750              : 
    2751          164 :       op1 = assign_temp (TREE_TYPE (arg), 1, 1);
    2752          164 :       op2 = assign_temp (TREE_TYPE (arg), 1, 1);
    2753          164 :       op1a = copy_addr_to_reg (XEXP (op1, 0));
    2754          164 :       op2a = copy_addr_to_reg (XEXP (op2, 0));
    2755          164 :       top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
    2756          164 :       top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
    2757              : 
    2758              :       /* Make sure not to fold the sincos call again.  */
    2759          164 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2760          164 :       expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
    2761              :                                       call, 3, arg, top1, top2));
    2762              :     }
    2763              :   else
    2764              :     {
    2765            0 :       tree call, fn = NULL_TREE, narg;
    2766            0 :       tree ctype = build_complex_type (type);
    2767              : 
    2768            0 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2769            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPF);
    2770            0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2771            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXP);
    2772            0 :       else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2773            0 :         fn = builtin_decl_explicit (BUILT_IN_CEXPL);
    2774              :       else
    2775            0 :         gcc_unreachable ();
    2776              : 
    2777              :       /* If we don't have a decl for cexp create one.  This is the
    2778              :          friendliest fallback if the user calls __builtin_cexpi
    2779              :          without full target C99 function support.  */
    2780            0 :       if (fn == NULL_TREE)
    2781              :         {
    2782            0 :           tree fntype;
    2783            0 :           const char *name = NULL;
    2784              : 
    2785            0 :           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
    2786              :             name = "cexpf";
    2787            0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
    2788              :             name = "cexp";
    2789            0 :           else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
    2790            0 :             name = "cexpl";
    2791              : 
    2792            0 :           fntype = build_function_type_list (ctype, ctype, NULL_TREE);
    2793            0 :           fn = build_fn_decl (name, fntype);
    2794              :         }
    2795              : 
    2796            0 :       narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
    2797              :                           build_real (type, dconst0), arg);
    2798              : 
    2799              :       /* Make sure not to fold the cexp call again.  */
    2800            0 :       call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
    2801            0 :       return expand_expr (build_call_nary (ctype, call, 1, narg),
    2802            0 :                           target, VOIDmode, EXPAND_NORMAL);
    2803              :     }
    2804              : 
    2805              :   /* Now build the proper return type.  */
    2806          340 :   return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
    2807          170 :                               make_tree (TREE_TYPE (arg), op2),
    2808          170 :                               make_tree (TREE_TYPE (arg), op1)),
    2809          170 :                       target, VOIDmode, EXPAND_NORMAL);
    2810              : }
    2811              : 
    2812              : /* Conveniently construct a function call expression.  FNDECL names the
    2813              :    function to be called, N is the number of arguments, and the "..."
    2814              :    parameters are the argument expressions.  Unlike build_call_exr
    2815              :    this doesn't fold the call, hence it will always return a CALL_EXPR.  */
    2816              : 
    2817              : static tree
    2818       136103 : build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
    2819              : {
    2820       136103 :   va_list ap;
    2821       136103 :   tree fntype = TREE_TYPE (fndecl);
    2822       136103 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
    2823              : 
    2824       136103 :   va_start (ap, n);
    2825       136103 :   fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
    2826       136103 :   va_end (ap);
    2827       136103 :   SET_EXPR_LOCATION (fn, loc);
    2828       136103 :   return fn;
    2829              : }
    2830              : 
    2831              : /* Expand the __builtin_issignaling builtin.  This needs to handle
    2832              :    all floating point formats that do support NaNs (for those that
    2833              :    don't it just sets target to 0).  */
    2834              : 
    2835              : static rtx
    2836          784 : expand_builtin_issignaling (tree exp, rtx target)
    2837              : {
    2838          784 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    2839              :     return NULL_RTX;
    2840              : 
    2841          784 :   tree arg = CALL_EXPR_ARG (exp, 0);
    2842          784 :   scalar_float_mode fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
    2843          784 :   const struct real_format *fmt = REAL_MODE_FORMAT (fmode);
    2844              : 
    2845              :   /* Expand the argument yielding a RTX expression. */
    2846          784 :   rtx temp = expand_normal (arg);
    2847              : 
    2848              :   /* If mode doesn't support NaN, always return 0.
    2849              :      Don't use !HONOR_SNANS (fmode) here, so there is some possibility of
    2850              :      __builtin_issignaling working without -fsignaling-nans.  Especially
    2851              :      when -fno-signaling-nans is the default.
    2852              :      On the other side, MODE_HAS_NANS (fmode) is unnecessary, with
    2853              :      -ffinite-math-only even __builtin_isnan or __builtin_fpclassify
    2854              :      fold to 0 or non-NaN/Inf classification.  */
    2855          784 :   if (!HONOR_NANS (fmode))
    2856              :     {
    2857            0 :       emit_move_insn (target, const0_rtx);
    2858            0 :       return target;
    2859              :     }
    2860              : 
    2861              :   /* Check if the back end provides an insn that handles issignaling for the
    2862              :      argument's mode. */
    2863          784 :   enum insn_code icode = optab_handler (issignaling_optab, fmode);
    2864          784 :   if (icode != CODE_FOR_nothing)
    2865              :     {
    2866          142 :       rtx_insn *last = get_last_insn ();
    2867          142 :       rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    2868          142 :       if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
    2869              :         return this_target;
    2870            0 :       delete_insns_since (last);
    2871              :     }
    2872              : 
    2873          642 :   if (DECIMAL_FLOAT_MODE_P (fmode))
    2874              :     {
    2875           63 :       scalar_int_mode imode;
    2876           63 :       rtx hi;
    2877           63 :       switch (fmt->ieee_bits)
    2878              :         {
    2879           42 :         case 32:
    2880           42 :         case 64:
    2881           42 :           imode = int_mode_for_mode (fmode).require ();
    2882           42 :           temp = gen_lowpart (imode, temp);
    2883           42 :           break;
    2884           21 :         case 128:
    2885           21 :           imode = int_mode_for_size (64, 1).require ();
    2886           21 :           hi = NULL_RTX;
    2887              :           /* For decimal128, TImode support isn't always there and even when
    2888              :              it is, working on the DImode high part is usually better.  */
    2889           21 :           if (!MEM_P (temp))
    2890              :             {
    2891            6 :               if (rtx t = force_highpart_subreg (imode, temp, fmode))
    2892              :                 hi = t;
    2893              :               else
    2894              :                 {
    2895            0 :                   scalar_int_mode imode2;
    2896            0 :                   if (int_mode_for_mode (fmode).exists (&imode2))
    2897              :                     {
    2898            0 :                       rtx temp2 = gen_lowpart (imode2, temp);
    2899            0 :                       if (rtx t = force_highpart_subreg (imode, temp2, imode2))
    2900              :                         hi = t;
    2901              :                     }
    2902              :                 }
    2903            0 :               if (!hi)
    2904              :                 {
    2905            0 :                   rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    2906            0 :                   emit_move_insn (mem, temp);
    2907            0 :                   temp = mem;
    2908              :                 }
    2909              :             }
    2910            0 :           if (!hi)
    2911              :             {
    2912           15 :               poly_int64 offset
    2913           15 :                 = subreg_highpart_offset (imode, GET_MODE (temp));
    2914           15 :               hi = adjust_address (temp, imode, offset);
    2915              :             }
    2916              :           temp = hi;
    2917              :           break;
    2918            0 :         default:
    2919            0 :           gcc_unreachable ();
    2920              :         }
    2921              :       /* In all of decimal{32,64,128}, there is MSB sign bit and sNaN
    2922              :          have 6 bits below it all set.  */
    2923           63 :       rtx val
    2924           63 :         = GEN_INT (HOST_WIDE_INT_C (0x3f) << (GET_MODE_BITSIZE (imode) - 7));
    2925           63 :       temp = expand_binop (imode, and_optab, temp, val,
    2926              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2927           63 :       temp = emit_store_flag_force (target, EQ, temp, val, imode, 1, 1);
    2928           63 :       return temp;
    2929              :     }
    2930              : 
    2931              :   /* Only PDP11 has these defined differently but doesn't support NaNs.  */
    2932          579 :   gcc_assert (FLOAT_WORDS_BIG_ENDIAN == WORDS_BIG_ENDIAN);
    2933          579 :   gcc_assert (fmt->signbit_ro > 0 && fmt->b == 2);
    2934         4053 :   gcc_assert (MODE_COMPOSITE_P (fmode)
    2935              :               || (fmt->pnan == fmt->p
    2936              :                   && fmt->signbit_ro == fmt->signbit_rw));
    2937              : 
    2938          579 :   switch (fmt->p)
    2939              :     {
    2940            0 :     case 106: /* IBM double double  */
    2941              :       /* For IBM double double, recurse on the most significant double.  */
    2942            0 :       gcc_assert (MODE_COMPOSITE_P (fmode));
    2943            0 :       temp = convert_modes (DFmode, fmode, temp, 0);
    2944            0 :       fmode = DFmode;
    2945            0 :       fmt = REAL_MODE_FORMAT (DFmode);
    2946              :       /* FALLTHRU */
    2947          479 :     case 8: /* bfloat */
    2948          479 :     case 11: /* IEEE half */
    2949          479 :     case 24: /* IEEE single */
    2950          479 :     case 53: /* IEEE double or Intel extended with rounding to double */
    2951          479 :       if (fmt->p == 53 && fmt->signbit_ro == 79)
    2952            0 :         goto extended;
    2953          479 :       {
    2954          479 :         scalar_int_mode imode = int_mode_for_mode (fmode).require ();
    2955          479 :         temp = gen_lowpart (imode, temp);
    2956          479 :         rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2))
    2957              :                            & ~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
    2958          479 :         if (fmt->qnan_msb_set)
    2959              :           {
    2960          479 :             rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << fmt->signbit_ro));
    2961          479 :             rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2));
    2962              :             /* For non-MIPS/PA IEEE single/double/half or bfloat, expand to:
    2963              :                ((temp ^ bit) & mask) > val.  */
    2964          479 :             temp = expand_binop (imode, xor_optab, temp, bit,
    2965              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2966          479 :             temp = expand_binop (imode, and_optab, temp, mask,
    2967              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2968          479 :             temp = emit_store_flag_force (target, GTU, temp, val, imode,
    2969              :                                           1, 1);
    2970              :           }
    2971              :         else
    2972              :           {
    2973              :             /* For MIPS/PA IEEE single/double, expand to:
    2974              :                (temp & val) == val.  */
    2975            0 :             temp = expand_binop (imode, and_optab, temp, val,
    2976              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    2977            0 :             temp = emit_store_flag_force (target, EQ, temp, val, imode,
    2978              :                                           1, 1);
    2979              :           }
    2980              :       }
    2981              :       break;
    2982          100 :     case 113: /* IEEE quad */
    2983          100 :       {
    2984          100 :         rtx hi = NULL_RTX, lo = NULL_RTX;
    2985          100 :         scalar_int_mode imode = int_mode_for_size (64, 1).require ();
    2986              :         /* For IEEE quad, TImode support isn't always there and even when
    2987              :            it is, working on DImode parts is usually better.  */
    2988          100 :         if (!MEM_P (temp))
    2989              :           {
    2990           85 :             hi = force_highpart_subreg (imode, temp, fmode);
    2991           85 :             lo = force_lowpart_subreg (imode, temp, fmode);
    2992           85 :             if (!hi || !lo)
    2993              :               {
    2994            0 :                 scalar_int_mode imode2;
    2995            0 :                 if (int_mode_for_mode (fmode).exists (&imode2))
    2996              :                   {
    2997            0 :                     rtx temp2 = gen_lowpart (imode2, temp);
    2998            0 :                     hi = force_highpart_subreg (imode, temp2, imode2);
    2999            0 :                     lo = force_lowpart_subreg (imode, temp2, imode2);
    3000              :                   }
    3001              :               }
    3002           85 :             if (!hi || !lo)
    3003              :               {
    3004            0 :                 rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    3005            0 :                 emit_move_insn (mem, temp);
    3006            0 :                 temp = mem;
    3007              :               }
    3008              :           }
    3009          100 :         if (!hi || !lo)
    3010              :           {
    3011           15 :             poly_int64 offset
    3012           15 :               = subreg_highpart_offset (imode, GET_MODE (temp));
    3013           15 :             hi = adjust_address (temp, imode, offset);
    3014           15 :             offset = subreg_lowpart_offset (imode, GET_MODE (temp));
    3015           15 :             lo = adjust_address (temp, imode, offset);
    3016              :           }
    3017          100 :         rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2 - 64))
    3018              :                            & ~(HOST_WIDE_INT_M1U << (fmt->signbit_ro - 64)));
    3019          100 :         if (fmt->qnan_msb_set)
    3020              :           {
    3021          100 :             rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << (fmt->signbit_ro
    3022              :                                                         - 64)));
    3023          100 :             rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2 - 64));
    3024              :             /* For non-MIPS/PA IEEE quad, expand to:
    3025              :                (((hi ^ bit) | ((lo | -lo) >> 63)) & mask) > val.  */
    3026          100 :             rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
    3027          100 :             lo = expand_binop (imode, ior_optab, lo, nlo,
    3028              :                                NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3029          100 :             lo = expand_shift (RSHIFT_EXPR, imode, lo, 63, NULL_RTX, 1);
    3030          100 :             temp = expand_binop (imode, xor_optab, hi, bit,
    3031              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3032          100 :             temp = expand_binop (imode, ior_optab, temp, lo,
    3033              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3034          100 :             temp = expand_binop (imode, and_optab, temp, mask,
    3035              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3036          100 :             temp = emit_store_flag_force (target, GTU, temp, val, imode,
    3037              :                                           1, 1);
    3038              :           }
    3039              :         else
    3040              :           {
    3041              :             /* For MIPS/PA IEEE quad, expand to:
    3042              :                (hi & val) == val.  */
    3043            0 :             temp = expand_binop (imode, and_optab, hi, val,
    3044              :                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3045            0 :             temp = emit_store_flag_force (target, EQ, temp, val, imode,
    3046              :                                           1, 1);
    3047              :           }
    3048              :       }
    3049              :       break;
    3050            0 :     case 64: /* Intel or Motorola extended */
    3051            0 :     extended:
    3052            0 :       {
    3053            0 :         rtx ex, hi, lo;
    3054            0 :         scalar_int_mode imode = int_mode_for_size (32, 1).require ();
    3055            0 :         scalar_int_mode iemode = int_mode_for_size (16, 1).require ();
    3056            0 :         if (!MEM_P (temp))
    3057              :           {
    3058            0 :             rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode));
    3059            0 :             emit_move_insn (mem, temp);
    3060            0 :             temp = mem;
    3061              :           }
    3062            0 :         if (fmt->signbit_ro == 95)
    3063              :           {
    3064              :             /* Motorola, always big endian, with 16-bit gap in between
    3065              :                16-bit sign+exponent and 64-bit mantissa.  */
    3066            0 :             ex = adjust_address (temp, iemode, 0);
    3067            0 :             hi = adjust_address (temp, imode, 4);
    3068            0 :             lo = adjust_address (temp, imode, 8);
    3069              :           }
    3070            0 :         else if (!WORDS_BIG_ENDIAN)
    3071              :           {
    3072              :             /* Intel little endian, 64-bit mantissa followed by 16-bit
    3073              :                sign+exponent and then either 16 or 48 bits of gap.  */
    3074            0 :             ex = adjust_address (temp, iemode, 8);
    3075            0 :             hi = adjust_address (temp, imode, 4);
    3076            0 :             lo = adjust_address (temp, imode, 0);
    3077              :           }
    3078              :         else
    3079              :           {
    3080              :             /* Big endian Itanium.  */
    3081              :             ex = adjust_address (temp, iemode, 0);
    3082              :             hi = adjust_address (temp, imode, 2);
    3083              :             lo = adjust_address (temp, imode, 6);
    3084              :           }
    3085            0 :         rtx val = GEN_INT (HOST_WIDE_INT_M1U << 30);
    3086            0 :         gcc_assert (fmt->qnan_msb_set);
    3087            0 :         rtx mask = GEN_INT (0x7fff);
    3088            0 :         rtx bit = GEN_INT (HOST_WIDE_INT_1U << 30);
    3089              :         /* For Intel/Motorola extended format, expand to:
    3090              :            (ex & mask) == mask && ((hi ^ bit) | ((lo | -lo) >> 31)) > val.  */
    3091            0 :         rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0);
    3092            0 :         lo = expand_binop (imode, ior_optab, lo, nlo,
    3093              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3094            0 :         lo = expand_shift (RSHIFT_EXPR, imode, lo, 31, NULL_RTX, 1);
    3095            0 :         temp = expand_binop (imode, xor_optab, hi, bit,
    3096              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3097            0 :         temp = expand_binop (imode, ior_optab, temp, lo,
    3098              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3099            0 :         temp = emit_store_flag_force (target, GTU, temp, val, imode, 1, 1);
    3100            0 :         ex = expand_binop (iemode, and_optab, ex, mask,
    3101              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3102            0 :         ex = emit_store_flag_force (gen_reg_rtx (GET_MODE (temp)), EQ,
    3103              :                                     ex, mask, iemode, 1, 1);
    3104            0 :         temp = expand_binop (GET_MODE (temp), and_optab, temp, ex,
    3105              :                              NULL_RTX, 1, OPTAB_LIB_WIDEN);
    3106              :       }
    3107            0 :       break;
    3108            0 :     default:
    3109            0 :       gcc_unreachable ();
    3110              :     }
    3111              : 
    3112              :   return temp;
    3113              : }
    3114              : 
    3115              : /* Expand a call to one of the builtin rounding functions gcc defines
    3116              :    as an extension (lfloor and lceil).  As these are gcc extensions we
    3117              :    do not need to worry about setting errno to EDOM.
    3118              :    If expanding via optab fails, lower expression to (int)(floor(x)).
    3119              :    EXP is the expression that is a call to the builtin function;
    3120              :    if convenient, the result should be placed in TARGET.  */
    3121              : 
    3122              : static rtx
    3123          223 : expand_builtin_int_roundingfn (tree exp, rtx target)
    3124              : {
    3125          223 :   convert_optab builtin_optab;
    3126          223 :   rtx op0, tmp;
    3127          223 :   rtx_insn *insns;
    3128          223 :   tree fndecl = get_callee_fndecl (exp);
    3129          223 :   enum built_in_function fallback_fn;
    3130          223 :   tree fallback_fndecl;
    3131          223 :   machine_mode mode;
    3132          223 :   tree arg;
    3133              : 
    3134          223 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    3135              :     return NULL_RTX;
    3136              : 
    3137          223 :   arg = CALL_EXPR_ARG (exp, 0);
    3138              : 
    3139          223 :   switch (DECL_FUNCTION_CODE (fndecl))
    3140              :     {
    3141              :     CASE_FLT_FN (BUILT_IN_ICEIL):
    3142              :     CASE_FLT_FN (BUILT_IN_LCEIL):
    3143              :     CASE_FLT_FN (BUILT_IN_LLCEIL):
    3144              :       builtin_optab = lceil_optab;
    3145              :       fallback_fn = BUILT_IN_CEIL;
    3146              :       break;
    3147              : 
    3148          112 :     CASE_FLT_FN (BUILT_IN_IFLOOR):
    3149          112 :     CASE_FLT_FN (BUILT_IN_LFLOOR):
    3150          112 :     CASE_FLT_FN (BUILT_IN_LLFLOOR):
    3151          112 :       builtin_optab = lfloor_optab;
    3152          112 :       fallback_fn = BUILT_IN_FLOOR;
    3153          112 :       break;
    3154              : 
    3155            0 :     default:
    3156            0 :       gcc_unreachable ();
    3157              :     }
    3158              : 
    3159              :   /* Make a suitable register to place result in.  */
    3160          223 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3161              : 
    3162          223 :   target = gen_reg_rtx (mode);
    3163              : 
    3164              :   /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    3165              :      need to expand the argument again.  This way, we will not perform
    3166              :      side-effects more the once.  */
    3167          223 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    3168              : 
    3169          223 :   op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    3170              : 
    3171          223 :   start_sequence ();
    3172              : 
    3173              :   /* Compute into TARGET.  */
    3174          223 :   if (expand_sfix_optab (target, op0, builtin_optab))
    3175              :     {
    3176              :       /* Output the entire sequence.  */
    3177           32 :       insns = end_sequence ();
    3178           32 :       emit_insn (insns);
    3179           32 :       return target;
    3180              :     }
    3181              : 
    3182              :   /* If we were unable to expand via the builtin, stop the sequence
    3183              :      (without outputting the insns).  */
    3184          191 :   end_sequence ();
    3185              : 
    3186              :   /* Fall back to floating point rounding optab.  */
    3187          191 :   fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
    3188              : 
    3189              :   /* For non-C99 targets we may end up without a fallback fndecl here
    3190              :      if the user called __builtin_lfloor directly.  In this case emit
    3191              :      a call to the floor/ceil variants nevertheless.  This should result
    3192              :      in the best user experience for not full C99 targets.  */
    3193          191 :   if (fallback_fndecl == NULL_TREE)
    3194              :     {
    3195            0 :       tree fntype;
    3196            0 :       const char *name = NULL;
    3197              : 
    3198            0 :       switch (DECL_FUNCTION_CODE (fndecl))
    3199              :         {
    3200              :         case BUILT_IN_ICEIL:
    3201              :         case BUILT_IN_LCEIL:
    3202              :         case BUILT_IN_LLCEIL:
    3203              :           name = "ceil";
    3204              :           break;
    3205            0 :         case BUILT_IN_ICEILF:
    3206            0 :         case BUILT_IN_LCEILF:
    3207            0 :         case BUILT_IN_LLCEILF:
    3208            0 :           name = "ceilf";
    3209            0 :           break;
    3210            0 :         case BUILT_IN_ICEILL:
    3211            0 :         case BUILT_IN_LCEILL:
    3212            0 :         case BUILT_IN_LLCEILL:
    3213            0 :           name = "ceill";
    3214            0 :           break;
    3215            0 :         case BUILT_IN_IFLOOR:
    3216            0 :         case BUILT_IN_LFLOOR:
    3217            0 :         case BUILT_IN_LLFLOOR:
    3218            0 :           name = "floor";
    3219            0 :           break;
    3220            0 :         case BUILT_IN_IFLOORF:
    3221            0 :         case BUILT_IN_LFLOORF:
    3222            0 :         case BUILT_IN_LLFLOORF:
    3223            0 :           name = "floorf";
    3224            0 :           break;
    3225            0 :         case BUILT_IN_IFLOORL:
    3226            0 :         case BUILT_IN_LFLOORL:
    3227            0 :         case BUILT_IN_LLFLOORL:
    3228            0 :           name = "floorl";
    3229            0 :           break;
    3230            0 :         default:
    3231            0 :           gcc_unreachable ();
    3232              :         }
    3233              : 
    3234            0 :       fntype = build_function_type_list (TREE_TYPE (arg),
    3235            0 :                                          TREE_TYPE (arg), NULL_TREE);
    3236            0 :       fallback_fndecl = build_fn_decl (name, fntype);
    3237              :     }
    3238              : 
    3239          191 :   exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
    3240              : 
    3241          191 :   tmp = expand_normal (exp);
    3242          191 :   tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
    3243              : 
    3244              :   /* Truncate the result of floating point optab to integer
    3245              :      via expand_fix ().  */
    3246          191 :   target = gen_reg_rtx (mode);
    3247          191 :   expand_fix (target, tmp, 0);
    3248              : 
    3249          191 :   return target;
    3250              : }
    3251              : 
    3252              : /* Expand a call to one of the builtin math functions doing integer
    3253              :    conversion (lrint).
    3254              :    Return 0 if a normal call should be emitted rather than expanding the
    3255              :    function in-line.  EXP is the expression that is a call to the builtin
    3256              :    function; if convenient, the result should be placed in TARGET.  */
    3257              : 
    3258              : static rtx
    3259          588 : expand_builtin_int_roundingfn_2 (tree exp, rtx target)
    3260              : {
    3261          588 :   convert_optab builtin_optab;
    3262          588 :   rtx op0;
    3263          588 :   rtx_insn *insns;
    3264          588 :   tree fndecl = get_callee_fndecl (exp);
    3265          588 :   tree arg;
    3266          588 :   machine_mode mode;
    3267          588 :   enum built_in_function fallback_fn = BUILT_IN_NONE;
    3268              : 
    3269          588 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    3270              :     return NULL_RTX;
    3271              : 
    3272          488 :   arg = CALL_EXPR_ARG (exp, 0);
    3273              : 
    3274          488 :   switch (DECL_FUNCTION_CODE (fndecl))
    3275              :     {
    3276            4 :     CASE_FLT_FN (BUILT_IN_IRINT):
    3277            4 :       fallback_fn = BUILT_IN_LRINT;
    3278              :       gcc_fallthrough ();
    3279              :     CASE_FLT_FN (BUILT_IN_LRINT):
    3280              :     CASE_FLT_FN (BUILT_IN_LLRINT):
    3281              :       builtin_optab = lrint_optab;
    3282              :       break;
    3283              : 
    3284          223 :     CASE_FLT_FN (BUILT_IN_IROUND):
    3285          223 :       fallback_fn = BUILT_IN_LROUND;
    3286              :       gcc_fallthrough ();
    3287              :     CASE_FLT_FN (BUILT_IN_LROUND):
    3288              :     CASE_FLT_FN (BUILT_IN_LLROUND):
    3289              :       builtin_optab = lround_optab;
    3290              :       break;
    3291              : 
    3292            0 :     default:
    3293            0 :       gcc_unreachable ();
    3294              :     }
    3295              : 
    3296              :   /* There's no easy way to detect the case we need to set EDOM.  */
    3297          488 :   if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
    3298              :     return NULL_RTX;
    3299              : 
    3300              :   /* Make a suitable register to place result in.  */
    3301          257 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3302              : 
    3303              :   /* There's no easy way to detect the case we need to set EDOM.  */
    3304          257 :   if (!flag_errno_math)
    3305              :     {
    3306          257 :       rtx result = gen_reg_rtx (mode);
    3307              : 
    3308              :       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
    3309              :          need to expand the argument again.  This way, we will not perform
    3310              :          side-effects more the once.  */
    3311          257 :       CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    3312              : 
    3313          257 :       op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
    3314              : 
    3315          257 :       start_sequence ();
    3316              : 
    3317          257 :       if (expand_sfix_optab (result, op0, builtin_optab))
    3318              :         {
    3319              :           /* Output the entire sequence.  */
    3320           20 :           insns = end_sequence ();
    3321           20 :           emit_insn (insns);
    3322           20 :           return result;
    3323              :         }
    3324              : 
    3325              :       /* If we were unable to expand via the builtin, stop the sequence
    3326              :          (without outputting the insns) and call to the library function
    3327              :          with the stabilized argument list.  */
    3328          237 :       end_sequence ();
    3329              :     }
    3330              : 
    3331          237 :   if (fallback_fn != BUILT_IN_NONE)
    3332              :     {
    3333              :       /* Fall back to rounding to long int.  Use implicit_p 0 - for non-C99
    3334              :          targets, (int) round (x) should never be transformed into
    3335              :          BUILT_IN_IROUND and if __builtin_iround is called directly, emit
    3336              :          a call to lround in the hope that the target provides at least some
    3337              :          C99 functions.  This should result in the best user experience for
    3338              :          not full C99 targets.
    3339              :          As scalar float conversions with same mode are useless in GIMPLE,
    3340              :          we can end up e.g. with _Float32 argument passed to float builtin,
    3341              :          try to get the type from the builtin prototype first.  */
    3342          223 :       tree fallback_fndecl = NULL_TREE;
    3343          223 :       if (tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
    3344          223 :         fallback_fndecl
    3345          223 :           = mathfn_built_in_1 (TREE_VALUE (argtypes),
    3346              :                                as_combined_fn (fallback_fn), 0);
    3347          223 :       if (fallback_fndecl == NULL_TREE)
    3348            0 :         fallback_fndecl
    3349            0 :           = mathfn_built_in_1 (TREE_TYPE (arg),
    3350              :                                as_combined_fn (fallback_fn), 0);
    3351            0 :       if (fallback_fndecl)
    3352              :         {
    3353          223 :           exp = build_call_nofold_loc (EXPR_LOCATION (exp),
    3354              :                                        fallback_fndecl, 1, arg);
    3355              : 
    3356          223 :           target = expand_call (exp, NULL_RTX, target == const0_rtx);
    3357          223 :           target = maybe_emit_group_store (target, TREE_TYPE (exp));
    3358          223 :           return convert_to_mode (mode, target, 0);
    3359              :         }
    3360              :     }
    3361              : 
    3362           14 :   return expand_call (exp, target, target == const0_rtx);
    3363              : }
    3364              : 
    3365              : /* Expand a call to the powi built-in mathematical function.  Return NULL_RTX if
    3366              :    a normal call should be emitted rather than expanding the function
    3367              :    in-line.  EXP is the expression that is a call to the builtin
    3368              :    function; if convenient, the result should be placed in TARGET.  */
    3369              : 
    3370              : static rtx
    3371          292 : expand_builtin_powi (tree exp, rtx target)
    3372              : {
    3373          292 :   tree arg0, arg1;
    3374          292 :   rtx op0, op1;
    3375          292 :   machine_mode mode;
    3376          292 :   machine_mode mode2;
    3377              : 
    3378          292 :   if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
    3379              :     return NULL_RTX;
    3380              : 
    3381          292 :   arg0 = CALL_EXPR_ARG (exp, 0);
    3382          292 :   arg1 = CALL_EXPR_ARG (exp, 1);
    3383          292 :   mode = TYPE_MODE (TREE_TYPE (exp));
    3384              : 
    3385              :   /* Emit a libcall to libgcc.  */
    3386              : 
    3387              :   /* Mode of the 2nd argument must match that of an int.  */
    3388          292 :   mode2 = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
    3389              : 
    3390          292 :   if (target == NULL_RTX)
    3391            0 :     target = gen_reg_rtx (mode);
    3392              : 
    3393          292 :   op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    3394          292 :   if (GET_MODE (op0) != mode)
    3395            0 :     op0 = convert_to_mode (mode, op0, 0);
    3396          292 :   op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
    3397          292 :   if (GET_MODE (op1) != mode2)
    3398           52 :     op1 = convert_to_mode (mode2, op1, 0);
    3399              : 
    3400          292 :   target = emit_library_call_value (optab_libfunc (powi_optab, mode),
    3401              :                                     target, LCT_CONST, mode,
    3402              :                                     op0, mode, op1, mode2);
    3403              : 
    3404          292 :   return target;
    3405              : }
    3406              : 
    3407              : /* Expand expression EXP which is a call to the strlen builtin.  Return
    3408              :    NULL_RTX if we failed and the caller should emit a normal call, otherwise
    3409              :    try to get the result in TARGET, if convenient.  */
    3410              : 
    3411              : static rtx
    3412        14617 : expand_builtin_strlen (tree exp, rtx target,
    3413              :                        machine_mode target_mode)
    3414              : {
    3415        14617 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    3416              :     return NULL_RTX;
    3417              : 
    3418        14598 :   tree src = CALL_EXPR_ARG (exp, 0);
    3419              : 
    3420              :   /* If the length can be computed at compile-time, return it.  */
    3421        14598 :   if (tree len = c_strlen (src, 0))
    3422          141 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3423              : 
    3424              :   /* If the length can be computed at compile-time and is constant
    3425              :      integer, but there are side-effects in src, evaluate
    3426              :      src for side-effects, then return len.
    3427              :      E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
    3428              :      can be optimized into: i++; x = 3;  */
    3429        14457 :   tree len = c_strlen (src, 1);
    3430        14457 :   if (len && TREE_CODE (len) == INTEGER_CST)
    3431              :     {
    3432            0 :       expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
    3433            0 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3434              :     }
    3435              : 
    3436        14457 :   unsigned int align = get_pointer_alignment (src) / BITS_PER_UNIT;
    3437              : 
    3438              :   /* If SRC is not a pointer type, don't do this operation inline.  */
    3439        14457 :   if (align == 0)
    3440              :     return NULL_RTX;
    3441              : 
    3442              :   /* Bail out if we can't compute strlen in the right mode.  */
    3443              :   machine_mode insn_mode;
    3444              :   enum insn_code icode = CODE_FOR_nothing;
    3445        14457 :   FOR_EACH_MODE_FROM (insn_mode, target_mode)
    3446              :     {
    3447        14457 :       icode = optab_handler (strlen_optab, insn_mode);
    3448        14457 :       if (icode != CODE_FOR_nothing)
    3449              :         break;
    3450              :     }
    3451        14457 :   if (insn_mode == VOIDmode)
    3452              :     return NULL_RTX;
    3453              : 
    3454              :   /* Make a place to hold the source address.  We will not expand
    3455              :      the actual source until we are sure that the expansion will
    3456              :      not fail -- there are trees that cannot be expanded twice.  */
    3457        15074 :   rtx src_reg = gen_reg_rtx (Pmode);
    3458              : 
    3459              :   /* Mark the beginning of the strlen sequence so we can emit the
    3460              :      source operand later.  */
    3461        14457 :   rtx_insn *before_strlen = get_last_insn ();
    3462              : 
    3463        14457 :   class expand_operand ops[4];
    3464        14457 :   create_output_operand (&ops[0], target, insn_mode);
    3465        14457 :   create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
    3466        14457 :   create_integer_operand (&ops[2], 0);
    3467        14457 :   create_integer_operand (&ops[3], align);
    3468        14457 :   if (!maybe_expand_insn (icode, 4, ops))
    3469              :     return NULL_RTX;
    3470              : 
    3471              :   /* Check to see if the argument was declared attribute nonstring
    3472              :      and if so, issue a warning since at this point it's not known
    3473              :      to be nul-terminated.  */
    3474           11 :   maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    3475              : 
    3476              :   /* Now that we are assured of success, expand the source.  */
    3477           11 :   start_sequence ();
    3478           15 :   rtx pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
    3479           11 :   if (pat != src_reg)
    3480              :     {
    3481              : #ifdef POINTERS_EXTEND_UNSIGNED
    3482           15 :       if (GET_MODE (pat) != Pmode)
    3483            0 :         pat = convert_to_mode (Pmode, pat,
    3484              :                                POINTERS_EXTEND_UNSIGNED);
    3485              : #endif
    3486           11 :       emit_move_insn (src_reg, pat);
    3487              :     }
    3488           11 :   pat = end_sequence ();
    3489              : 
    3490           11 :   if (before_strlen)
    3491           11 :     emit_insn_after (pat, before_strlen);
    3492              :   else
    3493            0 :     emit_insn_before (pat, get_insns ());
    3494              : 
    3495              :   /* Return the value in the proper mode for this function.  */
    3496           11 :   if (GET_MODE (ops[0].value) == target_mode)
    3497              :     target = ops[0].value;
    3498            0 :   else if (target != 0)
    3499            0 :     convert_move (target, ops[0].value, 0);
    3500              :   else
    3501            0 :     target = convert_to_mode (target_mode, ops[0].value, 0);
    3502              : 
    3503              :   return target;
    3504              : }
    3505              : 
    3506              : /* Expand call EXP to the strnlen built-in, returning the result
    3507              :    and setting it in TARGET.  Otherwise return NULL_RTX on failure.  */
    3508              : 
    3509              : static rtx
    3510          580 : expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
    3511              : {
    3512          580 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3513              :     return NULL_RTX;
    3514              : 
    3515          571 :   tree src = CALL_EXPR_ARG (exp, 0);
    3516          571 :   tree bound = CALL_EXPR_ARG (exp, 1);
    3517              : 
    3518          571 :   if (!bound)
    3519              :     return NULL_RTX;
    3520              : 
    3521          571 :   location_t loc = UNKNOWN_LOCATION;
    3522          571 :   if (EXPR_HAS_LOCATION (exp))
    3523          571 :     loc = EXPR_LOCATION (exp);
    3524              : 
    3525              :   /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
    3526              :      so these conversions aren't necessary.  */
    3527          571 :   c_strlen_data lendata = { };
    3528          571 :   tree len = c_strlen (src, 0, &lendata, 1);
    3529          571 :   if (len)
    3530           63 :     len = fold_convert_loc (loc, TREE_TYPE (bound), len);
    3531              : 
    3532          571 :   if (TREE_CODE (bound) == INTEGER_CST)
    3533              :     {
    3534          304 :       if (!len)
    3535              :         return NULL_RTX;
    3536              : 
    3537           23 :       len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
    3538           23 :       return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3539              :     }
    3540              : 
    3541          267 :   if (TREE_CODE (bound) != SSA_NAME)
    3542              :     return NULL_RTX;
    3543              : 
    3544          267 :   wide_int min, max;
    3545          267 :   int_range_max r;
    3546          534 :   get_range_query (cfun)->range_of_expr (r, bound,
    3547              :                                          currently_expanding_gimple_stmt);
    3548          267 :   if (r.varying_p () || r.undefined_p ())
    3549              :     return NULL_RTX;
    3550          152 :   min = r.lower_bound ();
    3551          152 :   max = r.upper_bound ();
    3552              : 
    3553          152 :   if (!len || TREE_CODE (len) != INTEGER_CST)
    3554              :     {
    3555          115 :       bool exact;
    3556          115 :       lendata.decl = unterminated_array (src, &len, &exact);
    3557          115 :       if (!lendata.decl)
    3558           95 :         return NULL_RTX;
    3559              :     }
    3560              : 
    3561           57 :   if (lendata.decl)
    3562              :     return NULL_RTX;
    3563              : 
    3564           37 :   if (wi::gtu_p (min, wi::to_wide (len)))
    3565            7 :     return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3566              : 
    3567           30 :   len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, bound);
    3568           30 :   return expand_expr (len, target, target_mode, EXPAND_NORMAL);
    3569          267 : }
    3570              : 
    3571              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    3572              :    bytes from bytes at DATA + OFFSET and return it reinterpreted as
    3573              :    a target constant.  */
    3574              : 
    3575              : static rtx
    3576       171903 : builtin_memcpy_read_str (void *data, void *, HOST_WIDE_INT offset,
    3577              :                          fixed_size_mode mode)
    3578              : {
    3579              :   /* The REPresentation pointed to by DATA need not be a nul-terminated
    3580              :      string but the caller guarantees it's large enough for MODE.  */
    3581       171903 :   const char *rep = (const char *) data;
    3582              : 
    3583       171903 :   return c_readstr (rep + offset, mode, /*nul_terminated=*/false);
    3584              : }
    3585              : 
    3586              : /* LEN specify length of the block of memcpy/memset operation.
    3587              :    Figure out its range and put it into MIN_SIZE/MAX_SIZE.
    3588              :    In some cases we can make very likely guess on max size, then we
    3589              :    set it into PROBABLE_MAX_SIZE.  */
    3590              : 
    3591              : static void
    3592       190323 : determine_block_size (tree len, rtx &len_rtx,
    3593              :                       unsigned HOST_WIDE_INT *min_size,
    3594              :                       unsigned HOST_WIDE_INT *max_size,
    3595              :                       unsigned HOST_WIDE_INT *probable_max_size)
    3596              : {
    3597       190323 :   if (CONST_INT_P (len_rtx))
    3598              :     {
    3599        96062 :       *min_size = *max_size = *probable_max_size = UINTVAL (len_rtx);
    3600        96062 :       return;
    3601              :     }
    3602              :   else
    3603              :     {
    3604        94261 :       wide_int min, max;
    3605        94261 :       enum value_range_kind range_type = VR_UNDEFINED;
    3606              : 
    3607              :       /* Determine bounds from the type.  */
    3608        94261 :       if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
    3609        94260 :         *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
    3610              :       else
    3611              :         *min_size = 0;
    3612        94261 :       if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
    3613        94261 :         *probable_max_size = *max_size
    3614        94261 :           = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
    3615              :       else
    3616            0 :         *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
    3617              : 
    3618        94261 :       if (TREE_CODE (len) == SSA_NAME)
    3619              :         {
    3620        94261 :           int_range_max r;
    3621        94261 :           tree tmin, tmax;
    3622        94261 :           gimple *cg = currently_expanding_gimple_stmt;
    3623       188522 :           get_range_query (cfun)->range_of_expr (r, len, cg);
    3624        94261 :           range_type = get_legacy_range (r, tmin, tmax);
    3625        94261 :           if (range_type != VR_UNDEFINED)
    3626              :             {
    3627        94259 :               min = wi::to_wide (tmin);
    3628        94259 :               max = wi::to_wide (tmax);
    3629              :             }
    3630        94261 :         }
    3631        94261 :       if (range_type == VR_RANGE)
    3632              :         {
    3633        67961 :           if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
    3634        55329 :             *min_size = min.to_uhwi ();
    3635        67961 :           if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
    3636        61369 :             *probable_max_size = *max_size = max.to_uhwi ();
    3637              :         }
    3638        26300 :       else if (range_type == VR_ANTI_RANGE)
    3639              :         {
    3640              :           /* Code like
    3641              : 
    3642              :              int n;
    3643              :              if (n < 100)
    3644              :                memcpy (a, b, n)
    3645              : 
    3646              :              Produce anti range allowing negative values of N.  We still
    3647              :              can use the information and make a guess that N is not negative.
    3648              :              */
    3649         3066 :           if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
    3650         2928 :             *probable_max_size = min.to_uhwi () - 1;
    3651              :         }
    3652        94261 :     }
    3653              : 
    3654        94261 :   if (*min_size == *max_size)
    3655           11 :     len_rtx = GEN_INT (*min_size);
    3656              :   else
    3657        94250 :     gcc_checking_assert (*max_size <=
    3658              :                          (unsigned HOST_WIDE_INT)
    3659              :                          GET_MODE_MASK (GET_MODE (len_rtx)));
    3660              : }
    3661              : 
    3662              : /* Expand a call EXP to the memcpy builtin.
    3663              :    Return NULL_RTX if we failed, the caller should emit a normal call,
    3664              :    otherwise try to get the result in TARGET, if convenient (and in
    3665              :    mode MODE if that's convenient).  */
    3666              : 
    3667              : static rtx
    3668       108828 : expand_builtin_memcpy (tree exp, rtx target)
    3669              : {
    3670       108828 :   if (!validate_arglist (exp,
    3671              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3672              :     return NULL_RTX;
    3673              : 
    3674       108810 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3675       108810 :   tree src = CALL_EXPR_ARG (exp, 1);
    3676       108810 :   tree len = CALL_EXPR_ARG (exp, 2);
    3677              : 
    3678       108810 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    3679       108810 :                                           /*retmode=*/ RETURN_BEGIN, false);
    3680              : }
    3681              : 
    3682              : /* Check a call EXP to the memmove built-in for validity.
    3683              :    Return NULL_RTX on both success and failure.  */
    3684              : 
    3685              : static rtx
    3686        17563 : expand_builtin_memmove (tree exp, rtx target)
    3687              : {
    3688        17563 :   if (!validate_arglist (exp,
    3689              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3690              :     return NULL_RTX;
    3691              : 
    3692        17548 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3693        17548 :   tree src = CALL_EXPR_ARG (exp, 1);
    3694        17548 :   tree len = CALL_EXPR_ARG (exp, 2);
    3695              : 
    3696        17548 :   return expand_builtin_memory_copy_args (dest, src, len, target, exp,
    3697        17548 :                                           /*retmode=*/ RETURN_BEGIN, true);
    3698              : }
    3699              : 
    3700              : /* Expand a call EXP to the mempcpy builtin.
    3701              :    Return NULL_RTX if we failed; the caller should emit a normal call,
    3702              :    otherwise try to get the result in TARGET, if convenient (and in
    3703              :    mode MODE if that's convenient).  */
    3704              : 
    3705              : static rtx
    3706         1394 : expand_builtin_mempcpy (tree exp, rtx target)
    3707              : {
    3708         1394 :   if (!validate_arglist (exp,
    3709              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    3710              :     return NULL_RTX;
    3711              : 
    3712         1389 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3713         1389 :   tree src = CALL_EXPR_ARG (exp, 1);
    3714         1389 :   tree len = CALL_EXPR_ARG (exp, 2);
    3715              : 
    3716              :   /* Policy does not generally allow using compute_objsize (which
    3717              :      is used internally by check_memop_size) to change code generation
    3718              :      or drive optimization decisions.
    3719              : 
    3720              :      In this instance it is safe because the code we generate has
    3721              :      the same semantics regardless of the return value of
    3722              :      check_memop_sizes.   Exactly the same amount of data is copied
    3723              :      and the return value is exactly the same in both cases.
    3724              : 
    3725              :      Furthermore, check_memop_size always uses mode 0 for the call to
    3726              :      compute_objsize, so the imprecise nature of compute_objsize is
    3727              :      avoided.  */
    3728              : 
    3729              :   /* Avoid expanding mempcpy into memcpy when the call is determined
    3730              :      to overflow the buffer.  This also prevents the same overflow
    3731              :      from being diagnosed again when expanding memcpy.  */
    3732              : 
    3733         1389 :   return expand_builtin_mempcpy_args (dest, src, len,
    3734         1389 :                                       target, exp, /*retmode=*/ RETURN_END);
    3735              : }
    3736              : 
    3737              : /* Helper function to do the actual work for expand of memory copy family
    3738              :    functions (memcpy, mempcpy, stpcpy).  Expansing should assign LEN bytes
    3739              :    of memory from SRC to DEST and assign to TARGET if convenient.  Return
    3740              :    value is based on RETMODE argument.  */
    3741              : 
    3742              : static rtx
    3743       127770 : expand_builtin_memory_copy_args (tree dest, tree src, tree len,
    3744              :                                  rtx target, tree exp, memop_ret retmode,
    3745              :                                  bool might_overlap)
    3746              : {
    3747       127770 :   unsigned int src_align = get_pointer_alignment (src);
    3748       127770 :   unsigned int dest_align = get_pointer_alignment (dest);
    3749       127770 :   rtx dest_mem, src_mem, dest_addr, len_rtx;
    3750       127770 :   HOST_WIDE_INT expected_size = -1;
    3751       127770 :   unsigned int expected_align = 0;
    3752       127770 :   unsigned HOST_WIDE_INT min_size;
    3753       127770 :   unsigned HOST_WIDE_INT max_size;
    3754       127770 :   unsigned HOST_WIDE_INT probable_max_size;
    3755              : 
    3756       127770 :   bool is_move_done;
    3757              : 
    3758              :   /* If DEST is not a pointer type, call the normal function.  */
    3759       127770 :   if (dest_align == 0)
    3760              :     return NULL_RTX;
    3761              : 
    3762              :   /* If either SRC is not a pointer type, don't do this
    3763              :      operation in-line.  */
    3764       127770 :   if (src_align == 0)
    3765              :     return NULL_RTX;
    3766              : 
    3767       127770 :   if (currently_expanding_gimple_stmt)
    3768       127770 :     stringop_block_profile (currently_expanding_gimple_stmt,
    3769              :                             &expected_align, &expected_size);
    3770              : 
    3771       127770 :   if (expected_align < dest_align)
    3772       127748 :     expected_align = dest_align;
    3773       127770 :   dest_mem = get_memory_rtx (dest, len, true);
    3774       127770 :   set_mem_align (dest_mem, dest_align);
    3775       127770 :   len_rtx = expand_normal (len);
    3776       127770 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    3777              :                         &probable_max_size);
    3778              : 
    3779              :   /* Try to get the byte representation of the constant SRC points to,
    3780              :      with its byte size in NBYTES.  */
    3781       127770 :   unsigned HOST_WIDE_INT nbytes;
    3782       127770 :   const char *rep = getbyterep (src, &nbytes);
    3783              : 
    3784              :   /* If the function's constant bound LEN_RTX is less than or equal
    3785              :      to the byte size of the representation of the constant argument,
    3786              :      and if block move would be done by pieces, we can avoid loading
    3787              :      the bytes from memory and only store the computed constant.
    3788              :      This works in the overlap (memmove) case as well because
    3789              :      store_by_pieces just generates a series of stores of constants
    3790              :      from the representation returned by getbyterep().  */
    3791       127770 :   if (rep
    3792        31264 :       && CONST_INT_P (len_rtx)
    3793        29610 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes
    3794       157114 :       && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
    3795              :                               const_cast<char *> (rep),
    3796              :                               dest_align, false))
    3797              :     {
    3798        28865 :       dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
    3799              :                                   builtin_memcpy_read_str,
    3800              :                                   const_cast<char *> (rep),
    3801              :                                   dest_align, false, retmode);
    3802        28865 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    3803        28865 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    3804        28865 :       return dest_mem;
    3805              :     }
    3806              : 
    3807        98905 :   src_mem = get_memory_rtx (src, len, false);
    3808        98905 :   set_mem_align (src_mem, src_align);
    3809              : 
    3810              :   /* Copy word part most expediently.  */
    3811        98905 :   enum block_op_methods method = BLOCK_OP_NORMAL;
    3812        98905 :   if (CALL_EXPR_TAILCALL (exp)
    3813        98905 :       && (retmode == RETURN_BEGIN || target == const0_rtx))
    3814              :     method = BLOCK_OP_TAILCALL;
    3815        98905 :   bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
    3816        98905 :                            && retmode == RETURN_END
    3817        98905 :                            && !might_overlap
    3818        99979 :                            && target != const0_rtx);
    3819              :   if (use_mempcpy_call)
    3820        98905 :     method = BLOCK_OP_NO_LIBCALL_RET;
    3821        98905 :   dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
    3822              :                                      expected_align, expected_size,
    3823              :                                      min_size, max_size, probable_max_size,
    3824              :                                      use_mempcpy_call, &is_move_done,
    3825              :                                      might_overlap, tree_ctz (len));
    3826              : 
    3827              :   /* Bail out when a mempcpy call would be expanded as libcall and when
    3828              :      we have a target that provides a fast implementation
    3829              :      of mempcpy routine.  */
    3830        98905 :   if (!is_move_done)
    3831              :     return NULL_RTX;
    3832              : 
    3833        85831 :   if (dest_addr == pc_rtx)
    3834              :     return NULL_RTX;
    3835              : 
    3836        85831 :   if (dest_addr == 0)
    3837              :     {
    3838        33008 :       dest_addr = force_operand (XEXP (dest_mem, 0), target);
    3839        33008 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    3840              :     }
    3841              : 
    3842        85831 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    3843              :     {
    3844          815 :       dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
    3845              :       /* stpcpy pointer to last byte.  */
    3846          815 :       if (retmode == RETURN_END_MINUS_ONE)
    3847            0 :         dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
    3848              :     }
    3849              : 
    3850              :   return dest_addr;
    3851              : }
    3852              : 
    3853              : static rtx
    3854         1412 : expand_builtin_mempcpy_args (tree dest, tree src, tree len,
    3855              :                              rtx target, tree orig_exp, memop_ret retmode)
    3856              : {
    3857         1389 :   return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
    3858            0 :                                           retmode, false);
    3859              : }
    3860              : 
    3861              : /* Expand into a movstr instruction, if one is available.  Return NULL_RTX if
    3862              :    we failed, the caller should emit a normal call, otherwise try to
    3863              :    get the result in TARGET, if convenient.
    3864              :    Return value is based on RETMODE argument.  */
    3865              : 
    3866              : static rtx
    3867         2267 : expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
    3868              : {
    3869         2267 :   class expand_operand ops[3];
    3870         2267 :   rtx dest_mem;
    3871         2267 :   rtx src_mem;
    3872              : 
    3873         2267 :   if (!targetm.have_movstr ())
    3874              :     return NULL_RTX;
    3875              : 
    3876            0 :   dest_mem = get_memory_rtx (dest, NULL, true);
    3877            0 :   src_mem = get_memory_rtx (src, NULL, false);
    3878            0 :   if (retmode == RETURN_BEGIN)
    3879              :     {
    3880            0 :       target = force_reg (Pmode, XEXP (dest_mem, 0));
    3881            0 :       dest_mem = replace_equiv_address (dest_mem, target);
    3882              :     }
    3883              : 
    3884            0 :   create_output_operand (&ops[0],
    3885            0 :                          retmode != RETURN_BEGIN ? target : NULL_RTX, Pmode);
    3886            0 :   create_fixed_operand (&ops[1], dest_mem);
    3887            0 :   create_fixed_operand (&ops[2], src_mem);
    3888            0 :   if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
    3889              :     return NULL_RTX;
    3890              : 
    3891            0 :   if (retmode != RETURN_BEGIN && target != const0_rtx)
    3892              :     {
    3893            0 :       target = ops[0].value;
    3894              :       /* movstr is supposed to set end to the address of the NUL
    3895              :          terminator.  If the caller requested a mempcpy-like return value,
    3896              :          adjust it.  */
    3897            0 :       if (retmode == RETURN_END)
    3898              :         {
    3899            0 :           rtx tem = plus_constant (GET_MODE (target),
    3900            0 :                                    gen_lowpart (GET_MODE (target), target), 1);
    3901            0 :           emit_move_insn (target, force_operand (tem, NULL_RTX));
    3902              :         }
    3903              :     }
    3904              :   return target;
    3905              : }
    3906              : 
    3907              : /* Expand expression EXP, which is a call to the strcpy builtin.  Return
    3908              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    3909              :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    3910              :    convenient).  */
    3911              : 
    3912              : static rtx
    3913         1860 : expand_builtin_strcpy (tree exp, rtx target)
    3914              : {
    3915         1860 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    3916              :     return NULL_RTX;
    3917              : 
    3918         1845 :   tree dest = CALL_EXPR_ARG (exp, 0);
    3919         1845 :   tree src = CALL_EXPR_ARG (exp, 1);
    3920              : 
    3921         1845 :   return expand_builtin_strcpy_args (exp, dest, src, target);
    3922              : }
    3923              : 
    3924              : /* Helper function to do the actual work for expand_builtin_strcpy.  The
    3925              :    arguments to the builtin_strcpy call DEST and SRC are broken out
    3926              :    so that this can also be called without constructing an actual CALL_EXPR.
    3927              :    The other arguments and return value are the same as for
    3928              :    expand_builtin_strcpy.  */
    3929              : 
    3930              : static rtx
    3931         1845 : expand_builtin_strcpy_args (tree, tree dest, tree src, rtx target)
    3932              : {
    3933         1845 :   return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
    3934              : }
    3935              : 
    3936              : /* Expand a call EXP to the stpcpy builtin.
    3937              :    Return NULL_RTX if we failed the caller should emit a normal call,
    3938              :    otherwise try to get the result in TARGET, if convenient (and in
    3939              :    mode MODE if that's convenient).  */
    3940              : 
    3941              : static rtx
    3942          454 : expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
    3943              : {
    3944          454 :   tree dst, src;
    3945          454 :   location_t loc = EXPR_LOCATION (exp);
    3946              : 
    3947          454 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    3948              :     return NULL_RTX;
    3949              : 
    3950          445 :   dst = CALL_EXPR_ARG (exp, 0);
    3951          445 :   src = CALL_EXPR_ARG (exp, 1);
    3952              : 
    3953              :   /* If return value is ignored, transform stpcpy into strcpy.  */
    3954          445 :   if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
    3955              :     {
    3956            0 :       tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
    3957            0 :       tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
    3958            0 :       return expand_expr (result, target, mode, EXPAND_NORMAL);
    3959              :     }
    3960              :   else
    3961              :     {
    3962          445 :       tree len, lenp1;
    3963          445 :       rtx ret;
    3964              : 
    3965              :       /* Ensure we get an actual string whose length can be evaluated at
    3966              :          compile-time, not an expression containing a string.  This is
    3967              :          because the latter will potentially produce pessimized code
    3968              :          when used to produce the return value.  */
    3969          445 :       c_strlen_data lendata = { };
    3970          445 :       if (!c_getstr (src)
    3971          445 :           || !(len = c_strlen (src, 0, &lendata, 1)))
    3972          422 :         return expand_movstr (dst, src, target,
    3973          422 :                               /*retmode=*/ RETURN_END_MINUS_ONE);
    3974              : 
    3975           23 :       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
    3976           23 :       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
    3977              :                                          target, exp,
    3978              :                                          /*retmode=*/ RETURN_END_MINUS_ONE);
    3979              : 
    3980           23 :       if (ret)
    3981              :         return ret;
    3982              : 
    3983            0 :       if (TREE_CODE (len) == INTEGER_CST)
    3984              :         {
    3985            0 :           rtx len_rtx = expand_normal (len);
    3986              : 
    3987            0 :           if (CONST_INT_P (len_rtx))
    3988              :             {
    3989            0 :               ret = expand_builtin_strcpy_args (exp, dst, src, target);
    3990              : 
    3991            0 :               if (ret)
    3992              :                 {
    3993            0 :                   if (! target)
    3994              :                     {
    3995            0 :                       if (mode != VOIDmode)
    3996            0 :                         target = gen_reg_rtx (mode);
    3997              :                       else
    3998            0 :                         target = gen_reg_rtx (GET_MODE (ret));
    3999              :                     }
    4000            0 :                   if (GET_MODE (target) != GET_MODE (ret))
    4001            0 :                     ret = gen_lowpart (GET_MODE (target), ret);
    4002              : 
    4003            0 :                   ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
    4004            0 :                   ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
    4005            0 :                   gcc_assert (ret);
    4006              : 
    4007              :                   return target;
    4008              :                 }
    4009              :             }
    4010              :         }
    4011              : 
    4012            0 :       return expand_movstr (dst, src, target,
    4013            0 :                             /*retmode=*/ RETURN_END_MINUS_ONE);
    4014              :     }
    4015              : }
    4016              : 
    4017              : /* Expand a call EXP to the stpcpy builtin and diagnose uses of nonstring
    4018              :    arguments while being careful to avoid duplicate warnings (which could
    4019              :    be issued if the expander were to expand the call, resulting in it
    4020              :    being emitted in expand_call().  */
    4021              : 
    4022              : static rtx
    4023          454 : expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
    4024              : {
    4025          454 :   if (rtx ret = expand_builtin_stpcpy_1 (exp, target, mode))
    4026              :     {
    4027              :       /* The call has been successfully expanded.  Check for nonstring
    4028              :          arguments and issue warnings as appropriate.  */
    4029           23 :       maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp);
    4030           23 :       return ret;
    4031              :     }
    4032              : 
    4033              :   return NULL_RTX;
    4034              : }
    4035              : 
    4036              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4037              :    bytes from constant string DATA + OFFSET and return it as target
    4038              :    constant.  */
    4039              : 
    4040              : rtx
    4041         9867 : builtin_strncpy_read_str (void *data, void *, HOST_WIDE_INT offset,
    4042              :                           fixed_size_mode mode)
    4043              : {
    4044         9867 :   const char *str = (const char *) data;
    4045              : 
    4046         9867 :   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
    4047          260 :     return const0_rtx;
    4048              : 
    4049         9607 :   return c_readstr (str + offset, mode);
    4050              : }
    4051              : 
    4052              : /* Helper to check the sizes of sequences and the destination of calls
    4053              :    to __builtin_strncat and __builtin___strncat_chk.  Returns true on
    4054              :    success (no overflow or invalid sizes), false otherwise.  */
    4055              : 
    4056              : static bool
    4057          108 : check_strncat_sizes (tree exp, tree objsize)
    4058              : {
    4059          108 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4060          108 :   tree src = CALL_EXPR_ARG (exp, 1);
    4061          108 :   tree maxread = CALL_EXPR_ARG (exp, 2);
    4062              : 
    4063              :   /* Try to determine the range of lengths that the source expression
    4064              :      refers to.  */
    4065          108 :   c_strlen_data lendata = { };
    4066          108 :   get_range_strlen (src, &lendata, /* eltsize = */ 1);
    4067              : 
    4068              :   /* Try to verify that the destination is big enough for the shortest
    4069              :      string.  */
    4070              : 
    4071          108 :   access_data data (nullptr, exp, access_read_write, maxread, true);
    4072          108 :   if (!objsize && warn_stringop_overflow)
    4073              :     {
    4074              :       /* If it hasn't been provided by __strncat_chk, try to determine
    4075              :          the size of the destination object into which the source is
    4076              :          being copied.  */
    4077            0 :       objsize = compute_objsize (dest, warn_stringop_overflow - 1, &data.dst);
    4078              :     }
    4079              : 
    4080              :   /* Add one for the terminating nul.  */
    4081          108 :   tree srclen = (lendata.minlen
    4082          108 :                  ? fold_build2 (PLUS_EXPR, size_type_node, lendata.minlen,
    4083              :                                 size_one_node)
    4084              :                  : NULL_TREE);
    4085              : 
    4086              :   /* The strncat function copies at most MAXREAD bytes and always appends
    4087              :      the terminating nul so the specified upper bound should never be equal
    4088              :      to (or greater than) the size of the destination.  */
    4089           55 :   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
    4090          155 :       && tree_int_cst_equal (objsize, maxread))
    4091              :     {
    4092           23 :       location_t loc = EXPR_LOCATION (exp);
    4093           23 :       warning_at (loc, OPT_Wstringop_overflow_,
    4094              :                   "%qD specified bound %E equals destination size",
    4095              :                   get_callee_fndecl (exp), maxread);
    4096              : 
    4097           23 :       return false;
    4098              :     }
    4099              : 
    4100           85 :   if (!srclen
    4101           85 :       || (maxread && tree_fits_uhwi_p (maxread)
    4102           32 :           && tree_fits_uhwi_p (srclen)
    4103           32 :           && tree_int_cst_lt (maxread, srclen)))
    4104              :     srclen = maxread;
    4105              : 
    4106              :   /* The number of bytes to write is LEN but check_access will alsoa
    4107              :      check SRCLEN if LEN's value isn't known.  */
    4108           85 :   return check_access (exp, /*dstwrite=*/NULL_TREE, maxread, srclen,
    4109           85 :                        objsize, data.mode, &data);
    4110              : }
    4111              : 
    4112              : /* Expand expression EXP, which is a call to the strncpy builtin.  Return
    4113              :    NULL_RTX if we failed the caller should emit a normal call.  */
    4114              : 
    4115              : static rtx
    4116         2177 : expand_builtin_strncpy (tree exp, rtx target)
    4117              : {
    4118         2177 :   location_t loc = EXPR_LOCATION (exp);
    4119              : 
    4120         2177 :   if (!validate_arglist (exp,
    4121              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4122              :     return NULL_RTX;
    4123         2165 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4124         2165 :   tree src = CALL_EXPR_ARG (exp, 1);
    4125              :   /* The number of bytes to write (not the maximum).  */
    4126         2165 :   tree len = CALL_EXPR_ARG (exp, 2);
    4127              : 
    4128              :   /* The length of the source sequence.  */
    4129         2165 :   tree slen = c_strlen (src, 1);
    4130              : 
    4131              :   /* We must be passed a constant len and src parameter.  */
    4132         2165 :   if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
    4133              :     return NULL_RTX;
    4134              : 
    4135          237 :   slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
    4136              : 
    4137              :   /* We're required to pad with trailing zeros if the requested
    4138              :      len is greater than strlen(s2)+1.  In that case try to
    4139              :      use store_by_pieces, if it fails, punt.  */
    4140          237 :   if (tree_int_cst_lt (slen, len))
    4141              :     {
    4142          142 :       unsigned int dest_align = get_pointer_alignment (dest);
    4143          142 :       const char *p = c_getstr (src);
    4144          142 :       rtx dest_mem;
    4145              : 
    4146          136 :       if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
    4147          278 :           || !can_store_by_pieces (tree_to_uhwi (len),
    4148              :                                    builtin_strncpy_read_str,
    4149              :                                    const_cast<char *> (p),
    4150              :                                    dest_align, false))
    4151              :         return NULL_RTX;
    4152              : 
    4153          128 :       dest_mem = get_memory_rtx (dest, len, true);
    4154          128 :       store_by_pieces (dest_mem, tree_to_uhwi (len),
    4155              :                        builtin_strncpy_read_str,
    4156              :                        const_cast<char *> (p), dest_align, false,
    4157              :                        RETURN_BEGIN);
    4158          128 :       dest_mem = force_operand (XEXP (dest_mem, 0), target);
    4159          128 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4160          128 :       return dest_mem;
    4161              :     }
    4162              : 
    4163              :   return NULL_RTX;
    4164              : }
    4165              : 
    4166              : /* Return the RTL of a register in MODE generated from PREV in the
    4167              :    previous iteration.  */
    4168              : 
    4169              : static rtx
    4170       251353 : gen_memset_value_from_prev (by_pieces_prev *prev, fixed_size_mode mode)
    4171              : {
    4172       251353 :   rtx target = nullptr;
    4173       251353 :   if (prev != nullptr && prev->data != nullptr)
    4174              :     {
    4175              :       /* Use the previous data in the same mode.  */
    4176       139172 :       if (prev->mode == mode)
    4177       251353 :         return prev->data;
    4178              : 
    4179        32442 :       fixed_size_mode prev_mode = prev->mode;
    4180              : 
    4181              :       /* Don't use the previous data to write QImode if it is in a
    4182              :          vector mode.  */
    4183        32442 :       if (VECTOR_MODE_P (prev_mode) && mode == QImode)
    4184              :         return target;
    4185              : 
    4186        32043 :       rtx prev_rtx = prev->data;
    4187              : 
    4188        32043 :       if (REG_P (prev_rtx)
    4189        23662 :           && HARD_REGISTER_P (prev_rtx)
    4190        32043 :           && lowpart_subreg_regno (REGNO (prev_rtx), prev_mode, mode) < 0)
    4191              :         {
    4192              :           /* This case occurs when PREV_MODE is a vector and when
    4193              :              MODE is too small to store using vector operations.
    4194              :              After register allocation, the code will need to move the
    4195              :              lowpart of the vector register into a non-vector register.
    4196              : 
    4197              :              Also, the target has chosen to use a hard register
    4198              :              instead of going with the default choice of using a
    4199              :              pseudo register.  We should respect that choice and try to
    4200              :              avoid creating a pseudo register with the same mode as the
    4201              :              current hard register.
    4202              : 
    4203              :              In principle, we could just use a lowpart MODE subreg of
    4204              :              the vector register.  However, the vector register mode might
    4205              :              be too wide for non-vector registers, and we already know
    4206              :              that the non-vector mode is too small for vector registers.
    4207              :              It's therefore likely that we'd need to spill to memory in
    4208              :              the vector mode and reload the non-vector value from there.
    4209              : 
    4210              :              Try to avoid that by reducing the vector register to the
    4211              :              smallest size that it can hold.  This should increase the
    4212              :              chances that non-vector registers can hold both the inner
    4213              :              and outer modes of the subreg that we generate later.  */
    4214            0 :           machine_mode m;
    4215            0 :           fixed_size_mode candidate;
    4216            0 :           FOR_EACH_MODE_IN_CLASS (m, GET_MODE_CLASS (mode))
    4217            0 :             if (is_a<fixed_size_mode> (m, &candidate))
    4218              :               {
    4219            0 :                 if (GET_MODE_SIZE (candidate)
    4220            0 :                     >= GET_MODE_SIZE (prev_mode))
    4221              :                   break;
    4222            0 :                 if (GET_MODE_SIZE (candidate) >= GET_MODE_SIZE (mode)
    4223            0 :                     && lowpart_subreg_regno (REGNO (prev_rtx),
    4224              :                                              prev_mode, candidate) >= 0)
    4225              :                   {
    4226            0 :                     target = lowpart_subreg (candidate, prev_rtx,
    4227              :                                              prev_mode);
    4228            0 :                     prev_rtx = target;
    4229            0 :                     prev_mode = candidate;
    4230            0 :                     break;
    4231              :                   }
    4232              :               }
    4233            0 :           if (target == nullptr)
    4234            0 :             prev_rtx = copy_to_reg (prev_rtx);
    4235              :         }
    4236              : 
    4237        32043 :       target = lowpart_subreg (mode, prev_rtx, prev_mode);
    4238              :     }
    4239              :   return target;
    4240              : }
    4241              : 
    4242              : /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
    4243              :    bytes from constant string DATA + OFFSET and return it as target
    4244              :    constant.  If PREV isn't nullptr, it has the RTL info from the
    4245              :    previous iteration.  */
    4246              : 
    4247              : rtx
    4248       250089 : builtin_memset_read_str (void *data, void *prev,
    4249              :                          HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4250              :                          fixed_size_mode mode)
    4251              : {
    4252       250089 :   const char *c = (const char *) data;
    4253       250089 :   unsigned int size = GET_MODE_SIZE (mode);
    4254              : 
    4255       250089 :   rtx target = gen_memset_value_from_prev ((by_pieces_prev *) prev,
    4256              :                                            mode);
    4257       250089 :   if (target != nullptr)
    4258              :     return target;
    4259       111859 :   rtx src = gen_int_mode (*c, QImode);
    4260              : 
    4261       111859 :   if (VECTOR_MODE_P (mode))
    4262              :     {
    4263       161842 :       gcc_assert (GET_MODE_INNER (mode) == QImode);
    4264              : 
    4265        80921 :       rtx const_vec = gen_const_vec_duplicate (mode, src);
    4266        80921 :       if (prev == NULL)
    4267              :         /* Return CONST_VECTOR when called by a query function.  */
    4268              :         return const_vec;
    4269              : 
    4270              :       /* Use the move expander with CONST_VECTOR.  */
    4271        60102 :       target = gen_reg_rtx (mode);
    4272        60102 :       emit_move_insn (target, const_vec);
    4273        60102 :       return target;
    4274              :     }
    4275              : 
    4276        30938 :   char *p = XALLOCAVEC (char, size);
    4277              : 
    4278        30938 :   memset (p, *c, size);
    4279              : 
    4280        30938 :   return c_readstr (p, mode);
    4281              : }
    4282              : 
    4283              : /* Callback routine for store_by_pieces.  Return the RTL of a register
    4284              :    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
    4285              :    char value given in the RTL register data.  For example, if mode is
    4286              :    4 bytes wide, return the RTL for 0x01010101*data.  If PREV isn't
    4287              :    nullptr, it has the RTL info from the previous iteration.  */
    4288              : 
    4289              : static rtx
    4290         1403 : builtin_memset_gen_str (void *data, void *prev,
    4291              :                         HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    4292              :                         fixed_size_mode mode)
    4293              : {
    4294         1403 :   rtx target, coeff;
    4295         1403 :   size_t size;
    4296         1403 :   char *p;
    4297              : 
    4298         1403 :   size = GET_MODE_SIZE (mode);
    4299         1403 :   if (size == 1)
    4300              :     return (rtx) data;
    4301              : 
    4302         1264 :   target = gen_memset_value_from_prev ((by_pieces_prev *) prev, mode);
    4303         1264 :   if (target != nullptr)
    4304              :     return target;
    4305              : 
    4306          721 :   if (VECTOR_MODE_P (mode))
    4307              :     {
    4308          362 :       gcc_assert (GET_MODE_INNER (mode) == QImode);
    4309              : 
    4310              :       /* vec_duplicate_optab is a precondition to pick a vector mode for
    4311              :          the memset expander.  */
    4312          181 :       insn_code icode = optab_handler (vec_duplicate_optab, mode);
    4313              : 
    4314          181 :       target = gen_reg_rtx (mode);
    4315          181 :       class expand_operand ops[2];
    4316          181 :       create_output_operand (&ops[0], target, mode);
    4317          181 :       create_input_operand (&ops[1], (rtx) data, QImode);
    4318          181 :       expand_insn (icode, 2, ops);
    4319          181 :       if (!rtx_equal_p (target, ops[0].value))
    4320            0 :         emit_move_insn (target, ops[0].value);
    4321              : 
    4322          181 :       return target;
    4323              :     }
    4324              : 
    4325          540 :   p = XALLOCAVEC (char, size);
    4326          540 :   memset (p, 1, size);
    4327          540 :   coeff = c_readstr (p, mode);
    4328              : 
    4329          540 :   target = convert_to_mode (mode, (rtx) data, 1);
    4330          540 :   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
    4331          540 :   return force_reg (mode, target);
    4332              : }
    4333              : 
    4334              : /* Expand expression EXP, which is a call to the memset builtin.  Return
    4335              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    4336              :    try to get the result in TARGET, if convenient (and in mode MODE if that's
    4337              :    convenient).  */
    4338              : 
    4339              : rtx
    4340        62562 : expand_builtin_memset (tree exp, rtx target, machine_mode mode)
    4341              : {
    4342        62562 :   if (!validate_arglist (exp,
    4343              :                          POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4344              :     return NULL_RTX;
    4345              : 
    4346        62553 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4347        62553 :   tree val = CALL_EXPR_ARG (exp, 1);
    4348        62553 :   tree len = CALL_EXPR_ARG (exp, 2);
    4349              : 
    4350        62553 :   return expand_builtin_memset_args (dest, val, len, target, mode, exp);
    4351              : }
    4352              : 
    4353              : /* Check that store_by_pieces allows BITS + LEN (so that we don't
    4354              :    expand something too unreasonably long), and every power of 2 in
    4355              :    BITS.  It is assumed that LEN has already been tested by
    4356              :    itself.  */
    4357              : static bool
    4358        24683 : can_store_by_multiple_pieces (unsigned HOST_WIDE_INT bits,
    4359              :                               by_pieces_constfn constfun,
    4360              :                               void *constfundata, unsigned int align,
    4361              :                               bool memsetp,
    4362              :                               unsigned HOST_WIDE_INT len)
    4363              : {
    4364        24683 :   if (bits
    4365        24683 :       && !can_store_by_pieces (bits + len, constfun, constfundata,
    4366              :                                align, memsetp))
    4367              :     return false;
    4368              : 
    4369              :   /* BITS set are expected to be generally in the low range and
    4370              :      contiguous.  We do NOT want to repeat the test above in case BITS
    4371              :      has a single bit set, so we terminate the loop when BITS == BIT.
    4372              :      In the unlikely case that BITS has the MSB set, also terminate in
    4373              :      case BIT gets shifted out.  */
    4374         1122 :   for (unsigned HOST_WIDE_INT bit = 1; bit < bits && bit; bit <<= 1)
    4375              :     {
    4376          840 :       if ((bits & bit) == 0)
    4377          504 :         continue;
    4378              : 
    4379          336 :       if (!can_store_by_pieces (bit, constfun, constfundata,
    4380              :                                 align, memsetp))
    4381              :         return false;
    4382              :     }
    4383              : 
    4384              :   return true;
    4385              : }
    4386              : 
    4387              : /* Try to store VAL (or, if NULL_RTX, VALC) in LEN bytes starting at TO.
    4388              :    Return TRUE if successful, FALSE otherwise.  TO is assumed to be
    4389              :    aligned at an ALIGN-bits boundary.  LEN must be a multiple of
    4390              :    1<<CTZ_LEN between MIN_LEN and MAX_LEN.
    4391              : 
    4392              :    The strategy is to issue one store_by_pieces for each power of two,
    4393              :    from most to least significant, guarded by a test on whether there
    4394              :    are at least that many bytes left to copy in LEN.
    4395              : 
    4396              :    ??? Should we skip some powers of two in favor of loops?  Maybe start
    4397              :    at the max of TO/LEN/word alignment, at least when optimizing for
    4398              :    size, instead of ensuring O(log len) dynamic compares?  */
    4399              : 
    4400              : bool
    4401        22542 : try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len,
    4402              :                               unsigned HOST_WIDE_INT min_len,
    4403              :                               unsigned HOST_WIDE_INT max_len,
    4404              :                               rtx val, char valc, unsigned int align)
    4405              : {
    4406        22542 :   int max_bits = floor_log2 (max_len);
    4407        22542 :   int min_bits = floor_log2 (min_len);
    4408        22542 :   int sctz_len = ctz_len;
    4409              : 
    4410        22542 :   gcc_checking_assert (sctz_len >= 0);
    4411              : 
    4412        22542 :   if (val)
    4413          638 :     valc = 1;
    4414              : 
    4415              :   /* Bits more significant than TST_BITS are part of the shared prefix
    4416              :      in the binary representation of both min_len and max_len.  Since
    4417              :      they're identical, we don't need to test them in the loop.  */
    4418        22542 :   int tst_bits = (max_bits != min_bits ? max_bits
    4419        10029 :                   : floor_log2 (max_len ^ min_len));
    4420              : 
    4421              :   /* Save the pre-blksize values.  */
    4422        22542 :   int orig_max_bits = max_bits;
    4423        22542 :   int orig_tst_bits = tst_bits;
    4424              : 
    4425              :   /* Check whether it's profitable to start by storing a fixed BLKSIZE
    4426              :      bytes, to lower max_bits.  In the unlikely case of a constant LEN
    4427              :      (implied by identical MAX_LEN and MIN_LEN), we want to issue a
    4428              :      single store_by_pieces, but otherwise, select the minimum multiple
    4429              :      of the ALIGN (in bytes) and of the MCD of the possible LENs, that
    4430              :      brings MAX_LEN below TST_BITS, if that's lower than min_len.  */
    4431        22542 :   unsigned HOST_WIDE_INT blksize;
    4432        22542 :   if (max_len > min_len)
    4433              :     {
    4434        12526 :       unsigned HOST_WIDE_INT alrng = MAX (HOST_WIDE_INT_1U << ctz_len,
    4435              :                                           align / BITS_PER_UNIT);
    4436        12526 :       blksize = max_len - (HOST_WIDE_INT_1U << tst_bits) + alrng;
    4437        12526 :       blksize &= ~(alrng - 1);
    4438              :     }
    4439        10016 :   else if (max_len == min_len)
    4440              :     blksize = max_len;
    4441              :   else
    4442              :     /* Huh, max_len < min_len?  Punt.  See pr100843.c.  */
    4443              :     return false;
    4444        22541 :   if (min_len >= blksize
    4445              :       /* ??? Maybe try smaller fixed-prefix blksizes before
    4446              :          punting?  */
    4447        22541 :       && can_store_by_pieces (blksize, builtin_memset_read_str,
    4448              :                               &valc, align, true))
    4449              :     {
    4450          281 :       min_len -= blksize;
    4451          281 :       min_bits = floor_log2 (min_len);
    4452          281 :       max_len -= blksize;
    4453          281 :       max_bits = floor_log2 (max_len);
    4454              : 
    4455          281 :       tst_bits = (max_bits != min_bits ? max_bits
    4456          175 :                  : floor_log2 (max_len ^ min_len));
    4457              :     }
    4458              :   else
    4459              :     blksize = 0;
    4460              : 
    4461              :   /* Check that we can use store by pieces for the maximum store count
    4462              :      we may issue (initial fixed-size block, plus conditional
    4463              :      power-of-two-sized from max_bits to ctz_len.  */
    4464        22541 :   unsigned HOST_WIDE_INT xlenest = blksize;
    4465        22541 :   if (max_bits >= 0)
    4466        22366 :     xlenest += ((HOST_WIDE_INT_1U << max_bits) * 2
    4467        22366 :                 - (HOST_WIDE_INT_1U << ctz_len));
    4468        22541 :   bool max_loop = false;
    4469        22541 :   bool use_store_by_pieces = true;
    4470              :   /* Skip the test in case of overflow in xlenest.  It shouldn't
    4471              :      happen because of the way max_bits and blksize are related, but
    4472              :      it doesn't hurt to test.  */
    4473        22541 :   if (blksize > xlenest
    4474        22541 :       || !can_store_by_multiple_pieces (xlenest - blksize,
    4475              :                                         builtin_memset_read_str,
    4476              :                                         &valc, align, true, blksize))
    4477              :     {
    4478        22366 :       if (!(flag_inline_stringops & ILSOP_MEMSET))
    4479              :         return false;
    4480              : 
    4481         2067 :       for (max_bits = orig_max_bits;
    4482         2174 :            max_bits >= sctz_len;
    4483              :            --max_bits)
    4484              :         {
    4485         2174 :           xlenest = ((HOST_WIDE_INT_1U << max_bits) * 2
    4486         2174 :                      - (HOST_WIDE_INT_1U << ctz_len));
    4487              :           /* Check that blksize plus the bits to be stored as blocks
    4488              :              sized at powers of two can be stored by pieces.  This is
    4489              :              like the test above, but with smaller max_bits.  Skip
    4490              :              orig_max_bits (it would be redundant).  Also skip in case
    4491              :              of overflow.  */
    4492         2174 :           if (max_bits < orig_max_bits
    4493         2067 :               && xlenest + blksize >= xlenest
    4494         4241 :               && can_store_by_multiple_pieces (xlenest,
    4495              :                                                builtin_memset_read_str,
    4496              :                                                &valc, align, true, blksize))
    4497              :             {
    4498              :               max_loop = true;
    4499              :               break;
    4500              :             }
    4501         2067 :           if (blksize
    4502         2067 :               && can_store_by_multiple_pieces (xlenest,
    4503              :                                                builtin_memset_read_str,
    4504              :                                                &valc, align, true, 0))
    4505              :             {
    4506            0 :               max_len += blksize;
    4507            0 :               min_len += blksize;
    4508            0 :               tst_bits = orig_tst_bits;
    4509            0 :               blksize = 0;
    4510            0 :               max_loop = true;
    4511            0 :               break;
    4512              :             }
    4513         2067 :           if (max_bits == sctz_len)
    4514              :             {
    4515              :               /* We'll get here if can_store_by_pieces refuses to
    4516              :                  store even a single QImode.  We'll fall back to
    4517              :                  QImode stores then.  */
    4518           98 :               if (!sctz_len)
    4519              :                 {
    4520              :                   blksize = 0;
    4521              :                   max_loop = true;
    4522              :                   use_store_by_pieces = false;
    4523              :                   break;
    4524              :                 }
    4525           98 :               --sctz_len;
    4526           98 :               --ctz_len;
    4527              :             }
    4528              :         }
    4529          107 :       if (!max_loop)
    4530              :         return false;
    4531              :       /* If the boundaries are such that min and max may run a
    4532              :          different number of trips in the initial loop, the remainder
    4533              :          needs not be between the moduli, so set tst_bits to cover all
    4534              :          bits.  Otherwise, if the trip counts are the same, max_len
    4535              :          has the common prefix, and the previously-computed tst_bits
    4536              :          is usable.  */
    4537          107 :       if (max_len >> max_bits > min_len >> max_bits)
    4538           64 :         tst_bits = max_bits;
    4539              :     }
    4540              : 
    4541          282 :   by_pieces_constfn constfun;
    4542          282 :   void *constfundata;
    4543          282 :   if (val)
    4544              :     {
    4545            1 :       constfun = builtin_memset_gen_str;
    4546            1 :       constfundata = val = force_reg (TYPE_MODE (unsigned_char_type_node),
    4547              :                                       val);
    4548              :     }
    4549              :   else
    4550              :     {
    4551              :       constfun = builtin_memset_read_str;
    4552              :       constfundata = &valc;
    4553              :     }
    4554              : 
    4555          282 :   rtx ptr = copy_addr_to_reg (XEXP (to, 0));
    4556          282 :   rtx rem = copy_to_mode_reg (ptr_mode, convert_to_mode (ptr_mode, len, 0));
    4557          282 :   to = replace_equiv_address (to, ptr);
    4558          282 :   set_mem_align (to, align);
    4559              : 
    4560          282 :   if (blksize)
    4561              :     {
    4562          363 :       to = store_by_pieces (to, blksize,
    4563              :                             constfun, constfundata,
    4564              :                             align, true,
    4565              :                             max_len != 0 ? RETURN_END : RETURN_BEGIN);
    4566          189 :       if (max_len == 0)
    4567              :         return true;
    4568              : 
    4569              :       /* Adjust PTR, TO and REM.  Since TO's address is likely
    4570              :          PTR+offset, we have to replace it.  */
    4571           15 :       emit_move_insn (ptr, force_operand (XEXP (to, 0), NULL_RTX));
    4572           15 :       to = replace_equiv_address (to, ptr);
    4573           15 :       rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
    4574           15 :       emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
    4575              :     }
    4576              : 
    4577              :   /* Iterate over power-of-two block sizes from the maximum length to
    4578              :      the least significant bit possibly set in the length.  */
    4579          493 :   for (int i = max_bits; i >= sctz_len; i--)
    4580              :     {
    4581          385 :       rtx_code_label *loop_label = NULL;
    4582          385 :       rtx_code_label *label = NULL;
    4583              : 
    4584          385 :       blksize = HOST_WIDE_INT_1U << i;
    4585              : 
    4586              :       /* If we're past the bits shared between min_ and max_len, expand
    4587              :          a test on the dynamic length, comparing it with the
    4588              :          BLKSIZE.  */
    4589          385 :       if (i <= tst_bits)
    4590              :         {
    4591          275 :           label = gen_label_rtx ();
    4592          275 :           emit_cmp_and_jump_insns (rem, GEN_INT (blksize), LT, NULL,
    4593              :                                    ptr_mode, 1, label,
    4594              :                                    profile_probability::even ());
    4595              :         }
    4596              :       /* If we are at a bit that is in the prefix shared by min_ and
    4597              :          max_len, skip the current BLKSIZE if the bit is clear, but do
    4598              :          not skip the loop, even if it doesn't require
    4599              :          prechecking.  */
    4600          110 :       else if ((max_len & blksize) == 0
    4601           69 :                && !(max_loop && i == max_bits))
    4602           39 :         continue;
    4603              : 
    4604          346 :       if (max_loop && i == max_bits)
    4605              :         {
    4606          107 :           loop_label = gen_label_rtx ();
    4607          107 :           emit_label (loop_label);
    4608              :           /* Since we may run this multiple times, don't assume we
    4609              :              know anything about the offset.  */
    4610          107 :           clear_mem_offset (to);
    4611              :         }
    4612              : 
    4613          346 :       bool update_needed = i != sctz_len || loop_label;
    4614          346 :       rtx next_ptr = NULL_RTX;
    4615          346 :       if (!use_store_by_pieces)
    4616              :         {
    4617            0 :           gcc_checking_assert (blksize == 1);
    4618            0 :           if (!val)
    4619            0 :             val = gen_int_mode (valc, QImode);
    4620            0 :           to = change_address (to, QImode, 0);
    4621            0 :           emit_move_insn (to, val);
    4622            0 :           if (update_needed)
    4623            0 :             next_ptr = plus_constant (GET_MODE (ptr), ptr, blksize);
    4624              :         }
    4625              :       else
    4626              :         {
    4627              :           /* Issue a store of BLKSIZE bytes.  */
    4628          404 :           to = store_by_pieces (to, blksize,
    4629              :                                 constfun, constfundata,
    4630              :                                 align, true,
    4631              :                                 update_needed ? RETURN_END : RETURN_BEGIN);
    4632          346 :           next_ptr = XEXP (to, 0);
    4633              :         }
    4634              :       /* Adjust REM and PTR, unless this is the last iteration.  */
    4635          346 :       if (update_needed)
    4636              :         {
    4637          288 :           emit_move_insn (ptr, force_operand (next_ptr, NULL_RTX));
    4638          288 :           to = replace_equiv_address (to, ptr);
    4639          288 :           rtx rem_minus_blksize = plus_constant (ptr_mode, rem, -blksize);
    4640          288 :           emit_move_insn (rem, force_operand (rem_minus_blksize, NULL_RTX));
    4641              :         }
    4642              : 
    4643          288 :       if (loop_label)
    4644          107 :         emit_cmp_and_jump_insns (rem, GEN_INT (blksize), GE, NULL,
    4645              :                                  ptr_mode, 1, loop_label,
    4646              :                                  profile_probability::likely ());
    4647              : 
    4648          346 :       if (label)
    4649              :         {
    4650          275 :           emit_label (label);
    4651              : 
    4652              :           /* Given conditional stores, the offset can no longer be
    4653              :              known, so clear it.  */
    4654          275 :           clear_mem_offset (to);
    4655              :         }
    4656              :     }
    4657              : 
    4658              :   return true;
    4659              : }
    4660              : 
    4661              : /* Helper function to do the actual work for expand_builtin_memset.  The
    4662              :    arguments to the builtin_memset call DEST, VAL, and LEN are broken out
    4663              :    so that this can also be called without constructing an actual CALL_EXPR.
    4664              :    The other arguments and return value are the same as for
    4665              :    expand_builtin_memset.  */
    4666              : 
    4667              : static rtx
    4668        62553 : expand_builtin_memset_args (tree dest, tree val, tree len,
    4669              :                             rtx target, machine_mode mode, tree orig_exp)
    4670              : {
    4671        62553 :   tree fndecl, fn;
    4672        62553 :   enum built_in_function fcode;
    4673        62553 :   machine_mode val_mode;
    4674        62553 :   char c;
    4675        62553 :   unsigned int dest_align;
    4676        62553 :   rtx dest_mem, dest_addr, len_rtx;
    4677        62553 :   HOST_WIDE_INT expected_size = -1;
    4678        62553 :   unsigned int expected_align = 0;
    4679        62553 :   unsigned HOST_WIDE_INT min_size;
    4680        62553 :   unsigned HOST_WIDE_INT max_size;
    4681        62553 :   unsigned HOST_WIDE_INT probable_max_size;
    4682              : 
    4683        62553 :   dest_align = get_pointer_alignment (dest);
    4684              : 
    4685              :   /* If DEST is not a pointer type, don't do this operation in-line.  */
    4686        62553 :   if (dest_align == 0)
    4687              :     return NULL_RTX;
    4688              : 
    4689        62553 :   if (currently_expanding_gimple_stmt)
    4690        62553 :     stringop_block_profile (currently_expanding_gimple_stmt,
    4691              :                             &expected_align, &expected_size);
    4692              : 
    4693        62553 :   if (expected_align < dest_align)
    4694        62545 :     expected_align = dest_align;
    4695              : 
    4696              :   /* If the LEN parameter is zero, return DEST.  */
    4697        62553 :   if (integer_zerop (len))
    4698              :     {
    4699              :       /* Evaluate and ignore VAL in case it has side-effects.  */
    4700            0 :       expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
    4701            0 :       return expand_expr (dest, target, mode, EXPAND_NORMAL);
    4702              :     }
    4703              : 
    4704              :   /* Stabilize the arguments in case we fail.  */
    4705        62553 :   dest = builtin_save_expr (dest);
    4706        62553 :   val = builtin_save_expr (val);
    4707        62553 :   len = builtin_save_expr (len);
    4708              : 
    4709        62553 :   len_rtx = expand_normal (len);
    4710        62553 :   determine_block_size (len, len_rtx, &min_size, &max_size,
    4711              :                         &probable_max_size);
    4712        62553 :   dest_mem = get_memory_rtx (dest, len, true);
    4713        62553 :   val_mode = TYPE_MODE (unsigned_char_type_node);
    4714              : 
    4715        62553 :   if (TREE_CODE (val) != INTEGER_CST
    4716        62553 :       || target_char_cast (val, &c))
    4717              :     {
    4718         1721 :       rtx val_rtx;
    4719              : 
    4720         1721 :       val_rtx = expand_normal (val);
    4721         1721 :       val_rtx = convert_to_mode (val_mode, val_rtx, 0);
    4722              : 
    4723              :       /* Assume that we can memset by pieces if we can store
    4724              :        * the coefficients by pieces (in the required modes).
    4725              :        * We can't pass builtin_memset_gen_str as that emits RTL.  */
    4726         1721 :       c = 1;
    4727         1721 :       if (tree_fits_uhwi_p (len)
    4728         1721 :           && can_store_by_pieces (tree_to_uhwi (len),
    4729              :                                   builtin_memset_read_str, &c, dest_align,
    4730              :                                   true))
    4731              :         {
    4732          724 :           val_rtx = force_reg (val_mode, val_rtx);
    4733          724 :           store_by_pieces (dest_mem, tree_to_uhwi (len),
    4734              :                            builtin_memset_gen_str, val_rtx, dest_align,
    4735              :                            true, RETURN_BEGIN);
    4736              :         }
    4737          997 :       else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
    4738              :                                         dest_align, expected_align,
    4739              :                                         expected_size, min_size, max_size,
    4740              :                                         probable_max_size)
    4741          997 :                && !try_store_by_multiple_pieces (dest_mem, len_rtx,
    4742              :                                                  tree_ctz (len),
    4743              :                                                  min_size, max_size,
    4744              :                                                  val_rtx, 0,
    4745              :                                                  dest_align))
    4746          637 :         goto do_libcall;
    4747              : 
    4748         1084 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4749         1084 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4750         1084 :       return dest_mem;
    4751              :     }
    4752              : 
    4753        60832 :   if (c)
    4754              :     {
    4755        13406 :       if (tree_fits_uhwi_p (len)
    4756        13406 :           && can_store_by_pieces (tree_to_uhwi (len),
    4757              :                                   builtin_memset_read_str, &c, dest_align,
    4758              :                                   true))
    4759         5741 :         store_by_pieces (dest_mem, tree_to_uhwi (len),
    4760              :                          builtin_memset_read_str, &c, dest_align, true,
    4761              :                          RETURN_BEGIN);
    4762         9583 :       else if (!set_storage_via_setmem (dest_mem, len_rtx,
    4763         7665 :                                         gen_int_mode (c, val_mode),
    4764              :                                         dest_align, expected_align,
    4765              :                                         expected_size, min_size, max_size,
    4766              :                                         probable_max_size)
    4767         7665 :                && !try_store_by_multiple_pieces (dest_mem, len_rtx,
    4768              :                                                  tree_ctz (len),
    4769              :                                                  min_size, max_size,
    4770              :                                                  NULL_RTX, c,
    4771              :                                                  dest_align))
    4772         5747 :         goto do_libcall;
    4773              : 
    4774         7659 :       dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4775         7659 :       dest_mem = convert_memory_address (ptr_mode, dest_mem);
    4776         7659 :       return dest_mem;
    4777              :     }
    4778              : 
    4779        47426 :   set_mem_align (dest_mem, dest_align);
    4780        94852 :   dest_addr = clear_storage_hints (dest_mem, len_rtx,
    4781        47426 :                                    CALL_EXPR_TAILCALL (orig_exp)
    4782              :                                    ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
    4783              :                                    expected_align, expected_size,
    4784              :                                    min_size, max_size,
    4785              :                                    probable_max_size, tree_ctz (len));
    4786              : 
    4787        47426 :   if (dest_addr == 0)
    4788              :     {
    4789        37422 :       dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
    4790        37422 :       dest_addr = convert_memory_address (ptr_mode, dest_addr);
    4791              :     }
    4792              : 
    4793              :   return dest_addr;
    4794              : 
    4795         6384 :  do_libcall:
    4796         6384 :   fndecl = get_callee_fndecl (orig_exp);
    4797         6384 :   fcode = DECL_FUNCTION_CODE (fndecl);
    4798         6384 :   if (fcode == BUILT_IN_MEMSET)
    4799         6384 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
    4800              :                                 dest, val, len);
    4801            0 :   else if (fcode == BUILT_IN_BZERO)
    4802            0 :     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
    4803              :                                 dest, len);
    4804              :   else
    4805            0 :     gcc_unreachable ();
    4806         6384 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    4807         6384 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
    4808         6384 :   return expand_call (fn, target, target == const0_rtx);
    4809              : }
    4810              : 
    4811              : /* Expand expression EXP, which is a call to the bzero builtin.  Return
    4812              :    NULL_RTX if we failed the caller should emit a normal call.  */
    4813              : 
    4814              : static rtx
    4815            0 : expand_builtin_bzero (tree exp)
    4816              : {
    4817            0 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4818              :     return NULL_RTX;
    4819              : 
    4820            0 :   tree dest = CALL_EXPR_ARG (exp, 0);
    4821            0 :   tree size = CALL_EXPR_ARG (exp, 1);
    4822              : 
    4823              :   /* New argument list transforming bzero(ptr x, int y) to
    4824              :      memset(ptr x, int 0, size_t y).   This is done this way
    4825              :      so that if it isn't expanded inline, we fallback to
    4826              :      calling bzero instead of memset.  */
    4827              : 
    4828            0 :   location_t loc = EXPR_LOCATION (exp);
    4829              : 
    4830            0 :   return expand_builtin_memset_args (dest, integer_zero_node,
    4831              :                                      fold_convert_loc (loc,
    4832              :                                                        size_type_node, size),
    4833            0 :                                      const0_rtx, VOIDmode, exp);
    4834              : }
    4835              : 
    4836              : /* Try to expand cmpstr operation ICODE with the given operands.
    4837              :    Return the result rtx on success, otherwise return null.  */
    4838              : 
    4839              : static rtx
    4840            0 : expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
    4841              :                HOST_WIDE_INT align)
    4842              : {
    4843            0 :   machine_mode insn_mode = insn_data[icode].operand[0].mode;
    4844              : 
    4845            0 :   if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
    4846              :     target = NULL_RTX;
    4847              : 
    4848            0 :   class expand_operand ops[4];
    4849            0 :   create_output_operand (&ops[0], target, insn_mode);
    4850            0 :   create_fixed_operand (&ops[1], arg1_rtx);
    4851            0 :   create_fixed_operand (&ops[2], arg2_rtx);
    4852            0 :   create_integer_operand (&ops[3], align);
    4853            0 :   if (maybe_expand_insn (icode, 4, ops))
    4854            0 :     return ops[0].value;
    4855              :   return NULL_RTX;
    4856              : }
    4857              : 
    4858              : /* Expand expression EXP, which is a call to the memcmp built-in function.
    4859              :    Return NULL_RTX if we failed and the caller should emit a normal call,
    4860              :    otherwise try to get the result in TARGET, if convenient.
    4861              :    RESULT_EQ is true if we can relax the returned value to be either zero
    4862              :    or nonzero, without caring about the sign.  */
    4863              : 
    4864              : static rtx
    4865       106532 : expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
    4866              : {
    4867       106532 :   if (!validate_arglist (exp,
    4868              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    4869              :     return NULL_RTX;
    4870              : 
    4871       106528 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    4872       106528 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    4873       106528 :   tree len = CALL_EXPR_ARG (exp, 2);
    4874              : 
    4875              :   /* Due to the performance benefit, always inline the calls first
    4876              :      when result_eq is false.  */
    4877       106528 :   rtx result = NULL_RTX;
    4878       106528 :   enum built_in_function fcode = DECL_FUNCTION_CODE (get_callee_fndecl (exp));
    4879       106528 :   if (!result_eq && fcode != BUILT_IN_BCMP)
    4880              :     {
    4881        14903 :       result = inline_expand_builtin_bytecmp (exp, target);
    4882        14903 :       if (result)
    4883              :         return result;
    4884              :     }
    4885              : 
    4886       106510 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    4887       106510 :   location_t loc = EXPR_LOCATION (exp);
    4888              : 
    4889       106510 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    4890       106510 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    4891              : 
    4892              :   /* If we don't have POINTER_TYPE, call the function.  */
    4893       106510 :   if (arg1_align == 0 || arg2_align == 0)
    4894              :     return NULL_RTX;
    4895              : 
    4896       106510 :   rtx arg1_rtx = get_memory_rtx (arg1, len, false);
    4897       106510 :   rtx arg2_rtx = get_memory_rtx (arg2, len, false);
    4898       106510 :   rtx len_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
    4899              : 
    4900              :   /* Set MEM_SIZE as appropriate.  */
    4901       106510 :   if (CONST_INT_P (len_rtx))
    4902              :     {
    4903        81406 :       set_mem_size (arg1_rtx, INTVAL (len_rtx));
    4904        81406 :       set_mem_size (arg2_rtx, INTVAL (len_rtx));
    4905              :     }
    4906              : 
    4907       106510 :   by_pieces_constfn constfn = NULL;
    4908              : 
    4909              :   /* Try to get the byte representation of the constant ARG2 (or, only
    4910              :      when the function's result is used for equality to zero, ARG1)
    4911              :      points to, with its byte size in NBYTES.  */
    4912       106510 :   unsigned HOST_WIDE_INT nbytes;
    4913       106510 :   const char *rep = getbyterep (arg2, &nbytes);
    4914       106510 :   if (result_eq && rep == NULL)
    4915              :     {
    4916              :       /* For equality to zero the arguments are interchangeable.  */
    4917        63602 :       rep = getbyterep (arg1, &nbytes);
    4918        63602 :       if (rep != NULL)
    4919              :         std::swap (arg1_rtx, arg2_rtx);
    4920              :     }
    4921              : 
    4922              :   /* If the function's constant bound LEN_RTX is less than or equal
    4923              :      to the byte size of the representation of the constant argument,
    4924              :      and if block move would be done by pieces, we can avoid loading
    4925              :      the bytes from memory and only store the computed constant result.  */
    4926        42908 :   if (rep
    4927        30154 :       && CONST_INT_P (len_rtx)
    4928        30001 :       && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= nbytes)
    4929       106510 :     constfn = builtin_memcpy_read_str;
    4930              : 
    4931       213020 :   result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
    4932       106510 :                                  TREE_TYPE (len), target,
    4933              :                                  result_eq, constfn,
    4934              :                                  const_cast<char *> (rep),
    4935              :                                  tree_ctz (len));
    4936              : 
    4937       106510 :   if (result)
    4938              :     {
    4939              :       /* Return the value in the proper mode for this function.  */
    4940        68942 :       if (GET_MODE (result) == mode)
    4941              :         return result;
    4942              : 
    4943            0 :       if (target != 0)
    4944              :         {
    4945            0 :           convert_move (target, result, 0);
    4946            0 :           return target;
    4947              :         }
    4948              : 
    4949            0 :       return convert_to_mode (mode, result, 0);
    4950              :     }
    4951              : 
    4952              :   return NULL_RTX;
    4953              : }
    4954              : 
    4955              : /* Expand expression EXP, which is a call to the strcmp builtin.  Return NULL_RTX
    4956              :    if we failed the caller should emit a normal call, otherwise try to get
    4957              :    the result in TARGET, if convenient.  */
    4958              : 
    4959              : static rtx
    4960       127970 : expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
    4961              : {
    4962       127970 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    4963              :     return NULL_RTX;
    4964              : 
    4965       127955 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    4966       127955 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    4967              : 
    4968              :   /* Due to the performance benefit, always inline the calls first.  */
    4969       127955 :   rtx result = NULL_RTX;
    4970       127955 :   result = inline_expand_builtin_bytecmp (exp, target);
    4971       127955 :   if (result)
    4972              :     return result;
    4973              : 
    4974       127556 :   insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
    4975       127556 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    4976       127556 :   if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing)
    4977              :     return NULL_RTX;
    4978              : 
    4979       127556 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    4980       127556 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    4981              : 
    4982              :   /* If we don't have POINTER_TYPE, call the function.  */
    4983       127556 :   if (arg1_align == 0 || arg2_align == 0)
    4984              :     return NULL_RTX;
    4985              : 
    4986              :   /* Stabilize the arguments in case gen_cmpstr(n)si fail.  */
    4987       127556 :   arg1 = builtin_save_expr (arg1);
    4988       127556 :   arg2 = builtin_save_expr (arg2);
    4989              : 
    4990       127556 :   rtx arg1_rtx = get_memory_rtx (arg1, NULL, false);
    4991       127556 :   rtx arg2_rtx = get_memory_rtx (arg2, NULL, false);
    4992              : 
    4993              :   /* Try to call cmpstrsi.  */
    4994       127556 :   if (cmpstr_icode != CODE_FOR_nothing)
    4995            0 :     result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
    4996            0 :                             MIN (arg1_align, arg2_align));
    4997              : 
    4998              :   /* Try to determine at least one length and call cmpstrnsi.  */
    4999       127556 :   if (!result && cmpstrn_icode != CODE_FOR_nothing)
    5000              :     {
    5001       127556 :       tree len;
    5002       127556 :       rtx arg3_rtx;
    5003              : 
    5004       127556 :       tree len1 = c_strlen (arg1, 1);
    5005       127556 :       tree len2 = c_strlen (arg2, 1);
    5006              : 
    5007       127556 :       if (len1)
    5008          224 :         len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
    5009       127556 :       if (len2)
    5010       125928 :         len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
    5011              : 
    5012              :       /* If we don't have a constant length for the first, use the length
    5013              :          of the second, if we know it.  We don't require a constant for
    5014              :          this case; some cost analysis could be done if both are available
    5015              :          but neither is constant.  For now, assume they're equally cheap,
    5016              :          unless one has side effects.  If both strings have constant lengths,
    5017              :          use the smaller.  */
    5018              : 
    5019       127556 :       if (!len1)
    5020              :         len = len2;
    5021          224 :       else if (!len2)
    5022              :         len = len1;
    5023           17 :       else if (TREE_SIDE_EFFECTS (len1))
    5024              :         len = len2;
    5025           17 :       else if (TREE_SIDE_EFFECTS (len2))
    5026              :         len = len1;
    5027           17 :       else if (TREE_CODE (len1) != INTEGER_CST)
    5028              :         len = len2;
    5029           17 :       else if (TREE_CODE (len2) != INTEGER_CST)
    5030              :         len = len1;
    5031           10 :       else if (tree_int_cst_lt (len1, len2))
    5032              :         len = len1;
    5033              :       else
    5034       127556 :         len = len2;
    5035              : 
    5036              :       /* If both arguments have side effects, we cannot optimize.  */
    5037       127556 :       if (len && !TREE_SIDE_EFFECTS (len))
    5038              :         {
    5039       126135 :           arg3_rtx = expand_normal (len);
    5040       126135 :           result = expand_cmpstrn_or_cmpmem
    5041       126135 :             (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len),
    5042       126135 :              arg3_rtx, MIN (arg1_align, arg2_align));
    5043              :         }
    5044              :     }
    5045              : 
    5046       127556 :   tree fndecl = get_callee_fndecl (exp);
    5047       127556 :   if (result)
    5048              :     {
    5049              :       /* Return the value in the proper mode for this function.  */
    5050           52 :       machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    5051           52 :       if (GET_MODE (result) == mode)
    5052              :         return result;
    5053            0 :       if (target == 0)
    5054            0 :         return convert_to_mode (mode, result, 0);
    5055            0 :       convert_move (target, result, 0);
    5056            0 :       return target;
    5057              :     }
    5058              : 
    5059              :   /* Expand the library call ourselves using a stabilized argument
    5060              :      list to avoid re-evaluating the function's arguments twice.  */
    5061       127504 :   tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
    5062       127504 :   copy_warning (fn, exp);
    5063       127504 :   gcc_assert (TREE_CODE (fn) == CALL_EXPR);
    5064       127504 :   CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
    5065       127504 :   return expand_call (fn, target, target == const0_rtx);
    5066              : }
    5067              : 
    5068              : /* Expand expression EXP, which is a call to the strncmp builtin. Return
    5069              :    NULL_RTX if we failed the caller should emit a normal call, otherwise
    5070              :    try to get the result in TARGET, if convenient.  */
    5071              : 
    5072              : static rtx
    5073         2027 : expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
    5074              :                         ATTRIBUTE_UNUSED machine_mode mode)
    5075              : {
    5076         2027 :   if (!validate_arglist (exp,
    5077              :                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    5078              :     return NULL_RTX;
    5079              : 
    5080         2021 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    5081         2021 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    5082         2021 :   tree arg3 = CALL_EXPR_ARG (exp, 2);
    5083              : 
    5084         2021 :   location_t loc = EXPR_LOCATION (exp);
    5085         2021 :   tree len1 = c_strlen (arg1, 1);
    5086         2021 :   tree len2 = c_strlen (arg2, 1);
    5087              : 
    5088              :   /* Due to the performance benefit, always inline the calls first.  */
    5089         2021 :   rtx result = NULL_RTX;
    5090         2021 :   result = inline_expand_builtin_bytecmp (exp, target);
    5091         2021 :   if (result)
    5092              :     return result;
    5093              : 
    5094              :   /* If c_strlen can determine an expression for one of the string
    5095              :      lengths, and it doesn't have side effects, then emit cmpstrnsi
    5096              :      using length MIN(strlen(string)+1, arg3).  */
    5097         1803 :   insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
    5098         1803 :   if (cmpstrn_icode == CODE_FOR_nothing)
    5099              :     return NULL_RTX;
    5100              : 
    5101         1803 :   tree len;
    5102              : 
    5103         1803 :   unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
    5104         1803 :   unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
    5105              : 
    5106         1803 :   if (len1)
    5107          160 :     len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
    5108         1803 :   if (len2)
    5109          674 :     len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
    5110              : 
    5111         1803 :   tree len3 = fold_convert_loc (loc, sizetype, arg3);
    5112              : 
    5113              :   /* If we don't have a constant length for the first, use the length
    5114              :      of the second, if we know it.  If neither string is constant length,
    5115              :      use the given length argument.  We don't require a constant for
    5116              :      this case; some cost analysis could be done if both are available
    5117              :      but neither is constant.  For now, assume they're equally cheap,
    5118              :      unless one has side effects.  If both strings have constant lengths,
    5119              :      use the smaller.  */
    5120              : 
    5121         1803 :   if (!len1 && !len2)
    5122              :     len = len3;
    5123          717 :   else if (!len1)
    5124              :     len = len2;
    5125          160 :   else if (!len2)
    5126              :     len = len1;
    5127          117 :   else if (TREE_SIDE_EFFECTS (len1))
    5128              :     len = len2;
    5129          117 :   else if (TREE_SIDE_EFFECTS (len2))
    5130              :     len = len1;
    5131          117 :   else if (TREE_CODE (len1) != INTEGER_CST)
    5132              :     len = len2;
    5133          117 :   else if (TREE_CODE (len2) != INTEGER_CST)
    5134              :     len = len1;
    5135          117 :   else if (tree_int_cst_lt (len1, len2))
    5136              :     len = len1;
    5137              :   else
    5138         1803 :     len = len2;
    5139              : 
    5140              :   /* If we are not using the given length, we must incorporate it here.
    5141              :      The actual new length parameter will be MIN(len,arg3) in this case.  */
    5142         1803 :   if (len != len3)
    5143              :     {
    5144          717 :       len = fold_convert_loc (loc, sizetype, len);
    5145          717 :       len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
    5146              :     }
    5147         1803 :   rtx arg1_rtx = get_memory_rtx (arg1, len, false);
    5148         1803 :   rtx arg2_rtx = get_memory_rtx (arg2, len, false);
    5149         1803 :   rtx arg3_rtx = expand_normal (len);
    5150         1803 :   result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx,
    5151         1803 :                                      arg2_rtx, TREE_TYPE (len), arg3_rtx,
    5152         1803 :                                      MIN (arg1_align, arg2_align));
    5153              : 
    5154         1803 :   tree fndecl = get_callee_fndecl (exp);
    5155         1803 :   if (result)
    5156              :     {
    5157              :       /* Return the value in the proper mode for this function.  */
    5158           17 :       mode = TYPE_MODE (TREE_TYPE (exp));
    5159           17 :       if (GET_MODE (result) == mode)
    5160              :         return result;
    5161            0 :       if (target == 0)
    5162            0 :         return convert_to_mode (mode, result, 0);
    5163            0 :       convert_move (target, result, 0);
    5164            0 :       return target;
    5165              :     }
    5166              : 
    5167              :   /* Expand the library call ourselves using a stabilized argument
    5168              :      list to avoid re-evaluating the function's arguments twice.  */
    5169         1786 :   tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
    5170         1786 :   copy_warning (call, exp);
    5171         1786 :   gcc_assert (TREE_CODE (call) == CALL_EXPR);
    5172         1786 :   CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
    5173         1786 :   return expand_call (call, target, target == const0_rtx);
    5174              : }
    5175              : 
    5176              : /* Expand a call to __builtin_saveregs, generating the result in TARGET,
    5177              :    if that's convenient.  */
    5178              : 
    5179              : rtx
    5180            0 : expand_builtin_saveregs (void)
    5181              : {
    5182            0 :   rtx val;
    5183            0 :   rtx_insn *seq;
    5184              : 
    5185              :   /* Don't do __builtin_saveregs more than once in a function.
    5186              :      Save the result of the first call and reuse it.  */
    5187            0 :   if (saveregs_value != 0)
    5188              :     return saveregs_value;
    5189              : 
    5190              :   /* When this function is called, it means that registers must be
    5191              :      saved on entry to this function.  So we migrate the call to the
    5192              :      first insn of this function.  */
    5193              : 
    5194            0 :   start_sequence ();
    5195              : 
    5196              :   /* Do whatever the machine needs done in this case.  */
    5197            0 :   val = targetm.calls.expand_builtin_saveregs ();
    5198              : 
    5199            0 :   seq = end_sequence ();
    5200              : 
    5201            0 :   saveregs_value = val;
    5202              : 
    5203              :   /* Put the insns after the NOTE that starts the function.  If this
    5204              :      is inside a start_sequence, make the outer-level insn chain current, so
    5205              :      the code is placed at the start of the function.  */
    5206            0 :   push_topmost_sequence ();
    5207            0 :   emit_insn_after (seq, entry_of_function ());
    5208            0 :   pop_topmost_sequence ();
    5209              : 
    5210            0 :   return val;
    5211              : }
    5212              : 
    5213              : /* Expand a call to __builtin_next_arg.  */
    5214              : 
    5215              : static rtx
    5216        21240 : expand_builtin_next_arg (void)
    5217              : {
    5218              :   /* Checking arguments is already done in fold_builtin_next_arg
    5219              :      that must be called before this function.  */
    5220        21240 :   return expand_binop (ptr_mode, add_optab,
    5221              :                        crtl->args.internal_arg_pointer,
    5222              :                        crtl->args.arg_offset_rtx,
    5223        21240 :                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
    5224              : }
    5225              : 
    5226              : /* Make it easier for the backends by protecting the valist argument
    5227              :    from multiple evaluations.  */
    5228              : 
    5229              : static tree
    5230        21562 : stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
    5231              : {
    5232        21562 :   tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
    5233              : 
    5234              :   /* The current way of determining the type of valist is completely
    5235              :      bogus.  We should have the information on the va builtin instead.  */
    5236        21562 :   if (!vatype)
    5237        21438 :     vatype = targetm.fn_abi_va_list (cfun->decl);
    5238              : 
    5239        21562 :   if (TREE_CODE (vatype) == ARRAY_TYPE)
    5240              :     {
    5241        15896 :       if (TREE_SIDE_EFFECTS (valist))
    5242            0 :         valist = save_expr (valist);
    5243              : 
    5244              :       /* For this case, the backends will be expecting a pointer to
    5245              :          vatype, but it's possible we've actually been given an array
    5246              :          (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
    5247              :          So fix it.  */
    5248        15896 :       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
    5249              :         {
    5250            0 :           tree p1 = build_pointer_type (TREE_TYPE (vatype));
    5251            0 :           valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
    5252              :         }
    5253              :     }
    5254              :   else
    5255              :     {
    5256         5666 :       tree pt = build_pointer_type (vatype);
    5257              : 
    5258         5666 :       if (! needs_lvalue)
    5259              :         {
    5260            6 :           if (! TREE_SIDE_EFFECTS (valist))
    5261              :             return valist;
    5262              : 
    5263            0 :           valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
    5264            0 :           TREE_SIDE_EFFECTS (valist) = 1;
    5265              :         }
    5266              : 
    5267         5660 :       if (TREE_SIDE_EFFECTS (valist))
    5268            0 :         valist = save_expr (valist);
    5269         5660 :       valist = fold_build2_loc (loc, MEM_REF,
    5270              :                                 vatype, valist, build_int_cst (pt, 0));
    5271              :     }
    5272              : 
    5273              :   return valist;
    5274              : }
    5275              : 
    5276              : /* The "standard" definition of va_list is void*.  */
    5277              : 
    5278              : tree
    5279            0 : std_build_builtin_va_list (void)
    5280              : {
    5281            0 :   return ptr_type_node;
    5282              : }
    5283              : 
    5284              : /* The "standard" abi va_list is va_list_type_node.  */
    5285              : 
    5286              : tree
    5287            0 : std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
    5288              : {
    5289            0 :   return va_list_type_node;
    5290              : }
    5291              : 
    5292              : /* The "standard" type of va_list is va_list_type_node.  */
    5293              : 
    5294              : tree
    5295          502 : std_canonical_va_list_type (tree type)
    5296              : {
    5297          502 :   tree wtype, htype;
    5298              : 
    5299          502 :   wtype = va_list_type_node;
    5300          502 :   htype = type;
    5301              : 
    5302          502 :   if (TREE_CODE (wtype) == ARRAY_TYPE)
    5303              :     {
    5304              :       /* If va_list is an array type, the argument may have decayed
    5305              :          to a pointer type, e.g. by being passed to another function.
    5306              :          In that case, unwrap both types so that we can compare the
    5307              :          underlying records.  */
    5308            0 :       if (TREE_CODE (htype) == ARRAY_TYPE
    5309            0 :           || POINTER_TYPE_P (htype))
    5310              :         {
    5311            0 :           wtype = TREE_TYPE (wtype);
    5312            0 :           htype = TREE_TYPE (htype);
    5313              :         }
    5314              :     }
    5315          502 :   if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
    5316          332 :     return va_list_type_node;
    5317              : 
    5318              :   return NULL_TREE;
    5319              : }
    5320              : 
    5321              : /* The "standard" implementation of va_start: just assign `nextarg' to
    5322              :    the variable.  */
    5323              : 
    5324              : void
    5325         5656 : std_expand_builtin_va_start (tree valist, rtx nextarg)
    5326              : {
    5327         5656 :   rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
    5328         5656 :   convert_move (va_r, nextarg, 0);
    5329         5656 : }
    5330              : 
    5331              : /* Expand EXP, a call to __builtin_va_start.  */
    5332              : 
    5333              : static rtx
    5334        21082 : expand_builtin_va_start (tree exp)
    5335              : {
    5336        21082 :   rtx nextarg;
    5337        21082 :   tree valist;
    5338        21082 :   location_t loc = EXPR_LOCATION (exp);
    5339              : 
    5340        21082 :   if (call_expr_nargs (exp) < 2)
    5341              :     {
    5342            0 :       error_at (loc, "too few arguments to function %<va_start%>");
    5343            0 :       return const0_rtx;
    5344              :     }
    5345              : 
    5346        21082 :   if (fold_builtin_next_arg (exp, true))
    5347            0 :     return const0_rtx;
    5348              : 
    5349        21082 :   nextarg = expand_builtin_next_arg ();
    5350        21082 :   valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
    5351              : 
    5352        21082 :   if (targetm.expand_builtin_va_start)
    5353        21082 :     targetm.expand_builtin_va_start (valist, nextarg);
    5354              :   else
    5355            0 :     std_expand_builtin_va_start (valist, nextarg);
    5356              : 
    5357        21082 :   return const0_rtx;
    5358              : }
    5359              : 
    5360              : /* Expand EXP, a call to __builtin_va_end.  */
    5361              : 
    5362              : static rtx
    5363        12161 : expand_builtin_va_end (tree exp)
    5364              : {
    5365        12161 :   tree valist = CALL_EXPR_ARG (exp, 0);
    5366              : 
    5367              :   /* Evaluate for side effects, if needed.  I hate macros that don't
    5368              :      do that.  */
    5369        12161 :   if (TREE_SIDE_EFFECTS (valist))
    5370            0 :     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5371              : 
    5372        12161 :   return const0_rtx;
    5373              : }
    5374              : 
    5375              : /* Expand EXP, a call to __builtin_va_copy.  We do this as a
    5376              :    builtin rather than just as an assignment in stdarg.h because of the
    5377              :    nastiness of array-type va_list types.  */
    5378              : 
    5379              : static rtx
    5380          240 : expand_builtin_va_copy (tree exp)
    5381              : {
    5382          240 :   tree dst, src, t;
    5383          240 :   location_t loc = EXPR_LOCATION (exp);
    5384              : 
    5385          240 :   dst = CALL_EXPR_ARG (exp, 0);
    5386          240 :   src = CALL_EXPR_ARG (exp, 1);
    5387              : 
    5388          240 :   dst = stabilize_va_list_loc (loc, dst, 1);
    5389          240 :   src = stabilize_va_list_loc (loc, src, 0);
    5390              : 
    5391          240 :   gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
    5392              : 
    5393          240 :   if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
    5394              :     {
    5395            0 :       t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
    5396            0 :       TREE_SIDE_EFFECTS (t) = 1;
    5397            0 :       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
    5398              :     }
    5399              :   else
    5400              :     {
    5401          240 :       rtx dstb, srcb, size;
    5402              : 
    5403              :       /* Evaluate to pointers.  */
    5404          240 :       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
    5405          240 :       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
    5406          240 :       size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
    5407              :                   NULL_RTX, VOIDmode, EXPAND_NORMAL);
    5408              : 
    5409          240 :       dstb = convert_memory_address (Pmode, dstb);
    5410          240 :       srcb = convert_memory_address (Pmode, srcb);
    5411              : 
    5412              :       /* "Dereference" to BLKmode memories.  */
    5413          240 :       dstb = gen_rtx_MEM (BLKmode, dstb);
    5414          240 :       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
    5415          240 :       set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5416          240 :       srcb = gen_rtx_MEM (BLKmode, srcb);
    5417          240 :       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
    5418          240 :       set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
    5419              : 
    5420              :       /* Copy.  */
    5421          240 :       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
    5422              :     }
    5423              : 
    5424          240 :   return const0_rtx;
    5425              : }
    5426              : 
    5427              : /* Expand a call to one of the builtin functions __builtin_frame_address or
    5428              :    __builtin_return_address.  */
    5429              : 
    5430              : static rtx
    5431        15936 : expand_builtin_frame_address (tree fndecl, tree exp)
    5432              : {
    5433              :   /* The argument must be a nonnegative integer constant.
    5434              :      It counts the number of frames to scan up the stack.
    5435              :      The value is either the frame pointer value or the return
    5436              :      address saved in that frame.  */
    5437        15936 :   if (call_expr_nargs (exp) == 0)
    5438              :     /* Warning about missing arg was already issued.  */
    5439            0 :     return const0_rtx;
    5440        15936 :   else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
    5441              :     {
    5442            0 :       error ("invalid argument to %qD", fndecl);
    5443            0 :       return const0_rtx;
    5444              :     }
    5445              :   else
    5446              :     {
    5447              :       /* Number of frames to scan up the stack.  */
    5448        15936 :       unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
    5449              : 
    5450        15936 :       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
    5451              : 
    5452              :       /* Some ports cannot access arbitrary stack frames.  */
    5453        15936 :       if (tem == NULL)
    5454              :         {
    5455            0 :           warning (0, "unsupported argument to %qD", fndecl);
    5456            0 :           return const0_rtx;
    5457              :         }
    5458              : 
    5459        15936 :       if (count)
    5460              :         {
    5461              :           /* Warn since no effort is made to ensure that any frame
    5462              :              beyond the current one exists or can be safely reached.  */
    5463          938 :           warning (OPT_Wframe_address, "calling %qD with "
    5464              :                    "a nonzero argument is unsafe", fndecl);
    5465              :         }
    5466              : 
    5467              :       /* For __builtin_frame_address, return what we've got.  */
    5468        15936 :       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
    5469              :         return tem;
    5470              : 
    5471         5173 :       if (!REG_P (tem)
    5472         5173 :           && ! CONSTANT_P (tem))
    5473         5173 :         tem = copy_addr_to_reg (tem);
    5474              :       return tem;
    5475              :     }
    5476              : }
    5477              : 
    5478              : #if ! STACK_GROWS_DOWNWARD
    5479              : # define STACK_TOPS GT
    5480              : #else
    5481              : # define STACK_TOPS LT
    5482              : #endif
    5483              : 
    5484              : #ifdef POINTERS_EXTEND_UNSIGNED
    5485              : # define STACK_UNSIGNED POINTERS_EXTEND_UNSIGNED
    5486              : #else
    5487              : # define STACK_UNSIGNED true
    5488              : #endif
    5489              : 
    5490              : /* Expand a call to builtin function __builtin_stack_address.  */
    5491              : 
    5492              : static rtx
    5493         3455 : expand_builtin_stack_address ()
    5494              : {
    5495         3455 :   rtx ret = convert_to_mode (ptr_mode, copy_to_reg (stack_pointer_rtx),
    5496              :                              STACK_UNSIGNED);
    5497              : 
    5498              : #ifdef STACK_ADDRESS_OFFSET
    5499              :   /* Unbias the stack pointer, bringing it to the boundary between the
    5500              :      stack area claimed by the active function calling this builtin,
    5501              :      and stack ranges that could get clobbered if it called another
    5502              :      function.  It should NOT encompass any stack red zone, that is
    5503              :      used in leaf functions.
    5504              : 
    5505              :      On SPARC, the register save area is *not* considered active or
    5506              :      used by the active function, but rather as akin to the area in
    5507              :      which call-preserved registers are saved by callees.  This
    5508              :      enables __strub_leave to clear what would otherwise overlap with
    5509              :      its own register save area.
    5510              : 
    5511              :      If the address is computed too high or too low, parts of a stack
    5512              :      range that should be scrubbed may be left unscrubbed, scrubbing
    5513              :      may corrupt active portions of the stack frame, and stack ranges
    5514              :      may be doubly-scrubbed by caller and callee.
    5515              : 
    5516              :      In order for it to be just right, the area delimited by
    5517              :      @code{__builtin_stack_address} and @code{__builtin_frame_address
    5518              :      (0)} should encompass caller's registers saved by the function,
    5519              :      local on-stack variables and @code{alloca} stack areas.
    5520              :      Accumulated outgoing on-stack arguments, preallocated as part of
    5521              :      a function's own prologue, are to be regarded as part of the
    5522              :      (caller) function's active area as well, whereas those pushed or
    5523              :      allocated temporarily for a call are regarded as part of the
    5524              :      callee's stack range, rather than the caller's.  */
    5525              :   ret = plus_constant (ptr_mode, ret, STACK_ADDRESS_OFFSET);
    5526              : #endif
    5527              : 
    5528         3455 :   return force_reg (ptr_mode, ret);
    5529              : }
    5530              : 
    5531              : /* Expand a call to builtin function __builtin_strub_enter.  */
    5532              : 
    5533              : static rtx
    5534         2170 : expand_builtin_strub_enter (tree exp)
    5535              : {
    5536         2170 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5537              :     return NULL_RTX;
    5538              : 
    5539         2170 :   if (optimize < 1 || flag_no_inline)
    5540              :     return NULL_RTX;
    5541              : 
    5542         1526 :   rtx stktop = expand_builtin_stack_address ();
    5543              : 
    5544         1526 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5545         1526 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5546         1526 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5547              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5548         1526 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5549              : 
    5550         1526 :   emit_move_insn (wmark, stktop);
    5551              : 
    5552         1526 :   return const0_rtx;
    5553              : }
    5554              : 
    5555              : /* Expand a call to builtin function __builtin_strub_update.  */
    5556              : 
    5557              : static rtx
    5558         1085 : expand_builtin_strub_update (tree exp)
    5559              : {
    5560         1085 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5561              :     return NULL_RTX;
    5562              : 
    5563         1085 :   if (optimize < 2 || flag_no_inline)
    5564              :     return NULL_RTX;
    5565              : 
    5566          663 :   rtx stktop = expand_builtin_stack_address ();
    5567              : 
    5568              : #ifdef RED_ZONE_SIZE
    5569              :   /* Here's how the strub enter, update and leave functions deal with red zones.
    5570              : 
    5571              :      If it weren't for red zones, update, called from within a strub context,
    5572              :      would bump the watermark to the top of the stack.  Enter and leave, running
    5573              :      in the caller, would use the caller's top of stack address both to
    5574              :      initialize the watermark passed to the callee, and to start strubbing the
    5575              :      stack afterwards.
    5576              : 
    5577              :      Ideally, we'd update the watermark so as to cover the used amount of red
    5578              :      zone, and strub starting at the caller's other end of the (presumably
    5579              :      unused) red zone.  Normally, only leaf functions use the red zone, but at
    5580              :      this point we can't tell whether a function is a leaf, nor can we tell how
    5581              :      much of the red zone it uses.  Furthermore, some strub contexts may have
    5582              :      been inlined so that update and leave are called from the same stack frame,
    5583              :      and the strub builtins may all have been inlined, turning a strub function
    5584              :      into a leaf.
    5585              : 
    5586              :      So cleaning the range from the caller's stack pointer (one end of the red
    5587              :      zone) to the (potentially inlined) callee's (other end of the) red zone
    5588              :      could scribble over the caller's own red zone.
    5589              : 
    5590              :      We avoid this possibility by arranging for callers that are strub contexts
    5591              :      to use their own watermark as the strub starting point.  So, if A calls B,
    5592              :      and B calls C, B will tell A to strub up to the end of B's red zone, and
    5593              :      will strub itself only the part of C's stack frame and red zone that
    5594              :      doesn't overlap with B's.  With that, we don't need to know who's leaf and
    5595              :      who isn't: inlined calls will shrink their strub window to zero, each
    5596              :      remaining call will strub some portion of the stack, and eventually the
    5597              :      strub context will return to a caller that isn't a strub context itself,
    5598              :      that will therefore use its own stack pointer as the strub starting point.
    5599              :      It's not a leaf, because strub contexts can't be inlined into non-strub
    5600              :      contexts, so it doesn't use the red zone, and it will therefore correctly
    5601              :      strub up the callee's stack frame up to the end of the callee's red zone.
    5602              :      Neat!  */
    5603          663 :   if (true /* (flags_from_decl_or_type (current_function_decl) & ECF_LEAF) */)
    5604              :     {
    5605          663 :       poly_int64 red_zone_size = RED_ZONE_SIZE;
    5606              : #if STACK_GROWS_DOWNWARD
    5607          663 :       red_zone_size = -red_zone_size;
    5608              : #endif
    5609          663 :       stktop = plus_constant (ptr_mode, stktop, red_zone_size);
    5610          663 :       stktop = force_reg (ptr_mode, stktop);
    5611              :     }
    5612              : #endif
    5613              : 
    5614          663 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5615          663 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5616          663 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5617              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5618          663 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5619              : 
    5620          663 :   rtx wmark_load = shallow_copy_rtx (wmark);
    5621          663 :   MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
    5622          663 :   rtx wmarkr = force_reg (ptr_mode, wmark_load);
    5623              : 
    5624          663 :   rtx_code_label *lab = gen_label_rtx ();
    5625          663 :   do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
    5626              :                            ptr_mode, NULL_RTX, lab, NULL,
    5627              :                            profile_probability::very_likely ());
    5628          663 :   emit_move_insn (wmark, stktop);
    5629              : 
    5630              :   /* If this is an inlined strub function, also bump the watermark for the
    5631              :      enclosing function.  This avoids a problem with the following scenario: A
    5632              :      calls B and B calls C, and both B and C get inlined into A.  B allocates
    5633              :      temporary stack space before calling C.  If we don't update A's watermark,
    5634              :      we may use an outdated baseline for the post-C strub_leave, erasing B's
    5635              :      temporary stack allocation.  We only need this if we're fully expanding
    5636              :      strub_leave inline.  */
    5637          663 :   tree xwmptr = (optimize > 2
    5638          663 :                  ? strub_watermark_parm (current_function_decl)
    5639              :                  : wmptr);
    5640          663 :   if (wmptr != xwmptr)
    5641              :     {
    5642          156 :       wmptr = xwmptr;
    5643          156 :       wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5644          156 :       wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5645              :                             build_int_cst (TREE_TYPE (wmptr), 0));
    5646          156 :       wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5647          156 :       wmark_load = shallow_copy_rtx (wmark);
    5648          156 :       MEM_NOTRAP_P (wmark_load) = !tree_could_trap_p (wmtree);
    5649          156 :       wmarkr = force_reg (ptr_mode, wmark_load);
    5650              : 
    5651          156 :       do_compare_rtx_and_jump (stktop, wmarkr, STACK_TOPS, STACK_UNSIGNED,
    5652              :                                ptr_mode, NULL_RTX, lab, NULL,
    5653              :                                profile_probability::very_likely ());
    5654          156 :       emit_move_insn (wmark, stktop);
    5655              :     }
    5656              : 
    5657          663 :   emit_label (lab);
    5658              : 
    5659          663 :   return const0_rtx;
    5660              : }
    5661              : 
    5662              : 
    5663              : /* Expand a call to builtin function __builtin_strub_leave.  */
    5664              : 
    5665              : static rtx
    5666         2740 : expand_builtin_strub_leave (tree exp)
    5667              : {
    5668         2740 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    5669              :     return NULL_RTX;
    5670              : 
    5671         2740 :   if (optimize < 2 || optimize_size || flag_no_inline)
    5672              :     return NULL_RTX;
    5673              : 
    5674         1239 :   rtx stktop = NULL_RTX;
    5675              : 
    5676         1239 :   if (tree wmptr = (optimize
    5677         1239 :                     ? strub_watermark_parm (current_function_decl)
    5678              :                     : NULL_TREE))
    5679              :     {
    5680          513 :       tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5681          513 :       tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5682              :                                  build_int_cst (TREE_TYPE (wmptr), 0));
    5683          513 :       rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5684          513 :       MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
    5685          513 :       stktop = force_reg (ptr_mode, wmark);
    5686              :     }
    5687              : 
    5688          513 :   if (!stktop)
    5689          726 :     stktop = expand_builtin_stack_address ();
    5690              : 
    5691         1239 :   tree wmptr = CALL_EXPR_ARG (exp, 0);
    5692         1239 :   tree wmtype = TREE_TYPE (TREE_TYPE (wmptr));
    5693         1239 :   tree wmtree = fold_build2 (MEM_REF, wmtype, wmptr,
    5694              :                              build_int_cst (TREE_TYPE (wmptr), 0));
    5695         1239 :   rtx wmark = expand_expr (wmtree, NULL_RTX, ptr_mode, EXPAND_MEMORY);
    5696         1239 :   MEM_NOTRAP_P (wmark) = !tree_could_trap_p (wmtree);
    5697              : 
    5698         1239 :   rtx wmarkr = force_reg (ptr_mode, wmark);
    5699              : 
    5700              : #if ! STACK_GROWS_DOWNWARD
    5701              :   rtx base = stktop;
    5702              :   rtx end = wmarkr;
    5703              : #else
    5704         1239 :   rtx base = wmarkr;
    5705         1239 :   rtx end = stktop;
    5706              : #endif
    5707              : 
    5708              :   /* We're going to modify it, so make sure it's not e.g. the stack pointer.  */
    5709         1239 :   base = copy_to_reg (base);
    5710              : 
    5711         1239 :   rtx_code_label *done = gen_label_rtx ();
    5712         1239 :   do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
    5713              :                            ptr_mode, NULL_RTX, done, NULL,
    5714              :                            profile_probability::very_likely ());
    5715              : 
    5716         1239 :   if (optimize < 3)
    5717          919 :     expand_call (exp, NULL_RTX, true);
    5718              :   else
    5719              :     {
    5720              :       /* Ok, now we've determined we want to copy the block, so convert the
    5721              :          addresses to Pmode, as needed to dereference them to access ptr_mode
    5722              :          memory locations, so that we don't have to convert anything within the
    5723              :          loop.  */
    5724          320 :       base = memory_address (ptr_mode, base);
    5725          320 :       end = memory_address (ptr_mode, end);
    5726              : 
    5727          320 :       rtx zero = force_operand (const0_rtx, NULL_RTX);
    5728          320 :       int ulen = GET_MODE_SIZE (ptr_mode);
    5729              : 
    5730              :       /* ??? It would be nice to use setmem or similar patterns here,
    5731              :          but they do not necessarily obey the stack growth direction,
    5732              :          which has security implications.  We also have to avoid calls
    5733              :          (memset, bzero or any machine-specific ones), which are
    5734              :          likely unsafe here (see TARGET_STRUB_MAY_USE_MEMSET).  */
    5735              : #if ! STACK_GROWS_DOWNWARD
    5736              :       rtx incr = plus_constant (Pmode, base, ulen);
    5737              :       rtx dstm = gen_rtx_MEM (ptr_mode, base);
    5738              : 
    5739              :       rtx_code_label *loop = gen_label_rtx ();
    5740              :       emit_label (loop);
    5741              :       emit_move_insn (dstm, zero);
    5742              :       emit_move_insn (base, force_operand (incr, NULL_RTX));
    5743              : #else
    5744          320 :       rtx decr = plus_constant (Pmode, end, -ulen);
    5745          320 :       rtx dstm = gen_rtx_MEM (ptr_mode, end);
    5746              : 
    5747          320 :       rtx_code_label *loop = gen_label_rtx ();
    5748          320 :       emit_label (loop);
    5749          320 :       emit_move_insn (end, force_operand (decr, NULL_RTX));
    5750          320 :       emit_move_insn (dstm, zero);
    5751              : #endif
    5752          640 :       do_compare_rtx_and_jump (base, end, LT, STACK_UNSIGNED,
    5753          320 :                                Pmode, NULL_RTX, NULL, loop,
    5754              :                                profile_probability::very_likely ());
    5755              :     }
    5756              : 
    5757         1239 :   emit_label (done);
    5758              : 
    5759         1239 :   return const0_rtx;
    5760              : }
    5761              : 
    5762              : /* Expand EXP, a call to the alloca builtin.  Return NULL_RTX if we
    5763              :    failed and the caller should emit a normal call.  */
    5764              : 
    5765              : static rtx
    5766        27611 : expand_builtin_alloca (tree exp)
    5767              : {
    5768        27611 :   rtx op0;
    5769        27611 :   rtx result;
    5770        27611 :   unsigned int align;
    5771        27611 :   tree fndecl = get_callee_fndecl (exp);
    5772        27611 :   HOST_WIDE_INT max_size;
    5773        27611 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    5774        27611 :   bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
    5775        27611 :   bool valid_arglist
    5776              :     = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5777        27611 :        ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
    5778              :                            VOID_TYPE)
    5779              :        : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
    5780        27609 :          ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
    5781        27611 :          : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
    5782              : 
    5783        27611 :   if (!valid_arglist)
    5784              :     return NULL_RTX;
    5785              : 
    5786              :   /* Compute the argument.  */
    5787        27606 :   op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
    5788              : 
    5789              :   /* Compute the alignment.  */
    5790        51221 :   align = (fcode == BUILT_IN_ALLOCA
    5791        23616 :            ? BIGGEST_ALIGNMENT
    5792         3990 :            : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
    5793              : 
    5794              :   /* Compute the maximum size.  */
    5795            2 :   max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
    5796        27608 :               ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
    5797              :               : -1);
    5798              : 
    5799              :   /* Allocate the desired space.  If the allocation stems from the declaration
    5800              :      of a variable-sized object, it cannot accumulate.  */
    5801        27606 :   result
    5802        27606 :     = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
    5803        27606 :   result = convert_memory_address (ptr_mode, result);
    5804              : 
    5805              :   /* Dynamic allocations for variables are recorded during gimplification.  */
    5806        27606 :   if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
    5807            0 :     record_dynamic_alloc (exp);
    5808              : 
    5809              :   return result;
    5810              : }
    5811              : 
    5812              : /* Emit a call to __asan_allocas_unpoison call in EXP.  Add to second argument
    5813              :    of the call virtual_stack_dynamic_rtx - stack_pointer_rtx, which is the
    5814              :    STACK_DYNAMIC_OFFSET value.  See motivation for this in comment to
    5815              :    handle_builtin_stack_restore function.  */
    5816              : 
    5817              : static rtx
    5818          204 : expand_asan_emit_allocas_unpoison (tree exp)
    5819              : {
    5820          204 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    5821          204 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    5822          204 :   rtx top = expand_expr (arg0, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5823          204 :   rtx bot = expand_expr (arg1, NULL_RTX, ptr_mode, EXPAND_NORMAL);
    5824          204 :   rtx off = expand_simple_binop (Pmode, MINUS, virtual_stack_dynamic_rtx,
    5825              :                                  stack_pointer_rtx, NULL_RTX, 0,
    5826              :                                  OPTAB_LIB_WIDEN);
    5827          204 :   off = convert_modes (ptr_mode, Pmode, off, 0);
    5828          204 :   bot = expand_simple_binop (ptr_mode, PLUS, bot, off, NULL_RTX, 0,
    5829              :                              OPTAB_LIB_WIDEN);
    5830          204 :   rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
    5831          204 :   ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
    5832              :                                  top, ptr_mode, bot, ptr_mode);
    5833          204 :   return ret;
    5834              : }
    5835              : 
    5836              : /* Expand a call to bswap builtin in EXP.
    5837              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5838              :    function in-line.  If convenient, the result should be placed in TARGET.
    5839              :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5840              : 
    5841              : static rtx
    5842         1279 : expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
    5843              :                       rtx subtarget)
    5844              : {
    5845         1279 :   tree arg;
    5846         1279 :   rtx op0;
    5847              : 
    5848         1279 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5849              :     return NULL_RTX;
    5850              : 
    5851         1279 :   arg = CALL_EXPR_ARG (exp, 0);
    5852         1279 :   op0 = expand_expr (arg,
    5853           56 :                      subtarget && GET_MODE (subtarget) == target_mode
    5854              :                      ? subtarget : NULL_RTX,
    5855              :                      target_mode, EXPAND_NORMAL);
    5856         1279 :   if (GET_MODE (op0) != target_mode)
    5857            0 :     op0 = convert_to_mode (target_mode, op0, 1);
    5858              : 
    5859         1279 :   target = expand_unop (target_mode, bswap_optab, op0, target, 1);
    5860              : 
    5861         1279 :   gcc_assert (target);
    5862              : 
    5863         1279 :   return convert_to_mode (target_mode, target, 1);
    5864              : }
    5865              : 
    5866              : /* Expand a call to a unary builtin in EXP.
    5867              :    Return NULL_RTX if a normal call should be emitted rather than expanding the
    5868              :    function in-line.  If convenient, the result should be placed in TARGET.
    5869              :    SUBTARGET may be used as the target for computing one of EXP's operands.  */
    5870              : 
    5871              : static rtx
    5872          854 : expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
    5873              :                      rtx subtarget, optab op_optab)
    5874              : {
    5875          854 :   rtx op0;
    5876              : 
    5877          854 :   if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
    5878              :     return NULL_RTX;
    5879              : 
    5880              :   /* Compute the argument.  */
    5881         1708 :   op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
    5882              :                      (subtarget
    5883          102 :                       && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
    5884          102 :                           == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
    5885              :                      VOIDmode, EXPAND_NORMAL);
    5886              :   /* Compute op, into TARGET if possible.
    5887              :      Set TARGET to wherever the result comes back.  */
    5888          854 :   target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
    5889              :                         op_optab, op0, target, op_optab != clrsb_optab);
    5890          854 :   gcc_assert (target);
    5891              : 
    5892          854 :   return convert_to_mode (target_mode, target, 0);
    5893              : }
    5894              : 
    5895              : /* Expand a call to __builtin_expect.  We just return our argument
    5896              :    as the builtin_expect semantic should've been already executed by
    5897              :    tree branch prediction pass. */
    5898              : 
    5899              : static rtx
    5900         1407 : expand_builtin_expect (tree exp, rtx target)
    5901              : {
    5902         1407 :   tree arg;
    5903              : 
    5904         1407 :   if (call_expr_nargs (exp) < 2)
    5905            0 :     return const0_rtx;
    5906         1407 :   arg = CALL_EXPR_ARG (exp, 0);
    5907              : 
    5908         1407 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5909              :   /* When guessing was done, the hints should be already stripped away.  */
    5910         1407 :   gcc_assert (!flag_guess_branch_prob
    5911              :               || optimize == 0 || seen_error ());
    5912              :   return target;
    5913              : }
    5914              : 
    5915              : /* Expand a call to __builtin_expect_with_probability.  We just return our
    5916              :    argument as the builtin_expect semantic should've been already executed by
    5917              :    tree branch prediction pass.  */
    5918              : 
    5919              : static rtx
    5920            5 : expand_builtin_expect_with_probability (tree exp, rtx target)
    5921              : {
    5922            5 :   tree arg;
    5923              : 
    5924            5 :   if (call_expr_nargs (exp) < 3)
    5925            0 :     return const0_rtx;
    5926            5 :   arg = CALL_EXPR_ARG (exp, 0);
    5927              : 
    5928            5 :   target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    5929              :   /* When guessing was done, the hints should be already stripped away.  */
    5930            5 :   gcc_assert (!flag_guess_branch_prob
    5931              :               || optimize == 0 || seen_error ());
    5932              :   return target;
    5933              : }
    5934              : 
    5935              : 
    5936              : /* Expand a call to __builtin_assume_aligned.  We just return our first
    5937              :    argument as the builtin_assume_aligned semantic should've been already
    5938              :    executed by CCP.  */
    5939              : 
    5940              : static rtx
    5941          665 : expand_builtin_assume_aligned (tree exp, rtx target)
    5942              : {
    5943          665 :   if (call_expr_nargs (exp) < 2)
    5944            0 :     return const0_rtx;
    5945          665 :   target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
    5946              :                         EXPAND_NORMAL);
    5947          665 :   gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
    5948              :               && (call_expr_nargs (exp) < 3
    5949              :                   || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
    5950              :   return target;
    5951              : }
    5952              : 
    5953              : void
    5954        38677 : expand_builtin_trap (void)
    5955              : {
    5956        38677 :   if (targetm.have_trap ())
    5957              :     {
    5958        38677 :       rtx_insn *insn = emit_insn (targetm.gen_trap ());
    5959              :       /* For trap insns when not accumulating outgoing args force
    5960              :          REG_ARGS_SIZE note to prevent crossjumping of calls with
    5961              :          different args sizes.  */
    5962        38677 :       if (!ACCUMULATE_OUTGOING_ARGS)
    5963        38675 :         add_args_size_note (insn, stack_pointer_delta);
    5964              :     }
    5965              :   else
    5966              :     {
    5967            0 :       tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
    5968            0 :       tree call_expr = build_call_expr (fn, 0);
    5969            0 :       expand_call (call_expr, NULL_RTX, false);
    5970              :     }
    5971              : 
    5972        38677 :   emit_barrier ();
    5973        38677 : }
    5974              : 
    5975              : /* Expand a call to __builtin_unreachable.  We do nothing except emit
    5976              :    a barrier saying that control flow will not pass here.
    5977              : 
    5978              :    It is the responsibility of the program being compiled to ensure
    5979              :    that control flow does never reach __builtin_unreachable.  */
    5980              : static void
    5981         2563 : expand_builtin_unreachable (void)
    5982              : {
    5983              :   /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable
    5984              :      to avoid this.  */
    5985         2563 :   gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE));
    5986         2563 :   emit_barrier ();
    5987         2563 : }
    5988              : 
    5989              : /* Expand EXP, a call to fabs, fabsf or fabsl.
    5990              :    Return NULL_RTX if a normal call should be emitted rather than expanding
    5991              :    the function inline.  If convenient, the result should be placed
    5992              :    in TARGET.  SUBTARGET may be used as the target for computing
    5993              :    the operand.  */
    5994              : 
    5995              : static rtx
    5996            4 : expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
    5997              : {
    5998            4 :   machine_mode mode;
    5999            4 :   tree arg;
    6000            4 :   rtx op0;
    6001              : 
    6002            4 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    6003              :     return NULL_RTX;
    6004              : 
    6005            0 :   arg = CALL_EXPR_ARG (exp, 0);
    6006            0 :   CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
    6007            0 :   mode = TYPE_MODE (TREE_TYPE (arg));
    6008            0 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6009            0 :   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
    6010              : }
    6011              : 
    6012              : /* Expand EXP, a call to copysign, copysignf, or copysignl.
    6013              :    Return NULL is a normal call should be emitted rather than expanding the
    6014              :    function inline.  If convenient, the result should be placed in TARGET.
    6015              :    SUBTARGET may be used as the target for computing the operand.  */
    6016              : 
    6017              : static rtx
    6018        11677 : expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
    6019              : {
    6020        11677 :   rtx op0, op1;
    6021        11677 :   tree arg;
    6022              : 
    6023        11677 :   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
    6024              :     return NULL_RTX;
    6025              : 
    6026        11676 :   arg = CALL_EXPR_ARG (exp, 0);
    6027        11676 :   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
    6028              : 
    6029        11676 :   arg = CALL_EXPR_ARG (exp, 1);
    6030        11676 :   op1 = expand_normal (arg);
    6031              : 
    6032        11676 :   return expand_copysign (op0, op1, target);
    6033              : }
    6034              : 
    6035              : /* Emit a call to __builtin___clear_cache.  */
    6036              : 
    6037              : void
    6038            0 : default_emit_call_builtin___clear_cache (rtx begin, rtx end)
    6039              : {
    6040            0 :   rtx callee = gen_rtx_SYMBOL_REF (Pmode,
    6041              :                                    BUILTIN_ASM_NAME_PTR
    6042              :                                    (BUILT_IN_CLEAR_CACHE));
    6043              : 
    6044            0 :   emit_library_call (callee,
    6045              :                      LCT_NORMAL, VOIDmode,
    6046              :                      convert_memory_address (ptr_mode, begin), ptr_mode,
    6047              :                      convert_memory_address (ptr_mode, end), ptr_mode);
    6048            0 : }
    6049              : 
    6050              : /* Emit a call to __builtin___clear_cache, unless the target specifies
    6051              :    it as do-nothing.  This function can be used by trampoline
    6052              :    finalizers to duplicate the effects of expanding a call to the
    6053              :    clear_cache builtin.  */
    6054              : 
    6055              : void
    6056           28 : maybe_emit_call_builtin___clear_cache (rtx begin, rtx end)
    6057              : {
    6058           28 :   gcc_assert ((GET_MODE (begin) == ptr_mode || GET_MODE (begin) == Pmode
    6059              :                || CONST_INT_P (begin))
    6060              :               && (GET_MODE (end) == ptr_mode || GET_MODE (end) == Pmode
    6061              :                   || CONST_INT_P (end)));
    6062              : 
    6063           28 :   if (targetm.have_clear_cache ())
    6064              :     {
    6065              :       /* We have a "clear_cache" insn, and it will handle everything.  */
    6066            0 :       class expand_operand ops[2];
    6067              : 
    6068            0 :       create_address_operand (&ops[0], begin);
    6069            0 :       create_address_operand (&ops[1], end);
    6070              : 
    6071            0 :       if (maybe_expand_insn (targetm.code_for_clear_cache, 2, ops))
    6072            0 :         return;
    6073              :     }
    6074              :   else
    6075              :     {
    6076              : #ifndef CLEAR_INSN_CACHE
    6077              :       /* There is no "clear_cache" insn, and __clear_cache() in libgcc
    6078              :          does nothing.  There is no need to call it.  Do nothing.  */
    6079              :       return;
    6080              : #endif /* CLEAR_INSN_CACHE */
    6081              :     }
    6082              : 
    6083            0 :   targetm.calls.emit_call_builtin___clear_cache (begin, end);
    6084              : }
    6085              : 
    6086              : /* Expand a call to __builtin___clear_cache.  */
    6087              : 
    6088              : static void
    6089           28 : expand_builtin___clear_cache (tree exp)
    6090              : {
    6091           28 :   tree begin, end;
    6092           28 :   rtx begin_rtx, end_rtx;
    6093              : 
    6094              :   /* We must not expand to a library call.  If we did, any
    6095              :      fallback library function in libgcc that might contain a call to
    6096              :      __builtin___clear_cache() would recurse infinitely.  */
    6097           28 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    6098              :     {
    6099            0 :       error ("both arguments to %<__builtin___clear_cache%> must be pointers");
    6100            0 :       return;
    6101              :     }
    6102              : 
    6103           28 :   begin = CALL_EXPR_ARG (exp, 0);
    6104           30 :   begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
    6105              : 
    6106           28 :   end = CALL_EXPR_ARG (exp, 1);
    6107           30 :   end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
    6108              : 
    6109           28 :   maybe_emit_call_builtin___clear_cache (begin_rtx, end_rtx);
    6110              : }
    6111              : 
    6112              : /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
    6113              : 
    6114              : static rtx
    6115          659 : round_trampoline_addr (rtx tramp)
    6116              : {
    6117          659 :   rtx temp, addend, mask;
    6118              : 
    6119              :   /* If we don't need too much alignment, we'll have been guaranteed
    6120              :      proper alignment by get_trampoline_type.  */
    6121          659 :   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
    6122              :     return tramp;
    6123              : 
    6124              :   /* Round address up to desired boundary.  */
    6125            0 :   temp = gen_reg_rtx (Pmode);
    6126            0 :   addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
    6127            0 :   mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
    6128              : 
    6129            0 :   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
    6130              :                                temp, 0, OPTAB_LIB_WIDEN);
    6131            0 :   tramp = expand_simple_binop (Pmode, AND, temp, mask,
    6132              :                                temp, 0, OPTAB_LIB_WIDEN);
    6133              : 
    6134            0 :   return tramp;
    6135              : }
    6136              : 
    6137              : static rtx
    6138          306 : expand_builtin_init_trampoline (tree exp, bool onstack)
    6139              : {
    6140          306 :   tree t_tramp, t_func, t_chain;
    6141          306 :   rtx m_tramp, r_tramp, r_chain, tmp;
    6142              : 
    6143          306 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
    6144              :                          POINTER_TYPE, VOID_TYPE))
    6145              :     return NULL_RTX;
    6146              : 
    6147          306 :   t_tramp = CALL_EXPR_ARG (exp, 0);
    6148          306 :   t_func = CALL_EXPR_ARG (exp, 1);
    6149          306 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6150              : 
    6151          306 :   r_tramp = expand_normal (t_tramp);
    6152          306 :   m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
    6153          306 :   MEM_NOTRAP_P (m_tramp) = 1;
    6154              : 
    6155              :   /* If ONSTACK, the TRAMP argument should be the address of a field
    6156              :      within the local function's FRAME decl.  Either way, let's see if
    6157              :      we can fill in the MEM_ATTRs for this memory.  */
    6158          306 :   if (TREE_CODE (t_tramp) == ADDR_EXPR)
    6159          306 :     set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
    6160              : 
    6161              :   /* Creator of a heap trampoline is responsible for making sure the
    6162              :      address is aligned to at least STACK_BOUNDARY.  Normally malloc
    6163              :      will ensure this anyhow.  */
    6164          306 :   tmp = round_trampoline_addr (r_tramp);
    6165          306 :   if (tmp != r_tramp)
    6166              :     {
    6167            0 :       m_tramp = change_address (m_tramp, BLKmode, tmp);
    6168            0 :       set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
    6169            0 :       set_mem_size (m_tramp, TRAMPOLINE_SIZE);
    6170              :     }
    6171              : 
    6172              :   /* The FUNC argument should be the address of the nested function.
    6173              :      Extract the actual function decl to pass to the hook.  */
    6174          306 :   gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
    6175          306 :   t_func = TREE_OPERAND (t_func, 0);
    6176          306 :   gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
    6177              : 
    6178          306 :   r_chain = expand_normal (t_chain);
    6179              : 
    6180              :   /* Generate insns to initialize the trampoline.  */
    6181          306 :   targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
    6182              : 
    6183          306 :   if (onstack)
    6184              :     {
    6185          306 :       trampolines_created = 1;
    6186              : 
    6187          306 :       if (targetm.calls.custom_function_descriptors != 0)
    6188          306 :         warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
    6189              :                     "trampoline generated for nested function %qD", t_func);
    6190              :     }
    6191              : 
    6192          306 :   return const0_rtx;
    6193              : }
    6194              : 
    6195              : static rtx
    6196          353 : expand_builtin_adjust_trampoline (tree exp)
    6197              : {
    6198          353 :   rtx tramp;
    6199              : 
    6200          353 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6201              :     return NULL_RTX;
    6202              : 
    6203          353 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6204          353 :   tramp = round_trampoline_addr (tramp);
    6205          353 :   if (targetm.calls.trampoline_adjust_address)
    6206            0 :     tramp = targetm.calls.trampoline_adjust_address (tramp);
    6207              : 
    6208              :   return tramp;
    6209              : }
    6210              : 
    6211              : /* Expand a call to the builtin descriptor initialization routine.
    6212              :    A descriptor is made up of a couple of pointers to the static
    6213              :    chain and the code entry in this order.  */
    6214              : 
    6215              : static rtx
    6216            0 : expand_builtin_init_descriptor (tree exp)
    6217              : {
    6218            0 :   tree t_descr, t_func, t_chain;
    6219            0 :   rtx m_descr, r_descr, r_func, r_chain;
    6220              : 
    6221            0 :   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
    6222              :                          VOID_TYPE))
    6223              :     return NULL_RTX;
    6224              : 
    6225            0 :   t_descr = CALL_EXPR_ARG (exp, 0);
    6226            0 :   t_func = CALL_EXPR_ARG (exp, 1);
    6227            0 :   t_chain = CALL_EXPR_ARG (exp, 2);
    6228              : 
    6229            0 :   r_descr = expand_normal (t_descr);
    6230            0 :   m_descr = gen_rtx_MEM (BLKmode, r_descr);
    6231            0 :   MEM_NOTRAP_P (m_descr) = 1;
    6232            0 :   set_mem_align (m_descr, GET_MODE_ALIGNMENT (ptr_mode));
    6233              : 
    6234            0 :   r_func = expand_normal (t_func);
    6235            0 :   r_chain = expand_normal (t_chain);
    6236              : 
    6237              :   /* Generate insns to initialize the descriptor.  */
    6238            0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode, 0), r_chain);
    6239            0 :   emit_move_insn (adjust_address_nv (m_descr, ptr_mode,
    6240              :                                      POINTER_SIZE / BITS_PER_UNIT), r_func);
    6241              : 
    6242            0 :   return const0_rtx;
    6243              : }
    6244              : 
    6245              : /* Expand a call to the builtin descriptor adjustment routine.  */
    6246              : 
    6247              : static rtx
    6248            0 : expand_builtin_adjust_descriptor (tree exp)
    6249              : {
    6250            0 :   rtx tramp;
    6251              : 
    6252            0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    6253              :     return NULL_RTX;
    6254              : 
    6255            0 :   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
    6256              : 
    6257              :   /* Unalign the descriptor to allow runtime identification.  */
    6258            0 :   tramp = plus_constant (ptr_mode, tramp,
    6259            0 :                          targetm.calls.custom_function_descriptors);
    6260              : 
    6261            0 :   return force_operand (tramp, NULL_RTX);
    6262              : }
    6263              : 
    6264              : /* Expand the call EXP to the built-in signbit, signbitf or signbitl
    6265              :    function.  The function first checks whether the back end provides
    6266              :    an insn to implement signbit for the respective mode.  If not, it
    6267              :    checks whether the floating point format of the value is such that
    6268              :    the sign bit can be extracted.  If that is not the case, error out.
    6269              :    EXP is the expression that is a call to the builtin function; if
    6270              :    convenient, the result should be placed in TARGET.  */
    6271              : static rtx
    6272         1368 : expand_builtin_signbit (tree exp, rtx target)
    6273              : {
    6274         1368 :   const struct real_format *fmt;
    6275         1368 :   scalar_float_mode fmode;
    6276         1368 :   scalar_int_mode rmode, imode;
    6277         1368 :   tree arg;
    6278         1368 :   int word, bitpos;
    6279         1368 :   enum insn_code icode;
    6280         1368 :   rtx temp;
    6281         1368 :   location_t loc = EXPR_LOCATION (exp);
    6282              : 
    6283         1368 :   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
    6284              :     return NULL_RTX;
    6285              : 
    6286         1368 :   arg = CALL_EXPR_ARG (exp, 0);
    6287         1368 :   fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
    6288         1368 :   rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
    6289         1368 :   fmt = REAL_MODE_FORMAT (fmode);
    6290              : 
    6291         1368 :   arg = builtin_save_expr (arg);
    6292              : 
    6293              :   /* Expand the argument yielding a RTX expression. */
    6294         1368 :   temp = expand_normal (arg);
    6295              : 
    6296              :   /* Check if the back end provides an insn that handles signbit for the
    6297              :      argument's mode. */
    6298         1368 :   icode = optab_handler (signbit_optab, fmode);
    6299         1368 :   if (icode != CODE_FOR_nothing)
    6300              :     {
    6301           10 :       rtx_insn *last = get_last_insn ();
    6302           10 :       rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    6303           10 :       if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN))
    6304              :         return this_target;
    6305            0 :       delete_insns_since (last);
    6306              :     }
    6307              : 
    6308              :   /* For floating point formats without a sign bit, implement signbit
    6309              :      as "ARG < 0.0".  */
    6310         1358 :   bitpos = fmt->signbit_ro;
    6311         1358 :   if (bitpos < 0)
    6312              :   {
    6313              :     /* But we can't do this if the format supports signed zero.  */
    6314            0 :     gcc_assert (!fmt->has_signed_zero || !HONOR_SIGNED_ZEROS (fmode));
    6315              : 
    6316            0 :     arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
    6317            0 :                        build_real (TREE_TYPE (arg), dconst0));
    6318            0 :     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
    6319              :   }
    6320              : 
    6321         2720 :   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
    6322              :     {
    6323         1254 :       imode = int_mode_for_mode (fmode).require ();
    6324         1254 :       temp = gen_lowpart (imode, temp);
    6325              :     }
    6326              :   else
    6327              :     {
    6328          104 :       imode = word_mode;
    6329              :       /* Handle targets with different FP word orders.  */
    6330          104 :       if (FLOAT_WORDS_BIG_ENDIAN)
    6331              :         word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
    6332              :       else
    6333          104 :         word = bitpos / BITS_PER_WORD;
    6334          104 :       temp = operand_subword_force (temp, word, fmode);
    6335          104 :       bitpos = bitpos % BITS_PER_WORD;
    6336              :     }
    6337              : 
    6338              :   /* Force the intermediate word_mode (or narrower) result into a
    6339              :      register.  This avoids attempting to create paradoxical SUBREGs
    6340              :      of floating point modes below.  */
    6341         1358 :   temp = force_reg (imode, temp);
    6342              : 
    6343              :   /* If the bitpos is within the "result mode" lowpart, the operation
    6344              :      can be implement with a single bitwise AND.  Otherwise, we need
    6345              :      a right shift and an AND.  */
    6346              : 
    6347         2716 :   if (bitpos < GET_MODE_BITSIZE (rmode))
    6348              :     {
    6349         1150 :       wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
    6350              : 
    6351         3450 :       if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
    6352            0 :         temp = gen_lowpart (rmode, temp);
    6353         2300 :       temp = expand_binop (rmode, and_optab, temp,
    6354         2300 :                            immed_wide_int_const (mask, rmode),
    6355              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6356         1150 :     }
    6357              :   else
    6358              :     {
    6359              :       /* Perform a logical right shift to place the signbit in the least
    6360              :          significant bit, then truncate the result to the desired mode
    6361              :          and mask just this bit.  */
    6362          208 :       temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
    6363          208 :       temp = gen_lowpart (rmode, temp);
    6364          208 :       temp = expand_binop (rmode, and_optab, temp, const1_rtx,
    6365              :                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
    6366              :     }
    6367              : 
    6368              :   return temp;
    6369              : }
    6370              : 
    6371              : /* Expand fork or exec calls.  TARGET is the desired target of the
    6372              :    call.  EXP is the call. FN is the
    6373              :    identificator of the actual function.  IGNORE is nonzero if the
    6374              :    value is to be ignored.  */
    6375              : 
    6376              : static rtx
    6377          111 : expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
    6378              : {
    6379          111 :   tree id, decl;
    6380          111 :   tree call;
    6381              : 
    6382              :   /* If we are not profiling, just call the function.  */
    6383          111 :   if (!coverage_instrumentation_p ())
    6384              :     return NULL_RTX;
    6385              : 
    6386              :   /* Otherwise call the wrapper.  This should be equivalent for the rest of
    6387              :      compiler, so the code does not diverge, and the wrapper may run the
    6388              :      code necessary for keeping the profiling sane.  */
    6389              : 
    6390            4 :   switch (DECL_FUNCTION_CODE (fn))
    6391              :     {
    6392            4 :     case BUILT_IN_FORK:
    6393            4 :       id = get_identifier ("__gcov_fork");
    6394            4 :       break;
    6395              : 
    6396            0 :     case BUILT_IN_EXECL:
    6397            0 :       id = get_identifier ("__gcov_execl");
    6398            0 :       break;
    6399              : 
    6400            0 :     case BUILT_IN_EXECV:
    6401            0 :       id = get_identifier ("__gcov_execv");
    6402            0 :       break;
    6403              : 
    6404            0 :     case BUILT_IN_EXECLP:
    6405            0 :       id = get_identifier ("__gcov_execlp");
    6406            0 :       break;
    6407              : 
    6408            0 :     case BUILT_IN_EXECLE:
    6409            0 :       id = get_identifier ("__gcov_execle");
    6410            0 :       break;
    6411              : 
    6412            0 :     case BUILT_IN_EXECVP:
    6413            0 :       id = get_identifier ("__gcov_execvp");
    6414            0 :       break;
    6415              : 
    6416            0 :     case BUILT_IN_EXECVE:
    6417            0 :       id = get_identifier ("__gcov_execve");
    6418            0 :       break;
    6419              : 
    6420            0 :     default:
    6421            0 :       gcc_unreachable ();
    6422              :     }
    6423              : 
    6424            4 :   decl = build_decl (DECL_SOURCE_LOCATION (fn),
    6425            4 :                      FUNCTION_DECL, id, TREE_TYPE (fn));
    6426            4 :   DECL_EXTERNAL (decl) = 1;
    6427            4 :   TREE_PUBLIC (decl) = 1;
    6428            4 :   DECL_ARTIFICIAL (decl) = 1;
    6429            4 :   TREE_NOTHROW (decl) = 1;
    6430            4 :   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
    6431            4 :   DECL_VISIBILITY_SPECIFIED (decl) = 1;
    6432            4 :   call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
    6433            4 :   return expand_call (call, target, ignore);
    6434              :  }
    6435              : 
    6436              : 
    6437              : 
    6438              : /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
    6439              :    the pointer in these functions is void*, the tree optimizers may remove
    6440              :    casts.  The mode computed in expand_builtin isn't reliable either, due
    6441              :    to __sync_bool_compare_and_swap.
    6442              : 
    6443              :    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
    6444              :    group of builtins.  This gives us log2 of the mode size.  */
    6445              : 
    6446              : static inline machine_mode
    6447       134161 : get_builtin_sync_mode (int fcode_diff)
    6448              : {
    6449              :   /* The size is not negotiable, so ask not to get BLKmode in return
    6450              :      if the target indicates that a smaller size would be better.  */
    6451       134161 :   return int_mode_for_size (BITS_PER_UNIT << fcode_diff, 0).require ();
    6452              : }
    6453              : 
    6454              : /* Expand the memory expression LOC and return the appropriate memory operand
    6455              :    for the builtin_sync operations.  */
    6456              : 
    6457              : static rtx
    6458       150797 : get_builtin_sync_mem (tree loc, machine_mode mode)
    6459              : {
    6460       150797 :   rtx addr, mem;
    6461       150797 :   int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
    6462              :                                     ? TREE_TYPE (TREE_TYPE (loc))
    6463              :                                     : TREE_TYPE (loc));
    6464       150797 :   scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
    6465              : 
    6466       150797 :   addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
    6467       150797 :   addr = convert_memory_address (addr_mode, addr);
    6468              : 
    6469              :   /* Note that we explicitly do not want any alias information for this
    6470              :      memory, so that we kill all other live memories.  Otherwise we don't
    6471              :      satisfy the full barrier semantics of the intrinsic.  */
    6472       150797 :   mem = gen_rtx_MEM (mode, addr);
    6473              : 
    6474       150797 :   set_mem_addr_space (mem, addr_space);
    6475              : 
    6476       150797 :   mem = validize_mem (mem);
    6477              : 
    6478              :   /* The alignment needs to be at least according to that of the mode.  */
    6479       150797 :   set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
    6480              :                            get_pointer_alignment (loc)));
    6481       150797 :   set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
    6482       150797 :   MEM_VOLATILE_P (mem) = 1;
    6483              : 
    6484       150797 :   return mem;
    6485              : }
    6486              : 
    6487              : /* Make sure an argument is in the right mode.
    6488              :    EXP is the tree argument.
    6489              :    MODE is the mode it should be in.  */
    6490              : 
    6491              : static rtx
    6492        94182 : expand_expr_force_mode (tree exp, machine_mode mode)
    6493              : {
    6494        94182 :   rtx val;
    6495        94182 :   machine_mode old_mode;
    6496              : 
    6497        94182 :   if (TREE_CODE (exp) == SSA_NAME
    6498        94182 :       && TYPE_MODE (TREE_TYPE (exp)) != mode)
    6499              :     {
    6500              :       /* Undo argument promotion if possible, as combine might not
    6501              :          be able to do it later due to MEM_VOLATILE_P uses in the
    6502              :          patterns.  */
    6503           25 :       gimple *g = get_gimple_for_ssa_name (exp);
    6504           25 :       if (g && gimple_assign_cast_p (g))
    6505              :         {
    6506            0 :           tree rhs = gimple_assign_rhs1 (g);
    6507            0 :           tree_code code = gimple_assign_rhs_code (g);
    6508            0 :           if (CONVERT_EXPR_CODE_P (code)
    6509            0 :               && TYPE_MODE (TREE_TYPE (rhs)) == mode
    6510            0 :               && INTEGRAL_TYPE_P (TREE_TYPE (exp))
    6511            0 :               && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
    6512            0 :               && (TYPE_PRECISION (TREE_TYPE (exp))
    6513            0 :                   > TYPE_PRECISION (TREE_TYPE (rhs))))
    6514              :             exp = rhs;
    6515              :         }
    6516              :     }
    6517              : 
    6518        94182 :   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
    6519              :   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
    6520              :      of CONST_INTs, where we know the old_mode only from the call argument.  */
    6521              : 
    6522        94182 :   old_mode = GET_MODE (val);
    6523        94182 :   if (old_mode == VOIDmode)
    6524        44268 :     old_mode = TYPE_MODE (TREE_TYPE (exp));
    6525        94182 :   val = convert_modes (mode, old_mode, val, 1);
    6526        94182 :   return val;
    6527              : }
    6528              : 
    6529              : 
    6530              : /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
    6531              :    EXP is the CALL_EXPR.  CODE is the rtx code
    6532              :    that corresponds to the arithmetic or logical operation from the name;
    6533              :    an exception here is that NOT actually means NAND.  TARGET is an optional
    6534              :    place for us to store the results; AFTER is true if this is the
    6535              :    fetch_and_xxx form.  */
    6536              : 
    6537              : static rtx
    6538         4028 : expand_builtin_sync_operation (machine_mode mode, tree exp,
    6539              :                                enum rtx_code code, bool after,
    6540              :                                rtx target)
    6541              : {
    6542         4028 :   rtx val, mem;
    6543         4028 :   location_t loc = EXPR_LOCATION (exp);
    6544              : 
    6545         4028 :   if (code == NOT && warn_sync_nand)
    6546              :     {
    6547          523 :       tree fndecl = get_callee_fndecl (exp);
    6548          523 :       enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    6549              : 
    6550          523 :       static bool warned_f_a_n, warned_n_a_f;
    6551              : 
    6552          523 :       switch (fcode)
    6553              :         {
    6554          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    6555          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    6556          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    6557          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    6558          434 :         case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    6559          434 :           if (warned_f_a_n)
    6560              :             break;
    6561              : 
    6562           30 :           fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
    6563           30 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6564           30 :           warned_f_a_n = true;
    6565           30 :           break;
    6566              : 
    6567           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    6568           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    6569           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    6570           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    6571           89 :         case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    6572           89 :           if (warned_n_a_f)
    6573              :             break;
    6574              : 
    6575           22 :          fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
    6576           22 :           inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
    6577           22 :           warned_n_a_f = true;
    6578           22 :           break;
    6579              : 
    6580            0 :         default:
    6581            0 :           gcc_unreachable ();
    6582              :         }
    6583              :     }
    6584              : 
    6585              :   /* Expand the operands.  */
    6586         4028 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6587         4028 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6588              : 
    6589         4028 :   return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
    6590         4028 :                                  after);
    6591              : }
    6592              : 
    6593              : /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
    6594              :    intrinsics. EXP is the CALL_EXPR.  IS_BOOL is
    6595              :    true if this is the boolean form.  TARGET is a place for us to store the
    6596              :    results; this is NOT optional if IS_BOOL is true.  */
    6597              : 
    6598              : static rtx
    6599          460 : expand_builtin_compare_and_swap (machine_mode mode, tree exp,
    6600              :                                  bool is_bool, rtx target)
    6601              : {
    6602          460 :   rtx old_val, new_val, mem;
    6603          460 :   rtx *pbool, *poval;
    6604              : 
    6605              :   /* Expand the operands.  */
    6606          460 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6607          460 :   old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6608          460 :   new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6609              : 
    6610          460 :   pbool = poval = NULL;
    6611          460 :   if (target != const0_rtx)
    6612              :     {
    6613          434 :       if (is_bool)
    6614              :         pbool = &target;
    6615              :       else
    6616          230 :         poval = &target;
    6617              :     }
    6618          460 :   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
    6619              :                                        false, MEMMODEL_SYNC_SEQ_CST,
    6620              :                                        MEMMODEL_SYNC_SEQ_CST))
    6621              :     return NULL_RTX;
    6622              : 
    6623          458 :   return target;
    6624              : }
    6625              : 
    6626              : /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
    6627              :    general form is actually an atomic exchange, and some targets only
    6628              :    support a reduced form with the second argument being a constant 1.
    6629              :    EXP is the CALL_EXPR; TARGET is an optional place for us to store
    6630              :    the results.  */
    6631              : 
    6632              : static rtx
    6633          326 : expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
    6634              :                                        rtx target)
    6635              : {
    6636          326 :   rtx val, mem;
    6637              : 
    6638              :   /* Expand the operands.  */
    6639          326 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6640          326 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6641              : 
    6642          326 :   return expand_sync_lock_test_and_set (target, mem, val);
    6643              : }
    6644              : 
    6645              : /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
    6646              : 
    6647              : static rtx
    6648          146 : expand_builtin_sync_lock_release (machine_mode mode, tree exp)
    6649              : {
    6650          146 :   rtx mem;
    6651              : 
    6652              :   /* Expand the operands.  */
    6653          146 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6654              : 
    6655          146 :   return expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
    6656              : }
    6657              : 
    6658              : /* Given an integer representing an ``enum memmodel'', verify its
    6659              :    correctness and return the memory model enum.  */
    6660              : 
    6661              : static enum memmodel
    6662       169300 : get_memmodel (tree exp)
    6663              : {
    6664              :   /* If the parameter is not a constant, it's a run time value so we'll just
    6665              :      convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking.  */
    6666       169300 :   if (TREE_CODE (exp) != INTEGER_CST)
    6667              :     return MEMMODEL_SEQ_CST;
    6668              : 
    6669       168473 :   rtx op = expand_normal (exp);
    6670              : 
    6671       168473 :   unsigned HOST_WIDE_INT val = INTVAL (op);
    6672       168473 :   if (targetm.memmodel_check)
    6673       168473 :     val = targetm.memmodel_check (val);
    6674            0 :   else if (val & ~MEMMODEL_MASK)
    6675              :     return MEMMODEL_SEQ_CST;
    6676              : 
    6677              :   /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
    6678       168473 :   if (memmodel_base (val) >= MEMMODEL_LAST)
    6679              :     return MEMMODEL_SEQ_CST;
    6680              : 
    6681              :   /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
    6682              :      be conservative and promote consume to acquire.  */
    6683       168470 :   if (val == MEMMODEL_CONSUME)
    6684          755 :     val = MEMMODEL_ACQUIRE;
    6685              : 
    6686       168470 :   return (enum memmodel) val;
    6687              : }
    6688              : 
    6689              : /* Expand the __atomic_exchange intrinsic:
    6690              :         TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
    6691              :    EXP is the CALL_EXPR.
    6692              :    TARGET is an optional place for us to store the results.  */
    6693              : 
    6694              : static rtx
    6695         2937 : expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
    6696              : {
    6697         2937 :   rtx val, mem;
    6698         2937 :   enum memmodel model;
    6699              : 
    6700         2937 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6701              : 
    6702         2937 :   if (!flag_inline_atomics)
    6703              :     return NULL_RTX;
    6704              : 
    6705              :   /* Expand the operands.  */
    6706         2886 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6707         2886 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6708              : 
    6709         2886 :   return expand_atomic_exchange (target, mem, val, model);
    6710              : }
    6711              : 
    6712              : /* Expand the __atomic_compare_exchange intrinsic:
    6713              :         bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
    6714              :                                         TYPE desired, BOOL weak,
    6715              :                                         enum memmodel success,
    6716              :                                         enum memmodel failure)
    6717              :    EXP is the CALL_EXPR.
    6718              :    TARGET is an optional place for us to store the results.  */
    6719              : 
    6720              : static rtx
    6721         9129 : expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
    6722              :                                         rtx target)
    6723              : {
    6724         9129 :   rtx expect, desired, mem, oldval;
    6725         9129 :   rtx_code_label *label;
    6726         9129 :   tree weak;
    6727         9129 :   bool is_weak;
    6728              : 
    6729         9129 :   memmodel success = get_memmodel (CALL_EXPR_ARG (exp, 4));
    6730         9129 :   memmodel failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
    6731              : 
    6732         9129 :   if (failure > success)
    6733           22 :     success = MEMMODEL_SEQ_CST;
    6734              : 
    6735         9129 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6736              :     {
    6737              :       failure = MEMMODEL_SEQ_CST;
    6738              :       success = MEMMODEL_SEQ_CST;
    6739              :     }
    6740              : 
    6741              : 
    6742         9129 :   if (!flag_inline_atomics)
    6743              :     return NULL_RTX;
    6744              : 
    6745              :   /* Expand the operands.  */
    6746         9078 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6747              : 
    6748         9078 :   expect = expand_normal (CALL_EXPR_ARG (exp, 1));
    6749         9114 :   expect = convert_memory_address (Pmode, expect);
    6750         9078 :   expect = gen_rtx_MEM (mode, expect);
    6751         9078 :   desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
    6752              : 
    6753         9078 :   weak = CALL_EXPR_ARG (exp, 3);
    6754         9078 :   is_weak = false;
    6755         9078 :   if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
    6756         9078 :     is_weak = true;
    6757              : 
    6758         9078 :   if (target == const0_rtx)
    6759          287 :     target = NULL;
    6760              : 
    6761              :   /* Lest the rtl backend create a race condition with an imporoper store
    6762              :      to memory, always create a new pseudo for OLDVAL.  */
    6763         9078 :   oldval = NULL;
    6764              : 
    6765         9078 :   if (!expand_atomic_compare_and_swap (&target, &oldval, mem, expect, desired,
    6766              :                                        is_weak, success, failure))
    6767              :     return NULL_RTX;
    6768              : 
    6769              :   /* Conditionally store back to EXPECT, lest we create a race condition
    6770              :      with an improper store to memory.  */
    6771              :   /* ??? With a rearrangement of atomics at the gimple level, we can handle
    6772              :      the normal case where EXPECT is totally private, i.e. a register.  At
    6773              :      which point the store can be unconditional.  */
    6774         7329 :   label = gen_label_rtx ();
    6775         7329 :   emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
    6776         7329 :                            GET_MODE (target), 1, label);
    6777         7329 :   emit_move_insn (expect, oldval);
    6778         7329 :   emit_label (label);
    6779              : 
    6780         7329 :   return target;
    6781              : }
    6782              : 
    6783              : /* Helper function for expand_ifn_atomic_compare_exchange - expand
    6784              :    internal ATOMIC_COMPARE_EXCHANGE call into __atomic_compare_exchange_N
    6785              :    call.  The weak parameter must be dropped to match the expected parameter
    6786              :    list and the expected argument changed from value to pointer to memory
    6787              :    slot.  */
    6788              : 
    6789              : static void
    6790            0 : expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
    6791              : {
    6792            0 :   unsigned int z;
    6793            0 :   vec<tree, va_gc> *vec;
    6794              : 
    6795            0 :   vec_alloc (vec, 5);
    6796            0 :   vec->quick_push (gimple_call_arg (call, 0));
    6797            0 :   tree expected = gimple_call_arg (call, 1);
    6798            0 :   rtx x = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
    6799            0 :                                       TREE_TYPE (expected));
    6800            0 :   rtx expd = expand_expr (expected, x, mode, EXPAND_NORMAL);
    6801            0 :   if (expd != x)
    6802            0 :     emit_move_insn (x, expd);
    6803            0 :   tree v = make_tree (TREE_TYPE (expected), x);
    6804            0 :   vec->quick_push (build1 (ADDR_EXPR,
    6805            0 :                            build_pointer_type (TREE_TYPE (expected)), v));
    6806            0 :   vec->quick_push (gimple_call_arg (call, 2));
    6807              :   /* Skip the boolean weak parameter.  */
    6808            0 :   for (z = 4; z < 6; z++)
    6809            0 :     vec->quick_push (gimple_call_arg (call, z));
    6810              :   /* At present we only have BUILT_IN_ATOMIC_COMPARE_EXCHANGE_{1,2,4,8,16}.  */
    6811            0 :   unsigned int bytes_log2 = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
    6812            0 :   gcc_assert (bytes_log2 < 5);
    6813            0 :   built_in_function fncode
    6814              :     = (built_in_function) ((int) BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1
    6815              :                            + bytes_log2);
    6816            0 :   tree fndecl = builtin_decl_explicit (fncode);
    6817            0 :   tree fn = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fndecl)),
    6818              :                     fndecl);
    6819            0 :   tree exp = build_call_vec (boolean_type_node, fn, vec);
    6820            0 :   tree lhs = gimple_call_lhs (call);
    6821            0 :   rtx boolret = expand_call (exp, NULL_RTX, lhs == NULL_TREE);
    6822            0 :   if (lhs)
    6823              :     {
    6824            0 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6825            0 :       if (GET_MODE (boolret) != mode)
    6826            0 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6827            0 :       x = force_reg (mode, x);
    6828            0 :       write_complex_part (target, boolret, true, true);
    6829            0 :       write_complex_part (target, x, false, false);
    6830              :     }
    6831            0 : }
    6832              : 
    6833              : /* Expand IFN_ATOMIC_COMPARE_EXCHANGE internal function.  */
    6834              : 
    6835              : void
    6836        13946 : expand_ifn_atomic_compare_exchange (gcall *call)
    6837              : {
    6838        13946 :   int size = tree_to_shwi (gimple_call_arg (call, 3)) & 255;
    6839        13946 :   gcc_assert (size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
    6840        13946 :   machine_mode mode = int_mode_for_size (BITS_PER_UNIT * size, 0).require ();
    6841              : 
    6842        13946 :   memmodel success = get_memmodel (gimple_call_arg (call, 4));
    6843        13946 :   memmodel failure = get_memmodel (gimple_call_arg (call, 5));
    6844              : 
    6845        13946 :   if (failure > success)
    6846            0 :     success = MEMMODEL_SEQ_CST;
    6847              : 
    6848        13946 :   if (is_mm_release (failure) || is_mm_acq_rel (failure))
    6849              :     {
    6850              :       failure = MEMMODEL_SEQ_CST;
    6851              :       success = MEMMODEL_SEQ_CST;
    6852              :     }
    6853              : 
    6854        13946 :   if (!flag_inline_atomics)
    6855              :     {
    6856            0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6857            0 :       return;
    6858              :     }
    6859              : 
    6860              :   /* Expand the operands.  */
    6861        13946 :   rtx mem = get_builtin_sync_mem (gimple_call_arg (call, 0), mode);
    6862              : 
    6863        13946 :   rtx expect = expand_expr_force_mode (gimple_call_arg (call, 1), mode);
    6864        13946 :   rtx desired = expand_expr_force_mode (gimple_call_arg (call, 2), mode);
    6865              : 
    6866        13946 :   bool is_weak = (tree_to_shwi (gimple_call_arg (call, 3)) & 256) != 0;
    6867              : 
    6868        13946 :   rtx boolret = NULL;
    6869        13946 :   rtx oldval = NULL;
    6870              : 
    6871        13946 :   if (!expand_atomic_compare_and_swap (&boolret, &oldval, mem, expect, desired,
    6872              :                                        is_weak, success, failure))
    6873              :     {
    6874            0 :       expand_ifn_atomic_compare_exchange_into_call (call, mode);
    6875            0 :       return;
    6876              :     }
    6877              : 
    6878        13946 :   tree lhs = gimple_call_lhs (call);
    6879        13946 :   if (lhs)
    6880              :     {
    6881        13738 :       rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    6882        13738 :       if (GET_MODE (boolret) != mode)
    6883        12290 :         boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
    6884        13738 :       write_complex_part (target, boolret, true, true);
    6885        13738 :       write_complex_part (target, oldval, false, false);
    6886              :     }
    6887              : }
    6888              : 
    6889              : /* Expand the __atomic_load intrinsic:
    6890              :         TYPE __atomic_load (TYPE *object, enum memmodel)
    6891              :    EXP is the CALL_EXPR.
    6892              :    TARGET is an optional place for us to store the results.  */
    6893              : 
    6894              : static rtx
    6895        70597 : expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
    6896              : {
    6897        70597 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    6898        70597 :   if (is_mm_release (model) || is_mm_acq_rel (model))
    6899              :     model = MEMMODEL_SEQ_CST;
    6900              : 
    6901        70597 :   if (!flag_inline_atomics)
    6902              :     return NULL_RTX;
    6903              : 
    6904              :   /* Expand the operand.  */
    6905        70556 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6906              : 
    6907        70556 :   return expand_atomic_load (target, mem, model);
    6908              : }
    6909              : 
    6910              : 
    6911              : /* Expand the __atomic_store intrinsic:
    6912              :         void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
    6913              :    EXP is the CALL_EXPR.
    6914              :    TARGET is an optional place for us to store the results.  */
    6915              : 
    6916              : static rtx
    6917        17465 : expand_builtin_atomic_store (machine_mode mode, tree exp)
    6918              : {
    6919        17465 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6920        17465 :   if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
    6921         1592 :         || is_mm_release (model)))
    6922              :     model = MEMMODEL_SEQ_CST;
    6923              : 
    6924        17465 :   if (!flag_inline_atomics)
    6925              :     return NULL_RTX;
    6926              : 
    6927              :   /* Expand the operands.  */
    6928        17434 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6929        17434 :   rtx val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6930              : 
    6931        17434 :   return expand_atomic_store (mem, val, model, false);
    6932              : }
    6933              : 
    6934              : /* Expand the __atomic_fetch_XXX intrinsic:
    6935              :         TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
    6936              :    EXP is the CALL_EXPR.
    6937              :    TARGET is an optional place for us to store the results.
    6938              :    CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
    6939              :    FETCH_AFTER is true if returning the result of the operation.
    6940              :    FETCH_AFTER is false if returning the value before the operation.
    6941              :    IGNORE is true if the result is not used.
    6942              :    EXT_CALL is the correct builtin for an external call if this cannot be
    6943              :    resolved to an instruction sequence.  */
    6944              : 
    6945              : static rtx
    6946        29043 : expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
    6947              :                                 enum rtx_code code, bool fetch_after,
    6948              :                                 bool ignore, enum built_in_function ext_call)
    6949              : {
    6950        29043 :   rtx val, mem, ret;
    6951        29043 :   enum memmodel model;
    6952        29043 :   tree fndecl;
    6953        29043 :   tree addr;
    6954              : 
    6955        29043 :   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
    6956              : 
    6957              :   /* Expand the operands.  */
    6958        29043 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    6959        29043 :   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
    6960              : 
    6961              :   /* Only try generating instructions if inlining is turned on.  */
    6962        29043 :   if (flag_inline_atomics)
    6963              :     {
    6964        28500 :       ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
    6965        28500 :       if (ret)
    6966              :         return ret;
    6967              :     }
    6968              : 
    6969              :   /* Return if a different routine isn't needed for the library call.  */
    6970         1158 :   if (ext_call == BUILT_IN_NONE)
    6971              :     return NULL_RTX;
    6972              : 
    6973              :   /* Change the call to the specified function.  */
    6974          287 :   fndecl = get_callee_fndecl (exp);
    6975          287 :   addr = CALL_EXPR_FN (exp);
    6976          287 :   STRIP_NOPS (addr);
    6977              : 
    6978          287 :   gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
    6979          287 :   TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
    6980              : 
    6981              :   /* If we will emit code after the call, the call cannot be a tail call.
    6982              :      If it is emitted as a tail call, a barrier is emitted after it, and
    6983              :      then all trailing code is removed.  */
    6984          287 :   if (!ignore)
    6985          190 :     CALL_EXPR_TAILCALL (exp) = 0;
    6986              : 
    6987              :   /* Expand the call here so we can emit trailing code.  */
    6988          287 :   ret = expand_call (exp, target, ignore);
    6989              : 
    6990              :   /* Replace the original function just in case it matters.  */
    6991          287 :   TREE_OPERAND (addr, 0) = fndecl;
    6992              : 
    6993              :   /* Then issue the arithmetic correction to return the right result.  */
    6994          287 :   if (!ignore)
    6995              :     {
    6996          190 :       if (code == NOT)
    6997              :         {
    6998           33 :           ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
    6999              :                                      OPTAB_LIB_WIDEN);
    7000           33 :           ret = expand_simple_unop (mode, NOT, ret, target, true);
    7001              :         }
    7002              :       else
    7003          157 :         ret = expand_simple_binop (mode, code, ret, val, target, true,
    7004              :                                    OPTAB_LIB_WIDEN);
    7005              :     }
    7006              :   return ret;
    7007              : }
    7008              : 
    7009              : /* Expand IFN_ATOMIC_BIT_TEST_AND_* internal function.  */
    7010              : 
    7011              : void
    7012          427 : expand_ifn_atomic_bit_test_and (gcall *call)
    7013              : {
    7014          427 :   tree ptr = gimple_call_arg (call, 0);
    7015          427 :   tree bit = gimple_call_arg (call, 1);
    7016          427 :   tree flag = gimple_call_arg (call, 2);
    7017          427 :   tree lhs = gimple_call_lhs (call);
    7018          427 :   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
    7019          427 :   machine_mode mode = TYPE_MODE (TREE_TYPE (flag));
    7020          427 :   enum rtx_code code;
    7021          427 :   optab optab;
    7022          427 :   class expand_operand ops[5];
    7023              : 
    7024          427 :   gcc_assert (flag_inline_atomics);
    7025              : 
    7026          427 :   if (gimple_call_num_args (call) == 5)
    7027          296 :     model = get_memmodel (gimple_call_arg (call, 3));
    7028              : 
    7029          427 :   rtx mem = get_builtin_sync_mem (ptr, mode);
    7030          427 :   rtx val = expand_expr_force_mode (bit, mode);
    7031              : 
    7032          427 :   switch (gimple_call_internal_fn (call))
    7033              :     {
    7034              :     case IFN_ATOMIC_BIT_TEST_AND_SET:
    7035              :       code = IOR;
    7036              :       optab = atomic_bit_test_and_set_optab;
    7037              :       break;
    7038              :     case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
    7039              :       code = XOR;
    7040              :       optab = atomic_bit_test_and_complement_optab;
    7041              :       break;
    7042              :     case IFN_ATOMIC_BIT_TEST_AND_RESET:
    7043              :       code = AND;
    7044              :       optab = atomic_bit_test_and_reset_optab;
    7045              :       break;
    7046            0 :     default:
    7047            0 :       gcc_unreachable ();
    7048              :     }
    7049              : 
    7050          427 :   if (lhs == NULL_TREE)
    7051              :     {
    7052            0 :       rtx val2 = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7053              :                                       val, NULL_RTX, true, OPTAB_DIRECT);
    7054            0 :       if (code == AND)
    7055            0 :         val2 = expand_simple_unop (mode, NOT, val2, NULL_RTX, true);
    7056            0 :       if (expand_atomic_fetch_op (const0_rtx, mem, val2, code, model, false))
    7057          427 :         return;
    7058              :     }
    7059              : 
    7060            0 :   rtx target;
    7061            0 :   if (lhs)
    7062          427 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    7063              :   else
    7064            0 :     target = gen_reg_rtx (mode);
    7065          427 :   enum insn_code icode = direct_optab_handler (optab, mode);
    7066          427 :   gcc_assert (icode != CODE_FOR_nothing);
    7067          427 :   create_output_operand (&ops[0], target, mode);
    7068          427 :   create_fixed_operand (&ops[1], mem);
    7069          427 :   create_convert_operand_to (&ops[2], val, mode, true);
    7070          427 :   create_integer_operand (&ops[3], model);
    7071          427 :   create_integer_operand (&ops[4], integer_onep (flag));
    7072          427 :   if (maybe_expand_insn (icode, 5, ops))
    7073              :     return;
    7074              : 
    7075            0 :   rtx bitval = val;
    7076            0 :   val = expand_simple_binop (mode, ASHIFT, const1_rtx,
    7077              :                              val, NULL_RTX, true, OPTAB_DIRECT);
    7078            0 :   rtx maskval = val;
    7079            0 :   if (code == AND)
    7080            0 :     val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
    7081            0 :   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, val,
    7082              :                                        code, model, false);
    7083            0 :   if (!result)
    7084              :     {
    7085            0 :       bool is_atomic = gimple_call_num_args (call) == 5;
    7086            0 :       tree tcall = gimple_call_arg (call, 3 + is_atomic);
    7087            0 :       tree fndecl = gimple_call_addr_fndecl (tcall);
    7088            0 :       tree type = TREE_TYPE (TREE_TYPE (fndecl));
    7089            0 :       tree exp;
    7090            0 :       if (is_atomic)
    7091            0 :         exp = build_call_nary (type, tcall, 3,
    7092              :                                ptr, make_tree (type, val),
    7093              :                                gimple_call_arg (call, 3));
    7094              :       else
    7095            0 :         exp = build_call_nary (type, tcall, 2, ptr, make_tree (type, val));
    7096            0 :       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
    7097              :                                mode, !lhs);
    7098              :     }
    7099            0 :   if (!lhs)
    7100              :     return;
    7101            0 :   if (integer_onep (flag))
    7102              :     {
    7103            0 :       result = expand_simple_binop (mode, ASHIFTRT, result, bitval,
    7104              :                                     NULL_RTX, true, OPTAB_DIRECT);
    7105            0 :       result = expand_simple_binop (mode, AND, result, const1_rtx, target,
    7106              :                                     true, OPTAB_DIRECT);
    7107              :     }
    7108              :   else
    7109            0 :     result = expand_simple_binop (mode, AND, result, maskval, target, true,
    7110              :                                   OPTAB_DIRECT);
    7111            0 :   if (result != target)
    7112            0 :     emit_move_insn (target, result);
    7113              : }
    7114              : 
    7115              : /* Expand IFN_ATOMIC_*_FETCH_CMP_0 internal function.  */
    7116              : 
    7117              : void
    7118         2148 : expand_ifn_atomic_op_fetch_cmp_0 (gcall *call)
    7119              : {
    7120         2148 :   tree cmp = gimple_call_arg (call, 0);
    7121         2148 :   tree ptr = gimple_call_arg (call, 1);
    7122         2148 :   tree arg = gimple_call_arg (call, 2);
    7123         2148 :   tree lhs = gimple_call_lhs (call);
    7124         2148 :   enum memmodel model = MEMMODEL_SYNC_SEQ_CST;
    7125         2148 :   machine_mode mode = TYPE_MODE (TREE_TYPE (cmp));
    7126         2148 :   optab optab;
    7127         2148 :   rtx_code code;
    7128         2148 :   class expand_operand ops[5];
    7129              : 
    7130         2148 :   gcc_assert (flag_inline_atomics);
    7131              : 
    7132         2148 :   if (gimple_call_num_args (call) == 5)
    7133         1740 :     model = get_memmodel (gimple_call_arg (call, 3));
    7134              : 
    7135         2148 :   rtx mem = get_builtin_sync_mem (ptr, mode);
    7136         2148 :   rtx op = expand_expr_force_mode (arg, mode);
    7137              : 
    7138         2148 :   switch (gimple_call_internal_fn (call))
    7139              :     {
    7140              :     case IFN_ATOMIC_ADD_FETCH_CMP_0:
    7141              :       code = PLUS;
    7142              :       optab = atomic_add_fetch_cmp_0_optab;
    7143              :       break;
    7144              :     case IFN_ATOMIC_SUB_FETCH_CMP_0:
    7145              :       code = MINUS;
    7146              :       optab = atomic_sub_fetch_cmp_0_optab;
    7147              :       break;
    7148              :     case IFN_ATOMIC_AND_FETCH_CMP_0:
    7149              :       code = AND;
    7150              :       optab = atomic_and_fetch_cmp_0_optab;
    7151              :       break;
    7152              :     case IFN_ATOMIC_OR_FETCH_CMP_0:
    7153              :       code = IOR;
    7154              :       optab = atomic_or_fetch_cmp_0_optab;
    7155              :       break;
    7156              :     case IFN_ATOMIC_XOR_FETCH_CMP_0:
    7157              :       code = XOR;
    7158              :       optab = atomic_xor_fetch_cmp_0_optab;
    7159              :       break;
    7160            0 :     default:
    7161            0 :       gcc_unreachable ();
    7162              :     }
    7163              : 
    7164         2148 :   enum rtx_code comp = UNKNOWN;
    7165         2148 :   switch (tree_to_uhwi (cmp))
    7166              :     {
    7167              :     case ATOMIC_OP_FETCH_CMP_0_EQ: comp = EQ; break;
    7168              :     case ATOMIC_OP_FETCH_CMP_0_NE: comp = NE; break;
    7169              :     case ATOMIC_OP_FETCH_CMP_0_GT: comp = GT; break;
    7170              :     case ATOMIC_OP_FETCH_CMP_0_GE: comp = GE; break;
    7171              :     case ATOMIC_OP_FETCH_CMP_0_LT: comp = LT; break;
    7172              :     case ATOMIC_OP_FETCH_CMP_0_LE: comp = LE; break;
    7173            0 :     default: gcc_unreachable ();
    7174              :     }
    7175              : 
    7176         2148 :   rtx target;
    7177         2148 :   if (lhs == NULL_TREE)
    7178            0 :     target = gen_reg_rtx (TYPE_MODE (boolean_type_node));
    7179              :   else
    7180         2148 :     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    7181         2148 :   enum insn_code icode = direct_optab_handler (optab, mode);
    7182         2148 :   gcc_assert (icode != CODE_FOR_nothing);
    7183         2148 :   create_output_operand (&ops[0], target, TYPE_MODE (boolean_type_node));
    7184         2148 :   create_fixed_operand (&ops[1], mem);
    7185         2148 :   create_convert_operand_to (&ops[2], op, mode, true);
    7186         2148 :   create_integer_operand (&ops[3], model);
    7187         2148 :   create_integer_operand (&ops[4], comp);
    7188         2148 :   if (maybe_expand_insn (icode, 5, ops))
    7189         2116 :     return;
    7190              : 
    7191           32 :   rtx result = expand_atomic_fetch_op (gen_reg_rtx (mode), mem, op,
    7192              :                                        code, model, true);
    7193           32 :   if (!result)
    7194              :     {
    7195            0 :       bool is_atomic = gimple_call_num_args (call) == 5;
    7196            0 :       tree tcall = gimple_call_arg (call, 3 + is_atomic);
    7197            0 :       tree fndecl = gimple_call_addr_fndecl (tcall);
    7198            0 :       tree type = TREE_TYPE (TREE_TYPE (fndecl));
    7199            0 :       tree exp;
    7200            0 :       if (is_atomic)
    7201            0 :         exp = build_call_nary (type, tcall, 3,
    7202              :                                ptr, arg,
    7203              :                                gimple_call_arg (call, 3));
    7204              :       else
    7205            0 :         exp = build_call_nary (type, tcall, 2, ptr, arg);
    7206            0 :       result = expand_builtin (exp, gen_reg_rtx (mode), NULL_RTX,
    7207              :                                mode, !lhs);
    7208              :     }
    7209              : 
    7210           32 :   if (lhs)
    7211              :     {
    7212           32 :       result = emit_store_flag_force (target, comp, result, const0_rtx, mode,
    7213              :                                       0, 1);
    7214           32 :       if (result != target)
    7215           32 :         emit_move_insn (target, result);
    7216              :     }
    7217              : }
    7218              : 
    7219              : /* Expand an atomic clear operation.
    7220              :         void _atomic_clear (BOOL *obj, enum memmodel)
    7221              :    EXP is the call expression.  */
    7222              : 
    7223              : static rtx
    7224           53 : expand_builtin_atomic_clear (tree exp)
    7225              : {
    7226           53 :   machine_mode mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7227           53 :   rtx mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7228           53 :   memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7229              : 
    7230           53 :   if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
    7231              :     model = MEMMODEL_SEQ_CST;
    7232              : 
    7233              :   /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
    7234              :      Failing that, a store is issued by __atomic_store.  The only way this can
    7235              :      fail is if the bool type is larger than a word size.  Unlikely, but
    7236              :      handle it anyway for completeness.  Assume a single threaded model since
    7237              :      there is no atomic support in this case, and no barriers are required.  */
    7238           53 :   rtx ret = expand_atomic_store (mem, const0_rtx, model, true);
    7239           53 :   if (!ret)
    7240            0 :     emit_move_insn (mem, const0_rtx);
    7241           53 :   return const0_rtx;
    7242              : }
    7243              : 
    7244              : /* Expand an atomic test_and_set operation.
    7245              :         bool _atomic_test_and_set (BOOL *obj, enum memmodel)
    7246              :    EXP is the call expression.  */
    7247              : 
    7248              : static rtx
    7249          266 : expand_builtin_atomic_test_and_set (tree exp, rtx target)
    7250              : {
    7251          266 :   rtx mem;
    7252          266 :   enum memmodel model;
    7253          266 :   machine_mode mode;
    7254              : 
    7255          266 :   mode = int_mode_for_size (BOOL_TYPE_SIZE, 0).require ();
    7256          266 :   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    7257          266 :   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
    7258              : 
    7259          266 :   return expand_atomic_test_and_set (target, mem, model);
    7260              : }
    7261              : 
    7262              : 
    7263              : /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
    7264              :    this architecture.  If ARG1 is NULL, use typical alignment for size ARG0.  */
    7265              : 
    7266              : static tree
    7267       144319 : fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
    7268              : {
    7269       144319 :   HOST_WIDE_INT size;
    7270       144319 :   machine_mode mode;
    7271       144319 :   unsigned int mode_align, type_align;
    7272              : 
    7273       144319 :   if (!tree_fits_shwi_p (arg0))
    7274              :     return NULL_TREE;
    7275              : 
    7276              :   /* We need a corresponding integer mode for the access to be lock-free.  */
    7277       144166 :   size = tree_to_shwi (arg0) * BITS_PER_UNIT;
    7278       144166 :   if (!int_mode_for_size (size, 0).exists (&mode))
    7279            9 :     return boolean_false_node;
    7280              : 
    7281       144157 :   mode_align = GET_MODE_ALIGNMENT (mode);
    7282              : 
    7283       144157 :   if (tree_fits_uhwi_p (arg1))
    7284              :     {
    7285       124415 :       unsigned HOST_WIDE_INT val = tree_to_uhwi (arg1);
    7286              : 
    7287              :       /* Either this argument is null, or it's a fake pointer encoding
    7288              :          the alignment of the object.  */
    7289       124415 :       val = least_bit_hwi (val);
    7290       124415 :       val *= BITS_PER_UNIT;
    7291              : 
    7292       124415 :       if (val == 0 || mode_align < val)
    7293              :         type_align = mode_align;
    7294              :       else
    7295        18985 :         type_align = val;
    7296              :     }
    7297              :   else
    7298              :     {
    7299        19742 :       tree ttype = TREE_TYPE (arg1);
    7300              : 
    7301              :       /* This function is usually invoked and folded immediately by the front
    7302              :          end before anything else has a chance to look at it.  The pointer
    7303              :          parameter at this point is usually cast to a void *, so check for that
    7304              :          and look past the cast.  */
    7305          195 :       if (CONVERT_EXPR_P (arg1)
    7306        19578 :           && POINTER_TYPE_P (ttype)
    7307        19578 :           && VOID_TYPE_P (TREE_TYPE (ttype))
    7308        39320 :           && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
    7309        19547 :         arg1 = TREE_OPERAND (arg1, 0);
    7310              : 
    7311        19742 :       ttype = TREE_TYPE (arg1);
    7312        19742 :       gcc_assert (POINTER_TYPE_P (ttype));
    7313              : 
    7314              :       /* Get the underlying type of the object.  */
    7315        19742 :       ttype = TREE_TYPE (ttype);
    7316        19742 :       type_align = TYPE_ALIGN (ttype);
    7317              :     }
    7318              : 
    7319              :   /* If the object has smaller alignment, the lock free routines cannot
    7320              :      be used.  */
    7321       144157 :   if (type_align < mode_align)
    7322          247 :     return boolean_false_node;
    7323              : 
    7324              :   /* Check if a compare_and_swap pattern exists for the mode which represents
    7325              :      the required size.  The pattern is not allowed to fail, so the existence
    7326              :      of the pattern indicates support is present.  Also require that an
    7327              :      atomic load exists for the required size.  */
    7328       143910 :   if (can_compare_and_swap_p (mode, true) && can_atomic_load_p (mode))
    7329       143868 :     return boolean_true_node;
    7330              :   else
    7331           42 :     return boolean_false_node;
    7332              : }
    7333              : 
    7334              : /* Return true if the parameters to call EXP represent an object which will
    7335              :    always generate lock free instructions.  The first argument represents the
    7336              :    size of the object, and the second parameter is a pointer to the object
    7337              :    itself.  If NULL is passed for the object, then the result is based on
    7338              :    typical alignment for an object of the specified size.  Otherwise return
    7339              :    false.  */
    7340              : 
    7341              : static rtx
    7342            1 : expand_builtin_atomic_always_lock_free (tree exp)
    7343              : {
    7344            1 :   tree size;
    7345            1 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7346            1 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7347              : 
    7348            1 :   if (TREE_CODE (arg0) != INTEGER_CST)
    7349              :     {
    7350            1 :       error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
    7351            1 :       return const0_rtx;
    7352              :     }
    7353              : 
    7354            0 :   size = fold_builtin_atomic_always_lock_free (arg0, arg1);
    7355            0 :   if (size == boolean_true_node)
    7356            0 :     return const1_rtx;
    7357            0 :   return const0_rtx;
    7358              : }
    7359              : 
    7360              : /* Return a one or zero if it can be determined that object ARG1 of size ARG
    7361              :    is lock free on this architecture.  */
    7362              : 
    7363              : static tree
    7364        38826 : fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
    7365              : {
    7366        38826 :   if (!flag_inline_atomics)
    7367              :     return NULL_TREE;
    7368              : 
    7369              :   /* If it isn't always lock free, don't generate a result.  */
    7370        38817 :   if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
    7371        38458 :     return boolean_true_node;
    7372              : 
    7373              :   return NULL_TREE;
    7374              : }
    7375              : 
    7376              : /* Return true if the parameters to call EXP represent an object which will
    7377              :    always generate lock free instructions.  The first argument represents the
    7378              :    size of the object, and the second parameter is a pointer to the object
    7379              :    itself.  If NULL is passed for the object, then the result is based on
    7380              :    typical alignment for an object of the specified size.  Otherwise return
    7381              :    NULL*/
    7382              : 
    7383              : static rtx
    7384           10 : expand_builtin_atomic_is_lock_free (tree exp)
    7385              : {
    7386           10 :   tree size;
    7387           10 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7388           10 :   tree arg1 = CALL_EXPR_ARG (exp, 1);
    7389              : 
    7390           10 :   if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
    7391              :     {
    7392            0 :       error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
    7393            0 :       return NULL_RTX;
    7394              :     }
    7395              : 
    7396           10 :   if (!flag_inline_atomics)
    7397              :     return NULL_RTX;
    7398              : 
    7399              :   /* If the value is known at compile time, return the RTX for it.  */
    7400            9 :   size = fold_builtin_atomic_is_lock_free (arg0, arg1);
    7401            9 :   if (size == boolean_true_node)
    7402            0 :     return const1_rtx;
    7403              : 
    7404              :   return NULL_RTX;
    7405              : }
    7406              : 
    7407              : /* Expand the __atomic_thread_fence intrinsic:
    7408              :         void __atomic_thread_fence (enum memmodel)
    7409              :    EXP is the CALL_EXPR.  */
    7410              : 
    7411              : static void
    7412          693 : expand_builtin_atomic_thread_fence (tree exp)
    7413              : {
    7414          693 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7415          693 :   expand_mem_thread_fence (model);
    7416          693 : }
    7417              : 
    7418              : /* Expand the __atomic_signal_fence intrinsic:
    7419              :         void __atomic_signal_fence (enum memmodel)
    7420              :    EXP is the CALL_EXPR.  */
    7421              : 
    7422              : static void
    7423           60 : expand_builtin_atomic_signal_fence (tree exp)
    7424              : {
    7425           60 :   enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
    7426           60 :   expand_mem_signal_fence (model);
    7427           60 : }
    7428              : 
    7429              : /* Expand the __sync_synchronize intrinsic.  */
    7430              : 
    7431              : static void
    7432          273 : expand_builtin_sync_synchronize (void)
    7433              : {
    7434            0 :   expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
    7435            0 : }
    7436              : 
    7437              : static rtx
    7438            3 : expand_builtin_thread_pointer (tree exp, rtx target)
    7439              : {
    7440            3 :   enum insn_code icode;
    7441            3 :   if (!validate_arglist (exp, VOID_TYPE))
    7442            0 :     return const0_rtx;
    7443            3 :   icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
    7444            3 :   if (icode != CODE_FOR_nothing)
    7445              :     {
    7446            3 :       class expand_operand op;
    7447              :       /* If the target is not sutitable then create a new target. */
    7448            3 :       if (target == NULL_RTX
    7449            3 :           || !REG_P (target)
    7450            6 :           || GET_MODE (target) != Pmode)
    7451            0 :         target = gen_reg_rtx (Pmode);
    7452            3 :       create_output_operand (&op, target, Pmode);
    7453            3 :       expand_insn (icode, 1, &op);
    7454            3 :       return target;
    7455              :     }
    7456            0 :   error ("%<__builtin_thread_pointer%> is not supported on this target");
    7457            0 :   return const0_rtx;
    7458              : }
    7459              : 
    7460              : static void
    7461            0 : expand_builtin_set_thread_pointer (tree exp)
    7462              : {
    7463            0 :   enum insn_code icode;
    7464            0 :   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    7465              :     return;
    7466            0 :   icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
    7467            0 :   if (icode != CODE_FOR_nothing)
    7468              :     {
    7469            0 :       class expand_operand op;
    7470            0 :       rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
    7471            0 :                              Pmode, EXPAND_NORMAL);
    7472            0 :       create_input_operand (&op, val, Pmode);
    7473            0 :       expand_insn (icode, 1, &op);
    7474            0 :       return;
    7475              :     }
    7476            0 :   error ("%<__builtin_set_thread_pointer%> is not supported on this target");
    7477              : }
    7478              : 
    7479              : 
    7480              : /* Emit code to restore the current value of stack.  */
    7481              : 
    7482              : static void
    7483         1755 : expand_stack_restore (tree var)
    7484              : {
    7485         1755 :   rtx_insn *prev;
    7486         1755 :   rtx sa = expand_normal (var);
    7487              : 
    7488         1811 :   sa = convert_memory_address (Pmode, sa);
    7489              : 
    7490         1755 :   prev = get_last_insn ();
    7491         1755 :   emit_stack_restore (SAVE_BLOCK, sa);
    7492              : 
    7493         1755 :   record_new_stack_level ();
    7494              : 
    7495         1755 :   fixup_args_size_notes (prev, get_last_insn (), 0);
    7496         1755 : }
    7497              : 
    7498              : /* Emit code to save the current value of stack.  */
    7499              : 
    7500              : static rtx
    7501         1856 : expand_stack_save (void)
    7502              : {
    7503         1856 :   rtx ret = NULL_RTX;
    7504              : 
    7505            0 :   emit_stack_save (SAVE_BLOCK, &ret);
    7506         1856 :   return ret;
    7507              : }
    7508              : 
    7509              : /* Emit code to get the openacc gang, worker or vector id or size.  */
    7510              : 
    7511              : static rtx
    7512          356 : expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
    7513              : {
    7514          356 :   const char *name;
    7515          356 :   rtx fallback_retval;
    7516          356 :   rtx_insn *(*gen_fn) (rtx, rtx);
    7517          356 :   switch (DECL_FUNCTION_CODE (get_callee_fndecl (exp)))
    7518              :     {
    7519          244 :     case BUILT_IN_GOACC_PARLEVEL_ID:
    7520          244 :       name = "__builtin_goacc_parlevel_id";
    7521          244 :       fallback_retval = const0_rtx;
    7522          244 :       gen_fn = targetm.gen_oacc_dim_pos;
    7523          244 :       break;
    7524          112 :     case BUILT_IN_GOACC_PARLEVEL_SIZE:
    7525          112 :       name = "__builtin_goacc_parlevel_size";
    7526          112 :       fallback_retval = const1_rtx;
    7527          112 :       gen_fn = targetm.gen_oacc_dim_size;
    7528          112 :       break;
    7529            0 :     default:
    7530            0 :       gcc_unreachable ();
    7531              :     }
    7532              : 
    7533          356 :   if (oacc_get_fn_attrib (current_function_decl) == NULL_TREE)
    7534              :     {
    7535            8 :       error ("%qs only supported in OpenACC code", name);
    7536            8 :       return const0_rtx;
    7537              :     }
    7538              : 
    7539          348 :   tree arg = CALL_EXPR_ARG (exp, 0);
    7540          348 :   if (TREE_CODE (arg) != INTEGER_CST)
    7541              :     {
    7542            8 :       error ("non-constant argument 0 to %qs", name);
    7543            8 :       return const0_rtx;
    7544              :     }
    7545              : 
    7546          340 :   int dim = TREE_INT_CST_LOW (arg);
    7547          340 :   switch (dim)
    7548              :     {
    7549          324 :     case GOMP_DIM_GANG:
    7550          324 :     case GOMP_DIM_WORKER:
    7551          324 :     case GOMP_DIM_VECTOR:
    7552          324 :       break;
    7553           16 :     default:
    7554           16 :       error ("illegal argument 0 to %qs", name);
    7555           16 :       return const0_rtx;
    7556              :     }
    7557              : 
    7558          324 :   if (ignore)
    7559              :     return target;
    7560              : 
    7561          180 :   if (target == NULL_RTX)
    7562            0 :     target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
    7563              : 
    7564          180 :   if (!targetm.have_oacc_dim_size ())
    7565              :     {
    7566          180 :       emit_move_insn (target, fallback_retval);
    7567          180 :       return target;
    7568              :     }
    7569              : 
    7570            0 :   rtx reg = MEM_P (target) ? gen_reg_rtx (GET_MODE (target)) : target;
    7571            0 :   emit_insn (gen_fn (reg, GEN_INT (dim)));
    7572            0 :   if (reg != target)
    7573            0 :     emit_move_insn (target, reg);
    7574              : 
    7575              :   return target;
    7576              : }
    7577              : 
    7578              : /* Expand a string compare operation using a sequence of char comparison
    7579              :    to get rid of the calling overhead, with result going to TARGET if
    7580              :    that's convenient.
    7581              : 
    7582              :    VAR_STR is the variable string source;
    7583              :    CONST_STR is the constant string source;
    7584              :    LENGTH is the number of chars to compare;
    7585              :    CONST_STR_N indicates which source string is the constant string;
    7586              :    IS_MEMCMP indicates whether it's a memcmp or strcmp.
    7587              : 
    7588              :    to: (assume const_str_n is 2, i.e., arg2 is a constant string)
    7589              : 
    7590              :    target = (int) (unsigned char) var_str[0]
    7591              :             - (int) (unsigned char) const_str[0];
    7592              :    if (target != 0)
    7593              :      goto ne_label;
    7594              :      ...
    7595              :    target = (int) (unsigned char) var_str[length - 2]
    7596              :             - (int) (unsigned char) const_str[length - 2];
    7597              :    if (target != 0)
    7598              :      goto ne_label;
    7599              :    target = (int) (unsigned char) var_str[length - 1]
    7600              :             - (int) (unsigned char) const_str[length - 1];
    7601              :    ne_label:
    7602              :   */
    7603              : 
    7604              : static rtx
    7605          635 : inline_string_cmp (rtx target, tree var_str, const char *const_str,
    7606              :                    unsigned HOST_WIDE_INT length,
    7607              :                    int const_str_n, machine_mode mode)
    7608              : {
    7609          635 :   HOST_WIDE_INT offset = 0;
    7610          635 :   rtx var_rtx_array
    7611          635 :     = get_memory_rtx (var_str, build_int_cst (unsigned_type_node, length),
    7612              :                       false);
    7613          635 :   rtx var_rtx = NULL_RTX;
    7614          635 :   rtx const_rtx = NULL_RTX;
    7615          635 :   rtx result = target ? target : gen_reg_rtx (mode);
    7616          635 :   rtx_code_label *ne_label = gen_label_rtx ();
    7617          635 :   tree unit_type_node = unsigned_char_type_node;
    7618          635 :   scalar_int_mode unit_mode
    7619          635 :     = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
    7620              : 
    7621          635 :   start_sequence ();
    7622              : 
    7623         2964 :   for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
    7624              :     {
    7625         1694 :       var_rtx
    7626         1694 :         = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
    7627         1694 :       const_rtx = c_readstr (const_str + offset, unit_mode);
    7628         1694 :       rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
    7629         1544 :       rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
    7630              : 
    7631         1694 :       op0 = convert_modes (mode, unit_mode, op0, 1);
    7632         1694 :       op1 = convert_modes (mode, unit_mode, op1, 1);
    7633         1694 :       rtx diff = expand_simple_binop (mode, MINUS, op0, op1,
    7634              :                                       result, 1, OPTAB_WIDEN);
    7635              : 
    7636              :       /* Force the difference into result register.  We cannot reassign
    7637              :          result here ("result = diff") or we may end up returning
    7638              :          uninitialized result when expand_simple_binop allocates a new
    7639              :          pseudo-register for returning.  */
    7640         1694 :       if (diff != result)
    7641            0 :         emit_move_insn (result, diff);
    7642              : 
    7643         1694 :       if (i < length - 1)
    7644         1059 :         emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
    7645              :                                  mode, true, ne_label);
    7646         3388 :       offset += GET_MODE_SIZE (unit_mode);
    7647              :     }
    7648              : 
    7649          635 :   emit_label (ne_label);
    7650          635 :   rtx_insn *insns = end_sequence ();
    7651          635 :   emit_insn (insns);
    7652              : 
    7653          635 :   return result;
    7654              : }
    7655              : 
    7656              : /* Inline expansion of a call to str(n)cmp and memcmp, with result going
    7657              :    to TARGET if that's convenient.
    7658              :    If the call is not been inlined, return NULL_RTX.  */
    7659              : 
    7660              : static rtx
    7661       144879 : inline_expand_builtin_bytecmp (tree exp, rtx target)
    7662              : {
    7663       144879 :   tree fndecl = get_callee_fndecl (exp);
    7664       144879 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7665       144879 :   bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
    7666              : 
    7667              :   /* Do NOT apply this inlining expansion when optimizing for size or
    7668              :      optimization level below 2 or if unused *cmp hasn't been DCEd.  */
    7669       144879 :   if (optimize < 2 || optimize_insn_for_size_p () || target == const0_rtx)
    7670              :     return NULL_RTX;
    7671              : 
    7672        22736 :   gcc_checking_assert (fcode == BUILT_IN_STRCMP
    7673              :                        || fcode == BUILT_IN_STRNCMP
    7674              :                        || fcode == BUILT_IN_MEMCMP);
    7675              : 
    7676              :   /* On a target where the type of the call (int) has same or narrower precision
    7677              :      than unsigned char, give up the inlining expansion.  */
    7678        22736 :   if (TYPE_PRECISION (unsigned_char_type_node)
    7679        22736 :       >= TYPE_PRECISION (TREE_TYPE (exp)))
    7680              :     return NULL_RTX;
    7681              : 
    7682        22736 :   tree arg1 = CALL_EXPR_ARG (exp, 0);
    7683        22736 :   tree arg2 = CALL_EXPR_ARG (exp, 1);
    7684        22736 :   tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
    7685              : 
    7686        22736 :   unsigned HOST_WIDE_INT len1 = 0;
    7687        22736 :   unsigned HOST_WIDE_INT len2 = 0;
    7688        22736 :   unsigned HOST_WIDE_INT len3 = 0;
    7689              : 
    7690              :   /* Get the object representation of the initializers of ARG1 and ARG2
    7691              :      as strings, provided they refer to constant objects, with their byte
    7692              :      sizes in LEN1 and LEN2, respectively.  */
    7693        22736 :   const char *bytes1 = getbyterep (arg1, &len1);
    7694        22736 :   const char *bytes2 = getbyterep (arg2, &len2);
    7695              : 
    7696              :   /* Fail if neither argument refers to an initialized constant.  */
    7697        22736 :   if (!bytes1 && !bytes2)
    7698              :     return NULL_RTX;
    7699              : 
    7700        18497 :   if (is_ncmp)
    7701              :     {
    7702              :       /* Fail if the memcmp/strncmp bound is not a constant.  */
    7703         1382 :       if (!tree_fits_uhwi_p (len3_tree))
    7704              :         return NULL_RTX;
    7705              : 
    7706          962 :       len3 = tree_to_uhwi (len3_tree);
    7707              : 
    7708          962 :       if (fcode == BUILT_IN_MEMCMP)
    7709              :         {
    7710              :           /* Fail if the memcmp bound is greater than the size of either
    7711              :              of the two constant objects.  */
    7712          462 :           if ((bytes1 && len1 < len3)
    7713          462 :               || (bytes2 && len2 < len3))
    7714              :             return NULL_RTX;
    7715              :         }
    7716              :     }
    7717              : 
    7718              :   if (fcode != BUILT_IN_MEMCMP)
    7719              :     {
    7720              :       /* For string functions (i.e., strcmp and strncmp) reduce LEN1
    7721              :          and LEN2 to the length of the nul-terminated string stored
    7722              :          in each.  */
    7723        17615 :       if (bytes1 != NULL)
    7724          236 :         len1 = strnlen (bytes1, len1) + 1;
    7725        17615 :       if (bytes2 != NULL)
    7726        17382 :         len2 = strnlen (bytes2, len2) + 1;
    7727              :     }
    7728              : 
    7729              :   /* See inline_string_cmp.  */
    7730        18073 :   int const_str_n;
    7731        18073 :   if (!len1)
    7732              :     const_str_n = 2;
    7733          241 :   else if (!len2)
    7734              :     const_str_n = 1;
    7735            3 :   else if (len2 > len1)
    7736              :     const_str_n = 1;
    7737              :   else
    7738              :     const_str_n = 2;
    7739              : 
    7740              :   /* For strncmp only, compute the new bound as the smallest of
    7741              :      the lengths of the two strings (plus 1) and the bound provided
    7742              :      to the function.  */
    7743        17834 :   unsigned HOST_WIDE_INT bound = (const_str_n == 1) ? len1 : len2;
    7744        18073 :   if (is_ncmp && len3 < bound)
    7745          534 :     bound = len3;
    7746              : 
    7747              :   /* If the bound of the comparison is larger than the threshold,
    7748              :      do nothing.  */
    7749        18073 :   if (bound > (unsigned HOST_WIDE_INT) param_builtin_string_cmp_inline_length)
    7750              :     return NULL_RTX;
    7751              : 
    7752          635 :   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
    7753              : 
    7754              :   /* Now, start inline expansion the call.  */
    7755         1213 :   return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
    7756              :                             (const_str_n == 1) ? bytes1 : bytes2, bound,
    7757          635 :                             const_str_n, mode);
    7758              : }
    7759              : 
    7760              : /* Expand a call to __builtin_speculation_safe_value_<N>.  MODE
    7761              :    represents the size of the first argument to that call, or VOIDmode
    7762              :    if the argument is a pointer.  IGNORE will be true if the result
    7763              :    isn't used.  */
    7764              : static rtx
    7765           34 : expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
    7766              :                                bool ignore)
    7767              : {
    7768           34 :   rtx val, failsafe;
    7769           34 :   unsigned nargs = call_expr_nargs (exp);
    7770              : 
    7771           34 :   tree arg0 = CALL_EXPR_ARG (exp, 0);
    7772              : 
    7773           34 :   if (mode == VOIDmode)
    7774              :     {
    7775            4 :       mode = TYPE_MODE (TREE_TYPE (arg0));
    7776            4 :       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
    7777              :     }
    7778              : 
    7779           34 :   val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
    7780              : 
    7781              :   /* An optional second argument can be used as a failsafe value on
    7782              :      some machines.  If it isn't present, then the failsafe value is
    7783              :      assumed to be 0.  */
    7784           34 :   if (nargs > 1)
    7785              :     {
    7786            4 :       tree arg1 = CALL_EXPR_ARG (exp, 1);
    7787            4 :       failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
    7788              :     }
    7789              :   else
    7790           30 :     failsafe = const0_rtx;
    7791              : 
    7792              :   /* If the result isn't used, the behavior is undefined.  It would be
    7793              :      nice to emit a warning here, but path splitting means this might
    7794              :      happen with legitimate code.  So simply drop the builtin
    7795              :      expansion in that case; we've handled any side-effects above.  */
    7796           34 :   if (ignore)
    7797            0 :     return const0_rtx;
    7798              : 
    7799              :   /* If we don't have a suitable target, create one to hold the result.  */
    7800           34 :   if (target == NULL || GET_MODE (target) != mode)
    7801            0 :     target = gen_reg_rtx (mode);
    7802              : 
    7803           34 :   if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
    7804            0 :     val = convert_modes (mode, VOIDmode, val, false);
    7805              : 
    7806           34 :   return targetm.speculation_safe_value (mode, target, val, failsafe);
    7807              : }
    7808              : 
    7809              : /* Expand CRC* or REV_CRC* built-ins.  */
    7810              : 
    7811              : rtx
    7812           45 : expand_builtin_crc_table_based (internal_fn fn, scalar_mode crc_mode,
    7813              :                                 scalar_mode data_mode, machine_mode mode,
    7814              :                                 tree exp, rtx target)
    7815              : {
    7816           45 :   tree rhs1 = CALL_EXPR_ARG (exp, 0); // crc
    7817           45 :   tree rhs2 = CALL_EXPR_ARG (exp, 1); // data
    7818           45 :   tree rhs3 = CALL_EXPR_ARG (exp, 2); // polynomial
    7819              : 
    7820           45 :   if (!target || mode == VOIDmode)
    7821            0 :     target = gen_reg_rtx (crc_mode);
    7822              : 
    7823           45 :   rtx op1 = expand_normal (rhs1);
    7824           45 :   rtx op2 = expand_normal (rhs2);
    7825           45 :   rtx op3;
    7826           45 :   if (TREE_CODE (rhs3) != INTEGER_CST)
    7827              :     {
    7828            1 :       error ("third argument to %<crc%> builtins must be a constant");
    7829            1 :       op3 = const0_rtx;
    7830              :     }
    7831              :   else
    7832           44 :     op3 = convert_to_mode (crc_mode, expand_normal (rhs3), 0);
    7833              : 
    7834           45 :   if (CONST_INT_P (op2))
    7835           32 :     op2 = convert_to_mode (crc_mode, op2, 0);
    7836              : 
    7837           45 :   if (fn == IFN_CRC)
    7838           28 :     expand_crc_table_based (target, op1, op2, op3, data_mode);
    7839              :   else
    7840              :     /* If it's IFN_CRC_REV generate bit-reversed CRC.  */
    7841           17 :     expand_reversed_crc_table_based (target, op1, op2, op3,
    7842              :                                      data_mode);
    7843           45 :   return target;
    7844              : }
    7845              : 
    7846              : /* Expand an expression EXP that calls a built-in function,
    7847              :    with result going to TARGET if that's convenient
    7848              :    (and in mode MODE if that's convenient).
    7849              :    SUBTARGET may be used as the target for computing one of EXP's operands.
    7850              :    IGNORE is nonzero if the value is to be ignored.  */
    7851              : 
    7852              : rtx
    7853      2018241 : expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
    7854              :                 int ignore)
    7855              : {
    7856      2018241 :   tree fndecl = get_callee_fndecl (exp);
    7857      2018241 :   machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
    7858      2018241 :   int flags;
    7859              : 
    7860      2018241 :   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
    7861       177486 :     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
    7862              : 
    7863              :   /* When ASan is enabled, we don't want to expand some memory/string
    7864              :      builtins and rely on libsanitizer's hooks.  This allows us to avoid
    7865              :      redundant checks and be sure, that possible overflow will be detected
    7866              :      by ASan.  */
    7867              : 
    7868      1840755 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
    7869      1840755 :   if (param_asan_kernel_mem_intrinsic_prefix
    7870      1840755 :       && sanitize_flags_p (SANITIZE_KERNEL_ADDRESS
    7871              :                            | SANITIZE_KERNEL_HWADDRESS))
    7872           42 :     switch (fcode)
    7873              :       {
    7874           42 :         rtx save_decl_rtl, ret;
    7875           42 :       case BUILT_IN_MEMCPY:
    7876           42 :       case BUILT_IN_MEMMOVE:
    7877           42 :       case BUILT_IN_MEMSET:
    7878           42 :         save_decl_rtl = DECL_RTL (fndecl);
    7879           42 :         DECL_RTL (fndecl) = asan_memfn_rtl (fndecl);
    7880           42 :         ret = expand_call (exp, target, ignore);
    7881           42 :         DECL_RTL (fndecl) = save_decl_rtl;
    7882           42 :         return ret;
    7883              :       default:
    7884              :         break;
    7885              :       }
    7886      1840713 :   if (sanitize_flags_p (SANITIZE_ADDRESS | SANITIZE_HWADDRESS)
    7887      1840713 :                   && asan_intercepted_p (fcode))
    7888          938 :     return expand_call (exp, target, ignore);
    7889              : 
    7890              :   /* When not optimizing, generate calls to library functions for a certain
    7891              :      set of builtins.  */
    7892      1839775 :   if (!optimize
    7893       430051 :       && !called_as_built_in (fndecl)
    7894       145875 :       && fcode != BUILT_IN_FORK
    7895       145875 :       && fcode != BUILT_IN_EXECL
    7896       145862 :       && fcode != BUILT_IN_EXECV
    7897       145862 :       && fcode != BUILT_IN_EXECLP
    7898       145860 :       && fcode != BUILT_IN_EXECLE
    7899       145860 :       && fcode != BUILT_IN_EXECVP
    7900       145859 :       && fcode != BUILT_IN_EXECVE
    7901       145859 :       && fcode != BUILT_IN_CLEAR_CACHE
    7902       145856 :       && !ALLOCA_FUNCTION_CODE_P (fcode)
    7903       145802 :       && fcode != BUILT_IN_FREE
    7904       143658 :       && (fcode != BUILT_IN_MEMSET
    7905        55893 :           || !(flag_inline_stringops & ILSOP_MEMSET))
    7906       143655 :       && (fcode != BUILT_IN_MEMCPY
    7907          918 :           || !(flag_inline_stringops & ILSOP_MEMCPY))
    7908       143519 :       && (fcode != BUILT_IN_MEMMOVE
    7909          348 :           || !(flag_inline_stringops & ILSOP_MEMMOVE))
    7910      1983294 :       && (fcode != BUILT_IN_MEMCMP
    7911         2529 :           || !(flag_inline_stringops & ILSOP_MEMCMP)))
    7912       143471 :     return expand_call (exp, target, ignore);
    7913              : 
    7914              :   /* The built-in function expanders test for target == const0_rtx
    7915              :      to determine whether the function's result will be ignored.  */
    7916      1696304 :   if (ignore)
    7917      1004387 :     target = const0_rtx;
    7918              : 
    7919              :   /* If the result of a pure or const built-in function is ignored, and
    7920              :      none of its arguments are volatile, we can avoid expanding the
    7921              :      built-in call and just evaluate the arguments for side-effects.  */
    7922      1696304 :   if (target == const0_rtx
    7923      1004387 :       && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
    7924      1699973 :       && !(flags & ECF_LOOPING_CONST_OR_PURE))
    7925              :     {
    7926            6 :       bool volatilep = false;
    7927            6 :       tree arg;
    7928            6 :       call_expr_arg_iterator iter;
    7929              : 
    7930           20 :       FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
    7931            8 :         if (TREE_THIS_VOLATILE (arg))
    7932              :           {
    7933              :             volatilep = true;
    7934              :             break;
    7935              :           }
    7936              : 
    7937            6 :       if (! volatilep)
    7938              :         {
    7939           20 :           FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
    7940            8 :             expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
    7941            6 :           return const0_rtx;
    7942              :         }
    7943              :     }
    7944              : 
    7945      1696298 :   switch (fcode)
    7946              :     {
    7947            4 :     CASE_FLT_FN (BUILT_IN_FABS):
    7948            4 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
    7949            4 :     case BUILT_IN_FABSD32:
    7950            4 :     case BUILT_IN_FABSD64:
    7951            4 :     case BUILT_IN_FABSD128:
    7952            4 :     case BUILT_IN_FABSD64X:
    7953            4 :       target = expand_builtin_fabs (exp, target, subtarget);
    7954            4 :       if (target)
    7955       843087 :         return target;
    7956       853211 :       break;
    7957              : 
    7958        11677 :     CASE_FLT_FN (BUILT_IN_COPYSIGN):
    7959        11677 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
    7960        11677 :       target = expand_builtin_copysign (exp, target, subtarget);
    7961        11677 :       if (target)
    7962              :         return target;
    7963              :       break;
    7964              : 
    7965              :       /* Just do a normal library call if we were unable to fold
    7966              :          the values.  */
    7967              :     CASE_FLT_FN (BUILT_IN_CABS):
    7968              :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_CABS):
    7969              :       break;
    7970              : 
    7971          368 :     CASE_FLT_FN (BUILT_IN_FMA):
    7972          368 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
    7973          368 :       target = expand_builtin_mathfn_ternary (exp, target, subtarget);
    7974          368 :       if (target)
    7975              :         return target;
    7976              :       break;
    7977              : 
    7978          232 :     CASE_FLT_FN (BUILT_IN_ILOGB):
    7979          232 :       if (! flag_unsafe_math_optimizations)
    7980              :         break;
    7981            4 :       gcc_fallthrough ();
    7982            4 :     CASE_FLT_FN (BUILT_IN_ISINF):
    7983            4 :     CASE_FLT_FN (BUILT_IN_FINITE):
    7984            4 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    7985            4 :     case BUILT_IN_ISFINITE:
    7986            4 :     case BUILT_IN_ISNORMAL:
    7987            4 :       target = expand_builtin_interclass_mathfn (exp, target);
    7988            4 :       if (target)
    7989              :         return target;
    7990              :       break;
    7991              : 
    7992          784 :     case BUILT_IN_ISSIGNALING:
    7993          784 :       target = expand_builtin_issignaling (exp, target);
    7994          784 :       if (target)
    7995              :         return target;
    7996              :       break;
    7997              : 
    7998          223 :     CASE_FLT_FN (BUILT_IN_ICEIL):
    7999          223 :     CASE_FLT_FN (BUILT_IN_LCEIL):
    8000          223 :     CASE_FLT_FN (BUILT_IN_LLCEIL):
    8001          223 :     CASE_FLT_FN (BUILT_IN_LFLOOR):
    8002          223 :     CASE_FLT_FN (BUILT_IN_IFLOOR):
    8003          223 :     CASE_FLT_FN (BUILT_IN_LLFLOOR):
    8004          223 :       target = expand_builtin_int_roundingfn (exp, target);
    8005          223 :       if (target)
    8006              :         return target;
    8007              :       break;
    8008              : 
    8009          588 :     CASE_FLT_FN (BUILT_IN_IRINT):
    8010          588 :     CASE_FLT_FN (BUILT_IN_LRINT):
    8011          588 :     CASE_FLT_FN (BUILT_IN_LLRINT):
    8012          588 :     CASE_FLT_FN (BUILT_IN_IROUND):
    8013          588 :     CASE_FLT_FN (BUILT_IN_LROUND):
    8014          588 :     CASE_FLT_FN (BUILT_IN_LLROUND):
    8015          588 :       target = expand_builtin_int_roundingfn_2 (exp, target);
    8016          588 :       if (target)
    8017              :         return target;
    8018              :       break;
    8019              : 
    8020          292 :     CASE_FLT_FN (BUILT_IN_POWI):
    8021          292 :       target = expand_builtin_powi (exp, target);
    8022          292 :       if (target)
    8023              :         return target;
    8024              :       break;
    8025              : 
    8026          170 :     CASE_FLT_FN (BUILT_IN_CEXPI):
    8027          170 :       target = expand_builtin_cexpi (exp, target);
    8028          170 :       gcc_assert (target);
    8029              :       return target;
    8030              : 
    8031         1018 :     CASE_FLT_FN (BUILT_IN_SIN):
    8032         1018 :     CASE_FLT_FN (BUILT_IN_COS):
    8033         1018 :       if (! flag_unsafe_math_optimizations)
    8034              :         break;
    8035           47 :       target = expand_builtin_mathfn_3 (exp, target, subtarget);
    8036           47 :       if (target)
    8037              :         return target;
    8038              :       break;
    8039              : 
    8040          164 :     CASE_FLT_FN (BUILT_IN_SINCOS):
    8041          164 :       if (! flag_unsafe_math_optimizations)
    8042              :         break;
    8043            3 :       target = expand_builtin_sincos (exp);
    8044            3 :       if (target)
    8045              :         return target;
    8046              :       break;
    8047              : 
    8048           60 :     case BUILT_IN_FEGETROUND:
    8049           60 :       target = expand_builtin_fegetround (exp, target, target_mode);
    8050           60 :       if (target)
    8051              :         return target;
    8052              :       break;
    8053              : 
    8054         1064 :     case BUILT_IN_FECLEAREXCEPT:
    8055         1064 :       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
    8056              :                                                       feclearexcept_optab);
    8057         1064 :       if (target)
    8058              :         return target;
    8059              :       break;
    8060              : 
    8061          831 :     case BUILT_IN_FERAISEEXCEPT:
    8062          831 :       target = expand_builtin_feclear_feraise_except (exp, target, target_mode,
    8063              :                                                       feraiseexcept_optab);
    8064          831 :       if (target)
    8065              :         return target;
    8066              :       break;
    8067              : 
    8068          464 :     case BUILT_IN_APPLY_ARGS:
    8069          464 :       return expand_builtin_apply_args ();
    8070              : 
    8071              :       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
    8072              :          FUNCTION with a copy of the parameters described by
    8073              :          ARGUMENTS, and ARGSIZE.  It returns a block of memory
    8074              :          allocated on the stack into which is stored all the registers
    8075              :          that might possibly be used for returning the result of a
    8076              :          function.  ARGUMENTS is the value returned by
    8077              :          __builtin_apply_args.  ARGSIZE is the number of bytes of
    8078              :          arguments that must be copied.  ??? How should this value be
    8079              :          computed?  We'll also need a safe worst case value for varargs
    8080              :          functions.  */
    8081          483 :     case BUILT_IN_APPLY:
    8082          483 :       if (!validate_arglist (exp, POINTER_TYPE,
    8083              :                              POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
    8084          483 :           && !validate_arglist (exp, REFERENCE_TYPE,
    8085              :                                 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    8086            0 :         return const0_rtx;
    8087              :       else
    8088              :         {
    8089          483 :           rtx ops[3];
    8090              : 
    8091          483 :           ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
    8092          483 :           ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
    8093          483 :           ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
    8094              : 
    8095          483 :           return expand_builtin_apply (ops[0], ops[1], ops[2]);
    8096              :         }
    8097              : 
    8098              :       /* __builtin_return (RESULT) causes the function to return the
    8099              :          value described by RESULT.  RESULT is address of the block of
    8100              :          memory returned by __builtin_apply.  */
    8101          379 :     case BUILT_IN_RETURN:
    8102          379 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8103          379 :         expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
    8104          379 :       return const0_rtx;
    8105              : 
    8106            0 :     case BUILT_IN_CALL_CODE_ADDRESS:
    8107              :       /* All valid uses of __builtin_call_code_address () are removed in
    8108              :          in tree-nested.cc or gimple-fold.cc.  */
    8109            0 :       error ("argument to %<__builtin_call_code_address%> must be a function");
    8110            0 :       return const0_rtx;
    8111              : 
    8112            0 :     case BUILT_IN_CALL_STATIC_CHAIN:
    8113              :        /* All valid uses of __builtin_call_static_chain () are removed in
    8114              :           in tree-nested.cc or gimple-fold.cc.  */
    8115            0 :       error ("argument to %<__builtin_call_static_chain%> must be a function");
    8116            0 :       return const0_rtx;
    8117              : 
    8118            0 :     case BUILT_IN_SAVEREGS:
    8119            0 :       return expand_builtin_saveregs ();
    8120              : 
    8121           16 :     case BUILT_IN_VA_ARG_PACK:
    8122              :       /* All valid uses of __builtin_va_arg_pack () are removed during
    8123              :          inlining.  */
    8124           16 :       error ("invalid use of %<__builtin_va_arg_pack ()%>");
    8125           16 :       return const0_rtx;
    8126              : 
    8127            0 :     case BUILT_IN_VA_ARG_PACK_LEN:
    8128              :       /* All valid uses of __builtin_va_arg_pack_len () are removed during
    8129              :          inlining.  */
    8130            0 :       error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
    8131            0 :       return const0_rtx;
    8132              : 
    8133              :       /* Return the address of the first anonymous stack arg.  */
    8134          158 :     case BUILT_IN_NEXT_ARG:
    8135          158 :       if (fold_builtin_next_arg (exp, false))
    8136            0 :         return const0_rtx;
    8137          158 :       return expand_builtin_next_arg ();
    8138              : 
    8139           28 :     case BUILT_IN_CLEAR_CACHE:
    8140           28 :       expand_builtin___clear_cache (exp);
    8141           28 :       return const0_rtx;
    8142              : 
    8143            0 :     case BUILT_IN_CLASSIFY_TYPE:
    8144            0 :       return expand_builtin_classify_type (exp);
    8145              : 
    8146            0 :     case BUILT_IN_CONSTANT_P:
    8147            0 :       return const0_rtx;
    8148              : 
    8149        15936 :     case BUILT_IN_FRAME_ADDRESS:
    8150        15936 :     case BUILT_IN_RETURN_ADDRESS:
    8151        15936 :       return expand_builtin_frame_address (fndecl, exp);
    8152              : 
    8153          540 :     case BUILT_IN_STACK_ADDRESS:
    8154          540 :       return expand_builtin_stack_address ();
    8155              : 
    8156         2170 :     case BUILT_IN___STRUB_ENTER:
    8157         2170 :       target = expand_builtin_strub_enter (exp);
    8158         2170 :       if (target)
    8159              :         return target;
    8160              :       break;
    8161              : 
    8162         1085 :     case BUILT_IN___STRUB_UPDATE:
    8163         1085 :       target = expand_builtin_strub_update (exp);
    8164         1085 :       if (target)
    8165              :         return target;
    8166              :       break;
    8167              : 
    8168         2740 :     case BUILT_IN___STRUB_LEAVE:
    8169         2740 :       target = expand_builtin_strub_leave (exp);
    8170         2740 :       if (target)
    8171              :         return target;
    8172              :       break;
    8173              : 
    8174              :     /* Returns the address of the area where the structure is returned.
    8175              :        0 otherwise.  */
    8176            0 :     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
    8177            0 :       if (call_expr_nargs (exp) != 0
    8178            0 :           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
    8179            0 :           || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
    8180            0 :         return const0_rtx;
    8181              :       else
    8182            0 :         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
    8183              : 
    8184        27611 :     CASE_BUILT_IN_ALLOCA:
    8185        27611 :       target = expand_builtin_alloca (exp);
    8186        27611 :       if (target)
    8187              :         return target;
    8188              :       break;
    8189              : 
    8190          204 :     case BUILT_IN_ASAN_ALLOCAS_UNPOISON:
    8191          204 :       return expand_asan_emit_allocas_unpoison (exp);
    8192              : 
    8193         1856 :     case BUILT_IN_STACK_SAVE:
    8194         1856 :       return expand_stack_save ();
    8195              : 
    8196         1755 :     case BUILT_IN_STACK_RESTORE:
    8197         1755 :       expand_stack_restore (CALL_EXPR_ARG (exp, 0));
    8198         1755 :       return const0_rtx;
    8199              : 
    8200         1279 :     case BUILT_IN_BSWAP16:
    8201         1279 :     case BUILT_IN_BSWAP32:
    8202         1279 :     case BUILT_IN_BSWAP64:
    8203         1279 :     case BUILT_IN_BSWAP128:
    8204         1279 :       target = expand_builtin_bswap (target_mode, exp, target, subtarget);
    8205         1279 :       if (target)
    8206              :         return target;
    8207              :       break;
    8208              : 
    8209           52 :     case BUILT_IN_BITREVERSE8:
    8210           52 :     case BUILT_IN_BITREVERSE16:
    8211           52 :     case BUILT_IN_BITREVERSE32:
    8212           52 :     case BUILT_IN_BITREVERSE64:
    8213           52 :     case BUILT_IN_BITREVERSE128:
    8214           52 :       target = expand_builtin_unop (target_mode, exp, target, subtarget,
    8215              :                                     bitreverse_optab);
    8216           52 :       if (target)
    8217              :         return target;
    8218              :       break;
    8219              : 
    8220            0 :     CASE_INT_FN (BUILT_IN_FFS):
    8221            0 :       target = expand_builtin_unop (target_mode, exp, target,
    8222              :                                     subtarget, ffs_optab);
    8223            0 :       if (target)
    8224              :         return target;
    8225              :       break;
    8226              : 
    8227          205 :     CASE_INT_FN (BUILT_IN_CLZ):
    8228          205 :       target = expand_builtin_unop (target_mode, exp, target,
    8229              :                                     subtarget, clz_optab);
    8230          205 :       if (target)
    8231              :         return target;
    8232              :       break;
    8233              : 
    8234           48 :     CASE_INT_FN (BUILT_IN_CTZ):
    8235           48 :       target = expand_builtin_unop (target_mode, exp, target,
    8236              :                                     subtarget, ctz_optab);
    8237           48 :       if (target)
    8238              :         return target;
    8239              :       break;
    8240              : 
    8241           91 :     CASE_INT_FN (BUILT_IN_CLRSB):
    8242           91 :       target = expand_builtin_unop (target_mode, exp, target,
    8243              :                                     subtarget, clrsb_optab);
    8244           91 :       if (target)
    8245              :         return target;
    8246              :       break;
    8247              : 
    8248          447 :     CASE_INT_FN (BUILT_IN_POPCOUNT):
    8249          447 :       target = expand_builtin_unop (target_mode, exp, target,
    8250              :                                     subtarget, popcount_optab);
    8251          447 :       if (target)
    8252              :         return target;
    8253              :       break;
    8254              : 
    8255           11 :     CASE_INT_FN (BUILT_IN_PARITY):
    8256           11 :       target = expand_builtin_unop (target_mode, exp, target,
    8257              :                                     subtarget, parity_optab);
    8258           11 :       if (target)
    8259              :         return target;
    8260              :       break;
    8261              : 
    8262        14617 :     case BUILT_IN_STRLEN:
    8263        14617 :       target = expand_builtin_strlen (exp, target, target_mode);
    8264        14617 :       if (target)
    8265              :         return target;
    8266              :       break;
    8267              : 
    8268          580 :     case BUILT_IN_STRNLEN:
    8269          580 :       target = expand_builtin_strnlen (exp, target, target_mode);
    8270          580 :       if (target)
    8271              :         return target;
    8272              :       break;
    8273              : 
    8274         1860 :     case BUILT_IN_STRCPY:
    8275         1860 :       target = expand_builtin_strcpy (exp, target);
    8276         1860 :       if (target)
    8277              :         return target;
    8278              :       break;
    8279              : 
    8280         2177 :     case BUILT_IN_STRNCPY:
    8281         2177 :       target = expand_builtin_strncpy (exp, target);
    8282         2177 :       if (target)
    8283              :         return target;
    8284              :       break;
    8285              : 
    8286          454 :     case BUILT_IN_STPCPY:
    8287          454 :       target = expand_builtin_stpcpy (exp, target, mode);
    8288          454 :       if (target)
    8289              :         return target;
    8290              :       break;
    8291              : 
    8292       108828 :     case BUILT_IN_MEMCPY:
    8293       108828 :       target = expand_builtin_memcpy (exp, target);
    8294       108828 :       if (target)
    8295              :         return target;
    8296              :       break;
    8297              : 
    8298        17563 :     case BUILT_IN_MEMMOVE:
    8299        17563 :       target = expand_builtin_memmove (exp, target);
    8300        17563 :       if (target)
    8301              :         return target;
    8302              :       break;
    8303              : 
    8304         1394 :     case BUILT_IN_MEMPCPY:
    8305         1394 :       target = expand_builtin_mempcpy (exp, target);
    8306         1394 :       if (target)
    8307              :         return target;
    8308              :       break;
    8309              : 
    8310        36761 :     case BUILT_IN_MEMSET:
    8311        36761 :       target = expand_builtin_memset (exp, target, mode);
    8312        36761 :       if (target)
    8313              :         return target;
    8314              :       break;
    8315              : 
    8316            0 :     case BUILT_IN_BZERO:
    8317            0 :       target = expand_builtin_bzero (exp);
    8318            0 :       if (target)
    8319              :         return target;
    8320              :       break;
    8321              : 
    8322              :     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
    8323              :        back to a BUILT_IN_STRCMP. Remember to delete the 3rd parameter
    8324              :        when changing it to a strcmp call.  */
    8325          371 :     case BUILT_IN_STRCMP_EQ:
    8326          371 :       target = expand_builtin_memcmp (exp, target, true);
    8327          371 :       if (target)
    8328              :         return target;
    8329              : 
    8330              :       /* Change this call back to a BUILT_IN_STRCMP.  */
    8331           25 :       TREE_OPERAND (exp, 1)
    8332           25 :         = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
    8333              : 
    8334              :       /* Delete the last parameter.  */
    8335           25 :       unsigned int i;
    8336           25 :       vec<tree, va_gc> *arg_vec;
    8337           25 :       vec_alloc (arg_vec, 2);
    8338          100 :       for (i = 0; i < 2; i++)
    8339           50 :         arg_vec->quick_push (CALL_EXPR_ARG (exp, i));
    8340           25 :       exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), arg_vec);
    8341              :       /* FALLTHROUGH */
    8342              : 
    8343       127970 :     case BUILT_IN_STRCMP:
    8344       127970 :       target = expand_builtin_strcmp (exp, target);
    8345       127970 :       if (target)
    8346              :         return target;
    8347              :       break;
    8348              : 
    8349              :     /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
    8350              :        back to a BUILT_IN_STRNCMP.  */
    8351           38 :     case BUILT_IN_STRNCMP_EQ:
    8352           38 :       target = expand_builtin_memcmp (exp, target, true);
    8353           38 :       if (target)
    8354              :         return target;
    8355              : 
    8356              :       /* Change it back to a BUILT_IN_STRNCMP.  */
    8357            0 :       TREE_OPERAND (exp, 1)
    8358            0 :         = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
    8359              :       /* FALLTHROUGH */
    8360              : 
    8361         2027 :     case BUILT_IN_STRNCMP:
    8362         2027 :       target = expand_builtin_strncmp (exp, target, mode);
    8363         2027 :       if (target)
    8364              :         return target;
    8365              :       break;
    8366              : 
    8367       106123 :     case BUILT_IN_BCMP:
    8368       106123 :     case BUILT_IN_MEMCMP:
    8369       106123 :     case BUILT_IN_MEMCMP_EQ:
    8370       106123 :       target = expand_builtin_memcmp (exp, target, fcode == BUILT_IN_MEMCMP_EQ);
    8371       106123 :       if (target)
    8372              :         return target;
    8373        37547 :       if (fcode == BUILT_IN_MEMCMP_EQ)
    8374              :         {
    8375        23031 :           tree newdecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
    8376        23031 :           TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
    8377              :         }
    8378              :       break;
    8379              : 
    8380            0 :     case BUILT_IN_SETJMP:
    8381              :       /* This should have been lowered to the builtins below.  */
    8382            0 :       gcc_unreachable ();
    8383              : 
    8384          842 :     case BUILT_IN_SETJMP_SETUP:
    8385              :       /* __builtin_setjmp_setup is passed a pointer to an array of five words
    8386              :           and the receiver label.  */
    8387          842 :       if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
    8388              :         {
    8389          842 :           rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
    8390              :                                       VOIDmode, EXPAND_NORMAL);
    8391          842 :           tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
    8392          842 :           rtx_insn *label_r = label_rtx (label);
    8393              : 
    8394          842 :           expand_builtin_setjmp_setup (buf_addr, label_r);
    8395          842 :           return const0_rtx;
    8396              :         }
    8397              :       break;
    8398              : 
    8399          842 :     case BUILT_IN_SETJMP_RECEIVER:
    8400              :        /* __builtin_setjmp_receiver is passed the receiver label.  */
    8401          842 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8402              :         {
    8403          842 :           tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
    8404          842 :           rtx_insn *label_r = label_rtx (label);
    8405              : 
    8406          842 :           expand_builtin_setjmp_receiver (label_r);
    8407          842 :           nonlocal_goto_handler_labels
    8408         1684 :             = gen_rtx_INSN_LIST (VOIDmode, label_r,
    8409          842 :                                  nonlocal_goto_handler_labels);
    8410              :           /* ??? Do not let expand_label treat us as such since we would
    8411              :              not want to be both on the list of non-local labels and on
    8412              :              the list of forced labels.  */
    8413          842 :           FORCED_LABEL (label) = 0;
    8414          842 :           return const0_rtx;
    8415              :         }
    8416              :       break;
    8417              : 
    8418              :       /* __builtin_longjmp is passed a pointer to an array of five words.
    8419              :          It's similar to the C library longjmp function but works with
    8420              :          __builtin_setjmp above.  */
    8421          392 :     case BUILT_IN_LONGJMP:
    8422          392 :       if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
    8423              :         {
    8424          392 :           rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
    8425              :                                       VOIDmode, EXPAND_NORMAL);
    8426          392 :           rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
    8427              : 
    8428          392 :           if (value != const1_rtx)
    8429              :             {
    8430            0 :               error ("%<__builtin_longjmp%> second argument must be 1");
    8431            0 :               return const0_rtx;
    8432              :             }
    8433              : 
    8434          392 :           expand_builtin_longjmp (buf_addr, value);
    8435          392 :           return const0_rtx;
    8436              :         }
    8437              :       break;
    8438              : 
    8439          512 :     case BUILT_IN_NONLOCAL_GOTO:
    8440          512 :       target = expand_builtin_nonlocal_goto (exp);
    8441          512 :       if (target)
    8442              :         return target;
    8443              :       break;
    8444              : 
    8445              :       /* This updates the setjmp buffer that is its argument with the value
    8446              :          of the current stack pointer.  */
    8447            0 :     case BUILT_IN_UPDATE_SETJMP_BUF:
    8448            0 :       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
    8449              :         {
    8450            0 :           rtx buf_addr
    8451            0 :             = expand_normal (CALL_EXPR_ARG (exp, 0));
    8452              : 
    8453            0 :           expand_builtin_update_setjmp_buf (buf_addr);
    8454            0 :           return const0_rtx;
    8455              :         }
    8456              :       break;
    8457              : 
    8458        38675 :     case BUILT_IN_TRAP:
    8459        38675 :     case BUILT_IN_UNREACHABLE_TRAP:
    8460        38675 :       expand_builtin_trap ();
    8461        38675 :       return const0_rtx;
    8462              : 
    8463         2563 :     case BUILT_IN_UNREACHABLE:
    8464         2563 :       expand_builtin_unreachable ();
    8465         2563 :       return const0_rtx;
    8466              : 
    8467          402 :     case BUILT_IN_OBSERVABLE_CHKPT:
    8468              :       /* Generate no code.  */
    8469          402 :       return const0_rtx;
    8470              : 
    8471         1368 :     CASE_FLT_FN (BUILT_IN_SIGNBIT):
    8472         1368 :     case BUILT_IN_SIGNBITD32:
    8473         1368 :     case BUILT_IN_SIGNBITD64:
    8474         1368 :     case BUILT_IN_SIGNBITD128:
    8475         1368 :       target = expand_builtin_signbit (exp, target);
    8476         1368 :       if (target)
    8477              :         return target;
    8478              :       break;
    8479              : 
    8480              :       /* Various hooks for the DWARF 2 __throw routine.  */
    8481           34 :     case BUILT_IN_UNWIND_INIT:
    8482           34 :       expand_builtin_unwind_init ();
    8483           34 :       return const0_rtx;
    8484         1224 :     case BUILT_IN_DWARF_CFA:
    8485         1224 :       return virtual_cfa_rtx;
    8486              : #ifdef DWARF2_UNWIND_INFO
    8487           48 :     case BUILT_IN_DWARF_SP_COLUMN:
    8488           48 :       return expand_builtin_dwarf_sp_column ();
    8489            8 :     case BUILT_IN_INIT_DWARF_REG_SIZES:
    8490            8 :       expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
    8491            8 :       return const0_rtx;
    8492              : #endif
    8493           19 :     case BUILT_IN_FROB_RETURN_ADDR:
    8494           19 :       return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
    8495         2352 :     case BUILT_IN_EXTRACT_RETURN_ADDR:
    8496         2352 :       return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
    8497           29 :     case BUILT_IN_EH_RETURN:
    8498           58 :       expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
    8499           29 :                                 CALL_EXPR_ARG (exp, 1));
    8500           29 :       return const0_rtx;
    8501           21 :     case BUILT_IN_EH_RETURN_DATA_REGNO:
    8502           21 :       return expand_builtin_eh_return_data_regno (exp);
    8503            2 :     case BUILT_IN_EXTEND_POINTER:
    8504            2 :       return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
    8505       102017 :     case BUILT_IN_EH_POINTER:
    8506       102017 :       return expand_builtin_eh_pointer (exp);
    8507         5721 :     case BUILT_IN_EH_FILTER:
    8508         5721 :       return expand_builtin_eh_filter (exp);
    8509       100295 :     case BUILT_IN_EH_COPY_VALUES:
    8510       100295 :       return expand_builtin_eh_copy_values (exp);
    8511              : 
    8512        21082 :     case BUILT_IN_VA_START:
    8513        21082 :       return expand_builtin_va_start (exp);
    8514        12161 :     case BUILT_IN_VA_END:
    8515        12161 :       return expand_builtin_va_end (exp);
    8516          240 :     case BUILT_IN_VA_COPY:
    8517          240 :       return expand_builtin_va_copy (exp);
    8518         1407 :     case BUILT_IN_EXPECT:
    8519         1407 :       return expand_builtin_expect (exp, target);
    8520            5 :     case BUILT_IN_EXPECT_WITH_PROBABILITY:
    8521            5 :       return expand_builtin_expect_with_probability (exp, target);
    8522          665 :     case BUILT_IN_ASSUME_ALIGNED:
    8523          665 :       return expand_builtin_assume_aligned (exp, target);
    8524         2058 :     case BUILT_IN_PREFETCH:
    8525         2058 :       expand_builtin_prefetch (exp);
    8526         2058 :       return const0_rtx;
    8527              : 
    8528          306 :     case BUILT_IN_INIT_TRAMPOLINE:
    8529          306 :       return expand_builtin_init_trampoline (exp, true);
    8530            0 :     case BUILT_IN_INIT_HEAP_TRAMPOLINE:
    8531            0 :       return expand_builtin_init_trampoline (exp, false);
    8532          353 :     case BUILT_IN_ADJUST_TRAMPOLINE:
    8533          353 :       return expand_builtin_adjust_trampoline (exp);
    8534              : 
    8535            0 :     case BUILT_IN_INIT_DESCRIPTOR:
    8536            0 :       return expand_builtin_init_descriptor (exp);
    8537            0 :     case BUILT_IN_ADJUST_DESCRIPTOR:
    8538            0 :       return expand_builtin_adjust_descriptor (exp);
    8539              : 
    8540              :     case BUILT_IN_GCC_NESTED_PTR_CREATED:
    8541              :     case BUILT_IN_GCC_NESTED_PTR_DELETED:
    8542              :       break; /* At present, no expansion, just call the function.  */
    8543              : 
    8544          111 :     case BUILT_IN_FORK:
    8545          111 :     case BUILT_IN_EXECL:
    8546          111 :     case BUILT_IN_EXECV:
    8547          111 :     case BUILT_IN_EXECLP:
    8548          111 :     case BUILT_IN_EXECLE:
    8549          111 :     case BUILT_IN_EXECVP:
    8550          111 :     case BUILT_IN_EXECVE:
    8551          111 :       target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
    8552          111 :       if (target)
    8553              :         return target;
    8554              :       break;
    8555              : 
    8556          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_1:
    8557          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_2:
    8558          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_4:
    8559          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_8:
    8560          712 :     case BUILT_IN_SYNC_FETCH_AND_ADD_16:
    8561          712 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
    8562          712 :       target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
    8563          712 :       if (target)
    8564              :         return target;
    8565              :       break;
    8566              : 
    8567          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_1:
    8568          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_2:
    8569          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_4:
    8570          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_8:
    8571          585 :     case BUILT_IN_SYNC_FETCH_AND_SUB_16:
    8572          585 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
    8573          585 :       target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
    8574          585 :       if (target)
    8575              :         return target;
    8576              :       break;
    8577              : 
    8578          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_1:
    8579          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_2:
    8580          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_4:
    8581          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_8:
    8582          512 :     case BUILT_IN_SYNC_FETCH_AND_OR_16:
    8583          512 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
    8584          512 :       target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
    8585          512 :       if (target)
    8586              :         return target;
    8587              :       break;
    8588              : 
    8589          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_1:
    8590          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_2:
    8591          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_4:
    8592          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_8:
    8593          488 :     case BUILT_IN_SYNC_FETCH_AND_AND_16:
    8594          488 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
    8595          488 :       target = expand_builtin_sync_operation (mode, exp, AND, false, target);
    8596          488 :       if (target)
    8597              :         return target;
    8598              :       break;
    8599              : 
    8600          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_1:
    8601          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_2:
    8602          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_4:
    8603          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_8:
    8604          581 :     case BUILT_IN_SYNC_FETCH_AND_XOR_16:
    8605          581 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
    8606          581 :       target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
    8607          581 :       if (target)
    8608              :         return target;
    8609              :       break;
    8610              : 
    8611          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    8612          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    8613          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    8614          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    8615          434 :     case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    8616          434 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
    8617          434 :       target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
    8618          434 :       if (target)
    8619              :         return target;
    8620              :       break;
    8621              : 
    8622          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_1:
    8623          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_2:
    8624          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_4:
    8625          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_8:
    8626          161 :     case BUILT_IN_SYNC_ADD_AND_FETCH_16:
    8627          161 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
    8628          161 :       target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
    8629          161 :       if (target)
    8630              :         return target;
    8631              :       break;
    8632              : 
    8633          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_1:
    8634          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_2:
    8635          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_4:
    8636          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_8:
    8637          121 :     case BUILT_IN_SYNC_SUB_AND_FETCH_16:
    8638          121 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
    8639          121 :       target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
    8640          121 :       if (target)
    8641              :         return target;
    8642              :       break;
    8643              : 
    8644          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_1:
    8645          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_2:
    8646          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_4:
    8647          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_8:
    8648          115 :     case BUILT_IN_SYNC_OR_AND_FETCH_16:
    8649          115 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
    8650          115 :       target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
    8651          115 :       if (target)
    8652              :         return target;
    8653              :       break;
    8654              : 
    8655          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_1:
    8656          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_2:
    8657          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_4:
    8658          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_8:
    8659          116 :     case BUILT_IN_SYNC_AND_AND_FETCH_16:
    8660          116 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
    8661          116 :       target = expand_builtin_sync_operation (mode, exp, AND, true, target);
    8662          116 :       if (target)
    8663              :         return target;
    8664              :       break;
    8665              : 
    8666          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_1:
    8667          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_2:
    8668          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_4:
    8669          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_8:
    8670          114 :     case BUILT_IN_SYNC_XOR_AND_FETCH_16:
    8671          114 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
    8672          114 :       target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
    8673          114 :       if (target)
    8674              :         return target;
    8675              :       break;
    8676              : 
    8677           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    8678           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    8679           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    8680           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    8681           89 :     case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    8682           89 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
    8683           89 :       target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
    8684           89 :       if (target)
    8685              :         return target;
    8686              :       break;
    8687              : 
    8688          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
    8689          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
    8690          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
    8691          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
    8692          204 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
    8693          204 :       if (mode == VOIDmode)
    8694           40 :         mode = TYPE_MODE (boolean_type_node);
    8695          204 :       if (!target || !register_operand (target, mode))
    8696           40 :         target = gen_reg_rtx (mode);
    8697              : 
    8698          204 :       mode = get_builtin_sync_mode
    8699          204 :                                 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
    8700          204 :       target = expand_builtin_compare_and_swap (mode, exp, true, target);
    8701          204 :       if (target)
    8702              :         return target;
    8703              :       break;
    8704              : 
    8705          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
    8706          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
    8707          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
    8708          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
    8709          256 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
    8710          256 :       mode = get_builtin_sync_mode
    8711          256 :                                 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
    8712          256 :       target = expand_builtin_compare_and_swap (mode, exp, false, target);
    8713          256 :       if (target)
    8714              :         return target;
    8715              :       break;
    8716              : 
    8717          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
    8718          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
    8719          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
    8720          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
    8721          326 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
    8722          326 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
    8723          326 :       target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
    8724          326 :       if (target)
    8725              :         return target;
    8726              :       break;
    8727              : 
    8728          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_1:
    8729          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_2:
    8730          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_4:
    8731          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_8:
    8732          146 :     case BUILT_IN_SYNC_LOCK_RELEASE_16:
    8733          146 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
    8734          146 :       if (expand_builtin_sync_lock_release (mode, exp))
    8735          144 :         return const0_rtx;
    8736              :       break;
    8737              : 
    8738          273 :     case BUILT_IN_SYNC_SYNCHRONIZE:
    8739          273 :       expand_builtin_sync_synchronize ();
    8740          273 :       return const0_rtx;
    8741              : 
    8742         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_1:
    8743         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_2:
    8744         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_4:
    8745         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_8:
    8746         2937 :     case BUILT_IN_ATOMIC_EXCHANGE_16:
    8747         2937 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
    8748         2937 :       target = expand_builtin_atomic_exchange (mode, exp, target);
    8749         2937 :       if (target)
    8750              :         return target;
    8751              :       break;
    8752              : 
    8753         9129 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
    8754         9129 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
    8755         9129 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
    8756         9129 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
    8757         9129 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
    8758         9129 :       {
    8759         9129 :         unsigned int nargs, z;
    8760         9129 :         vec<tree, va_gc> *vec;
    8761              : 
    8762         9129 :         mode =
    8763         9129 :             get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
    8764         9129 :         target = expand_builtin_atomic_compare_exchange (mode, exp, target);
    8765         9129 :         if (target)
    8766         7329 :           return target;
    8767              : 
    8768              :         /* If this is turned into an external library call, the weak parameter
    8769              :            must be dropped to match the expected parameter list.  */
    8770         1800 :         nargs = call_expr_nargs (exp);
    8771         1800 :         vec_alloc (vec, nargs - 1);
    8772         9000 :         for (z = 0; z < 3; z++)
    8773         5400 :           vec->quick_push (CALL_EXPR_ARG (exp, z));
    8774              :         /* Skip the boolean weak parameter.  */
    8775         5400 :         for (z = 4; z < 6; z++)
    8776         3600 :           vec->quick_push (CALL_EXPR_ARG (exp, z));
    8777         1800 :         exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
    8778         1800 :         break;
    8779              :       }
    8780              : 
    8781        70597 :     case BUILT_IN_ATOMIC_LOAD_1:
    8782        70597 :     case BUILT_IN_ATOMIC_LOAD_2:
    8783        70597 :     case BUILT_IN_ATOMIC_LOAD_4:
    8784        70597 :     case BUILT_IN_ATOMIC_LOAD_8:
    8785        70597 :     case BUILT_IN_ATOMIC_LOAD_16:
    8786        70597 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
    8787        70597 :       target = expand_builtin_atomic_load (mode, exp, target);
    8788        70597 :       if (target)
    8789              :         return target;
    8790              :       break;
    8791              : 
    8792        17465 :     case BUILT_IN_ATOMIC_STORE_1:
    8793        17465 :     case BUILT_IN_ATOMIC_STORE_2:
    8794        17465 :     case BUILT_IN_ATOMIC_STORE_4:
    8795        17465 :     case BUILT_IN_ATOMIC_STORE_8:
    8796        17465 :     case BUILT_IN_ATOMIC_STORE_16:
    8797        17465 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
    8798        17465 :       target = expand_builtin_atomic_store (mode, exp);
    8799        17465 :       if (target)
    8800        15833 :         return const0_rtx;
    8801              :       break;
    8802              : 
    8803         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_1:
    8804         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_2:
    8805         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_4:
    8806         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_8:
    8807         4394 :     case BUILT_IN_ATOMIC_ADD_FETCH_16:
    8808         4394 :       {
    8809         4394 :         enum built_in_function lib;
    8810         4394 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
    8811         4394 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
    8812              :                                        (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
    8813         4394 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
    8814              :                                                  ignore, lib);
    8815         4394 :         if (target)
    8816              :           return target;
    8817              :         break;
    8818              :       }
    8819         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_1:
    8820         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_2:
    8821         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_4:
    8822         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_8:
    8823         2172 :     case BUILT_IN_ATOMIC_SUB_FETCH_16:
    8824         2172 :       {
    8825         2172 :         enum built_in_function lib;
    8826         2172 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
    8827         2172 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
    8828              :                                        (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
    8829         2172 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
    8830              :                                                  ignore, lib);
    8831         2172 :         if (target)
    8832              :           return target;
    8833              :         break;
    8834              :       }
    8835          902 :     case BUILT_IN_ATOMIC_AND_FETCH_1:
    8836          902 :     case BUILT_IN_ATOMIC_AND_FETCH_2:
    8837          902 :     case BUILT_IN_ATOMIC_AND_FETCH_4:
    8838          902 :     case BUILT_IN_ATOMIC_AND_FETCH_8:
    8839          902 :     case BUILT_IN_ATOMIC_AND_FETCH_16:
    8840          902 :       {
    8841          902 :         enum built_in_function lib;
    8842          902 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
    8843          902 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
    8844              :                                        (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
    8845          902 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
    8846              :                                                  ignore, lib);
    8847          902 :         if (target)
    8848              :           return target;
    8849              :         break;
    8850              :       }
    8851          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_1:
    8852          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_2:
    8853          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_4:
    8854          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_8:
    8855          162 :     case BUILT_IN_ATOMIC_NAND_FETCH_16:
    8856          162 :       {
    8857          162 :         enum built_in_function lib;
    8858          162 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
    8859          162 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
    8860              :                                        (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
    8861          162 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
    8862              :                                                  ignore, lib);
    8863          162 :         if (target)
    8864              :           return target;
    8865              :         break;
    8866              :       }
    8867          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_1:
    8868          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_2:
    8869          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_4:
    8870          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_8:
    8871          847 :     case BUILT_IN_ATOMIC_XOR_FETCH_16:
    8872          847 :       {
    8873          847 :         enum built_in_function lib;
    8874          847 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
    8875          847 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
    8876              :                                        (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
    8877          847 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
    8878              :                                                  ignore, lib);
    8879          847 :         if (target)
    8880              :           return target;
    8881              :         break;
    8882              :       }
    8883          965 :     case BUILT_IN_ATOMIC_OR_FETCH_1:
    8884          965 :     case BUILT_IN_ATOMIC_OR_FETCH_2:
    8885          965 :     case BUILT_IN_ATOMIC_OR_FETCH_4:
    8886          965 :     case BUILT_IN_ATOMIC_OR_FETCH_8:
    8887          965 :     case BUILT_IN_ATOMIC_OR_FETCH_16:
    8888          965 :       {
    8889          965 :         enum built_in_function lib;
    8890          965 :         mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
    8891          965 :         lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
    8892              :                                        (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
    8893          965 :         target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
    8894              :                                                  ignore, lib);
    8895          965 :         if (target)
    8896              :           return target;
    8897              :         break;
    8898              :       }
    8899        14569 :     case BUILT_IN_ATOMIC_FETCH_ADD_1:
    8900        14569 :     case BUILT_IN_ATOMIC_FETCH_ADD_2:
    8901        14569 :     case BUILT_IN_ATOMIC_FETCH_ADD_4:
    8902        14569 :     case BUILT_IN_ATOMIC_FETCH_ADD_8:
    8903        14569 :     case BUILT_IN_ATOMIC_FETCH_ADD_16:
    8904        14569 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
    8905        14569 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
    8906              :                                                ignore, BUILT_IN_NONE);
    8907        14569 :       if (target)
    8908              :         return target;
    8909              :       break;
    8910              : 
    8911         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_1:
    8912         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_2:
    8913         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_4:
    8914         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_8:
    8915         2107 :     case BUILT_IN_ATOMIC_FETCH_SUB_16:
    8916         2107 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
    8917         2107 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
    8918              :                                                ignore, BUILT_IN_NONE);
    8919         2107 :       if (target)
    8920              :         return target;
    8921              :       break;
    8922              : 
    8923          785 :     case BUILT_IN_ATOMIC_FETCH_AND_1:
    8924          785 :     case BUILT_IN_ATOMIC_FETCH_AND_2:
    8925          785 :     case BUILT_IN_ATOMIC_FETCH_AND_4:
    8926          785 :     case BUILT_IN_ATOMIC_FETCH_AND_8:
    8927          785 :     case BUILT_IN_ATOMIC_FETCH_AND_16:
    8928          785 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
    8929          785 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
    8930              :                                                ignore, BUILT_IN_NONE);
    8931          785 :       if (target)
    8932              :         return target;
    8933              :       break;
    8934              : 
    8935          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_1:
    8936          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_2:
    8937          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_4:
    8938          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_8:
    8939          125 :     case BUILT_IN_ATOMIC_FETCH_NAND_16:
    8940          125 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
    8941          125 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
    8942              :                                                ignore, BUILT_IN_NONE);
    8943          125 :       if (target)
    8944              :         return target;
    8945              :       break;
    8946              : 
    8947          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_1:
    8948          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_2:
    8949          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_4:
    8950          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_8:
    8951          875 :     case BUILT_IN_ATOMIC_FETCH_XOR_16:
    8952          875 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
    8953          875 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
    8954              :                                                ignore, BUILT_IN_NONE);
    8955          875 :       if (target)
    8956              :         return target;
    8957              :       break;
    8958              : 
    8959         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_1:
    8960         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_2:
    8961         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_4:
    8962         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_8:
    8963         1140 :     case BUILT_IN_ATOMIC_FETCH_OR_16:
    8964         1140 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
    8965         1140 :       target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
    8966              :                                                ignore, BUILT_IN_NONE);
    8967         1140 :       if (target)
    8968              :         return target;
    8969              :       break;
    8970              : 
    8971          266 :     case BUILT_IN_ATOMIC_TEST_AND_SET:
    8972          266 :       target = expand_builtin_atomic_test_and_set (exp, target);
    8973          266 :       if (target)
    8974              :         return target;
    8975              :       break;
    8976              : 
    8977           53 :     case BUILT_IN_ATOMIC_CLEAR:
    8978           53 :       return expand_builtin_atomic_clear (exp);
    8979              : 
    8980            1 :     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
    8981            1 :       return expand_builtin_atomic_always_lock_free (exp);
    8982              : 
    8983           10 :     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
    8984           10 :       target = expand_builtin_atomic_is_lock_free (exp);
    8985           10 :       if (target)
    8986              :         return target;
    8987              :       break;
    8988              : 
    8989          693 :     case BUILT_IN_ATOMIC_THREAD_FENCE:
    8990          693 :       expand_builtin_atomic_thread_fence (exp);
    8991          693 :       return const0_rtx;
    8992              : 
    8993           60 :     case BUILT_IN_ATOMIC_SIGNAL_FENCE:
    8994           60 :       expand_builtin_atomic_signal_fence (exp);
    8995           60 :       return const0_rtx;
    8996              : 
    8997          620 :     case BUILT_IN_OBJECT_SIZE:
    8998          620 :     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
    8999          620 :       return expand_builtin_object_size (exp);
    9000              : 
    9001          837 :     case BUILT_IN_MEMCPY_CHK:
    9002          837 :     case BUILT_IN_MEMPCPY_CHK:
    9003          837 :     case BUILT_IN_MEMMOVE_CHK:
    9004          837 :     case BUILT_IN_MEMSET_CHK:
    9005          837 :       target = expand_builtin_memory_chk (exp, target, mode, fcode);
    9006          837 :       if (target)
    9007              :         return target;
    9008              :       break;
    9009              : 
    9010         1086 :     case BUILT_IN_STRCPY_CHK:
    9011         1086 :     case BUILT_IN_STPCPY_CHK:
    9012         1086 :     case BUILT_IN_STRNCPY_CHK:
    9013         1086 :     case BUILT_IN_STPNCPY_CHK:
    9014         1086 :     case BUILT_IN_STRCAT_CHK:
    9015         1086 :     case BUILT_IN_STRNCAT_CHK:
    9016         1086 :     case BUILT_IN_SNPRINTF_CHK:
    9017         1086 :     case BUILT_IN_VSNPRINTF_CHK:
    9018         1086 :       maybe_emit_chk_warning (exp, fcode);
    9019         1086 :       break;
    9020              : 
    9021         1328 :     case BUILT_IN_SPRINTF_CHK:
    9022         1328 :     case BUILT_IN_VSPRINTF_CHK:
    9023         1328 :       maybe_emit_sprintf_chk_warning (exp, fcode);
    9024         1328 :       break;
    9025              : 
    9026            3 :     case BUILT_IN_THREAD_POINTER:
    9027            3 :       return expand_builtin_thread_pointer (exp, target);
    9028              : 
    9029            0 :     case BUILT_IN_SET_THREAD_POINTER:
    9030            0 :       expand_builtin_set_thread_pointer (exp);
    9031            0 :       return const0_rtx;
    9032              : 
    9033              :     case BUILT_IN_ACC_ON_DEVICE:
    9034              :       /* Do library call, if we failed to expand the builtin when
    9035              :          folding.  */
    9036              :       break;
    9037              : 
    9038          356 :     case BUILT_IN_GOACC_PARLEVEL_ID:
    9039          356 :     case BUILT_IN_GOACC_PARLEVEL_SIZE:
    9040          356 :       return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
    9041              : 
    9042            4 :     case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
    9043            4 :       return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
    9044              : 
    9045           30 :     case BUILT_IN_SPECULATION_SAFE_VALUE_1:
    9046           30 :     case BUILT_IN_SPECULATION_SAFE_VALUE_2:
    9047           30 :     case BUILT_IN_SPECULATION_SAFE_VALUE_4:
    9048           30 :     case BUILT_IN_SPECULATION_SAFE_VALUE_8:
    9049           30 :     case BUILT_IN_SPECULATION_SAFE_VALUE_16:
    9050           30 :       mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
    9051           30 :       return expand_speculation_safe_value (mode, exp, target, ignore);
    9052              : 
    9053            2 :     case BUILT_IN_CRC8_DATA8:
    9054            2 :       return expand_builtin_crc_table_based (IFN_CRC, QImode, QImode, mode,
    9055              :                                                exp, target);
    9056            2 :     case BUILT_IN_CRC16_DATA8:
    9057            2 :       return expand_builtin_crc_table_based (IFN_CRC, HImode, QImode, mode,
    9058              :                                                exp, target);
    9059            2 :     case BUILT_IN_CRC16_DATA16:
    9060            2 :       return expand_builtin_crc_table_based (IFN_CRC, HImode, HImode, mode,
    9061              :                                                exp, target);
    9062            2 :     case BUILT_IN_CRC32_DATA8:
    9063            2 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, QImode, mode,
    9064              :                                                exp, target);
    9065            2 :     case BUILT_IN_CRC32_DATA16:
    9066            2 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, HImode, mode,
    9067              :                                                exp, target);
    9068           14 :     case BUILT_IN_CRC32_DATA32:
    9069           14 :       return expand_builtin_crc_table_based (IFN_CRC, SImode, SImode, mode,
    9070              :                                                exp, target);
    9071            1 :     case BUILT_IN_CRC64_DATA8:
    9072            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, QImode, mode,
    9073              :                                                exp, target);
    9074            1 :     case BUILT_IN_CRC64_DATA16:
    9075            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, HImode, mode,
    9076              :                                                exp, target);
    9077            1 :     case BUILT_IN_CRC64_DATA32:
    9078            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, SImode, mode,
    9079              :                                                exp, target);
    9080            1 :     case BUILT_IN_CRC64_DATA64:
    9081            1 :       return expand_builtin_crc_table_based (IFN_CRC, DImode, DImode, mode,
    9082              :                                                exp, target);
    9083            2 :     case BUILT_IN_REV_CRC8_DATA8:
    9084            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, QImode, QImode,
    9085              :                                                mode, exp, target);
    9086            2 :     case BUILT_IN_REV_CRC16_DATA8:
    9087            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, QImode,
    9088              :                                                mode, exp, target);
    9089            2 :     case BUILT_IN_REV_CRC16_DATA16:
    9090            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, HImode, HImode,
    9091              :                                                mode, exp, target);
    9092            3 :     case BUILT_IN_REV_CRC32_DATA8:
    9093            3 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, QImode,
    9094              :                                                mode, exp, target);
    9095            2 :     case BUILT_IN_REV_CRC32_DATA16:
    9096            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, HImode,
    9097              :                                                mode, exp, target);
    9098            2 :     case BUILT_IN_REV_CRC32_DATA32:
    9099            2 :       return expand_builtin_crc_table_based (IFN_CRC_REV, SImode, SImode,
    9100              :                                                mode, exp, target);
    9101            1 :     case BUILT_IN_REV_CRC64_DATA8:
    9102            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, QImode,
    9103              :                                                mode, exp, target);
    9104            1 :     case BUILT_IN_REV_CRC64_DATA16:
    9105            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, HImode,
    9106              :                                                mode, exp, target);
    9107            1 :     case BUILT_IN_REV_CRC64_DATA32:
    9108            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, SImode,
    9109              :                                                mode, exp, target);
    9110            1 :     case BUILT_IN_REV_CRC64_DATA64:
    9111            1 :       return expand_builtin_crc_table_based (IFN_CRC_REV, DImode, DImode,
    9112              :                                                mode, exp, target);
    9113              :     default:    /* just do library call, if unknown builtin */
    9114              :       break;
    9115              :     }
    9116              : 
    9117              :   /* The switch statement above can drop through to cause the function
    9118              :      to be called normally.  */
    9119       853211 :   return expand_call (exp, target, ignore);
    9120              : }
    9121              : 
    9122              : /* Determine whether a tree node represents a call to a built-in
    9123              :    function.  If the tree T is a call to a built-in function with
    9124              :    the right number of arguments of the appropriate types, return
    9125              :    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
    9126              :    Otherwise the return value is END_BUILTINS.  */
    9127              : 
    9128              : enum built_in_function
    9129    109284668 : builtin_mathfn_code (const_tree t)
    9130              : {
    9131    109284668 :   const_tree fndecl, arg, parmlist;
    9132    109284668 :   const_tree argtype, parmtype;
    9133    109284668 :   const_call_expr_arg_iterator iter;
    9134              : 
    9135    109284668 :   if (TREE_CODE (t) != CALL_EXPR)
    9136              :     return END_BUILTINS;
    9137              : 
    9138      1460942 :   fndecl = get_callee_fndecl (t);
    9139      1460942 :   if (fndecl == NULL_TREE || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
    9140              :       return END_BUILTINS;
    9141              : 
    9142       657437 :   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
    9143       657437 :   init_const_call_expr_arg_iterator (t, &iter);
    9144      2121524 :   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
    9145              :     {
    9146              :       /* If a function doesn't take a variable number of arguments,
    9147              :          the last element in the list will have type `void'.  */
    9148      1444500 :       parmtype = TREE_VALUE (parmlist);
    9149      1444500 :       if (VOID_TYPE_P (parmtype))
    9150              :         {
    9151       637836 :           if (more_const_call_expr_args_p (&iter))
    9152              :             return END_BUILTINS;
    9153       637836 :           return DECL_FUNCTION_CODE (fndecl);
    9154              :         }
    9155              : 
    9156       806664 :       if (! more_const_call_expr_args_p (&iter))
    9157              :         return END_BUILTINS;
    9158              : 
    9159       806664 :       arg = next_const_call_expr_arg (&iter);
    9160       806664 :       argtype = TREE_TYPE (arg);
    9161              : 
    9162       806664 :       if (SCALAR_FLOAT_TYPE_P (parmtype))
    9163              :         {
    9164       545611 :           if (! SCALAR_FLOAT_TYPE_P (argtype))
    9165              :             return END_BUILTINS;
    9166              :         }
    9167       261053 :       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
    9168              :         {
    9169         7705 :           if (! COMPLEX_FLOAT_TYPE_P (argtype))
    9170              :             return END_BUILTINS;
    9171              :         }
    9172       253348 :       else if (POINTER_TYPE_P (parmtype))
    9173              :         {
    9174        75679 :           if (! POINTER_TYPE_P (argtype))
    9175              :             return END_BUILTINS;
    9176              :         }
    9177       177669 :       else if (INTEGRAL_TYPE_P (parmtype))
    9178              :         {
    9179       177669 :           if (! INTEGRAL_TYPE_P (argtype))
    9180              :             return END_BUILTINS;
    9181              :         }
    9182              :       else
    9183              :         return END_BUILTINS;
    9184              :     }
    9185              : 
    9186              :   /* Variable-length argument list.  */
    9187        19587 :   return DECL_FUNCTION_CODE (fndecl);
    9188              : }
    9189              : 
    9190              : /* Fold a call to __builtin_constant_p, if we know its argument ARG will
    9191              :    evaluate to a constant.  */
    9192              : 
    9193              : tree
    9194      3285511 : fold_builtin_constant_p (tree arg)
    9195              : {
    9196              :   /* We return 1 for a numeric type that's known to be a constant
    9197              :      value at compile-time or for an aggregate type that's a
    9198              :      literal constant.  */
    9199      3285511 :   STRIP_NOPS (arg);
    9200              : 
    9201              :   /* If we know this is a constant, emit the constant of one.  */
    9202      3285511 :   if (CONSTANT_CLASS_P (arg)
    9203      3285511 :       || (TREE_CODE (arg) == CONSTRUCTOR
    9204            6 :           && TREE_CONSTANT (arg)))
    9205      1835085 :     return integer_one_node;
    9206      1450426 :   if (TREE_CODE (arg) == ADDR_EXPR)
    9207              :     {
    9208          110 :        tree op = TREE_OPERAND (arg, 0);
    9209          110 :        if (TREE_CODE (op) == STRING_CST
    9210          110 :            || (TREE_CODE (op) == ARRAY_REF
    9211           57 :                && integer_zerop (TREE_OPERAND (op, 1))
    9212           57 :                && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
    9213           87 :          return integer_one_node;
    9214              :     }
    9215              : 
    9216              :   /* If this expression has side effects, show we don't know it to be a
    9217              :      constant.  Likewise if it's a pointer or aggregate type since in
    9218              :      those case we only want literals, since those are only optimized
    9219              :      when generating RTL, not later.
    9220              :      And finally, if we are compiling an initializer, not code, we
    9221              :      need to return a definite result now; there's not going to be any
    9222              :      more optimization done.  */
    9223      1450339 :   if (TREE_SIDE_EFFECTS (arg)
    9224      1450214 :       || AGGREGATE_TYPE_P (TREE_TYPE (arg))
    9225      1450208 :       || POINTER_TYPE_P (TREE_TYPE (arg))
    9226      1450037 :       || cfun == 0
    9227      1449944 :       || folding_initializer
    9228      2900276 :       || force_folding_builtin_constant_p)
    9229          497 :     return integer_zero_node;
    9230              : 
    9231              :   return NULL_TREE;
    9232              : }
    9233              : 
    9234              : /* Create builtin_expect or builtin_expect_with_probability
    9235              :    with PRED and EXPECTED as its arguments and return it as a truthvalue.
    9236              :    Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
    9237              :    builtin_expect_with_probability instead uses third argument as PROBABILITY
    9238              :    value.  */
    9239              : 
    9240              : static tree
    9241       225516 : build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
    9242              :                                 tree predictor, tree probability)
    9243              : {
    9244       225516 :   tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
    9245              : 
    9246       225516 :   fn = builtin_decl_explicit (probability == NULL_TREE ? BUILT_IN_EXPECT
    9247              :                               : BUILT_IN_EXPECT_WITH_PROBABILITY);
    9248       225516 :   arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
    9249       225516 :   ret_type = TREE_TYPE (TREE_TYPE (fn));
    9250       225516 :   pred_type = TREE_VALUE (arg_types);
    9251       225516 :   expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
    9252              : 
    9253       225516 :   pred = fold_convert_loc (loc, pred_type, pred);
    9254       225516 :   expected = fold_convert_loc (loc, expected_type, expected);
    9255              : 
    9256       225516 :   if (probability)
    9257            0 :     call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
    9258              :   else
    9259       451032 :     call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
    9260              :                                      predictor);
    9261              : 
    9262       225516 :   return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
    9263       225516 :                  build_int_cst (ret_type, 0));
    9264              : }
    9265              : 
    9266              : /* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3.  Return
    9267              :    NULL_TREE if no simplification is possible.  */
    9268              : 
    9269              : tree
    9270      7435730 : fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
    9271              :                      tree arg3)
    9272              : {
    9273      7435730 :   tree inner, fndecl, inner_arg0;
    9274      7435730 :   enum tree_code code;
    9275              : 
    9276              :   /* Distribute the expected value over short-circuiting operators.
    9277              :      See through the cast from truthvalue_type_node to long.  */
    9278      7435730 :   inner_arg0 = arg0;
    9279     15185252 :   while (CONVERT_EXPR_P (inner_arg0)
    9280      1068660 :          && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
    9281      9573049 :          && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
    9282      1068659 :     inner_arg0 = TREE_OPERAND (inner_arg0, 0);
    9283              : 
    9284              :   /* If this is a builtin_expect within a builtin_expect keep the
    9285              :      inner one.  See through a comparison against a constant.  It
    9286              :      might have been added to create a thruthvalue.  */
    9287      7435730 :   inner = inner_arg0;
    9288              : 
    9289      7435730 :   if (COMPARISON_CLASS_P (inner)
    9290      7435730 :       && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
    9291      1428515 :     inner = TREE_OPERAND (inner, 0);
    9292              : 
    9293      7435730 :   if (TREE_CODE (inner) == CALL_EXPR
    9294       176546 :       && (fndecl = get_callee_fndecl (inner))
    9295      7612276 :       && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT,
    9296              :                             BUILT_IN_EXPECT_WITH_PROBABILITY))
    9297              :     return arg0;
    9298              : 
    9299      7435722 :   inner = inner_arg0;
    9300      7435722 :   code = TREE_CODE (inner);
    9301      7435722 :   if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
    9302              :     {
    9303       112758 :       tree op0 = TREE_OPERAND (inner, 0);
    9304       112758 :       tree op1 = TREE_OPERAND (inner, 1);
    9305       112758 :       arg1 = save_expr (arg1);
    9306              : 
    9307       112758 :       op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2, arg3);
    9308       112758 :       op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2, arg3);
    9309       112758 :       inner = build2 (code, TREE_TYPE (inner), op0, op1);
    9310              : 
    9311       112758 :       return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
    9312              :     }
    9313              : 
    9314              :   /* If the argument isn't invariant then there's nothing else we can do.  */
    9315      7322964 :   if (!TREE_CONSTANT (inner_arg0))
    9316              :     return NULL_TREE;
    9317              : 
    9318              :   /* If we expect that a comparison against the argument will fold to
    9319              :      a constant return the constant.  In practice, this means a true
    9320              :      constant or the address of a non-weak symbol.  */
    9321       253254 :   inner = inner_arg0;
    9322       253254 :   STRIP_NOPS (inner);
    9323       253254 :   if (TREE_CODE (inner) == ADDR_EXPR)
    9324              :     {
    9325            1 :       do
    9326              :         {
    9327            1 :           inner = TREE_OPERAND (inner, 0);
    9328              :         }
    9329            1 :       while (TREE_CODE (inner) == COMPONENT_REF
    9330            1 :              || TREE_CODE (inner) == ARRAY_REF);
    9331            1 :       if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner))
    9332            0 :         return NULL_TREE;
    9333              :     }
    9334              : 
    9335              :   /* Otherwise, ARG0 already has the proper type for the return value.  */
    9336              :   return arg0;
    9337              : }
    9338              : 
    9339              : /* Fold a call to __builtin_classify_type with argument ARG.  */
    9340              : 
    9341              : static tree
    9342         2078 : fold_builtin_classify_type (tree arg)
    9343              : {
    9344         2078 :   if (arg == 0)
    9345            0 :     return build_int_cst (integer_type_node, no_type_class);
    9346              : 
    9347         2078 :   return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
    9348              : }
    9349              : 
    9350              : /* Fold a call EXPR (which may be null) to __builtin_strlen with argument
    9351              :    ARG.  */
    9352              : 
    9353              : static tree
    9354       476464 : fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg)
    9355              : {
    9356       476464 :   if (!validate_arg (arg, POINTER_TYPE))
    9357              :     return NULL_TREE;
    9358              :   else
    9359              :     {
    9360       476461 :       c_strlen_data lendata = { };
    9361       476461 :       tree len = c_strlen (arg, 0, &lendata);
    9362              : 
    9363       476461 :       if (len)
    9364         2231 :         return fold_convert_loc (loc, type, len);
    9365              : 
    9366              :       /* TODO: Move this to gimple-ssa-warn-access once the pass runs
    9367              :          also early enough to detect invalid reads in multimensional
    9368              :          arrays and struct members.  */
    9369       474230 :       if (!lendata.decl)
    9370       467052 :          c_strlen (arg, 1, &lendata);
    9371              : 
    9372       474230 :       if (lendata.decl)
    9373              :         {
    9374         7192 :           if (EXPR_HAS_LOCATION (arg))
    9375         2800 :             loc = EXPR_LOCATION (arg);
    9376         4392 :           else if (loc == UNKNOWN_LOCATION)
    9377            0 :             loc = input_location;
    9378         7192 :           warn_string_no_nul (loc, expr, "strlen", arg, lendata.decl);
    9379              :         }
    9380              : 
    9381              :       return NULL_TREE;
    9382              :     }
    9383              : }
    9384              : 
    9385              : /* Fold a call to __builtin_inf or __builtin_huge_val.  */
    9386              : 
    9387              : static tree
    9388       263612 : fold_builtin_inf (location_t loc, tree type, int warn)
    9389              : {
    9390              :   /* __builtin_inff is intended to be usable to define INFINITY on all
    9391              :      targets.  If an infinity is not available, INFINITY expands "to a
    9392              :      positive constant of type float that overflows at translation
    9393              :      time", footnote "In this case, using INFINITY will violate the
    9394              :      constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
    9395              :      Thus we pedwarn to ensure this constraint violation is
    9396              :      diagnosed.  */
    9397      1053639 :   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
    9398            0 :     pedwarn (loc, 0, "target format does not support infinity");
    9399              : 
    9400       263612 :   return build_real (type, dconstinf);
    9401              : }
    9402              : 
    9403              : /* Fold function call to builtin sincos, sincosf, or sincosl.  Return
    9404              :    NULL_TREE if no simplification can be made.  */
    9405              : 
    9406              : static tree
    9407          145 : fold_builtin_sincos (location_t loc,
    9408              :                      tree arg0, tree arg1, tree arg2)
    9409              : {
    9410          145 :   tree type;
    9411          145 :   tree fndecl, call = NULL_TREE;
    9412              : 
    9413          145 :   if (!validate_arg (arg0, REAL_TYPE)
    9414          145 :       || !validate_arg (arg1, POINTER_TYPE)
    9415          290 :       || !validate_arg (arg2, POINTER_TYPE))
    9416              :     return NULL_TREE;
    9417              : 
    9418          145 :   type = TREE_TYPE (arg0);
    9419              : 
    9420              :   /* Calculate the result when the argument is a constant.  */
    9421          145 :   built_in_function fn = mathfn_built_in_2 (type, CFN_BUILT_IN_CEXPI);
    9422          145 :   if (fn == END_BUILTINS)
    9423              :     return NULL_TREE;
    9424              : 
    9425              :   /* Canonicalize sincos to cexpi.  */
    9426          145 :   if (TREE_CODE (arg0) == REAL_CST)
    9427              :     {
    9428           86 :       tree complex_type = build_complex_type (type);
    9429           86 :       call = fold_const_call (as_combined_fn (fn), complex_type, arg0);
    9430              :     }
    9431           86 :   if (!call)
    9432              :     {
    9433           59 :       if (!targetm.libc_has_function (function_c99_math_complex, type)
    9434           59 :           || !builtin_decl_implicit_p (fn))
    9435              :         return NULL_TREE;
    9436           59 :       fndecl = builtin_decl_explicit (fn);
    9437           59 :       call = build_call_expr_loc (loc, fndecl, 1, arg0);
    9438           59 :       call = builtin_save_expr (call);
    9439              :     }
    9440              : 
    9441          145 :   tree ptype = build_pointer_type (type);
    9442          145 :   arg1 = fold_convert (ptype, arg1);
    9443          145 :   arg2 = fold_convert (ptype, arg2);
    9444          145 :   return build2 (COMPOUND_EXPR, void_type_node,
    9445              :                  build2 (MODIFY_EXPR, void_type_node,
    9446              :                          build_fold_indirect_ref_loc (loc, arg1),
    9447              :                          fold_build1_loc (loc, IMAGPART_EXPR, type, call)),
    9448              :                  build2 (MODIFY_EXPR, void_type_node,
    9449              :                          build_fold_indirect_ref_loc (loc, arg2),
    9450          145 :                          fold_build1_loc (loc, REALPART_EXPR, type, call)));
    9451              : }
    9452              : 
    9453              : /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
    9454              :    Return NULL_TREE if no simplification can be made.  */
    9455              : 
    9456              : static tree
    9457      2568558 : fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
    9458              : {
    9459      2568558 :   if (!validate_arg (arg1, POINTER_TYPE)
    9460      2568558 :       || !validate_arg (arg2, POINTER_TYPE)
    9461      5137116 :       || !validate_arg (len, INTEGER_TYPE))
    9462              :     return NULL_TREE;
    9463              : 
    9464              :   /* If the LEN parameter is zero, return zero.  */
    9465      2568558 :   if (integer_zerop (len))
    9466            0 :     return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
    9467            0 :                               arg1, arg2);
    9468              : 
    9469              :   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
    9470      2568558 :   if (operand_equal_p (arg1, arg2, 0))
    9471          697 :     return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
    9472              : 
    9473              :   /* If len parameter is one, return an expression corresponding to
    9474              :      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
    9475      2567861 :   if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
    9476              :     {
    9477        55087 :       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
    9478        55087 :       tree cst_uchar_ptr_node
    9479        55087 :         = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
    9480              : 
    9481        55087 :       tree ind1
    9482        55087 :         = fold_convert_loc (loc, integer_type_node,
    9483              :                             build1 (INDIRECT_REF, cst_uchar_node,
    9484              :                                     fold_convert_loc (loc,
    9485              :                                                       cst_uchar_ptr_node,
    9486              :                                                       arg1)));
    9487        55087 :       tree ind2
    9488        55087 :         = fold_convert_loc (loc, integer_type_node,
    9489              :                             build1 (INDIRECT_REF, cst_uchar_node,
    9490              :                                     fold_convert_loc (loc,
    9491              :                                                       cst_uchar_ptr_node,
    9492              :                                                       arg2)));
    9493        55087 :       return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
    9494              :     }
    9495              : 
    9496              :   return NULL_TREE;
    9497              : }
    9498              : 
    9499              : /* Fold a call to builtin isascii with argument ARG.  */
    9500              : 
    9501              : static tree
    9502          211 : fold_builtin_isascii (location_t loc, tree arg)
    9503              : {
    9504          211 :   if (!validate_arg (arg, INTEGER_TYPE))
    9505              :     return NULL_TREE;
    9506              :   else
    9507              :     {
    9508              :       /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
    9509          211 :       arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
    9510              :                          build_int_cst (integer_type_node,
    9511              :                                         ~ HOST_WIDE_INT_UC (0x7f)));
    9512          211 :       return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
    9513          211 :                               arg, integer_zero_node);
    9514              :     }
    9515              : }
    9516              : 
    9517              : /* Fold a call to builtin toascii with argument ARG.  */
    9518              : 
    9519              : static tree
    9520          168 : fold_builtin_toascii (location_t loc, tree arg)
    9521              : {
    9522          168 :   if (!validate_arg (arg, INTEGER_TYPE))
    9523              :     return NULL_TREE;
    9524              : 
    9525              :   /* Transform toascii(c) -> (c & 0x7f).  */
    9526          168 :   return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
    9527              :                           build_int_cst (integer_type_node, 0x7f));
    9528              : }
    9529              : 
    9530              : /* Fold a call to builtin isdigit with argument ARG.  */
    9531              : 
    9532              : static tree
    9533          325 : fold_builtin_isdigit (location_t loc, tree arg)
    9534              : {
    9535          325 :   if (!validate_arg (arg, INTEGER_TYPE))
    9536              :     return NULL_TREE;
    9537              :   else
    9538              :     {
    9539              :       /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
    9540              :       /* According to the C standard, isdigit is unaffected by locale.
    9541              :          However, it definitely is affected by the target character set.  */
    9542          313 :       unsigned HOST_WIDE_INT target_digit0
    9543          313 :         = lang_hooks.to_target_charset ('0');
    9544              : 
    9545          313 :       if (target_digit0 == 0)
    9546              :         return NULL_TREE;
    9547              : 
    9548          313 :       arg = fold_convert_loc (loc, unsigned_type_node, arg);
    9549          313 :       arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
    9550              :                          build_int_cst (unsigned_type_node, target_digit0));
    9551          313 :       return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
    9552              :                           build_int_cst (unsigned_type_node, 9));
    9553              :     }
    9554              : }
    9555              : 
    9556              : /* Fold a call to fabs, fabsf or fabsl with argument ARG.  */
    9557              : 
    9558              : static tree
    9559       378195 : fold_builtin_fabs (location_t loc, tree arg, tree type)
    9560              : {
    9561       378195 :   if (!validate_arg (arg, REAL_TYPE))
    9562              :     return NULL_TREE;
    9563              : 
    9564       378110 :   arg = fold_convert_loc (loc, type, arg);
    9565       378110 :   return fold_build1_loc (loc, ABS_EXPR, type, arg);
    9566              : }
    9567              : 
    9568              : /* Fold a call to abs, labs, llabs, imaxabs, uabs, ulabs, ullabs or uimaxabs
    9569              :    with argument ARG.  */
    9570              : 
    9571              : static tree
    9572       101153 : fold_builtin_abs (location_t loc, tree arg, tree type)
    9573              : {
    9574       101153 :   if (!validate_arg (arg, INTEGER_TYPE) || !INTEGRAL_TYPE_P (type))
    9575              :     return NULL_TREE;
    9576              : 
    9577       101105 :   if (TYPE_UNSIGNED (type))
    9578              :     {
    9579         1168 :       if (TYPE_PRECISION (TREE_TYPE (arg))
    9580         1168 :           != TYPE_PRECISION (type)
    9581         1168 :           || TYPE_UNSIGNED (TREE_TYPE (arg)))
    9582              :         return NULL_TREE;
    9583         1168 :       return fold_build1_loc (loc, ABSU_EXPR, type, arg);
    9584              :     }
    9585        99937 :   arg = fold_convert_loc (loc, type, arg);
    9586        99937 :   return fold_build1_loc (loc, ABS_EXPR, type, arg);
    9587              : }
    9588              : 
    9589              : /* Fold a call to builtin carg(a+bi) -> atan2(b,a).  */
    9590              : 
    9591              : static tree
    9592       104371 : fold_builtin_carg (location_t loc, tree arg, tree type)
    9593              : {
    9594       104371 :   if (validate_arg (arg, COMPLEX_TYPE)
    9595       104371 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
    9596              :     {
    9597       104371 :       tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
    9598              : 
    9599       104371 :       if (atan2_fn)
    9600              :         {
    9601       100503 :           tree new_arg = builtin_save_expr (arg);
    9602       100503 :           tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
    9603       100503 :           tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
    9604       100503 :           return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
    9605              :         }
    9606              :     }
    9607              : 
    9608              :   return NULL_TREE;
    9609              : }
    9610              : 
    9611              : /* Fold a call to builtin frexp, we can assume the base is 2.  */
    9612              : 
    9613              : static tree
    9614       115911 : fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
    9615              : {
    9616       115911 :   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
    9617              :     return NULL_TREE;
    9618              : 
    9619       115911 :   STRIP_NOPS (arg0);
    9620              : 
    9621       115911 :   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
    9622              :     return NULL_TREE;
    9623              : 
    9624         2210 :   arg1 = build_fold_indirect_ref_loc (loc, arg1);
    9625              : 
    9626              :   /* Proceed if a valid pointer type was passed in.  */
    9627         2210 :   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
    9628              :     {
    9629         2210 :       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
    9630         2210 :       tree frac, exp, res;
    9631              : 
    9632         2210 :       switch (value->cl)
    9633              :       {
    9634          276 :       case rvc_zero:
    9635          276 :       case rvc_nan:
    9636          276 :       case rvc_inf:
    9637              :         /* For +-0, return (*exp = 0, +-0).  */
    9638              :         /* For +-NaN or +-Inf, *exp is unspecified, but something should
    9639              :            be stored there so that it isn't read from uninitialized object.
    9640              :            As glibc and newlib store *exp = 0 for +-Inf/NaN, storing
    9641              :            0 here as well is easiest.  */
    9642          276 :         exp = integer_zero_node;
    9643          276 :         frac = arg0;
    9644          276 :         break;
    9645         1934 :       case rvc_normal:
    9646         1934 :         {
    9647              :           /* Since the frexp function always expects base 2, and in
    9648              :              GCC normalized significands are already in the range
    9649              :              [0.5, 1.0), we have exactly what frexp wants.  */
    9650         1934 :           REAL_VALUE_TYPE frac_rvt = *value;
    9651         1934 :           SET_REAL_EXP (&frac_rvt, 0);
    9652         1934 :           frac = build_real (rettype, frac_rvt);
    9653         1934 :           exp = build_int_cst (integer_type_node, REAL_EXP (value));
    9654              :         }
    9655         1934 :         break;
    9656            0 :       default:
    9657            0 :         gcc_unreachable ();
    9658              :       }
    9659              : 
    9660              :       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
    9661         2210 :       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
    9662         2210 :       TREE_SIDE_EFFECTS (arg1) = 1;
    9663         2210 :       res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
    9664         2210 :       suppress_warning (res, OPT_Wunused_value);
    9665         2210 :       return res;
    9666              :     }
    9667              : 
    9668              :   return NULL_TREE;
    9669              : }
    9670              : 
    9671              : /* Fold a call to builtin modf.  */
    9672              : 
    9673              : static tree
    9674        92826 : fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
    9675              : {
    9676        92826 :   if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
    9677              :     return NULL_TREE;
    9678              : 
    9679        92826 :   STRIP_NOPS (arg0);
    9680              : 
    9681        92826 :   if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
    9682              :     return NULL_TREE;
    9683              : 
    9684         2474 :   arg1 = build_fold_indirect_ref_loc (loc, arg1);
    9685              : 
    9686              :   /* Proceed if a valid pointer type was passed in.  */
    9687         2474 :   if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
    9688              :     {
    9689         2474 :       const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
    9690         2474 :       REAL_VALUE_TYPE trunc, frac;
    9691         2474 :       tree res;
    9692              : 
    9693         2474 :       switch (value->cl)
    9694              :       {
    9695          228 :       case rvc_nan:
    9696          228 :       case rvc_zero:
    9697              :         /* For +-NaN or +-0, return (*arg1 = arg0, arg0).  */
    9698          228 :         trunc = frac = *value;
    9699          228 :         break;
    9700           96 :       case rvc_inf:
    9701              :         /* For +-Inf, return (*arg1 = arg0, +-0).  */
    9702           96 :         frac = dconst0;
    9703           96 :         frac.sign = value->sign;
    9704           96 :         trunc = *value;
    9705           96 :         break;
    9706         2150 :       case rvc_normal:
    9707              :         /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)).  */
    9708         2150 :         real_trunc (&trunc, VOIDmode, value);
    9709         2150 :         real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
    9710              :         /* If the original number was negative and already
    9711              :            integral, then the fractional part is -0.0.  */
    9712         2150 :         if (value->sign && frac.cl == rvc_zero)
    9713           69 :           frac.sign = value->sign;
    9714              :         break;
    9715              :       }
    9716              : 
    9717              :       /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
    9718         2474 :       arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
    9719              :                           build_real (rettype, trunc));
    9720         2474 :       TREE_SIDE_EFFECTS (arg1) = 1;
    9721         2474 :       res = fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
    9722              :                              build_real (rettype, frac));
    9723         2474 :       suppress_warning (res, OPT_Wunused_value);
    9724         2474 :       return res;
    9725              :     }
    9726              : 
    9727              :   return NULL_TREE;
    9728              : }
    9729              : 
    9730              : /* Given a location LOC, an interclass builtin function decl FNDECL
    9731              :    and its single argument ARG, return an folded expression computing
    9732              :    the same, or NULL_TREE if we either couldn't or didn't want to fold
    9733              :    (the latter happen if there's an RTL instruction available).  */
    9734              : 
    9735              : static tree
    9736      1818515 : fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
    9737              : {
    9738      1818515 :   machine_mode mode;
    9739              : 
    9740      1818515 :   if (!validate_arg (arg, REAL_TYPE))
    9741              :     return NULL_TREE;
    9742              : 
    9743      1818515 :   if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
    9744              :     return NULL_TREE;
    9745              : 
    9746      1818515 :   mode = TYPE_MODE (TREE_TYPE (arg));
    9747              : 
    9748     12725763 :   bool is_ibm_extended = MODE_COMPOSITE_P (mode);
    9749              : 
    9750              :   /* If there is no optab, try generic code.  */
    9751      1818515 :   switch (DECL_FUNCTION_CODE (fndecl))
    9752              :     {
    9753       708836 :       tree result;
    9754              : 
    9755       708836 :     CASE_FLT_FN (BUILT_IN_ISINF):
    9756       708836 :       {
    9757              :         /* isinf(x) -> isgreater(fabs(x),DBL_MAX).  */
    9758       708836 :         tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
    9759       708836 :         tree type = TREE_TYPE (arg);
    9760       708836 :         REAL_VALUE_TYPE r;
    9761       708836 :         char buf[128];
    9762              : 
    9763       708836 :         if (is_ibm_extended)
    9764              :           {
    9765              :             /* NaN and Inf are encoded in the high-order double value
    9766              :                only.  The low-order value is not significant.  */
    9767            0 :             type = double_type_node;
    9768            0 :             mode = DFmode;
    9769            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9770              :           }
    9771       708836 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9772       708836 :         real_from_string3 (&r, buf, mode);
    9773       708836 :         result = build_call_expr (isgr_fn, 2,
    9774              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9775              :                                   build_real (type, r));
    9776       708836 :         return result;
    9777              :       }
    9778       625359 :     CASE_FLT_FN (BUILT_IN_FINITE):
    9779       625359 :     case BUILT_IN_ISFINITE:
    9780       625359 :       {
    9781              :         /* isfinite(x) -> islessequal(fabs(x),DBL_MAX).  */
    9782       625359 :         tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
    9783       625359 :         tree type = TREE_TYPE (arg);
    9784       625359 :         REAL_VALUE_TYPE r;
    9785       625359 :         char buf[128];
    9786              : 
    9787       625359 :         if (is_ibm_extended)
    9788              :           {
    9789              :             /* NaN and Inf are encoded in the high-order double value
    9790              :                only.  The low-order value is not significant.  */
    9791            0 :             type = double_type_node;
    9792            0 :             mode = DFmode;
    9793            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9794              :           }
    9795       625359 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9796       625359 :         real_from_string3 (&r, buf, mode);
    9797       625359 :         result = build_call_expr (isle_fn, 2,
    9798              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9799              :                                   build_real (type, r));
    9800              :         /*result = fold_build2_loc (loc, UNGT_EXPR,
    9801              :                                   TREE_TYPE (TREE_TYPE (fndecl)),
    9802              :                                   fold_build1_loc (loc, ABS_EXPR, type, arg),
    9803              :                                   build_real (type, r));
    9804              :         result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
    9805              :                                   TREE_TYPE (TREE_TYPE (fndecl)),
    9806              :                                   result);*/
    9807       625359 :         return result;
    9808              :       }
    9809       239896 :     case BUILT_IN_ISNORMAL:
    9810       239896 :       {
    9811              :         /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
    9812              :            islessequal(fabs(x),DBL_MAX).  */
    9813       239896 :         tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
    9814       239896 :         tree type = TREE_TYPE (arg);
    9815       239896 :         tree orig_arg, max_exp, min_exp;
    9816       239896 :         machine_mode orig_mode = mode;
    9817       239896 :         REAL_VALUE_TYPE rmax, rmin;
    9818       239896 :         char buf[128];
    9819              : 
    9820       239896 :         orig_arg = arg = builtin_save_expr (arg);
    9821       239896 :         if (is_ibm_extended)
    9822              :           {
    9823              :             /* Use double to test the normal range of IBM extended
    9824              :                precision.  Emin for IBM extended precision is
    9825              :                different to emin for IEEE double, being 53 higher
    9826              :                since the low double exponent is at least 53 lower
    9827              :                than the high double exponent.  */
    9828            0 :             type = double_type_node;
    9829            0 :             mode = DFmode;
    9830            0 :             arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
    9831              :           }
    9832       239896 :         arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
    9833              : 
    9834       239896 :         get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
    9835       239896 :         real_from_string3 (&rmax, buf, mode);
    9836       239896 :         if (DECIMAL_FLOAT_MODE_P (mode))
    9837            1 :           sprintf (buf, "1E%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
    9838              :         else
    9839       239895 :           sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
    9840       239896 :         real_from_string3 (&rmin, buf, orig_mode);
    9841       239896 :         max_exp = build_real (type, rmax);
    9842       239896 :         min_exp = build_real (type, rmin);
    9843              : 
    9844       239896 :         max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
    9845       239896 :         if (is_ibm_extended)
    9846              :           {
    9847              :             /* Testing the high end of the range is done just using
    9848              :                the high double, using the same test as isfinite().
    9849              :                For the subnormal end of the range we first test the
    9850              :                high double, then if its magnitude is equal to the
    9851              :                limit of 0x1p-969, we test whether the low double is
    9852              :                non-zero and opposite sign to the high double.  */
    9853            0 :             tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS);
    9854            0 :             tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
    9855            0 :             tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
    9856            0 :             tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
    9857              :                                        arg, min_exp);
    9858            0 :             tree as_complex = build1 (VIEW_CONVERT_EXPR,
    9859              :                                       complex_double_type_node, orig_arg);
    9860            0 :             tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
    9861            0 :             tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
    9862            0 :             tree zero = build_real (type, dconst0);
    9863            0 :             tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
    9864            0 :             tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
    9865            0 :             tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
    9866            0 :             tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
    9867              :                                       fold_build3 (COND_EXPR,
    9868              :                                                    integer_type_node,
    9869              :                                                    hilt, logt, lolt));
    9870            0 :             eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
    9871              :                                   eq_min, ok_lo);
    9872            0 :             min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
    9873              :                                    gt_min, eq_min);
    9874              :           }
    9875              :         else
    9876              :           {
    9877       239896 :             tree const isge_fn
    9878       239896 :               = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
    9879       239896 :             min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
    9880              :           }
    9881       239896 :         result = fold_build2 (BIT_AND_EXPR, integer_type_node,
    9882              :                               max_exp, min_exp);
    9883       239896 :         return result;
    9884              :       }
    9885       242890 :     CASE_FLT_FN (BUILT_IN_ISNAN):
    9886       242890 :     case BUILT_IN_ISNAND32:
    9887       242890 :     case BUILT_IN_ISNAND64:
    9888       242890 :     case BUILT_IN_ISNAND128:
    9889       242890 :       {
    9890              :         /* In IBM extended NaN and Inf are encoded in the high-order double
    9891              :            value only.  The low-order value is not significant.  */
    9892       242890 :         if (is_ibm_extended)
    9893            0 :           arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
    9894       242890 :         arg = builtin_save_expr (arg);
    9895       242890 :         tree type = TREE_TYPE (TREE_TYPE (fndecl));
    9896       242890 :         return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
    9897              :       }
    9898              :     default:
    9899              :       break;
    9900              :     }
    9901              : 
    9902              :   return NULL_TREE;
    9903              : }
    9904              : 
    9905              : /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
    9906              :    ARG is the argument for the call.  */
    9907              : 
    9908              : static tree
    9909      1607849 : fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
    9910              : {
    9911      1607849 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
    9912              : 
    9913      1607849 :   if (!validate_arg (arg, REAL_TYPE))
    9914              :     return NULL_TREE;
    9915              : 
    9916      1607849 :   switch (builtin_index)
    9917              :     {
    9918       710621 :     case BUILT_IN_ISINF:
    9919       710621 :       if (tree_expr_infinite_p (arg))
    9920            0 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9921       710621 :       if (!tree_expr_maybe_infinite_p (arg))
    9922          251 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9923              :       return NULL_TREE;
    9924              : 
    9925          708 :     case BUILT_IN_ISINF_SIGN:
    9926          708 :       {
    9927              :         /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
    9928              :         /* In a boolean context, GCC will fold the inner COND_EXPR to
    9929              :            1.  So e.g. "if (isinf_sign(x))" would be folded to just
    9930              :            "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
    9931          708 :         tree signbit_fn = builtin_decl_explicit (BUILT_IN_SIGNBIT);
    9932          708 :         tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
    9933          708 :         tree tmp = NULL_TREE;
    9934              : 
    9935          708 :         arg = builtin_save_expr (arg);
    9936              : 
    9937          708 :         if (signbit_fn && isinf_fn)
    9938              :           {
    9939          708 :             tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
    9940          708 :             tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
    9941              : 
    9942          708 :             signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
    9943              :                                         signbit_call, integer_zero_node);
    9944          708 :             isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
    9945              :                                       isinf_call, integer_zero_node);
    9946              : 
    9947          708 :             tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
    9948              :                                integer_minus_one_node, integer_one_node);
    9949          708 :             tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
    9950              :                                isinf_call, tmp,
    9951              :                                integer_zero_node);
    9952              :           }
    9953              : 
    9954              :         return tmp;
    9955              :       }
    9956              : 
    9957       625691 :     case BUILT_IN_ISFINITE:
    9958       625691 :       if (tree_expr_finite_p (arg))
    9959          332 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9960       625359 :       if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
    9961            0 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9962              :       return NULL_TREE;
    9963              : 
    9964       243014 :     case BUILT_IN_ISNAN:
    9965       243014 :       if (tree_expr_nan_p (arg))
    9966            0 :         return omit_one_operand_loc (loc, type, integer_one_node, arg);
    9967       243014 :       if (!tree_expr_maybe_nan_p (arg))
    9968          124 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9969              :       return NULL_TREE;
    9970              : 
    9971        27815 :     case BUILT_IN_ISSIGNALING:
    9972              :       /* Folding to true for REAL_CST is done in fold_const_call_ss.
    9973              :          Don't use tree_expr_signaling_nan_p (arg) -> integer_one_node
    9974              :          and !tree_expr_maybe_signaling_nan_p (arg) -> integer_zero_node
    9975              :          here, so there is some possibility of __builtin_issignaling working
    9976              :          without -fsignaling-nans.  Especially when -fno-signaling-nans is
    9977              :          the default.  */
    9978        27815 :       if (!tree_expr_maybe_nan_p (arg))
    9979            0 :         return omit_one_operand_loc (loc, type, integer_zero_node, arg);
    9980              :       return NULL_TREE;
    9981              : 
    9982            0 :     default:
    9983            0 :       gcc_unreachable ();
    9984              :     }
    9985              : }
    9986              : 
    9987              : /* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
    9988              :    This builtin will generate code to return the appropriate floating
    9989              :    point classification depending on the value of the floating point
    9990              :    number passed in.  The possible return values must be supplied as
    9991              :    int arguments to the call in the following order: FP_NAN, FP_INFINITE,
    9992              :    FP_NORMAL, FP_SUBNORMAL and FP_ZERO.  The ellipses is for exactly
    9993              :    one floating point argument which is "type generic".  */
    9994              : 
    9995              : static tree
    9996       104514 : fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
    9997              : {
    9998       104514 :   tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
    9999              :     arg, type, res, tmp;
   10000       104514 :   machine_mode mode;
   10001       104514 :   REAL_VALUE_TYPE r;
   10002       104514 :   char buf[128];
   10003              : 
   10004              :   /* Verify the required arguments in the original call.  */
   10005       104514 :   if (nargs != 6
   10006       104514 :       || !validate_arg (args[0], INTEGER_TYPE)
   10007       104514 :       || !validate_arg (args[1], INTEGER_TYPE)
   10008       104514 :       || !validate_arg (args[2], INTEGER_TYPE)
   10009       104514 :       || !validate_arg (args[3], INTEGER_TYPE)
   10010       104514 :       || !validate_arg (args[4], INTEGER_TYPE)
   10011       209028 :       || !validate_arg (args[5], REAL_TYPE))
   10012              :     return NULL_TREE;
   10013              : 
   10014       104514 :   fp_nan = args[0];
   10015       104514 :   fp_infinite = args[1];
   10016       104514 :   fp_normal = args[2];
   10017       104514 :   fp_subnormal = args[3];
   10018       104514 :   fp_zero = args[4];
   10019       104514 :   arg = args[5];
   10020       104514 :   type = TREE_TYPE (arg);
   10021       104514 :   mode = TYPE_MODE (type);
   10022       104514 :   arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
   10023              : 
   10024              :   /* fpclassify(x) ->
   10025              :        isnan(x) ? FP_NAN :
   10026              :          (fabs(x) == Inf ? FP_INFINITE :
   10027              :            (fabs(x) >= DBL_MIN ? FP_NORMAL :
   10028              :              (x == 0 ? FP_ZERO : FP_SUBNORMAL))).  */
   10029              : 
   10030       104514 :   tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   10031              :                          build_real (type, dconst0));
   10032       104514 :   res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
   10033              :                          tmp, fp_zero, fp_subnormal);
   10034              : 
   10035       104514 :   if (DECIMAL_FLOAT_MODE_P (mode))
   10036            3 :     sprintf (buf, "1E%d", REAL_MODE_FORMAT (mode)->emin - 1);
   10037              :   else
   10038       104511 :     sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
   10039       104514 :   real_from_string3 (&r, buf, mode);
   10040       104514 :   tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
   10041              :                          arg, build_real (type, r));
   10042       104514 :   res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10043              :                          fp_normal, res);
   10044              : 
   10045       104514 :   if (tree_expr_maybe_infinite_p (arg))
   10046              :     {
   10047       104426 :       tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
   10048              :                              build_real (type, dconstinf));
   10049       104426 :       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10050              :                              fp_infinite, res);
   10051              :     }
   10052              : 
   10053       104514 :   if (tree_expr_maybe_nan_p (arg))
   10054              :     {
   10055       104424 :       tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
   10056       104424 :       res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
   10057              :                              res, fp_nan);
   10058              :     }
   10059              : 
   10060              :   return res;
   10061              : }
   10062              : 
   10063              : /* Fold a call to an unordered comparison function such as
   10064              :    __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
   10065              :    being called and ARG0 and ARG1 are the arguments for the call.
   10066              :    UNORDERED_CODE and ORDERED_CODE are comparison codes that give
   10067              :    the opposite of the desired result.  UNORDERED_CODE is used
   10068              :    for modes that can hold NaNs and ORDERED_CODE is used for
   10069              :    the rest.  */
   10070              : 
   10071              : static tree
   10072      3257721 : fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
   10073              :                             enum tree_code unordered_code,
   10074              :                             enum tree_code ordered_code)
   10075              : {
   10076      3257721 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10077      3257721 :   enum tree_code code;
   10078      3257721 :   tree type0, type1;
   10079      3257721 :   enum tree_code code0, code1;
   10080      3257721 :   tree cmp_type = NULL_TREE;
   10081              : 
   10082      3257721 :   type0 = TREE_TYPE (arg0);
   10083      3257721 :   type1 = TREE_TYPE (arg1);
   10084              : 
   10085      3257721 :   code0 = TREE_CODE (type0);
   10086      3257721 :   code1 = TREE_CODE (type1);
   10087              : 
   10088      3257721 :   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
   10089              :     /* Choose the wider of two real types.  */
   10090      3257541 :     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   10091      3257541 :       ? type0 : type1;
   10092          180 :   else if (code0 == REAL_TYPE
   10093           91 :            && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
   10094              :     cmp_type = type0;
   10095           89 :   else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
   10096           89 :            && code1 == REAL_TYPE)
   10097          135 :     cmp_type = type1;
   10098              : 
   10099      3257721 :   arg0 = fold_convert_loc (loc, cmp_type, arg0);
   10100      3257721 :   arg1 = fold_convert_loc (loc, cmp_type, arg1);
   10101              : 
   10102      3257721 :   if (unordered_code == UNORDERED_EXPR)
   10103              :     {
   10104       240883 :       if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
   10105           16 :         return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
   10106       240867 :       if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
   10107          141 :         return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
   10108       240726 :       return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
   10109              :     }
   10110              : 
   10111      3019689 :   code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
   10112      3016838 :          ? unordered_code : ordered_code;
   10113      3016838 :   return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
   10114      3016838 :                       fold_build2_loc (loc, code, type, arg0, arg1));
   10115              : }
   10116              : 
   10117              : /* Fold a call to __builtin_iseqsig().  ARG0 and ARG1 are the arguments.
   10118              :    After choosing the wider floating-point type for the comparison,
   10119              :    the code is folded to:
   10120              :      SAVE_EXPR<ARG0> >= SAVE_EXPR<ARG1> && SAVE_EXPR<ARG0> <= SAVE_EXPR<ARG1>  */
   10121              : 
   10122              : static tree
   10123          709 : fold_builtin_iseqsig (location_t loc, tree arg0, tree arg1)
   10124              : {
   10125          709 :   tree type0, type1;
   10126          709 :   enum tree_code code0, code1;
   10127          709 :   tree cmp1, cmp2, cmp_type = NULL_TREE;
   10128              : 
   10129          709 :   type0 = TREE_TYPE (arg0);
   10130          709 :   type1 = TREE_TYPE (arg1);
   10131              : 
   10132          709 :   code0 = TREE_CODE (type0);
   10133          709 :   code1 = TREE_CODE (type1);
   10134              : 
   10135          709 :   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
   10136              :     /* Choose the wider of two real types.  */
   10137          690 :     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
   10138          690 :       ? type0 : type1;
   10139           19 :   else if (code0 == REAL_TYPE
   10140            6 :            && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
   10141              :     cmp_type = type0;
   10142           13 :   else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
   10143           13 :            && code1 == REAL_TYPE)
   10144           13 :     cmp_type = type1;
   10145              : 
   10146          709 :   arg0 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg0));
   10147          709 :   arg1 = builtin_save_expr (fold_convert_loc (loc, cmp_type, arg1));
   10148              : 
   10149          709 :   cmp1 = fold_build2_loc (loc, GE_EXPR, integer_type_node, arg0, arg1);
   10150          709 :   cmp2 = fold_build2_loc (loc, LE_EXPR, integer_type_node, arg0, arg1);
   10151              : 
   10152          709 :   return fold_build2_loc (loc, TRUTH_AND_EXPR, integer_type_node, cmp1, cmp2);
   10153              : }
   10154              : 
   10155              : /* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
   10156              :    arithmetics if it can never overflow, or into internal functions that
   10157              :    return both result of arithmetics and overflowed boolean flag in
   10158              :    a complex integer result, or some other check for overflow.
   10159              :    Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
   10160              :    checking part of that.  */
   10161              : 
   10162              : static tree
   10163       509878 : fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
   10164              :                              tree arg0, tree arg1, tree arg2)
   10165              : {
   10166       509878 :   enum internal_fn ifn = IFN_LAST;
   10167              :   /* The code of the expression corresponding to the built-in.  */
   10168       509878 :   enum tree_code opcode = ERROR_MARK;
   10169       509878 :   bool ovf_only = false;
   10170              : 
   10171       509878 :   switch (fcode)
   10172              :     {
   10173              :     case BUILT_IN_ADD_OVERFLOW_P:
   10174              :       ovf_only = true;
   10175              :       /* FALLTHRU */
   10176              :     case BUILT_IN_ADD_OVERFLOW:
   10177              :     case BUILT_IN_SADD_OVERFLOW:
   10178              :     case BUILT_IN_SADDL_OVERFLOW:
   10179              :     case BUILT_IN_SADDLL_OVERFLOW:
   10180              :     case BUILT_IN_UADD_OVERFLOW:
   10181              :     case BUILT_IN_UADDL_OVERFLOW:
   10182              :     case BUILT_IN_UADDLL_OVERFLOW:
   10183              :       opcode = PLUS_EXPR;
   10184              :       ifn = IFN_ADD_OVERFLOW;
   10185              :       break;
   10186        15577 :     case BUILT_IN_SUB_OVERFLOW_P:
   10187        15577 :       ovf_only = true;
   10188              :       /* FALLTHRU */
   10189        37597 :     case BUILT_IN_SUB_OVERFLOW:
   10190        37597 :     case BUILT_IN_SSUB_OVERFLOW:
   10191        37597 :     case BUILT_IN_SSUBL_OVERFLOW:
   10192        37597 :     case BUILT_IN_SSUBLL_OVERFLOW:
   10193        37597 :     case BUILT_IN_USUB_OVERFLOW:
   10194        37597 :     case BUILT_IN_USUBL_OVERFLOW:
   10195        37597 :     case BUILT_IN_USUBLL_OVERFLOW:
   10196        37597 :       opcode = MINUS_EXPR;
   10197        37597 :       ifn = IFN_SUB_OVERFLOW;
   10198        37597 :       break;
   10199        15871 :     case BUILT_IN_MUL_OVERFLOW_P:
   10200        15871 :       ovf_only = true;
   10201              :       /* FALLTHRU */
   10202       432847 :     case BUILT_IN_MUL_OVERFLOW:
   10203       432847 :     case BUILT_IN_SMUL_OVERFLOW:
   10204       432847 :     case BUILT_IN_SMULL_OVERFLOW:
   10205       432847 :     case BUILT_IN_SMULLL_OVERFLOW:
   10206       432847 :     case BUILT_IN_UMUL_OVERFLOW:
   10207       432847 :     case BUILT_IN_UMULL_OVERFLOW:
   10208       432847 :     case BUILT_IN_UMULLL_OVERFLOW:
   10209       432847 :       opcode = MULT_EXPR;
   10210       432847 :       ifn = IFN_MUL_OVERFLOW;
   10211       432847 :       break;
   10212            0 :     default:
   10213            0 :       gcc_unreachable ();
   10214              :     }
   10215              : 
   10216              :   /* For the "generic" overloads, the first two arguments can have different
   10217              :      types and the last argument determines the target type to use to check
   10218              :      for overflow.  The arguments of the other overloads all have the same
   10219              :      type.  */
   10220       509878 :   tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
   10221              : 
   10222              :   /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
   10223              :      arguments are constant, attempt to fold the built-in call into a constant
   10224              :      expression indicating whether or not it detected an overflow.  */
   10225       509878 :   if (ovf_only
   10226        43258 :       && TREE_CODE (arg0) == INTEGER_CST
   10227        13131 :       && TREE_CODE (arg1) == INTEGER_CST)
   10228              :     /* Perform the computation in the target type and check for overflow.  */
   10229         7347 :     return omit_one_operand_loc (loc, boolean_type_node,
   10230         7347 :                                  arith_overflowed_p (opcode, type, arg0, arg1)
   10231              :                                  ? boolean_true_node : boolean_false_node,
   10232         7347 :                                  arg2);
   10233              : 
   10234       502531 :   tree intres, ovfres;
   10235       502531 :   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
   10236              :     {
   10237        88944 :       intres = fold_binary_loc (loc, opcode, type,
   10238              :                                 fold_convert_loc (loc, type, arg0),
   10239              :                                 fold_convert_loc (loc, type, arg1));
   10240        88944 :       if (TREE_OVERFLOW (intres))
   10241         1629 :         intres = drop_tree_overflow (intres);
   10242       177888 :       ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
   10243        88944 :                 ? boolean_true_node : boolean_false_node);
   10244              :     }
   10245              :   else
   10246              :     {
   10247       413587 :       tree ctype = build_complex_type (type);
   10248       413587 :       tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10249              :                                                 arg0, arg1);
   10250       413587 :       tree tgt;
   10251       413587 :       if (ovf_only)
   10252              :         {
   10253              :           tgt = call;
   10254       413587 :           intres = NULL_TREE;
   10255              :         }
   10256              :       else
   10257              :         {
   10258              :           /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
   10259              :              as while the call itself is const, the REALPART_EXPR store is
   10260              :              certainly not.  And in any case, we want just one call,
   10261              :              not multiple and trying to CSE them later.  */
   10262       377676 :           TREE_SIDE_EFFECTS (call) = 1;
   10263       377676 :           tgt = save_expr (call);
   10264              :         }
   10265       413587 :       intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10266       413587 :       ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10267       413587 :       ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
   10268              :     }
   10269              : 
   10270       502531 :   if (ovf_only)
   10271        35911 :     return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
   10272              : 
   10273       466620 :   tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
   10274       466620 :   tree store
   10275       466620 :     = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
   10276       466620 :   return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
   10277              : }
   10278              : 
   10279              : /* Fold __builtin_{clz,ctz,clrsb,ffs,parity,popcount}g into corresponding
   10280              :    internal function.  */
   10281              : 
   10282              : static tree
   10283       265984 : fold_builtin_bit_query (location_t loc, enum built_in_function fcode,
   10284              :                         tree arg0, tree arg1)
   10285              : {
   10286       265984 :   enum internal_fn ifn;
   10287       265984 :   enum built_in_function fcodei, fcodel, fcodell;
   10288       265984 :   tree arg0_type = TREE_TYPE (arg0);
   10289       265984 :   tree cast_type = NULL_TREE;
   10290       265984 :   int addend = 0;
   10291              : 
   10292       265984 :   switch (fcode)
   10293              :     {
   10294       187709 :     case BUILT_IN_CLZG:
   10295       187709 :       if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
   10296              :         return NULL_TREE;
   10297              :       ifn = IFN_CLZ;
   10298              :       fcodei = BUILT_IN_CLZ;
   10299              :       fcodel = BUILT_IN_CLZL;
   10300              :       fcodell = BUILT_IN_CLZLL;
   10301              :       break;
   10302        66961 :     case BUILT_IN_CTZG:
   10303        66961 :       if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
   10304              :         return NULL_TREE;
   10305              :       ifn = IFN_CTZ;
   10306              :       fcodei = BUILT_IN_CTZ;
   10307              :       fcodel = BUILT_IN_CTZL;
   10308              :       fcodell = BUILT_IN_CTZLL;
   10309              :       break;
   10310              :     case BUILT_IN_CLRSBG:
   10311              :       ifn = IFN_CLRSB;
   10312              :       fcodei = BUILT_IN_CLRSB;
   10313              :       fcodel = BUILT_IN_CLRSBL;
   10314              :       fcodell = BUILT_IN_CLRSBLL;
   10315              :       break;
   10316           84 :     case BUILT_IN_FFSG:
   10317           84 :       ifn = IFN_FFS;
   10318           84 :       fcodei = BUILT_IN_FFS;
   10319           84 :       fcodel = BUILT_IN_FFSL;
   10320           84 :       fcodell = BUILT_IN_FFSLL;
   10321           84 :       break;
   10322           82 :     case BUILT_IN_PARITYG:
   10323           82 :       ifn = IFN_PARITY;
   10324           82 :       fcodei = BUILT_IN_PARITY;
   10325           82 :       fcodel = BUILT_IN_PARITYL;
   10326           82 :       fcodell = BUILT_IN_PARITYLL;
   10327           82 :       break;
   10328        11066 :     case BUILT_IN_POPCOUNTG:
   10329        11066 :       ifn = IFN_POPCOUNT;
   10330        11066 :       fcodei = BUILT_IN_POPCOUNT;
   10331        11066 :       fcodel = BUILT_IN_POPCOUNTL;
   10332        11066 :       fcodell = BUILT_IN_POPCOUNTLL;
   10333        11066 :       break;
   10334            0 :     default:
   10335            0 :       gcc_unreachable ();
   10336              :     }
   10337              : 
   10338       265781 :   if (TYPE_PRECISION (arg0_type)
   10339       265781 :       <= TYPE_PRECISION (long_long_unsigned_type_node))
   10340              :     {
   10341       226667 :       if (TYPE_PRECISION (arg0_type) <= TYPE_PRECISION (unsigned_type_node))
   10342              : 
   10343        79393 :         cast_type = (TYPE_UNSIGNED (arg0_type)
   10344        79339 :                      ? unsigned_type_node : integer_type_node);
   10345       147328 :       else if (TYPE_PRECISION (arg0_type)
   10346       147328 :                <= TYPE_PRECISION (long_unsigned_type_node))
   10347              :         {
   10348       147277 :           cast_type = (TYPE_UNSIGNED (arg0_type)
   10349       147205 :                        ? long_unsigned_type_node : long_integer_type_node);
   10350              :           fcodei = fcodel;
   10351              :         }
   10352              :       else
   10353              :         {
   10354          123 :           cast_type = (TYPE_UNSIGNED (arg0_type)
   10355          123 :                        ? long_long_unsigned_type_node
   10356              :                        : long_long_integer_type_node);
   10357              :           fcodei = fcodell;
   10358              :         }
   10359              :     }
   10360        78228 :   else if (TYPE_PRECISION (arg0_type) <= MAX_FIXED_MODE_SIZE)
   10361              :     {
   10362        39004 :       cast_type
   10363        39004 :         = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
   10364        39004 :                                           TYPE_UNSIGNED (arg0_type));
   10365        39004 :       gcc_assert (TYPE_PRECISION (cast_type)
   10366              :                   == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
   10367              :       fcodei = END_BUILTINS;
   10368              :     }
   10369              :   else
   10370              :     fcodei = END_BUILTINS;
   10371       265671 :   if (cast_type)
   10372              :     {
   10373       265671 :       switch (fcode)
   10374              :         {
   10375       187658 :         case BUILT_IN_CLZG:
   10376       187658 :         case BUILT_IN_CLRSBG:
   10377       187658 :           addend = TYPE_PRECISION (arg0_type) - TYPE_PRECISION (cast_type);
   10378       187658 :           break;
   10379              :         default:
   10380              :           break;
   10381              :         }
   10382       265671 :       arg0 = fold_convert (cast_type, arg0);
   10383       265671 :       arg0_type = cast_type;
   10384              :     }
   10385              : 
   10386       265781 :   if (arg1)
   10387       176341 :     arg1 = fold_convert (integer_type_node, arg1);
   10388              : 
   10389       265781 :   tree arg2 = arg1;
   10390       265781 :   if (fcode == BUILT_IN_CLZG && addend)
   10391              :     {
   10392         4344 :       if (arg1)
   10393         4311 :         arg0 = save_expr (arg0);
   10394              :       arg2 = NULL_TREE;
   10395              :     }
   10396       265781 :   tree call = NULL_TREE, tem;
   10397       265781 :   if (TYPE_PRECISION (arg0_type) == MAX_FIXED_MODE_SIZE
   10398        39127 :       && (TYPE_PRECISION (arg0_type)
   10399        39127 :           == 2 * TYPE_PRECISION (long_long_unsigned_type_node))
   10400              :       /* If the target supports the optab, then don't do the expansion. */
   10401       304785 :       && !direct_internal_fn_supported_p (ifn, arg0_type, OPTIMIZE_FOR_BOTH))
   10402              :     {
   10403              :       /* __int128 expansions using up to 2 long long builtins.  */
   10404        39004 :       arg0 = save_expr (arg0);
   10405        39004 :       tree type = (TYPE_UNSIGNED (arg0_type)
   10406        39004 :                    ? long_long_unsigned_type_node
   10407        39004 :                    : long_long_integer_type_node);
   10408        78008 :       tree hi = fold_build2 (RSHIFT_EXPR, arg0_type, arg0,
   10409              :                              build_int_cst (integer_type_node,
   10410              :                                             MAX_FIXED_MODE_SIZE / 2));
   10411        39004 :       hi = fold_convert (type, hi);
   10412        39004 :       tree lo = fold_convert (type, arg0);
   10413        39004 :       switch (fcode)
   10414              :         {
   10415        38921 :         case BUILT_IN_CLZG:
   10416        38921 :           call = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
   10417        77842 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10418              :                               build_int_cst (integer_type_node,
   10419              :                                              MAX_FIXED_MODE_SIZE / 2));
   10420        38921 :           if (arg2)
   10421        38901 :             call = fold_build3 (COND_EXPR, integer_type_node,
   10422              :                                 fold_build2 (NE_EXPR, boolean_type_node,
   10423              :                                              lo, build_zero_cst (type)),
   10424              :                                 call, arg2);
   10425        38921 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10426              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10427              :                                            hi, build_zero_cst (type)),
   10428              :                               fold_builtin_bit_query (loc, fcode, hi,
   10429              :                                                       NULL_TREE),
   10430              :                               call);
   10431        38921 :           break;
   10432           27 :         case BUILT_IN_CTZG:
   10433           27 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10434           54 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10435              :                               build_int_cst (integer_type_node,
   10436              :                                              MAX_FIXED_MODE_SIZE / 2));
   10437           27 :           if (arg2)
   10438           18 :             call = fold_build3 (COND_EXPR, integer_type_node,
   10439              :                                 fold_build2 (NE_EXPR, boolean_type_node,
   10440              :                                              hi, build_zero_cst (type)),
   10441              :                                 call, arg2);
   10442           27 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10443              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10444              :                                            lo, build_zero_cst (type)),
   10445              :                               fold_builtin_bit_query (loc, fcode, lo,
   10446              :                                                       NULL_TREE),
   10447              :                               call);
   10448           27 :           break;
   10449            9 :         case BUILT_IN_CLRSBG:
   10450            9 :           tem = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
   10451           18 :           tem = fold_build2 (PLUS_EXPR, integer_type_node, tem,
   10452              :                              build_int_cst (integer_type_node,
   10453              :                                             MAX_FIXED_MODE_SIZE / 2));
   10454           18 :           tem = fold_build3 (COND_EXPR, integer_type_node,
   10455              :                              fold_build2 (LT_EXPR, boolean_type_node,
   10456              :                                           fold_build2 (BIT_XOR_EXPR, type,
   10457              :                                                        lo, hi),
   10458              :                                           build_zero_cst (type)),
   10459              :                              build_int_cst (integer_type_node,
   10460              :                                             MAX_FIXED_MODE_SIZE / 2 - 1),
   10461              :                              tem);
   10462            9 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10463            9 :           call = save_expr (call);
   10464           18 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10465              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10466              :                                            call,
   10467              :                                            build_int_cst (integer_type_node,
   10468              :                                                           MAX_FIXED_MODE_SIZE
   10469              :                                                           / 2 - 1)),
   10470              :                               call, tem);
   10471            9 :           break;
   10472            9 :         case BUILT_IN_FFSG:
   10473            9 :           call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
   10474           18 :           call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10475              :                               build_int_cst (integer_type_node,
   10476              :                                              MAX_FIXED_MODE_SIZE / 2));
   10477            9 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10478              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10479              :                                            hi, build_zero_cst (type)),
   10480              :                               call, integer_zero_node);
   10481            9 :           call = fold_build3 (COND_EXPR, integer_type_node,
   10482              :                               fold_build2 (NE_EXPR, boolean_type_node,
   10483              :                                            lo, build_zero_cst (type)),
   10484              :                               fold_builtin_bit_query (loc, fcode, lo,
   10485              :                                                       NULL_TREE),
   10486              :                               call);
   10487            9 :           break;
   10488            9 :         case BUILT_IN_PARITYG:
   10489            9 :           call = fold_builtin_bit_query (loc, fcode,
   10490              :                                          fold_build2 (BIT_XOR_EXPR, type,
   10491              :                                                       lo, hi), NULL_TREE);
   10492            9 :           break;
   10493           29 :         case BUILT_IN_POPCOUNTG:
   10494           29 :           call = fold_build2 (PLUS_EXPR, integer_type_node,
   10495              :                               fold_builtin_bit_query (loc, fcode, hi,
   10496              :                                                       NULL_TREE),
   10497              :                               fold_builtin_bit_query (loc, fcode, lo,
   10498              :                                                       NULL_TREE));
   10499           29 :           break;
   10500              :         default:
   10501              :           gcc_unreachable ();
   10502              :         }
   10503              :     }
   10504              :   else
   10505              :     {
   10506              :       /* Only keep second argument to IFN_CLZ/IFN_CTZ if it is the
   10507              :          value defined at zero during GIMPLE, or for large/huge _BitInt
   10508              :          (which are then lowered during bitint lowering).  */
   10509       226777 :       if (arg2 && !BITINT_TYPE_P (TREE_TYPE (arg0)))
   10510              :         {
   10511       133091 :           int val;
   10512       133091 :           if (fcode == BUILT_IN_CLZG)
   10513              :             {
   10514        66424 :               if (CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
   10515              :                                              val) != 2
   10516        66424 :                   || wi::to_widest (arg2) != val)
   10517              :                 arg2 = NULL_TREE;
   10518              :             }
   10519        66667 :           else if (CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
   10520              :                                               val) != 2
   10521        66667 :                    || wi::to_widest (arg2) != val)
   10522              :             arg2 = NULL_TREE;
   10523       133091 :           if (!direct_internal_fn_supported_p (ifn, arg0_type,
   10524              :                                                OPTIMIZE_FOR_BOTH))
   10525              :             arg2 = NULL_TREE;
   10526       132980 :           if (arg2 == NULL_TREE)
   10527       133044 :             arg0 = save_expr (arg0);
   10528              :         }
   10529       226777 :       if (fcodei == END_BUILTINS || arg2)
   10530          247 :         call = build_call_expr_internal_loc (loc, ifn, integer_type_node,
   10531              :                                              arg2 ? 2 : 1, arg0, arg2);
   10532              :       else
   10533       226620 :         call = build_call_expr_loc (loc, builtin_decl_explicit (fcodei), 1,
   10534              :                                     arg0);
   10535              :     }
   10536       265781 :   if (addend)
   10537         4362 :     call = fold_build2 (PLUS_EXPR, integer_type_node, call,
   10538              :                         build_int_cst (integer_type_node, addend));
   10539       265781 :   if (arg1 && arg2 == NULL_TREE)
   10540       137355 :     call = fold_build3 (COND_EXPR, integer_type_node,
   10541              :                         fold_build2 (NE_EXPR, boolean_type_node,
   10542              :                                      arg0, build_zero_cst (arg0_type)),
   10543              :                         call, arg1);
   10544              : 
   10545              :   return call;
   10546              : }
   10547              : 
   10548              : /* Fold or build a __builtin_bswapg (ARG) (if IFN is IFN_BSWAP) or
   10549              :    __builtin_bitreverseg (ARG (otherwise) call.  The FE should have
   10550              :    verified earlier that the argument type is unsigned INTEGER_TYPE
   10551              :    or BITINT_TYPE, for __builtin_bswapg with precision divisible by 8.  */
   10552              : 
   10553              : tree
   10554          152 : fold_build_builtin_bswapg_bitreverseg (location_t loc, enum internal_fn ifn,
   10555              :                                        tree arg)
   10556              : {
   10557          152 :   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
   10558          152 :   if (ifn == IFN_BSWAP && TYPE_PRECISION (type) == 8)
   10559           11 :     return fold_convert_loc (loc, type, arg);
   10560          141 :   struct { tree type; built_in_function bswap, bitreverse; } fns[]
   10561          141 :     = { { unsigned_char_type_node, END_BUILTINS, BUILT_IN_BITREVERSE8 },
   10562          141 :         { uint16_type_node, BUILT_IN_BSWAP16, BUILT_IN_BITREVERSE16 },
   10563          141 :         { uint32_type_node, BUILT_IN_BSWAP32, BUILT_IN_BITREVERSE32 },
   10564          141 :         { uint64_type_node, BUILT_IN_BSWAP64, BUILT_IN_BITREVERSE64 },
   10565          141 :         { uint128_type_node, BUILT_IN_BSWAP128, BUILT_IN_BITREVERSE128 } };
   10566          141 :   if (TREE_CODE (arg) == INTEGER_CST)
   10567              :     {
   10568           76 :       wide_int res;
   10569           76 :       if (ifn == IFN_BSWAP)
   10570           37 :         res = wi::bswap (wi::to_wide (arg));
   10571              :       else
   10572           45 :         res = wi::bitreverse (wi::to_wide (arg));
   10573           76 :       return wide_int_to_tree (type, res);
   10574           76 :     }
   10575          256 :   for (unsigned i = 0; i < ARRAY_SIZE (fns); ++i)
   10576          239 :     if (fns[i].type
   10577          239 :         && TYPE_PRECISION (fns[i].type) >= TYPE_PRECISION (type))
   10578              :       {
   10579           48 :         arg = fold_convert_loc (loc, fns[i].type, arg);
   10580           48 :         tree fndecl
   10581           48 :           = builtin_decl_explicit (ifn == IFN_BSWAP
   10582              :                                    ? fns[i].bswap : fns[i].bitreverse);
   10583           48 :         tree ret = build_call_expr_loc (loc, fndecl, 1, arg);
   10584           48 :         if (TYPE_PRECISION (type) != TYPE_PRECISION (fns[i].type))
   10585            4 :           ret = fold_build2_loc (loc, RSHIFT_EXPR, fns[i].type, ret,
   10586              :                                  build_int_cst (unsigned_type_node,
   10587            4 :                                                 TYPE_PRECISION (fns[i].type)
   10588            4 :                                                 - TYPE_PRECISION (type)));
   10589           48 :         return fold_convert_loc (loc, type, ret);
   10590              :       }
   10591           17 :   gcc_assert (TREE_CODE (type) == BITINT_TYPE);
   10592           17 :   return build_call_expr_internal_loc (loc, ifn, type, 1, arg);
   10593              : }
   10594              : 
   10595              : /* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
   10596              :    that return both result of arithmetics and overflowed boolean
   10597              :    flag in a complex integer result.  */
   10598              : 
   10599              : static tree
   10600           55 : fold_builtin_addc_subc (location_t loc, enum built_in_function fcode,
   10601              :                         tree *args)
   10602              : {
   10603           55 :   enum internal_fn ifn;
   10604              : 
   10605           55 :   switch (fcode)
   10606              :     {
   10607              :     case BUILT_IN_ADDC:
   10608              :     case BUILT_IN_ADDCL:
   10609              :     case BUILT_IN_ADDCLL:
   10610              :       ifn = IFN_ADD_OVERFLOW;
   10611              :       break;
   10612           29 :     case BUILT_IN_SUBC:
   10613           29 :     case BUILT_IN_SUBCL:
   10614           29 :     case BUILT_IN_SUBCLL:
   10615           29 :       ifn = IFN_SUB_OVERFLOW;
   10616           29 :       break;
   10617            0 :     default:
   10618            0 :       gcc_unreachable ();
   10619              :     }
   10620              : 
   10621           55 :   tree type = TREE_TYPE (args[0]);
   10622           55 :   tree ctype = build_complex_type (type);
   10623           55 :   tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10624              :                                             args[0], args[1]);
   10625              :   /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1,
   10626              :      as while the call itself is const, the REALPART_EXPR store is
   10627              :      certainly not.  And in any case, we want just one call,
   10628              :      not multiple and trying to CSE them later.  */
   10629           55 :   TREE_SIDE_EFFECTS (call) = 1;
   10630           55 :   tree tgt = save_expr (call);
   10631           55 :   tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10632           55 :   tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10633           55 :   call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
   10634              :                                        intres, args[2]);
   10635           55 :   TREE_SIDE_EFFECTS (call) = 1;
   10636           55 :   tgt = save_expr (call);
   10637           55 :   intres = build1_loc (loc, REALPART_EXPR, type, tgt);
   10638           55 :   tree ovfres2 = build1_loc (loc, IMAGPART_EXPR, type, tgt);
   10639           55 :   ovfres = build2_loc (loc, BIT_IOR_EXPR, type, ovfres, ovfres2);
   10640           55 :   tree mem_arg3 = build_fold_indirect_ref_loc (loc, args[3]);
   10641           55 :   tree store
   10642           55 :     = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg3, ovfres);
   10643           55 :   return build2_loc (loc, COMPOUND_EXPR, type, store, intres);
   10644              : }
   10645              : 
   10646              : /* Fold a call to __builtin_FILE to a constant string.  */
   10647              : 
   10648              : static inline tree
   10649         5789 : fold_builtin_FILE (location_t loc)
   10650              : {
   10651         5789 :   if (const char *fname = LOCATION_FILE (loc))
   10652              :     {
   10653              :       /* The documentation says this builtin is equivalent to the preprocessor
   10654              :          __FILE__ macro so it appears appropriate to use the same file prefix
   10655              :          mappings.  */
   10656         5789 :       fname = remap_macro_filename (fname);
   10657         5789 :       return build_string_literal (fname);
   10658              :     }
   10659              : 
   10660            0 :   return build_string_literal ("");
   10661              : }
   10662              : 
   10663              : /* Fold a call to __builtin_FUNCTION to a constant string.  */
   10664              : 
   10665              : static inline tree
   10666           68 : fold_builtin_FUNCTION ()
   10667              : {
   10668           68 :   const char *name = "";
   10669              : 
   10670           68 :   if (current_function_decl)
   10671           43 :     name = lang_hooks.decl_printable_name (current_function_decl, 0);
   10672              : 
   10673           68 :   return build_string_literal (name);
   10674              : }
   10675              : 
   10676              : /* Fold a call to __builtin_LINE to an integer constant.  */
   10677              : 
   10678              : static inline tree
   10679        11545 : fold_builtin_LINE (location_t loc, tree type)
   10680              : {
   10681        11545 :   return build_int_cst (type, LOCATION_LINE (loc));
   10682              : }
   10683              : 
   10684              : /* Fold a call to built-in function FNDECL with 0 arguments.
   10685              :    This function returns NULL_TREE if no simplification was possible.  */
   10686              : 
   10687              : static tree
   10688     24044758 : fold_builtin_0 (location_t loc, tree fndecl)
   10689              : {
   10690     24044758 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10691     24044758 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10692     24044758 :   switch (fcode)
   10693              :     {
   10694         5789 :     case BUILT_IN_FILE:
   10695         5789 :       return fold_builtin_FILE (loc);
   10696              : 
   10697           68 :     case BUILT_IN_FUNCTION:
   10698           68 :       return fold_builtin_FUNCTION ();
   10699              : 
   10700        11545 :     case BUILT_IN_LINE:
   10701        11545 :       return fold_builtin_LINE (loc, type);
   10702              : 
   10703        33910 :     CASE_FLT_FN (BUILT_IN_INF):
   10704        33910 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
   10705        33910 :     case BUILT_IN_INFD32:
   10706        33910 :     case BUILT_IN_INFD64:
   10707        33910 :     case BUILT_IN_INFD128:
   10708        33910 :     case BUILT_IN_INFD64X:
   10709        33910 :       return fold_builtin_inf (loc, type, true);
   10710              : 
   10711       229702 :     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
   10712       229702 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
   10713       229702 :       return fold_builtin_inf (loc, type, false);
   10714              : 
   10715            0 :     case BUILT_IN_CLASSIFY_TYPE:
   10716            0 :       return fold_builtin_classify_type (NULL_TREE);
   10717              : 
   10718     20577305 :     case BUILT_IN_UNREACHABLE:
   10719              :       /* Rewrite any explicit calls to __builtin_unreachable.  */
   10720     20577305 :       if (sanitize_flags_p (SANITIZE_UNREACHABLE))
   10721           91 :         return build_builtin_unreachable (loc);
   10722              :       break;
   10723              : 
   10724              :     default:
   10725              :       break;
   10726              :     }
   10727              :   return NULL_TREE;
   10728              : }
   10729              : 
   10730              : /* Fold a call to built-in function FNDECL with 1 argument, ARG0.
   10731              :    This function returns NULL_TREE if no simplification was possible.  */
   10732              : 
   10733              : static tree
   10734     20223807 : fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
   10735              : {
   10736     20223807 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10737     20223807 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10738              : 
   10739     20223807 :   if (error_operand_p (arg0))
   10740              :     return NULL_TREE;
   10741              : 
   10742     20223807 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0))
   10743              :     return ret;
   10744              : 
   10745     19596916 :   switch (fcode)
   10746              :     {
   10747      3115536 :     case BUILT_IN_CONSTANT_P:
   10748      3115536 :       {
   10749      3115536 :         tree val = fold_builtin_constant_p (arg0);
   10750              : 
   10751              :         /* Gimplification will pull the CALL_EXPR for the builtin out of
   10752              :            an if condition.  When not optimizing, we'll not CSE it back.
   10753              :            To avoid link error types of regressions, return false now.  */
   10754      3115536 :         if (!val && !optimize)
   10755         1558 :           val = integer_zero_node;
   10756              : 
   10757              :         return val;
   10758              :       }
   10759              : 
   10760         2078 :     case BUILT_IN_CLASSIFY_TYPE:
   10761         2078 :       return fold_builtin_classify_type (arg0);
   10762              : 
   10763       476464 :     case BUILT_IN_STRLEN:
   10764       476464 :       return fold_builtin_strlen (loc, expr, type, arg0);
   10765              : 
   10766       378195 :     CASE_FLT_FN (BUILT_IN_FABS):
   10767       378195 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   10768       378195 :     case BUILT_IN_FABSD32:
   10769       378195 :     case BUILT_IN_FABSD64:
   10770       378195 :     case BUILT_IN_FABSD128:
   10771       378195 :     case BUILT_IN_FABSD64X:
   10772       378195 :       return fold_builtin_fabs (loc, arg0, type);
   10773              : 
   10774       101153 :     case BUILT_IN_ABS:
   10775       101153 :     case BUILT_IN_LABS:
   10776       101153 :     case BUILT_IN_LLABS:
   10777       101153 :     case BUILT_IN_IMAXABS:
   10778       101153 :     case BUILT_IN_UABS:
   10779       101153 :     case BUILT_IN_ULABS:
   10780       101153 :     case BUILT_IN_ULLABS:
   10781       101153 :     case BUILT_IN_UMAXABS:
   10782       101153 :       return fold_builtin_abs (loc, arg0, type);
   10783              : 
   10784        25461 :     CASE_FLT_FN (BUILT_IN_CONJ):
   10785        25461 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10786        25461 :         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10787        25461 :         return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
   10788              :     break;
   10789              : 
   10790          764 :     CASE_FLT_FN (BUILT_IN_CREAL):
   10791          764 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10792          764 :         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10793          764 :         return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
   10794              :     break;
   10795              : 
   10796         1884 :     CASE_FLT_FN (BUILT_IN_CIMAG):
   10797         1884 :       if (validate_arg (arg0, COMPLEX_TYPE)
   10798         1884 :           && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
   10799         1884 :         return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
   10800              :     break;
   10801              : 
   10802       104371 :     CASE_FLT_FN (BUILT_IN_CARG):
   10803       104371 :     CASE_FLT_FN_FLOATN_NX (BUILT_IN_CARG):
   10804       104371 :       return fold_builtin_carg (loc, arg0, type);
   10805              : 
   10806          211 :     case BUILT_IN_ISASCII:
   10807          211 :       return fold_builtin_isascii (loc, arg0);
   10808              : 
   10809          168 :     case BUILT_IN_TOASCII:
   10810          168 :       return fold_builtin_toascii (loc, arg0);
   10811              : 
   10812          325 :     case BUILT_IN_ISDIGIT:
   10813          325 :       return fold_builtin_isdigit (loc, arg0);
   10814              : 
   10815       625691 :     CASE_FLT_FN (BUILT_IN_FINITE):
   10816       625691 :     case BUILT_IN_FINITED32:
   10817       625691 :     case BUILT_IN_FINITED64:
   10818       625691 :     case BUILT_IN_FINITED128:
   10819       625691 :     case BUILT_IN_ISFINITE:
   10820       625691 :       {
   10821       625691 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
   10822       625691 :         if (ret)
   10823              :           return ret;
   10824       625359 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10825              :       }
   10826              : 
   10827       710621 :     CASE_FLT_FN (BUILT_IN_ISINF):
   10828       710621 :     case BUILT_IN_ISINFD32:
   10829       710621 :     case BUILT_IN_ISINFD64:
   10830       710621 :     case BUILT_IN_ISINFD128:
   10831       710621 :       {
   10832       710621 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
   10833       710621 :         if (ret)
   10834              :           return ret;
   10835       710370 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10836              :       }
   10837              : 
   10838       239896 :     case BUILT_IN_ISNORMAL:
   10839       239896 :       return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10840              : 
   10841          708 :     case BUILT_IN_ISINF_SIGN:
   10842          708 :       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
   10843              : 
   10844       243014 :     CASE_FLT_FN (BUILT_IN_ISNAN):
   10845       243014 :     case BUILT_IN_ISNAND32:
   10846       243014 :     case BUILT_IN_ISNAND64:
   10847       243014 :     case BUILT_IN_ISNAND128:
   10848       243014 :       {
   10849       243014 :         tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
   10850       243014 :         if (ret)
   10851              :           return ret;
   10852       242890 :         return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
   10853              :       }
   10854              : 
   10855        27815 :     case BUILT_IN_ISSIGNALING:
   10856        27815 :       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISSIGNALING);
   10857              : 
   10858       635983 :     case BUILT_IN_FREE:
   10859       635983 :       if (integer_zerop (arg0))
   10860         1077 :         return build_empty_stmt (loc);
   10861              :       break;
   10862              : 
   10863        11441 :     case BUILT_IN_CLZG:
   10864        11441 :     case BUILT_IN_CTZG:
   10865        11441 :     case BUILT_IN_CLRSBG:
   10866        11441 :     case BUILT_IN_FFSG:
   10867        11441 :     case BUILT_IN_PARITYG:
   10868        11441 :     case BUILT_IN_POPCOUNTG:
   10869        11441 :       return fold_builtin_bit_query (loc, fcode, arg0, NULL_TREE);
   10870              : 
   10871              :     default:
   10872              :       break;
   10873              :     }
   10874              : 
   10875              :   return NULL_TREE;
   10876              : 
   10877              : }
   10878              : 
   10879              : /* Folds a call EXPR (which may be null) to built-in function FNDECL
   10880              :    with 2 arguments, ARG0 and ARG1.  This function returns NULL_TREE
   10881              :    if no simplification was possible.  */
   10882              : 
   10883              : static tree
   10884     19481152 : fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
   10885              : {
   10886     19481152 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10887     19481152 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10888              : 
   10889     19481152 :   if (error_operand_p (arg0)
   10890     19481152 :       || error_operand_p (arg1))
   10891              :     return NULL_TREE;
   10892              : 
   10893     19481148 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type, arg0, arg1))
   10894              :     return ret;
   10895              : 
   10896     19264891 :   switch (fcode)
   10897              :     {
   10898         6504 :     CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
   10899         6504 :     CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
   10900         6504 :       if (validate_arg (arg0, REAL_TYPE)
   10901         6504 :           && validate_arg (arg1, POINTER_TYPE))
   10902         6504 :         return do_mpfr_lgamma_r (arg0, arg1, type);
   10903              :     break;
   10904              : 
   10905       115911 :     CASE_FLT_FN (BUILT_IN_FREXP):
   10906       115911 :       return fold_builtin_frexp (loc, arg0, arg1, type);
   10907              : 
   10908        92826 :     CASE_FLT_FN (BUILT_IN_MODF):
   10909        92826 :       return fold_builtin_modf (loc, arg0, arg1, type);
   10910              : 
   10911         2560 :     case BUILT_IN_STRSPN:
   10912         2560 :       return fold_builtin_strspn (loc, expr, arg0, arg1, type);
   10913              : 
   10914         2465 :     case BUILT_IN_STRCSPN:
   10915         2465 :       return fold_builtin_strcspn (loc, expr, arg0, arg1, type);
   10916              : 
   10917       100317 :     case BUILT_IN_STRPBRK:
   10918       100317 :       return fold_builtin_strpbrk (loc, expr, arg0, arg1, type);
   10919              : 
   10920      6750626 :     case BUILT_IN_EXPECT:
   10921      6750626 :       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
   10922              : 
   10923       950425 :     case BUILT_IN_ISGREATER:
   10924       950425 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10925       950425 :                                          arg0, arg1, UNLE_EXPR, LE_EXPR);
   10926       479886 :     case BUILT_IN_ISGREATEREQUAL:
   10927       479886 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10928       479886 :                                          arg0, arg1, UNLT_EXPR, LT_EXPR);
   10929       241559 :     case BUILT_IN_ISLESS:
   10930       241559 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10931       241559 :                                          arg0, arg1, UNGE_EXPR, GE_EXPR);
   10932      1105275 :     case BUILT_IN_ISLESSEQUAL:
   10933      1105275 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10934      1105275 :                                          arg0, arg1, UNGT_EXPR, GT_EXPR);
   10935       239693 :     case BUILT_IN_ISLESSGREATER:
   10936       239693 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10937       239693 :                                          arg0, arg1, UNEQ_EXPR, EQ_EXPR);
   10938       240883 :     case BUILT_IN_ISUNORDERED:
   10939       240883 :       return fold_builtin_unordered_cmp (loc, fndecl,
   10940              :                                          arg0, arg1, UNORDERED_EXPR,
   10941       240883 :                                          NOP_EXPR);
   10942              : 
   10943          709 :     case BUILT_IN_ISEQSIG:
   10944          709 :       return fold_builtin_iseqsig (loc, arg0, arg1);
   10945              : 
   10946              :       /* We do the folding for va_start in the expander.  */
   10947              :     case BUILT_IN_VA_START:
   10948              :       break;
   10949              : 
   10950       201103 :     case BUILT_IN_OBJECT_SIZE:
   10951       201103 :     case BUILT_IN_DYNAMIC_OBJECT_SIZE:
   10952       201103 :       return fold_builtin_object_size (arg0, arg1, fcode);
   10953              : 
   10954       105502 :     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
   10955       105502 :       return fold_builtin_atomic_always_lock_free (arg0, arg1);
   10956              : 
   10957        38817 :     case BUILT_IN_ATOMIC_IS_LOCK_FREE:
   10958        38817 :       return fold_builtin_atomic_is_lock_free (arg0, arg1);
   10959              : 
   10960       176544 :     case BUILT_IN_CLZG:
   10961       176544 :     case BUILT_IN_CTZG:
   10962       176544 :       return fold_builtin_bit_query (loc, fcode, arg0, arg1);
   10963              : 
   10964              :     default:
   10965              :       break;
   10966              :     }
   10967              :   return NULL_TREE;
   10968              : }
   10969              : 
   10970              : /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
   10971              :    and ARG2.
   10972              :    This function returns NULL_TREE if no simplification was possible.  */
   10973              : 
   10974              : static tree
   10975      7418370 : fold_builtin_3 (location_t loc, tree fndecl,
   10976              :                 tree arg0, tree arg1, tree arg2)
   10977              : {
   10978      7418370 :   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   10979      7418370 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   10980              : 
   10981      7418370 :   if (error_operand_p (arg0)
   10982      7418370 :       || error_operand_p (arg1)
   10983     14836740 :       || error_operand_p (arg2))
   10984              :     return NULL_TREE;
   10985              : 
   10986      7418368 :   if (tree ret = fold_const_call (as_combined_fn (fcode), type,
   10987              :                                   arg0, arg1, arg2))
   10988              :     return ret;
   10989              : 
   10990      7401341 :   switch (fcode)
   10991              :     {
   10992              : 
   10993          145 :     CASE_FLT_FN (BUILT_IN_SINCOS):
   10994          145 :       return fold_builtin_sincos (loc, arg0, arg1, arg2);
   10995              : 
   10996        99940 :     CASE_FLT_FN (BUILT_IN_REMQUO):
   10997        99940 :       if (validate_arg (arg0, REAL_TYPE)
   10998        99940 :           && validate_arg (arg1, REAL_TYPE)
   10999       199880 :           && validate_arg (arg2, POINTER_TYPE))
   11000        99940 :         return do_mpfr_remquo (arg0, arg1, arg2);
   11001              :     break;
   11002              : 
   11003      2568558 :     case BUILT_IN_MEMCMP:
   11004      2568558 :       return fold_builtin_memcmp (loc, arg0, arg1, arg2);
   11005              : 
   11006       518630 :     case BUILT_IN_EXPECT:
   11007       518630 :       return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
   11008              : 
   11009          395 :     case BUILT_IN_EXPECT_WITH_PROBABILITY:
   11010          395 :       return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg2);
   11011              : 
   11012       509878 :     case BUILT_IN_ADD_OVERFLOW:
   11013       509878 :     case BUILT_IN_SUB_OVERFLOW:
   11014       509878 :     case BUILT_IN_MUL_OVERFLOW:
   11015       509878 :     case BUILT_IN_ADD_OVERFLOW_P:
   11016       509878 :     case BUILT_IN_SUB_OVERFLOW_P:
   11017       509878 :     case BUILT_IN_MUL_OVERFLOW_P:
   11018       509878 :     case BUILT_IN_SADD_OVERFLOW:
   11019       509878 :     case BUILT_IN_SADDL_OVERFLOW:
   11020       509878 :     case BUILT_IN_SADDLL_OVERFLOW:
   11021       509878 :     case BUILT_IN_SSUB_OVERFLOW:
   11022       509878 :     case BUILT_IN_SSUBL_OVERFLOW:
   11023       509878 :     case BUILT_IN_SSUBLL_OVERFLOW:
   11024       509878 :     case BUILT_IN_SMUL_OVERFLOW:
   11025       509878 :     case BUILT_IN_SMULL_OVERFLOW:
   11026       509878 :     case BUILT_IN_SMULLL_OVERFLOW:
   11027       509878 :     case BUILT_IN_UADD_OVERFLOW:
   11028       509878 :     case BUILT_IN_UADDL_OVERFLOW:
   11029       509878 :     case BUILT_IN_UADDLL_OVERFLOW:
   11030       509878 :     case BUILT_IN_USUB_OVERFLOW:
   11031       509878 :     case BUILT_IN_USUBL_OVERFLOW:
   11032       509878 :     case BUILT_IN_USUBLL_OVERFLOW:
   11033       509878 :     case BUILT_IN_UMUL_OVERFLOW:
   11034       509878 :     case BUILT_IN_UMULL_OVERFLOW:
   11035       509878 :     case BUILT_IN_UMULLL_OVERFLOW:
   11036       509878 :       return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
   11037              : 
   11038              :     default:
   11039              :       break;
   11040              :     }
   11041              :   return NULL_TREE;
   11042              : }
   11043              : 
   11044              : /* Folds a call EXPR (which may be null) to built-in function FNDECL.
   11045              :    ARGS is an array of NARGS arguments.  IGNORE is true if the result
   11046              :    of the function call is ignored.  This function returns NULL_TREE
   11047              :    if no simplification was possible.  */
   11048              : 
   11049              : static tree
   11050     73786032 : fold_builtin_n (location_t loc, tree expr, tree fndecl, tree *args,
   11051              :                 int nargs, bool)
   11052              : {
   11053     73786032 :   tree ret = NULL_TREE;
   11054              : 
   11055     73786032 :   switch (nargs)
   11056              :     {
   11057     24044758 :     case 0:
   11058     24044758 :       ret = fold_builtin_0 (loc, fndecl);
   11059     24044758 :       break;
   11060     20223807 :     case 1:
   11061     20223807 :       ret = fold_builtin_1 (loc, expr, fndecl, args[0]);
   11062     20223807 :       break;
   11063     19481152 :     case 2:
   11064     19481152 :       ret = fold_builtin_2 (loc, expr, fndecl, args[0], args[1]);
   11065     19481152 :       break;
   11066      7418370 :     case 3:
   11067      7418370 :       ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]);
   11068      7418370 :       break;
   11069      2617945 :     default:
   11070      2617945 :       ret = fold_builtin_varargs (loc, fndecl, args, nargs);
   11071      2617945 :       break;
   11072              :     }
   11073     73786032 :   if (ret)
   11074              :     {
   11075     10058099 :       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   11076     10058099 :       SET_EXPR_LOCATION (ret, loc);
   11077     10058099 :       return ret;
   11078              :     }
   11079              :   return NULL_TREE;
   11080              : }
   11081              : 
   11082              : /* Construct a new CALL_EXPR to FNDECL using the tail of the argument
   11083              :    list ARGS along with N new arguments in NEWARGS.  SKIP is the number
   11084              :    of arguments in ARGS to be omitted.  OLDNARGS is the number of
   11085              :    elements in ARGS.  */
   11086              : 
   11087              : static tree
   11088            4 : rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
   11089              :                           int skip, tree fndecl, int n, va_list newargs)
   11090              : {
   11091            4 :   int nargs = oldnargs - skip + n;
   11092            4 :   tree *buffer;
   11093              : 
   11094            4 :   if (n > 0)
   11095              :     {
   11096            0 :       int i, j;
   11097              : 
   11098            0 :       buffer = XALLOCAVEC (tree, nargs);
   11099            0 :       for (i = 0; i < n; i++)
   11100            0 :         buffer[i] = va_arg (newargs, tree);
   11101            0 :       for (j = skip; j < oldnargs; j++, i++)
   11102            0 :         buffer[i] = args[j];
   11103              :     }
   11104              :   else
   11105            4 :     buffer = args + skip;
   11106              : 
   11107            4 :   return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
   11108              : }
   11109              : 
   11110              : /* Return true if FNDECL shouldn't be folded right now.
   11111              :    If a built-in function has an inline attribute always_inline
   11112              :    wrapper, defer folding it after always_inline functions have
   11113              :    been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
   11114              :    might not be performed.  */
   11115              : 
   11116              : bool
   11117    154553266 : avoid_folding_inline_builtin (tree fndecl)
   11118              : {
   11119    154553266 :   return (DECL_DECLARED_INLINE_P (fndecl)
   11120        13268 :           && DECL_DISREGARD_INLINE_LIMITS (fndecl)
   11121        13226 :           && cfun
   11122        13226 :           && !cfun->always_inline_functions_inlined
   11123    154566492 :           && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
   11124              : }
   11125              : 
   11126              : /* A wrapper function for builtin folding that prevents warnings for
   11127              :    "statement without effect" and the like, caused by removing the
   11128              :    call node earlier than the warning is generated.  */
   11129              : 
   11130              : tree
   11131    203600543 : fold_call_expr (location_t loc, tree exp, bool ignore)
   11132              : {
   11133    203600543 :   tree ret = NULL_TREE;
   11134    203600543 :   tree fndecl = get_callee_fndecl (exp);
   11135    201823960 :   if (fndecl && fndecl_built_in_p (fndecl)
   11136              :       /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
   11137              :          yet.  Defer folding until we see all the arguments
   11138              :          (after inlining).  */
   11139    263578766 :       && !CALL_EXPR_VA_ARG_PACK (exp))
   11140              :     {
   11141     59978192 :       int nargs = call_expr_nargs (exp);
   11142              : 
   11143              :       /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
   11144              :          instead last argument is __builtin_va_arg_pack ().  Defer folding
   11145              :          even in that case, until arguments are finalized.  */
   11146     59978192 :       if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
   11147              :         {
   11148       223183 :           tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
   11149       223183 :           if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   11150              :             return NULL_TREE;
   11151              :         }
   11152              : 
   11153     59978123 :       if (avoid_folding_inline_builtin (fndecl))
   11154              :         return NULL_TREE;
   11155              : 
   11156     59974585 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   11157     71889762 :         return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
   11158     71889762 :                                      CALL_EXPR_ARGP (exp), ignore);
   11159              :       else
   11160              :         {
   11161     24029704 :           tree *args = CALL_EXPR_ARGP (exp);
   11162     24029704 :           ret = fold_builtin_n (loc, exp, fndecl, args, nargs, ignore);
   11163     24029704 :           if (ret)
   11164              :             return ret;
   11165              :         }
   11166              :     }
   11167              :   return NULL_TREE;
   11168              : }
   11169              : 
   11170              : /* Fold a CALL_EXPR with type TYPE with FN as the function expression.
   11171              :    N arguments are passed in the array ARGARRAY.  Return a folded
   11172              :    expression or NULL_TREE if no simplification was possible.  */
   11173              : 
   11174              : tree
   11175     79409802 : fold_builtin_call_array (location_t loc, tree,
   11176              :                          tree fn,
   11177              :                          int n,
   11178              :                          tree *argarray)
   11179              : {
   11180     79409802 :   if (TREE_CODE (fn) != ADDR_EXPR)
   11181              :     return NULL_TREE;
   11182              : 
   11183     79409802 :   tree fndecl = TREE_OPERAND (fn, 0);
   11184     79409802 :   if (TREE_CODE (fndecl) == FUNCTION_DECL
   11185     79409802 :       && fndecl_built_in_p (fndecl))
   11186              :     {
   11187              :       /* If last argument is __builtin_va_arg_pack (), arguments to this
   11188              :          function are not finalized yet.  Defer folding until they are.  */
   11189     78799717 :       if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
   11190              :         {
   11191       137417 :           tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
   11192       137417 :           if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
   11193              :             return NULL_TREE;
   11194              :         }
   11195     78799678 :       if (avoid_folding_inline_builtin (fndecl))
   11196              :         return NULL_TREE;
   11197     78799678 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   11198     35179574 :         return targetm.fold_builtin (fndecl, n, argarray, false);
   11199              :       else
   11200     43620104 :         return fold_builtin_n (loc, NULL_TREE, fndecl, argarray, n, false);
   11201              :     }
   11202              : 
   11203              :   return NULL_TREE;
   11204              : }
   11205              : 
   11206              : /* Construct a new CALL_EXPR using the tail of the argument list of EXP
   11207              :    along with N new arguments specified as the "..." parameters.  SKIP
   11208              :    is the number of arguments in EXP to be omitted.  This function is used
   11209              :    to do varargs-to-varargs transformations.  */
   11210              : 
   11211              : static tree
   11212            4 : rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
   11213              : {
   11214            4 :   va_list ap;
   11215            4 :   tree t;
   11216              : 
   11217            4 :   va_start (ap, n);
   11218            8 :   t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
   11219            4 :                                 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
   11220            4 :   va_end (ap);
   11221              : 
   11222            4 :   return t;
   11223              : }
   11224              : 
   11225              : /* Validate a single argument ARG against a tree code CODE representing
   11226              :    a type.  Return true when argument is valid.  */
   11227              : 
   11228              : static bool
   11229     15455634 : validate_arg (const_tree arg, enum tree_code code)
   11230              : {
   11231     15455634 :   if (!arg)
   11232              :     return false;
   11233     15455611 :   else if (code == POINTER_TYPE)
   11234      7173066 :     return POINTER_TYPE_P (TREE_TYPE (arg));
   11235      8282545 :   else if (code == INTEGER_TYPE)
   11236      3797787 :     return INTEGRAL_TYPE_P (TREE_TYPE (arg));
   11237      4484758 :   return code == TREE_CODE (TREE_TYPE (arg));
   11238              : }
   11239              : 
   11240              : /* This function validates the types of a function call argument list
   11241              :    against a specified list of tree_codes.  If the last specifier is a 0,
   11242              :    that represents an ellipses, otherwise the last specifier must be a
   11243              :    VOID_TYPE.
   11244              : 
   11245              :    This is the GIMPLE version of validate_arglist.  Eventually we want to
   11246              :    completely convert builtins.cc to work from GIMPLEs and the tree based
   11247              :    validate_arglist will then be removed.  */
   11248              : 
   11249              : bool
   11250          136 : validate_gimple_arglist (const gcall *call, ...)
   11251              : {
   11252          136 :   enum tree_code code;
   11253          136 :   bool res = 0;
   11254          136 :   va_list ap;
   11255          136 :   const_tree arg;
   11256          136 :   size_t i;
   11257              : 
   11258          136 :   va_start (ap, call);
   11259          136 :   i = 0;
   11260              : 
   11261          544 :   do
   11262              :     {
   11263          544 :       code = (enum tree_code) va_arg (ap, int);
   11264          544 :       switch (code)
   11265              :         {
   11266            0 :         case 0:
   11267              :           /* This signifies an ellipses, any further arguments are all ok.  */
   11268            0 :           res = true;
   11269            0 :           goto end;
   11270          136 :         case VOID_TYPE:
   11271              :           /* This signifies an endlink, if no arguments remain, return
   11272              :              true, otherwise return false.  */
   11273          136 :           res = (i == gimple_call_num_args (call));
   11274          136 :           goto end;
   11275          408 :         default:
   11276              :           /* If no parameters remain or the parameter's code does not
   11277              :              match the specified code, return false.  Otherwise continue
   11278              :              checking any remaining arguments.  */
   11279          408 :           arg = gimple_call_arg (call, i++);
   11280          408 :           if (!validate_arg (arg, code))
   11281            0 :             goto end;
   11282              :           break;
   11283              :         }
   11284              :     }
   11285              :   while (1);
   11286              : 
   11287              :   /* We need gotos here since we can only have one VA_CLOSE in a
   11288              :      function.  */
   11289          136 :  end: ;
   11290          136 :   va_end (ap);
   11291              : 
   11292          136 :   return res;
   11293              : }
   11294              : 
   11295              : /* Default target-specific builtin expander that does nothing.  */
   11296              : 
   11297              : rtx
   11298            0 : default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
   11299              :                         rtx target ATTRIBUTE_UNUSED,
   11300              :                         rtx subtarget ATTRIBUTE_UNUSED,
   11301              :                         machine_mode mode ATTRIBUTE_UNUSED,
   11302              :                         int ignore ATTRIBUTE_UNUSED)
   11303              : {
   11304            0 :   return NULL_RTX;
   11305              : }
   11306              : 
   11307              : /* Returns true is EXP represents data that would potentially reside
   11308              :    in a readonly section.  */
   11309              : 
   11310              : bool
   11311       210733 : readonly_data_expr (tree exp)
   11312              : {
   11313       210733 :   STRIP_NOPS (exp);
   11314              : 
   11315       210733 :   if (TREE_CODE (exp) != ADDR_EXPR)
   11316              :     return false;
   11317              : 
   11318        26717 :   exp = get_base_address (TREE_OPERAND (exp, 0));
   11319        26717 :   if (!exp)
   11320              :     return false;
   11321              : 
   11322              :   /* Make sure we call decl_readonly_section only for trees it
   11323              :      can handle (since it returns true for everything it doesn't
   11324              :      understand).  */
   11325        26717 :   if (TREE_CODE (exp) == STRING_CST
   11326         5775 :       || TREE_CODE (exp) == CONSTRUCTOR
   11327         5775 :       || (VAR_P (exp) && TREE_STATIC (exp)))
   11328        23561 :     return decl_readonly_section (exp, 0);
   11329              :   else
   11330              :     return false;
   11331              : }
   11332              : 
   11333              : /* Simplify a call to the strpbrk builtin.  S1 and S2 are the arguments
   11334              :    to the call, and TYPE is its return type.
   11335              : 
   11336              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11337              :    simplified form of the call as a tree.
   11338              : 
   11339              :    The simplified form may be a constant or other expression which
   11340              :    computes the same value, but in a more efficient manner (including
   11341              :    calls to other builtin functions).
   11342              : 
   11343              :    The call may contain arguments which need to be evaluated, but
   11344              :    which are not useful to determine the result of the call.  In
   11345              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11346              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11347              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11348              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11349              :    form of the builtin function call.  */
   11350              : 
   11351              : static tree
   11352       100317 : fold_builtin_strpbrk (location_t loc, tree, tree s1, tree s2, tree type)
   11353              : {
   11354       100317 :   if (!validate_arg (s1, POINTER_TYPE)
   11355       100317 :       || !validate_arg (s2, POINTER_TYPE))
   11356              :     return NULL_TREE;
   11357              : 
   11358       100317 :   tree fn;
   11359       100317 :   const char *p1, *p2;
   11360              : 
   11361       100317 :   p2 = c_getstr (s2);
   11362       100317 :   if (p2 == NULL)
   11363              :     return NULL_TREE;
   11364              : 
   11365           92 :   p1 = c_getstr (s1);
   11366           92 :   if (p1 != NULL)
   11367              :     {
   11368           22 :       const char *r = strpbrk (p1, p2);
   11369           22 :       tree tem;
   11370              : 
   11371           22 :       if (r == NULL)
   11372            0 :         return build_int_cst (TREE_TYPE (s1), 0);
   11373              : 
   11374              :       /* Return an offset into the constant string argument.  */
   11375           22 :       tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
   11376           22 :       return fold_convert_loc (loc, type, tem);
   11377              :     }
   11378              : 
   11379           70 :   if (p2[0] == '\0')
   11380              :     /* strpbrk(x, "") == NULL.
   11381              :        Evaluate and ignore s1 in case it had side-effects.  */
   11382           26 :     return omit_one_operand_loc (loc, type, integer_zero_node, s1);
   11383              : 
   11384           44 :   if (p2[1] != '\0')
   11385              :     return NULL_TREE;  /* Really call strpbrk.  */
   11386              : 
   11387           41 :   fn = builtin_decl_implicit (BUILT_IN_STRCHR);
   11388           41 :   if (!fn)
   11389              :     return NULL_TREE;
   11390              : 
   11391              :   /* New argument list transforming strpbrk(s1, s2) to
   11392              :      strchr(s1, s2[0]).  */
   11393           41 :   return build_call_expr_loc (loc, fn, 2, s1,
   11394           41 :                               build_int_cst (integer_type_node, p2[0]));
   11395              : }
   11396              : 
   11397              : /* Simplify a call to the strspn builtin.  S1 and S2 are the arguments
   11398              :    to the call.
   11399              : 
   11400              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11401              :    simplified form of the call as a tree.
   11402              : 
   11403              :    The simplified form may be a constant or other expression which
   11404              :    computes the same value, but in a more efficient manner (including
   11405              :    calls to other builtin functions).
   11406              : 
   11407              :    The call may contain arguments which need to be evaluated, but
   11408              :    which are not useful to determine the result of the call.  In
   11409              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11410              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11411              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11412              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11413              :    form of the builtin function call.  */
   11414              : 
   11415              : static tree
   11416         2560 : fold_builtin_strspn (location_t loc, tree expr, tree s1, tree s2, tree type)
   11417              : {
   11418         2560 :   if (!validate_arg (s1, POINTER_TYPE)
   11419         2560 :       || !validate_arg (s2, POINTER_TYPE))
   11420              :     return NULL_TREE;
   11421              : 
   11422         2560 :   if (!check_nul_terminated_array (expr, s1)
   11423         2560 :       || !check_nul_terminated_array (expr, s2))
   11424              :     return NULL_TREE;
   11425              : 
   11426         2502 :   const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
   11427              : 
   11428              :   /* If either argument is "", return NULL_TREE.  */
   11429         2502 :   if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
   11430              :     /* Evaluate and ignore both arguments in case either one has
   11431              :        side-effects.  */
   11432          147 :     return omit_two_operands_loc (loc, type, size_zero_node, s1, s2);
   11433              :   return NULL_TREE;
   11434              : }
   11435              : 
   11436              : /* Simplify a call to the strcspn builtin.  S1 and S2 are the arguments
   11437              :    to the call.
   11438              : 
   11439              :    Return NULL_TREE if no simplification was possible, otherwise return the
   11440              :    simplified form of the call as a tree.
   11441              : 
   11442              :    The simplified form may be a constant or other expression which
   11443              :    computes the same value, but in a more efficient manner (including
   11444              :    calls to other builtin functions).
   11445              : 
   11446              :    The call may contain arguments which need to be evaluated, but
   11447              :    which are not useful to determine the result of the call.  In
   11448              :    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
   11449              :    COMPOUND_EXPR will be an argument which must be evaluated.
   11450              :    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
   11451              :    COMPOUND_EXPR in the chain will contain the tree for the simplified
   11452              :    form of the builtin function call.  */
   11453              : 
   11454              : static tree
   11455         2465 : fold_builtin_strcspn (location_t loc, tree expr, tree s1, tree s2, tree type)
   11456              : {
   11457         2465 :   if (!validate_arg (s1, POINTER_TYPE)
   11458         2465 :       || !validate_arg (s2, POINTER_TYPE))
   11459              :     return NULL_TREE;
   11460              : 
   11461         2465 :   if (!check_nul_terminated_array (expr, s1)
   11462         2465 :       || !check_nul_terminated_array (expr, s2))
   11463              :     return NULL_TREE;
   11464              : 
   11465              :   /* If the first argument is "", return NULL_TREE.  */
   11466         2407 :   const char *p1 = c_getstr (s1);
   11467         2407 :   if (p1 && *p1 == '\0')
   11468              :     {
   11469              :       /* Evaluate and ignore argument s2 in case it has
   11470              :          side-effects.  */
   11471           65 :       return omit_one_operand_loc (loc, type, size_zero_node, s2);
   11472              :     }
   11473              : 
   11474              :   /* If the second argument is "", return __builtin_strlen(s1).  */
   11475         2342 :   const char *p2 = c_getstr (s2);
   11476         2342 :   if (p2 && *p2 == '\0')
   11477              :     {
   11478           81 :       tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
   11479              : 
   11480              :       /* If the replacement _DECL isn't initialized, don't do the
   11481              :          transformation.  */
   11482           81 :       if (!fn)
   11483              :         return NULL_TREE;
   11484              : 
   11485           81 :       return fold_convert_loc (loc, type,
   11486           81 :                                build_call_expr_loc (loc, fn, 1, s1));
   11487              :     }
   11488              :   return NULL_TREE;
   11489              : }
   11490              : 
   11491              : /* Fold the next_arg or va_start call EXP. Returns true if there was an error
   11492              :    produced.  False otherwise.  This is done so that we don't output the error
   11493              :    or warning twice or three times.  */
   11494              : 
   11495              : bool
   11496        42132 : fold_builtin_next_arg (tree exp, bool va_start_p)
   11497              : {
   11498        42132 :   tree fntype = TREE_TYPE (current_function_decl);
   11499        42132 :   int nargs = call_expr_nargs (exp);
   11500        42132 :   tree arg;
   11501              :   /* There is good chance the current input_location points inside the
   11502              :      definition of the va_start macro (perhaps on the token for
   11503              :      builtin) in a system header, so warnings will not be emitted.
   11504              :      Use the location in real source code.  */
   11505        42132 :   location_t current_location =
   11506        42132 :     linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
   11507              :                                               NULL);
   11508              : 
   11509        42132 :   if (!stdarg_p (fntype))
   11510              :     {
   11511            8 :       error ("%<va_start%> used in function with fixed arguments");
   11512            8 :       return true;
   11513              :     }
   11514              : 
   11515        42124 :   if (va_start_p)
   11516              :     {
   11517        41966 :       if (va_start_p && (nargs != 2))
   11518              :         {
   11519            0 :           error ("wrong number of arguments to function %<va_start%>");
   11520            0 :           return true;
   11521              :         }
   11522        41966 :       arg = CALL_EXPR_ARG (exp, 1);
   11523              :     }
   11524              :   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
   11525              :      when we checked the arguments and if needed issued a warning.  */
   11526              :   else
   11527              :     {
   11528          158 :       if (nargs == 0)
   11529              :         {
   11530              :           /* Evidently an out of date version of <stdarg.h>; can't validate
   11531              :              va_start's second argument, but can still work as intended.  */
   11532            0 :           warning_at (current_location,
   11533            0 :                       OPT_Wvarargs,
   11534              :                    "%<__builtin_next_arg%> called without an argument");
   11535            0 :           return true;
   11536              :         }
   11537          158 :       else if (nargs > 1)
   11538              :         {
   11539            0 :           error ("wrong number of arguments to function %<__builtin_next_arg%>");
   11540            0 :           return true;
   11541              :         }
   11542          158 :       arg = CALL_EXPR_ARG (exp, 0);
   11543              :     }
   11544              : 
   11545        42124 :   if (TREE_CODE (arg) == SSA_NAME
   11546        42124 :       && SSA_NAME_VAR (arg))
   11547              :     arg = SSA_NAME_VAR (arg);
   11548              : 
   11549              :   /* We destructively modify the call to be __builtin_va_start (ap, 0)
   11550              :      or __builtin_next_arg (0) the first time we see it, after checking
   11551              :      the arguments and if needed issuing a warning.  */
   11552        42124 :   if (!integer_zerop (arg))
   11553              :     {
   11554         7025 :       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
   11555              : 
   11556              :       /* Strip off all nops for the sake of the comparison.  This
   11557              :          is not quite the same as STRIP_NOPS.  It does more.
   11558              :          We must also strip off INDIRECT_EXPR for C++ reference
   11559              :          parameters.  */
   11560        14052 :       while (CONVERT_EXPR_P (arg)
   11561        14063 :              || INDIRECT_REF_P (arg))
   11562           11 :         arg = TREE_OPERAND (arg, 0);
   11563         7025 :       if (arg != last_parm)
   11564              :         {
   11565              :           /* FIXME: Sometimes with the tree optimizers we can get the
   11566              :              not the last argument even though the user used the last
   11567              :              argument.  We just warn and set the arg to be the last
   11568              :              argument so that we will get wrong-code because of
   11569              :              it.  */
   11570           12 :           warning_at (current_location,
   11571           12 :                       OPT_Wvarargs,
   11572              :                       "second parameter of %<va_start%> not last named argument");
   11573              :         }
   11574              : 
   11575              :       /* Undefined by C99 7.15.1.4p4 (va_start):
   11576              :          "If the parameter parmN is declared with the register storage
   11577              :          class, with a function or array type, or with a type that is
   11578              :          not compatible with the type that results after application of
   11579              :          the default argument promotions, the behavior is undefined."
   11580              :       */
   11581         7013 :       else if (DECL_REGISTER (arg))
   11582              :         {
   11583           12 :           warning_at (current_location,
   11584           12 :                       OPT_Wvarargs,
   11585              :                       "undefined behavior when second parameter of "
   11586              :                       "%<va_start%> is declared with %<register%> storage");
   11587              :         }
   11588              : 
   11589              :       /* We want to verify the second parameter just once before the tree
   11590              :          optimizers are run and then avoid keeping it in the tree,
   11591              :          as otherwise we could warn even for correct code like:
   11592              :          void foo (int i, ...)
   11593              :          { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
   11594         7025 :       if (va_start_p)
   11595         7023 :         CALL_EXPR_ARG (exp, 1) = integer_zero_node;
   11596              :       else
   11597            2 :         CALL_EXPR_ARG (exp, 0) = integer_zero_node;
   11598              :     }
   11599              :   return false;
   11600              : }
   11601              : 
   11602              : 
   11603              : /* Expand a call EXP to __builtin_object_size.  */
   11604              : 
   11605              : static rtx
   11606          620 : expand_builtin_object_size (tree exp)
   11607              : {
   11608          620 :   tree ost;
   11609          620 :   int object_size_type;
   11610          620 :   tree fndecl = get_callee_fndecl (exp);
   11611              : 
   11612          620 :   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
   11613              :     {
   11614            0 :       error ("first argument of %qD must be a pointer, second integer constant",
   11615              :              fndecl);
   11616            0 :       expand_builtin_trap ();
   11617            0 :       return const0_rtx;
   11618              :     }
   11619              : 
   11620          620 :   ost = CALL_EXPR_ARG (exp, 1);
   11621          620 :   STRIP_NOPS (ost);
   11622              : 
   11623          620 :   if (TREE_CODE (ost) != INTEGER_CST
   11624          620 :       || tree_int_cst_sgn (ost) < 0
   11625         1240 :       || compare_tree_int (ost, 3) > 0)
   11626              :     {
   11627            0 :       error ("last argument of %qD is not integer constant between 0 and 3",
   11628              :               fndecl);
   11629            0 :       expand_builtin_trap ();
   11630            0 :       return const0_rtx;
   11631              :     }
   11632              : 
   11633          620 :   object_size_type = tree_to_shwi (ost);
   11634              : 
   11635          620 :   return object_size_type < 2 ? constm1_rtx : const0_rtx;
   11636              : }
   11637              : 
   11638              : /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
   11639              :    FCODE is the BUILT_IN_* to use.
   11640              :    Return NULL_RTX if we failed; the caller should emit a normal call,
   11641              :    otherwise try to get the result in TARGET, if convenient (and in
   11642              :    mode MODE if that's convenient).  */
   11643              : 
   11644              : static rtx
   11645          837 : expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
   11646              :                            enum built_in_function fcode)
   11647              : {
   11648         1410 :   if (!validate_arglist (exp,
   11649              :                          POINTER_TYPE,
   11650              :                          fcode == BUILT_IN_MEMSET_CHK
   11651              :                          ? INTEGER_TYPE : POINTER_TYPE,
   11652              :                          INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
   11653              :     return NULL_RTX;
   11654              : 
   11655          837 :   tree dest = CALL_EXPR_ARG (exp, 0);
   11656          837 :   tree src = CALL_EXPR_ARG (exp, 1);
   11657          837 :   tree len = CALL_EXPR_ARG (exp, 2);
   11658          837 :   tree size = CALL_EXPR_ARG (exp, 3);
   11659              : 
   11660              :   /* FIXME: Set access mode to write only for memset et al.  */
   11661          837 :   bool sizes_ok = check_access (exp, len, /*maxread=*/NULL_TREE,
   11662              :                                 /*srcstr=*/NULL_TREE, size, access_read_write);
   11663              : 
   11664          837 :   if (!tree_fits_uhwi_p (size))
   11665              :     return NULL_RTX;
   11666              : 
   11667          627 :   if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
   11668              :     {
   11669              :       /* Avoid transforming the checking call to an ordinary one when
   11670              :          an overflow has been detected or when the call couldn't be
   11671              :          validated because the size is not constant.  */
   11672          186 :       if (!sizes_ok && !integer_all_onesp (size) && tree_int_cst_lt (size, len))
   11673              :         return NULL_RTX;
   11674              : 
   11675            0 :       tree fn = NULL_TREE;
   11676              :       /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
   11677              :          mem{cpy,pcpy,move,set} is available.  */
   11678            0 :       switch (fcode)
   11679              :         {
   11680            0 :         case BUILT_IN_MEMCPY_CHK:
   11681            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
   11682            0 :           break;
   11683            0 :         case BUILT_IN_MEMPCPY_CHK:
   11684            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
   11685            0 :           break;
   11686            0 :         case BUILT_IN_MEMMOVE_CHK:
   11687            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
   11688            0 :           break;
   11689            0 :         case BUILT_IN_MEMSET_CHK:
   11690            0 :           fn = builtin_decl_explicit (BUILT_IN_MEMSET);
   11691            0 :           break;
   11692              :         default:
   11693              :           break;
   11694              :         }
   11695              : 
   11696            0 :       if (! fn)
   11697              :         return NULL_RTX;
   11698              : 
   11699            0 :       fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
   11700            0 :       gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   11701            0 :       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   11702            0 :       return expand_expr (fn, target, mode, EXPAND_NORMAL);
   11703              :     }
   11704          441 :   else if (fcode == BUILT_IN_MEMSET_CHK)
   11705              :     return NULL_RTX;
   11706              :   else
   11707              :     {
   11708          293 :       unsigned int dest_align = get_pointer_alignment (dest);
   11709              : 
   11710              :       /* If DEST is not a pointer type, call the normal function.  */
   11711          293 :       if (dest_align == 0)
   11712              :         return NULL_RTX;
   11713              : 
   11714              :       /* If SRC and DEST are the same (and not volatile), do nothing.  */
   11715          293 :       if (operand_equal_p (src, dest, 0))
   11716              :         {
   11717            0 :           tree expr;
   11718              : 
   11719            0 :           if (fcode != BUILT_IN_MEMPCPY_CHK)
   11720              :             {
   11721              :               /* Evaluate and ignore LEN in case it has side-effects.  */
   11722            0 :               expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
   11723            0 :               return expand_expr (dest, target, mode, EXPAND_NORMAL);
   11724              :             }
   11725              : 
   11726            0 :           expr = fold_build_pointer_plus (dest, len);
   11727            0 :           return expand_expr (expr, target, mode, EXPAND_NORMAL);
   11728              :         }
   11729              : 
   11730              :       /* __memmove_chk special case.  */
   11731          293 :       if (fcode == BUILT_IN_MEMMOVE_CHK)
   11732              :         {
   11733           79 :           unsigned int src_align = get_pointer_alignment (src);
   11734              : 
   11735           79 :           if (src_align == 0)
   11736              :             return NULL_RTX;
   11737              : 
   11738              :           /* If src is categorized for a readonly section we can use
   11739              :              normal __memcpy_chk.  */
   11740           79 :           if (readonly_data_expr (src))
   11741              :             {
   11742           15 :               tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
   11743           15 :               if (!fn)
   11744              :                 return NULL_RTX;
   11745           15 :               fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
   11746              :                                           dest, src, len, size);
   11747           15 :               gcc_assert (TREE_CODE (fn) == CALL_EXPR);
   11748           15 :               CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
   11749           15 :               return expand_expr (fn, target, mode, EXPAND_NORMAL);
   11750              :             }
   11751              :         }
   11752              :       return NULL_RTX;
   11753              :     }
   11754              : }
   11755              : 
   11756              : /* Emit warning if a buffer overflow is detected at compile time.  */
   11757              : 
   11758              : static void
   11759         1086 : maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
   11760              : {
   11761              :   /* The source string.  */
   11762         1086 :   tree srcstr = NULL_TREE;
   11763              :   /* The size of the destination object returned by __builtin_object_size.  */
   11764         1086 :   tree objsize = NULL_TREE;
   11765              :   /* The string that is being concatenated with (as in __strcat_chk)
   11766              :      or null if it isn't.  */
   11767         1086 :   tree catstr = NULL_TREE;
   11768              :   /* The maximum length of the source sequence in a bounded operation
   11769              :      (such as __strncat_chk) or null if the operation isn't bounded
   11770              :      (such as __strcat_chk).  */
   11771         1086 :   tree maxread = NULL_TREE;
   11772              :   /* The exact size of the access (such as in __strncpy_chk).  */
   11773         1086 :   tree size = NULL_TREE;
   11774              :   /* The access by the function that's checked.  Except for snprintf
   11775              :      both writing and reading is checked.  */
   11776         1086 :   access_mode mode = access_read_write;
   11777              : 
   11778         1086 :   switch (fcode)
   11779              :     {
   11780          275 :     case BUILT_IN_STRCPY_CHK:
   11781          275 :     case BUILT_IN_STPCPY_CHK:
   11782          275 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11783          275 :       objsize = CALL_EXPR_ARG (exp, 2);
   11784          275 :       break;
   11785              : 
   11786          151 :     case BUILT_IN_STRCAT_CHK:
   11787              :       /* For __strcat_chk the warning will be emitted only if overflowing
   11788              :          by at least strlen (dest) + 1 bytes.  */
   11789          151 :       catstr = CALL_EXPR_ARG (exp, 0);
   11790          151 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11791          151 :       objsize = CALL_EXPR_ARG (exp, 2);
   11792          151 :       break;
   11793              : 
   11794          108 :     case BUILT_IN_STRNCAT_CHK:
   11795          108 :       catstr = CALL_EXPR_ARG (exp, 0);
   11796          108 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11797          108 :       maxread = CALL_EXPR_ARG (exp, 2);
   11798          108 :       objsize = CALL_EXPR_ARG (exp, 3);
   11799          108 :       break;
   11800              : 
   11801          243 :     case BUILT_IN_STRNCPY_CHK:
   11802          243 :     case BUILT_IN_STPNCPY_CHK:
   11803          243 :       srcstr = CALL_EXPR_ARG (exp, 1);
   11804          243 :       size = CALL_EXPR_ARG (exp, 2);
   11805          243 :       objsize = CALL_EXPR_ARG (exp, 3);
   11806          243 :       break;
   11807              : 
   11808          309 :     case BUILT_IN_SNPRINTF_CHK:
   11809          309 :     case BUILT_IN_VSNPRINTF_CHK:
   11810          309 :       maxread = CALL_EXPR_ARG (exp, 1);
   11811          309 :       objsize = CALL_EXPR_ARG (exp, 3);
   11812              :       /* The only checked access the write to the destination.  */
   11813          309 :       mode = access_write_only;
   11814          309 :       break;
   11815            0 :     default:
   11816            0 :       gcc_unreachable ();
   11817              :     }
   11818              : 
   11819         1086 :   if (catstr && maxread)
   11820              :     {
   11821              :       /* Check __strncat_chk.  There is no way to determine the length
   11822              :          of the string to which the source string is being appended so
   11823              :          just warn when the length of the source string is not known.  */
   11824          108 :       check_strncat_sizes (exp, objsize);
   11825          108 :       return;
   11826              :     }
   11827              : 
   11828          978 :   check_access (exp, size, maxread, srcstr, objsize, mode);
   11829              : }
   11830              : 
   11831              : /* Emit warning if a buffer overflow is detected at compile time
   11832              :    in __sprintf_chk/__vsprintf_chk calls.  */
   11833              : 
   11834              : static void
   11835         1328 : maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
   11836              : {
   11837         1328 :   tree size, len, fmt;
   11838         1328 :   const char *fmt_str;
   11839         1328 :   int nargs = call_expr_nargs (exp);
   11840              : 
   11841              :   /* Verify the required arguments in the original call.  */
   11842              : 
   11843         1328 :   if (nargs < 4)
   11844              :     return;
   11845         1328 :   size = CALL_EXPR_ARG (exp, 2);
   11846         1328 :   fmt = CALL_EXPR_ARG (exp, 3);
   11847              : 
   11848         1328 :   if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
   11849              :     return;
   11850              : 
   11851              :   /* Check whether the format is a literal string constant.  */
   11852         1307 :   fmt_str = c_getstr (fmt);
   11853         1307 :   if (fmt_str == NULL)
   11854              :     return;
   11855              : 
   11856         1271 :   if (!init_target_chars ())
   11857              :     return;
   11858              : 
   11859              :   /* If the format doesn't contain % args or %%, we know its size.  */
   11860         1271 :   if (strchr (fmt_str, target_percent) == 0)
   11861           22 :     len = build_int_cstu (size_type_node, strlen (fmt_str));
   11862              :   /* If the format is "%s" and first ... argument is a string literal,
   11863              :      we know it too.  */
   11864         1249 :   else if (fcode == BUILT_IN_SPRINTF_CHK
   11865         1095 :            && strcmp (fmt_str, target_percent_s) == 0)
   11866              :     {
   11867           49 :       tree arg;
   11868              : 
   11869           49 :       if (nargs < 5)
   11870              :         return;
   11871           49 :       arg = CALL_EXPR_ARG (exp, 4);
   11872           49 :       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
   11873              :         return;
   11874              : 
   11875           45 :       len = c_strlen (arg, 1);
   11876           45 :       if (!len || ! tree_fits_uhwi_p (len))
   11877              :         return;
   11878              :     }
   11879              :   else
   11880              :     return;
   11881              : 
   11882              :   /* Add one for the terminating nul.  */
   11883           34 :   len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
   11884              : 
   11885           34 :   check_access (exp, /*size=*/NULL_TREE, /*maxread=*/NULL_TREE, len, size,
   11886              :                 access_write_only);
   11887              : }
   11888              : 
   11889              : /* Fold a call to __builtin_object_size with arguments PTR and OST,
   11890              :    if possible.  */
   11891              : 
   11892              : static tree
   11893       201103 : fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode)
   11894              : {
   11895       201103 :   tree bytes;
   11896       201103 :   int object_size_type;
   11897              : 
   11898       201103 :   if (!validate_arg (ptr, POINTER_TYPE)
   11899       201103 :       || !validate_arg (ost, INTEGER_TYPE))
   11900              :     return NULL_TREE;
   11901              : 
   11902       201103 :   STRIP_NOPS (ost);
   11903              : 
   11904       201103 :   if (TREE_CODE (ost) != INTEGER_CST
   11905       201103 :       || tree_int_cst_sgn (ost) < 0
   11906       402206 :       || compare_tree_int (ost, 3) > 0)
   11907              :     return NULL_TREE;
   11908              : 
   11909       201103 :   object_size_type = tree_to_shwi (ost);
   11910              : 
   11911              :   /* __builtin_object_size doesn't evaluate side-effects in its arguments;
   11912              :      if there are any side-effects, it returns (size_t) -1 for types 0 and 1
   11913              :      and (size_t) 0 for types 2 and 3.  */
   11914       201103 :   if (TREE_SIDE_EFFECTS (ptr))
   11915          603 :     return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
   11916              : 
   11917       200500 :   if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE)
   11918        67467 :     object_size_type |= OST_DYNAMIC;
   11919              : 
   11920       200500 :   if (TREE_CODE (ptr) == ADDR_EXPR)
   11921              :     {
   11922        12232 :       compute_builtin_object_size (ptr, object_size_type, &bytes);
   11923        12232 :       if ((object_size_type & OST_DYNAMIC)
   11924        10886 :           || int_fits_type_p (bytes, size_type_node))
   11925        12232 :         return fold_convert (size_type_node, bytes);
   11926              :     }
   11927       188268 :   else if (TREE_CODE (ptr) == SSA_NAME)
   11928              :     {
   11929              :       /* If object size is not known yet, delay folding until
   11930              :        later.  Maybe subsequent passes will help determining
   11931              :        it.  */
   11932       102230 :       if (compute_builtin_object_size (ptr, object_size_type, &bytes)
   11933       102230 :           && ((object_size_type & OST_DYNAMIC)
   11934         2538 :               || int_fits_type_p (bytes, size_type_node)))
   11935         4808 :         return fold_convert (size_type_node, bytes);
   11936              :     }
   11937              : 
   11938              :   return NULL_TREE;
   11939              : }
   11940              : 
   11941              : /* Builtins with folding operations that operate on "..." arguments
   11942              :    need special handling; we need to store the arguments in a convenient
   11943              :    data structure before attempting any folding.  Fortunately there are
   11944              :    only a few builtins that fall into this category.  FNDECL is the
   11945              :    function, EXP is the CALL_EXPR for the call.  */
   11946              : 
   11947              : static tree
   11948      2617945 : fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
   11949              : {
   11950      2617945 :   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   11951      2617945 :   tree ret = NULL_TREE;
   11952              : 
   11953      2617945 :   switch (fcode)
   11954              :     {
   11955       104514 :     case BUILT_IN_FPCLASSIFY:
   11956       104514 :       ret = fold_builtin_fpclassify (loc, args, nargs);
   11957       104514 :       break;
   11958              : 
   11959           55 :     case BUILT_IN_ADDC:
   11960           55 :     case BUILT_IN_ADDCL:
   11961           55 :     case BUILT_IN_ADDCLL:
   11962           55 :     case BUILT_IN_SUBC:
   11963           55 :     case BUILT_IN_SUBCL:
   11964           55 :     case BUILT_IN_SUBCLL:
   11965           55 :       return fold_builtin_addc_subc (loc, fcode, args);
   11966              : 
   11967              :     default:
   11968              :       break;
   11969              :     }
   11970       104514 :   if (ret)
   11971              :     {
   11972       104514 :       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
   11973       104514 :       SET_EXPR_LOCATION (ret, loc);
   11974       104514 :       suppress_warning (ret);
   11975       104514 :       return ret;
   11976              :     }
   11977              :   return NULL_TREE;
   11978              : }
   11979              : 
   11980              : /* Initialize format string characters in the target charset.  */
   11981              : 
   11982              : bool
   11983       290517 : init_target_chars (void)
   11984              : {
   11985       290517 :   static bool init;
   11986       290517 :   if (!init)
   11987              :     {
   11988       115421 :       target_newline = lang_hooks.to_target_charset ('\n');
   11989       115421 :       target_percent = lang_hooks.to_target_charset ('%');
   11990       115421 :       target_c = lang_hooks.to_target_charset ('c');
   11991       115421 :       target_s = lang_hooks.to_target_charset ('s');
   11992       115421 :       if (target_newline == 0 || target_percent == 0 || target_c == 0
   11993       115421 :           || target_s == 0)
   11994              :         return false;
   11995              : 
   11996       115421 :       target_percent_c[0] = target_percent;
   11997       115421 :       target_percent_c[1] = target_c;
   11998       115421 :       target_percent_c[2] = '\0';
   11999              : 
   12000       115421 :       target_percent_s[0] = target_percent;
   12001       115421 :       target_percent_s[1] = target_s;
   12002       115421 :       target_percent_s[2] = '\0';
   12003              : 
   12004       115421 :       target_percent_s_newline[0] = target_percent;
   12005       115421 :       target_percent_s_newline[1] = target_s;
   12006       115421 :       target_percent_s_newline[2] = target_newline;
   12007       115421 :       target_percent_s_newline[3] = '\0';
   12008              : 
   12009       115421 :       init = true;
   12010              :     }
   12011              :   return true;
   12012              : }
   12013              : 
   12014              : /* Helper function for do_mpfr_arg*().  Ensure M is a normal number
   12015              :    and no overflow/underflow occurred.  INEXACT is true if M was not
   12016              :    exactly calculated.  TYPE is the tree type for the result.  This
   12017              :    function assumes that you cleared the MPFR flags and then
   12018              :    calculated M to see if anything subsequently set a flag prior to
   12019              :    entering this function.  Return NULL_TREE if any checks fail.  */
   12020              : 
   12021              : static tree
   12022         2979 : do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
   12023              : {
   12024              :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   12025              :      overflow/underflow occurred.  If -frounding-math, proceed iff the
   12026              :      result of calling FUNC was exact.  */
   12027         4832 :   if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
   12028         4832 :       && (!flag_rounding_math || !inexact))
   12029              :     {
   12030         1853 :       REAL_VALUE_TYPE rr;
   12031              : 
   12032         1853 :       real_from_mpfr (&rr, m, type, MPFR_RNDN);
   12033              :       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
   12034              :          check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   12035              :          but the mpfr_t is not, then we underflowed in the
   12036              :          conversion.  */
   12037         1853 :       if (real_isfinite (&rr)
   12038         1853 :           && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
   12039              :         {
   12040         1853 :           REAL_VALUE_TYPE rmode;
   12041              : 
   12042         1853 :           real_convert (&rmode, TYPE_MODE (type), &rr);
   12043              :           /* Proceed iff the specified mode can hold the value.  */
   12044         1853 :           if (real_identical (&rmode, &rr))
   12045         1853 :             return build_real (type, rmode);
   12046              :         }
   12047              :     }
   12048              :   return NULL_TREE;
   12049              : }
   12050              : 
   12051              : /* Helper function for do_mpc_arg*().  Ensure M is a normal complex
   12052              :    number and no overflow/underflow occurred.  INEXACT is true if M
   12053              :    was not exactly calculated.  TYPE is the tree type for the result.
   12054              :    This function assumes that you cleared the MPFR flags and then
   12055              :    calculated M to see if anything subsequently set a flag prior to
   12056              :    entering this function.  Return NULL_TREE if any checks fail, if
   12057              :    FORCE_CONVERT is true, then bypass the checks.  */
   12058              : 
   12059              : static tree
   12060         4171 : do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
   12061              : {
   12062              :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
   12063              :      overflow/underflow occurred.  If -frounding-math, proceed iff the
   12064              :      result of calling FUNC was exact.  */
   12065         4171 :   if (force_convert
   12066         4171 :       || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
   12067         3852 :           && !mpfr_overflow_p () && !mpfr_underflow_p ()
   12068         3852 :           && (!flag_rounding_math || !inexact)))
   12069              :     {
   12070         3992 :       REAL_VALUE_TYPE re, im;
   12071              : 
   12072         3992 :       real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
   12073         3992 :       real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
   12074              :       /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
   12075              :          check for overflow/underflow.  If the REAL_VALUE_TYPE is zero
   12076              :          but the mpfr_t is not, then we underflowed in the
   12077              :          conversion.  */
   12078         3992 :       if (force_convert
   12079         3992 :           || (real_isfinite (&re) && real_isfinite (&im)
   12080         3852 :               && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
   12081         3852 :               && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
   12082              :         {
   12083         3992 :           REAL_VALUE_TYPE re_mode, im_mode;
   12084              : 
   12085         3992 :           real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
   12086         3992 :           real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
   12087              :           /* Proceed iff the specified mode can hold the value.  */
   12088         3992 :           if (force_convert
   12089         3992 :               || (real_identical (&re_mode, &re)
   12090         3852 :                   && real_identical (&im_mode, &im)))
   12091         3992 :             return build_complex (type, build_real (TREE_TYPE (type), re_mode),
   12092         7984 :                                   build_real (TREE_TYPE (type), im_mode));
   12093              :         }
   12094              :     }
   12095              :   return NULL_TREE;
   12096              : }
   12097              : 
   12098              : /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
   12099              :    the pointer *(ARG_QUO) and return the result.  The type is taken
   12100              :    from the type of ARG0 and is used for setting the precision of the
   12101              :    calculation and results.  */
   12102              : 
   12103              : static tree
   12104        99940 : do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
   12105              : {
   12106        99940 :   tree const type = TREE_TYPE (arg0);
   12107        99940 :   tree result = NULL_TREE;
   12108              : 
   12109        99940 :   STRIP_NOPS (arg0);
   12110        99940 :   STRIP_NOPS (arg1);
   12111              : 
   12112              :   /* To proceed, MPFR must exactly represent the target floating point
   12113              :      format, which only happens when the target base equals two.  */
   12114        99940 :   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   12115        99940 :       && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
   12116       102245 :       && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
   12117              :     {
   12118         2305 :       const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
   12119         2305 :       const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
   12120              : 
   12121         2305 :       if (real_isfinite (ra0) && real_isfinite (ra1))
   12122              :         {
   12123         2305 :           const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   12124         2305 :           const int prec = fmt->p;
   12125         2305 :           const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   12126         2305 :           tree result_rem;
   12127         2305 :           long integer_quo;
   12128         2305 :           mpfr_t m0, m1;
   12129              : 
   12130         2305 :           mpfr_inits2 (prec, m0, m1, NULL);
   12131         2305 :           mpfr_from_real (m0, ra0, MPFR_RNDN);
   12132         2305 :           mpfr_from_real (m1, ra1, MPFR_RNDN);
   12133         2305 :           mpfr_clear_flags ();
   12134         2305 :           mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
   12135              :           /* Remquo is independent of the rounding mode, so pass
   12136              :              inexact=0 to do_mpfr_ckconv().  */
   12137         2305 :           result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
   12138         2305 :           mpfr_clears (m0, m1, NULL);
   12139         2305 :           if (result_rem)
   12140              :             {
   12141              :               /* MPFR calculates quo in the host's long so it may
   12142              :                  return more bits in quo than the target int can hold
   12143              :                  if sizeof(host long) > sizeof(target int).  This can
   12144              :                  happen even for native compilers in LP64 mode.  In
   12145              :                  these cases, modulo the quo value with the largest
   12146              :                  number that the target int can hold while leaving one
   12147              :                  bit for the sign.  */
   12148         1179 :               if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
   12149         1179 :                 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
   12150              : 
   12151              :               /* Dereference the quo pointer argument.  */
   12152         1179 :               arg_quo = build_fold_indirect_ref (arg_quo);
   12153              :               /* Proceed iff a valid pointer type was passed in.  */
   12154         1179 :               if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
   12155              :                 {
   12156              :                   /* Set the value. */
   12157         1179 :                   tree result_quo
   12158         1179 :                     = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
   12159              :                                    build_int_cst (TREE_TYPE (arg_quo),
   12160              :                                                   integer_quo));
   12161         1179 :                   TREE_SIDE_EFFECTS (result_quo) = 1;
   12162              :                   /* Combine the quo assignment with the rem.  */
   12163         1179 :                   result = fold_build2 (COMPOUND_EXPR, type,
   12164              :                                         result_quo, result_rem);
   12165         1179 :                   suppress_warning (result, OPT_Wunused_value);
   12166         1179 :                   result = non_lvalue (result);
   12167              :                 }
   12168              :             }
   12169              :         }
   12170              :     }
   12171        99940 :   return result;
   12172              : }
   12173              : 
   12174              : /* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
   12175              :    resulting value as a tree with type TYPE.  The mpfr precision is
   12176              :    set to the precision of TYPE.  We assume that this mpfr function
   12177              :    returns zero if the result could be calculated exactly within the
   12178              :    requested precision.  In addition, the integer pointer represented
   12179              :    by ARG_SG will be dereferenced and set to the appropriate signgam
   12180              :    (-1,1) value.  */
   12181              : 
   12182              : static tree
   12183         6504 : do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
   12184              : {
   12185         6504 :   tree result = NULL_TREE;
   12186              : 
   12187         6504 :   STRIP_NOPS (arg);
   12188              : 
   12189              :   /* To proceed, MPFR must exactly represent the target floating point
   12190              :      format, which only happens when the target base equals two.  Also
   12191              :      verify ARG is a constant and that ARG_SG is an int pointer.  */
   12192         6504 :   if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
   12193         6504 :       && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
   12194         6470 :       && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
   12195        12974 :       && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
   12196              :     {
   12197         6470 :       const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
   12198              : 
   12199              :       /* In addition to NaN and Inf, the argument cannot be zero or a
   12200              :          negative integer.  */
   12201         6470 :       if (real_isfinite (ra)
   12202         6470 :           && ra->cl != rvc_zero
   12203        12940 :           && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
   12204              :         {
   12205          674 :           const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
   12206          674 :           const int prec = fmt->p;
   12207          674 :           const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
   12208          674 :           int inexact, sg;
   12209          674 :           tree result_lg;
   12210              : 
   12211          674 :           auto_mpfr m (prec);
   12212          674 :           mpfr_from_real (m, ra, MPFR_RNDN);
   12213          674 :           mpfr_clear_flags ();
   12214          674 :           inexact = mpfr_lgamma (m, &sg, m, rnd);
   12215          674 :           result_lg = do_mpfr_ckconv (m, type, inexact);
   12216          674 :           if (result_lg)
   12217              :             {
   12218          674 :               tree result_sg;
   12219              : 
   12220              :               /* Dereference the arg_sg pointer argument.  */
   12221          674 :               arg_sg = build_fold_indirect_ref (arg_sg);
   12222              :               /* Assign the signgam value into *arg_sg. */
   12223          674 :               result_sg = fold_build2 (MODIFY_EXPR,
   12224              :                                        TREE_TYPE (arg_sg), arg_sg,
   12225              :                                        build_int_cst (TREE_TYPE (arg_sg), sg));
   12226          674 :               TREE_SIDE_EFFECTS (result_sg) = 1;
   12227              :               /* Combine the signgam assignment with the lgamma result.  */
   12228          674 :               result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
   12229              :                                                 result_sg, result_lg));
   12230              :             }
   12231          674 :         }
   12232              :     }
   12233              : 
   12234         6504 :   return result;
   12235              : }
   12236              : 
   12237              : /* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
   12238              :    mpc function FUNC on it and return the resulting value as a tree
   12239              :    with type TYPE.  The mpfr precision is set to the precision of
   12240              :    TYPE.  We assume that function FUNC returns zero if the result
   12241              :    could be calculated exactly within the requested precision.  If
   12242              :    DO_NONFINITE is true, then fold expressions containing Inf or NaN
   12243              :    in the arguments and/or results.  */
   12244              : 
   12245              : tree
   12246         4523 : do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
   12247              :              int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
   12248              : {
   12249         4523 :   tree result = NULL_TREE;
   12250              : 
   12251         4523 :   STRIP_NOPS (arg0);
   12252         4523 :   STRIP_NOPS (arg1);
   12253              : 
   12254              :   /* To proceed, MPFR must exactly represent the target floating point
   12255              :      format, which only happens when the target base equals two.  */
   12256         4523 :   if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
   12257         4523 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
   12258         4523 :       && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
   12259         4523 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg1)))
   12260         9046 :       && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
   12261              :     {
   12262         4523 :       const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
   12263         4523 :       const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
   12264         4523 :       const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
   12265         4523 :       const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
   12266              : 
   12267         4523 :       if (do_nonfinite
   12268         4523 :           || (real_isfinite (re0) && real_isfinite (im0)
   12269         4059 :               && real_isfinite (re1) && real_isfinite (im1)))
   12270              :         {
   12271         4171 :           const struct real_format *const fmt =
   12272         4171 :             REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
   12273         4171 :           const int prec = fmt->p;
   12274         4171 :           const mpfr_rnd_t rnd = fmt->round_towards_zero
   12275         4171 :                                  ? MPFR_RNDZ : MPFR_RNDN;
   12276         4171 :           const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
   12277         4171 :           int inexact;
   12278         4171 :           mpc_t m0, m1;
   12279              : 
   12280         4171 :           mpc_init2 (m0, prec);
   12281         4171 :           mpc_init2 (m1, prec);
   12282         4171 :           mpfr_from_real (mpc_realref (m0), re0, rnd);
   12283         4171 :           mpfr_from_real (mpc_imagref (m0), im0, rnd);
   12284         4171 :           mpfr_from_real (mpc_realref (m1), re1, rnd);
   12285         4171 :           mpfr_from_real (mpc_imagref (m1), im1, rnd);
   12286         4171 :           mpfr_clear_flags ();
   12287         4171 :           inexact = func (m0, m0, m1, crnd);
   12288         4171 :           result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
   12289         4171 :           mpc_clear (m0);
   12290         4171 :           mpc_clear (m1);
   12291              :         }
   12292              :     }
   12293              : 
   12294         4523 :   return result;
   12295              : }
   12296              : 
   12297              : /* A wrapper function for builtin folding that prevents warnings for
   12298              :    "statement without effect" and the like, caused by removing the
   12299              :    call node earlier than the warning is generated.  */
   12300              : 
   12301              : tree
   12302      6136290 : fold_call_stmt (gcall *stmt, bool ignore)
   12303              : {
   12304      6136290 :   tree ret = NULL_TREE;
   12305      6136290 :   tree fndecl = gimple_call_fndecl (stmt);
   12306      6136290 :   location_t loc = gimple_location (stmt);
   12307      6136290 :   if (fndecl && fndecl_built_in_p (fndecl)
   12308     12272580 :       && !gimple_call_va_arg_pack_p (stmt))
   12309              :     {
   12310      6136224 :       int nargs = gimple_call_num_args (stmt);
   12311      6136224 :       tree *args = (nargs > 0
   12312      6136224 :                     ? gimple_call_arg_ptr (stmt, 0)
   12313              :                     : &error_mark_node);
   12314              : 
   12315      6136224 :       if (avoid_folding_inline_builtin (fndecl))
   12316              :         return NULL_TREE;
   12317      6136224 :       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
   12318              :         {
   12319            0 :           return targetm.fold_builtin (fndecl, nargs, args, ignore);
   12320              :         }
   12321              :       else
   12322              :         {
   12323      6136224 :           ret = fold_builtin_n (loc, NULL_TREE, fndecl, args, nargs, ignore);
   12324      6136224 :           if (ret)
   12325              :             {
   12326              :               /* Propagate location information from original call to
   12327              :                  expansion of builtin.  Otherwise things like
   12328              :                  maybe_emit_chk_warning, that operate on the expansion
   12329              :                  of a builtin, will use the wrong location information.  */
   12330         5093 :               if (gimple_has_location (stmt))
   12331              :                 {
   12332         5092 :                   tree realret = ret;
   12333         5092 :                   if (TREE_CODE (ret) == NOP_EXPR)
   12334         5092 :                     realret = TREE_OPERAND (ret, 0);
   12335         5092 :                   if (CAN_HAVE_LOCATION_P (realret)
   12336         9313 :                       && !EXPR_HAS_LOCATION (realret))
   12337            6 :                     SET_EXPR_LOCATION (realret, loc);
   12338              :                   return realret;
   12339              :                 }
   12340              :               return ret;
   12341              :             }
   12342              :         }
   12343              :     }
   12344              :   return NULL_TREE;
   12345              : }
   12346              : 
   12347              : /* Look up the function in builtin_decl that corresponds to DECL
   12348              :    and set ASMSPEC as its user assembler name.  DECL must be a
   12349              :    function decl that declares a builtin.  */
   12350              : 
   12351              : void
   12352       156250 : set_builtin_user_assembler_name (tree decl, const char *asmspec)
   12353              : {
   12354       156250 :   gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
   12355              :               && asmspec != 0);
   12356              : 
   12357       156250 :   tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
   12358       156250 :   set_user_assembler_name (builtin, asmspec);
   12359              : 
   12360       156250 :   if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
   12361       156250 :       && INT_TYPE_SIZE < BITS_PER_WORD)
   12362              :     {
   12363            1 :       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
   12364            1 :       set_user_assembler_libfunc ("ffs", asmspec);
   12365            1 :       set_optab_libfunc (ffs_optab, mode, "ffs");
   12366              :     }
   12367       156250 : }
   12368              : 
   12369              : /* Return true if DECL is a builtin that expands to a constant or similarly
   12370              :    simple code.  */
   12371              : bool
   12372     32527360 : is_simple_builtin (tree decl)
   12373              : {
   12374     32527360 :   if (decl && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
   12375     31207467 :     switch (DECL_FUNCTION_CODE (decl))
   12376              :       {
   12377              :         /* Builtins that expand to constants.  */
   12378              :       case BUILT_IN_CONSTANT_P:
   12379              :       case BUILT_IN_EXPECT:
   12380              :       case BUILT_IN_OBJECT_SIZE:
   12381              :       case BUILT_IN_UNREACHABLE:
   12382              :         /* Simple register moves or loads from stack.  */
   12383              :       case BUILT_IN_ASSUME_ALIGNED:
   12384              :       case BUILT_IN_RETURN_ADDRESS:
   12385              :       case BUILT_IN_EXTRACT_RETURN_ADDR:
   12386              :       case BUILT_IN_FROB_RETURN_ADDR:
   12387              :       case BUILT_IN_RETURN:
   12388              :       case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
   12389              :       case BUILT_IN_FRAME_ADDRESS:
   12390              :       case BUILT_IN_VA_END:
   12391              :       case BUILT_IN_STACK_SAVE:
   12392              :       case BUILT_IN_STACK_RESTORE:
   12393              :       case BUILT_IN_DWARF_CFA:
   12394              :       case BUILT_IN_CALL_CODE_ADDRESS:
   12395              :       case BUILT_IN_CALL_STATIC_CHAIN:
   12396              :         /* Exception state returns or moves registers around.  */
   12397              :       case BUILT_IN_EH_FILTER:
   12398              :       case BUILT_IN_EH_POINTER:
   12399              :       case BUILT_IN_EH_COPY_VALUES:
   12400              :         return true;
   12401              : 
   12402     28020832 :       default:
   12403     28020832 :         return false;
   12404              :       }
   12405              : 
   12406              :   return false;
   12407              : }
   12408              : 
   12409              : /* Return true if DECL is a builtin that is not expensive, i.e., they are
   12410              :    most probably expanded inline into reasonably simple code.  This is a
   12411              :    superset of is_simple_builtin.  */
   12412              : bool
   12413     19498225 : is_inexpensive_builtin (tree decl)
   12414              : {
   12415     19498225 :   if (!decl)
   12416              :     return false;
   12417     19483714 :   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
   12418              :     return true;
   12419     18137428 :   else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   12420     15173254 :     switch (DECL_FUNCTION_CODE (decl))
   12421              :       {
   12422              :       case BUILT_IN_ABS:
   12423              :       CASE_BUILT_IN_ALLOCA:
   12424              :       case BUILT_IN_BSWAP16:
   12425              :       case BUILT_IN_BSWAP32:
   12426              :       case BUILT_IN_BSWAP64:
   12427              :       case BUILT_IN_BSWAP128:
   12428              :       case BUILT_IN_BITREVERSE8:
   12429              :       case BUILT_IN_BITREVERSE16:
   12430              :       case BUILT_IN_BITREVERSE32:
   12431              :       case BUILT_IN_BITREVERSE64:
   12432              :       case BUILT_IN_BITREVERSE128:
   12433              :       case BUILT_IN_CLZ:
   12434              :       case BUILT_IN_CLZIMAX:
   12435              :       case BUILT_IN_CLZL:
   12436              :       case BUILT_IN_CLZLL:
   12437              :       case BUILT_IN_CTZ:
   12438              :       case BUILT_IN_CTZIMAX:
   12439              :       case BUILT_IN_CTZL:
   12440              :       case BUILT_IN_CTZLL:
   12441              :       case BUILT_IN_FFS:
   12442              :       case BUILT_IN_FFSIMAX:
   12443              :       case BUILT_IN_FFSL:
   12444              :       case BUILT_IN_FFSLL:
   12445              :       case BUILT_IN_IMAXABS:
   12446              :       case BUILT_IN_FINITE:
   12447              :       case BUILT_IN_FINITEF:
   12448              :       case BUILT_IN_FINITEL:
   12449              :       case BUILT_IN_FINITED32:
   12450              :       case BUILT_IN_FINITED64:
   12451              :       case BUILT_IN_FINITED128:
   12452              :       case BUILT_IN_FPCLASSIFY:
   12453              :       case BUILT_IN_ISFINITE:
   12454              :       case BUILT_IN_ISINF_SIGN:
   12455              :       case BUILT_IN_ISINF:
   12456              :       case BUILT_IN_ISINFF:
   12457              :       case BUILT_IN_ISINFL:
   12458              :       case BUILT_IN_ISINFD32:
   12459              :       case BUILT_IN_ISINFD64:
   12460              :       case BUILT_IN_ISINFD128:
   12461              :       case BUILT_IN_ISNAN:
   12462              :       case BUILT_IN_ISNANF:
   12463              :       case BUILT_IN_ISNANL:
   12464              :       case BUILT_IN_ISNAND32:
   12465              :       case BUILT_IN_ISNAND64:
   12466              :       case BUILT_IN_ISNAND128:
   12467              :       case BUILT_IN_ISNORMAL:
   12468              :       case BUILT_IN_ISGREATER:
   12469              :       case BUILT_IN_ISGREATEREQUAL:
   12470              :       case BUILT_IN_ISLESS:
   12471              :       case BUILT_IN_ISLESSEQUAL:
   12472              :       case BUILT_IN_ISLESSGREATER:
   12473              :       case BUILT_IN_ISUNORDERED:
   12474              :       case BUILT_IN_ISEQSIG:
   12475              :       case BUILT_IN_VA_ARG_PACK:
   12476              :       case BUILT_IN_VA_ARG_PACK_LEN:
   12477              :       case BUILT_IN_VA_COPY:
   12478              :       case BUILT_IN_TRAP:
   12479              :       case BUILT_IN_UNREACHABLE_TRAP:
   12480              :       case BUILT_IN_SAVEREGS:
   12481              :       case BUILT_IN_POPCOUNTL:
   12482              :       case BUILT_IN_POPCOUNTLL:
   12483              :       case BUILT_IN_POPCOUNTIMAX:
   12484              :       case BUILT_IN_POPCOUNT:
   12485              :       case BUILT_IN_PARITYL:
   12486              :       case BUILT_IN_PARITYLL:
   12487              :       case BUILT_IN_PARITYIMAX:
   12488              :       case BUILT_IN_PARITY:
   12489              :       case BUILT_IN_LABS:
   12490              :       case BUILT_IN_LLABS:
   12491              :       case BUILT_IN_PREFETCH:
   12492              :       case BUILT_IN_ACC_ON_DEVICE:
   12493              :         return true;
   12494              : 
   12495     14515565 :       default:
   12496     14515565 :         return is_simple_builtin (decl);
   12497              :       }
   12498              : 
   12499              :   return false;
   12500              : }
   12501              : 
   12502              : /* Return true if T is a constant and the value cast to a target char
   12503              :    can be represented by a host char.
   12504              :    Store the casted char constant in *P if so.  */
   12505              : 
   12506              : bool
   12507         3617 : target_char_cst_p (tree t, char *p)
   12508              : {
   12509         3617 :   if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
   12510              :     return false;
   12511              : 
   12512         1913 :   *p = (char)tree_to_uhwi (t);
   12513         1913 :   return true;
   12514              : }
   12515              : 
   12516              : /* Return true if the builtin DECL is implemented in a standard library.
   12517              :    Otherwise return false which doesn't guarantee it is not (thus the list
   12518              :    of handled builtins below may be incomplete).  */
   12519              : 
   12520              : bool
   12521        42288 : builtin_with_linkage_p (tree decl)
   12522              : {
   12523        42288 :   if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
   12524        42004 :     switch (DECL_FUNCTION_CODE (decl))
   12525              :     {
   12526         1304 :       CASE_FLT_FN (BUILT_IN_ACOS):
   12527         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS):
   12528         1304 :       CASE_FLT_FN (BUILT_IN_ACOSH):
   12529         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH):
   12530         1304 :       CASE_FLT_FN (BUILT_IN_ASIN):
   12531         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN):
   12532         1304 :       CASE_FLT_FN (BUILT_IN_ASINH):
   12533         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINH):
   12534         1304 :       CASE_FLT_FN (BUILT_IN_ATAN):
   12535         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN):
   12536         1304 :       CASE_FLT_FN (BUILT_IN_ATANH):
   12537         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATANH):
   12538         1304 :       CASE_FLT_FN (BUILT_IN_ATAN2):
   12539         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ATAN2):
   12540         1304 :       CASE_FLT_FN (BUILT_IN_CBRT):
   12541         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_CBRT):
   12542         1304 :       CASE_FLT_FN (BUILT_IN_CEIL):
   12543         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_CEIL):
   12544         1304 :       CASE_FLT_FN (BUILT_IN_COPYSIGN):
   12545         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
   12546         1304 :       CASE_FLT_FN (BUILT_IN_COS):
   12547         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS):
   12548         1304 :       CASE_FLT_FN (BUILT_IN_COSH):
   12549         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSH):
   12550         1304 :       CASE_FLT_FN (BUILT_IN_ERF):
   12551         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERF):
   12552         1304 :       CASE_FLT_FN (BUILT_IN_ERFC):
   12553         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ERFC):
   12554         1304 :       CASE_FLT_FN (BUILT_IN_EXP):
   12555         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP):
   12556         1304 :       CASE_FLT_FN (BUILT_IN_EXP2):
   12557         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXP2):
   12558         1304 :       CASE_FLT_FN (BUILT_IN_EXPM1):
   12559         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_EXPM1):
   12560         1304 :       CASE_FLT_FN (BUILT_IN_FABS):
   12561         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
   12562         1304 :       CASE_FLT_FN (BUILT_IN_FDIM):
   12563         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FDIM):
   12564         1304 :       CASE_FLT_FN (BUILT_IN_FLOOR):
   12565         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FLOOR):
   12566         1304 :       CASE_FLT_FN (BUILT_IN_FMA):
   12567         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMA):
   12568         1304 :       CASE_FLT_FN (BUILT_IN_FMAX):
   12569         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMAX):
   12570         1304 :       CASE_FLT_FN (BUILT_IN_FMIN):
   12571         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMIN):
   12572         1304 :       CASE_FLT_FN (BUILT_IN_FMOD):
   12573         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FMOD):
   12574         1304 :       CASE_FLT_FN (BUILT_IN_FREXP):
   12575         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_FREXP):
   12576         1304 :       CASE_FLT_FN (BUILT_IN_HYPOT):
   12577         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_HYPOT):
   12578         1304 :       CASE_FLT_FN (BUILT_IN_ILOGB):
   12579         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ILOGB):
   12580         1304 :       CASE_FLT_FN (BUILT_IN_LDEXP):
   12581         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LDEXP):
   12582         1304 :       CASE_FLT_FN (BUILT_IN_LGAMMA):
   12583         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LGAMMA):
   12584         1304 :       CASE_FLT_FN (BUILT_IN_LLRINT):
   12585         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLRINT):
   12586         1304 :       CASE_FLT_FN (BUILT_IN_LLROUND):
   12587         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LLROUND):
   12588         1304 :       CASE_FLT_FN (BUILT_IN_LOG):
   12589         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG):
   12590         1304 :       CASE_FLT_FN (BUILT_IN_LOG10):
   12591         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG10):
   12592         1304 :       CASE_FLT_FN (BUILT_IN_LOG1P):
   12593         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG1P):
   12594         1304 :       CASE_FLT_FN (BUILT_IN_LOG2):
   12595         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOG2):
   12596         1304 :       CASE_FLT_FN (BUILT_IN_LOGB):
   12597         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LOGB):
   12598         1304 :       CASE_FLT_FN (BUILT_IN_LRINT):
   12599         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LRINT):
   12600         1304 :       CASE_FLT_FN (BUILT_IN_LROUND):
   12601         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_LROUND):
   12602         1304 :       CASE_FLT_FN (BUILT_IN_MODF):
   12603         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_MODF):
   12604         1304 :       CASE_FLT_FN (BUILT_IN_NAN):
   12605         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NAN):
   12606         1304 :       CASE_FLT_FN (BUILT_IN_NEARBYINT):
   12607         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEARBYINT):
   12608         1304 :       CASE_FLT_FN (BUILT_IN_NEXTAFTER):
   12609         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_NEXTAFTER):
   12610         1304 :       CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
   12611         1304 :       CASE_FLT_FN (BUILT_IN_POW):
   12612         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_POW):
   12613         1304 :       CASE_FLT_FN (BUILT_IN_REMAINDER):
   12614         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMAINDER):
   12615         1304 :       CASE_FLT_FN (BUILT_IN_REMQUO):
   12616         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_REMQUO):
   12617         1304 :       CASE_FLT_FN (BUILT_IN_RINT):
   12618         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_RINT):
   12619         1304 :       CASE_FLT_FN (BUILT_IN_ROUND):
   12620         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_ROUND):
   12621         1304 :       CASE_FLT_FN (BUILT_IN_SCALBLN):
   12622         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBLN):
   12623         1304 :       CASE_FLT_FN (BUILT_IN_SCALBN):
   12624         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SCALBN):
   12625         1304 :       CASE_FLT_FN (BUILT_IN_SIN):
   12626         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN):
   12627         1304 :       CASE_FLT_FN (BUILT_IN_SINH):
   12628         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINH):
   12629         1304 :       CASE_FLT_FN (BUILT_IN_SINCOS):
   12630         1304 :       CASE_FLT_FN (BUILT_IN_SQRT):
   12631         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT):
   12632         1304 :       CASE_FLT_FN (BUILT_IN_TAN):
   12633         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TAN):
   12634         1304 :       CASE_FLT_FN (BUILT_IN_TANH):
   12635         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TANH):
   12636         1304 :       CASE_FLT_FN (BUILT_IN_TGAMMA):
   12637         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TGAMMA):
   12638         1304 :       CASE_FLT_FN (BUILT_IN_TRUNC):
   12639         1304 :       CASE_FLT_FN_FLOATN_NX (BUILT_IN_TRUNC):
   12640         1304 :         return true;
   12641              : 
   12642           16 :       case BUILT_IN_STPCPY:
   12643           16 :       case BUILT_IN_STPNCPY:
   12644              :         /* stpcpy is both referenced in libiberty's pex-win32.c and provided
   12645              :            by libiberty's stpcpy.c for MinGW targets so we need to return true
   12646              :            in order to be able to build libiberty in LTO mode for them.  */
   12647           16 :         return true;
   12648              : 
   12649              :       default:
   12650              :         break;
   12651              :     }
   12652              :   return false;
   12653              : }
   12654              : 
   12655              : /* Return true if OFFRNG is bounded to a subrange of offset values
   12656              :    valid for the largest possible object.  */
   12657              : 
   12658              : bool
   12659          501 : access_ref::offset_bounded () const
   12660              : {
   12661          501 :   tree min = TYPE_MIN_VALUE (ptrdiff_type_node);
   12662          501 :   tree max = TYPE_MAX_VALUE (ptrdiff_type_node);
   12663          975 :   return wi::to_offset (min) <= offrng[0] && offrng[1] <= wi::to_offset (max);
   12664              : }
   12665              : 
   12666              : /* If CALLEE has known side effects, fill in INFO and return true.
   12667              :    See tree-ssa-structalias.cc:find_func_aliases
   12668              :    for the list of builtins we might need to handle here.  */
   12669              : 
   12670              : attr_fnspec
   12671    113397479 : builtin_fnspec (tree callee)
   12672              : {
   12673    113397479 :   built_in_function code = DECL_FUNCTION_CODE (callee);
   12674              : 
   12675    113397479 :   switch (code)
   12676              :     {
   12677              :       /* All the following functions read memory pointed to by
   12678              :          their second argument and write memory pointed to by first
   12679              :          argument.
   12680              :          strcat/strncat additionally reads memory pointed to by the first
   12681              :          argument.  */
   12682       133258 :       case BUILT_IN_STRCAT:
   12683       133258 :       case BUILT_IN_STRCAT_CHK:
   12684       133258 :         return "1cW 1 ";
   12685        42125 :       case BUILT_IN_STRNCAT:
   12686        42125 :       case BUILT_IN_STRNCAT_CHK:
   12687        42125 :         return "1cW 13";
   12688       262952 :       case BUILT_IN_STRCPY:
   12689       262952 :       case BUILT_IN_STRCPY_CHK:
   12690       262952 :         return "1cO 1 ";
   12691        32336 :       case BUILT_IN_STPCPY:
   12692        32336 :       case BUILT_IN_STPCPY_CHK:
   12693        32336 :         return ".cO 1 ";
   12694     19219079 :       case BUILT_IN_STRNCPY:
   12695     19219079 :       case BUILT_IN_MEMCPY:
   12696     19219079 :       case BUILT_IN_MEMMOVE:
   12697     19219079 :       case BUILT_IN_TM_MEMCPY:
   12698     19219079 :       case BUILT_IN_TM_MEMMOVE:
   12699     19219079 :       case BUILT_IN_STRNCPY_CHK:
   12700     19219079 :       case BUILT_IN_MEMCPY_CHK:
   12701     19219079 :       case BUILT_IN_MEMMOVE_CHK:
   12702     19219079 :         return "1cO313";
   12703       143700 :       case BUILT_IN_MEMPCPY:
   12704       143700 :       case BUILT_IN_MEMPCPY_CHK:
   12705       143700 :         return ".cO313";
   12706        58163 :       case BUILT_IN_STPNCPY:
   12707        58163 :       case BUILT_IN_STPNCPY_CHK:
   12708        58163 :         return ".cO313";
   12709            0 :       case BUILT_IN_BCOPY:
   12710            0 :         return ".c23O3";
   12711            0 :       case BUILT_IN_BZERO:
   12712            0 :         return ".cO2";
   12713      9410513 :       case BUILT_IN_MEMCMP:
   12714      9410513 :       case BUILT_IN_MEMCMP_EQ:
   12715      9410513 :       case BUILT_IN_BCMP:
   12716      9410513 :       case BUILT_IN_STRNCMP:
   12717      9410513 :       case BUILT_IN_STRNCMP_EQ:
   12718      9410513 :       case BUILT_IN_STRNCASECMP:
   12719      9410513 :         return ".cR3R3";
   12720              : 
   12721              :       /* The following functions read memory pointed to by their
   12722              :          first argument.  */
   12723          773 :       CASE_BUILT_IN_TM_LOAD (1):
   12724          773 :       CASE_BUILT_IN_TM_LOAD (2):
   12725          773 :       CASE_BUILT_IN_TM_LOAD (4):
   12726          773 :       CASE_BUILT_IN_TM_LOAD (8):
   12727          773 :       CASE_BUILT_IN_TM_LOAD (FLOAT):
   12728          773 :       CASE_BUILT_IN_TM_LOAD (DOUBLE):
   12729          773 :       CASE_BUILT_IN_TM_LOAD (LDOUBLE):
   12730          773 :       CASE_BUILT_IN_TM_LOAD (M64):
   12731          773 :       CASE_BUILT_IN_TM_LOAD (M128):
   12732          773 :       CASE_BUILT_IN_TM_LOAD (M256):
   12733          773 :       case BUILT_IN_TM_LOG:
   12734          773 :       case BUILT_IN_TM_LOG_1:
   12735          773 :       case BUILT_IN_TM_LOG_2:
   12736          773 :       case BUILT_IN_TM_LOG_4:
   12737          773 :       case BUILT_IN_TM_LOG_8:
   12738          773 :       case BUILT_IN_TM_LOG_FLOAT:
   12739          773 :       case BUILT_IN_TM_LOG_DOUBLE:
   12740          773 :       case BUILT_IN_TM_LOG_LDOUBLE:
   12741          773 :       case BUILT_IN_TM_LOG_M64:
   12742          773 :       case BUILT_IN_TM_LOG_M128:
   12743          773 :       case BUILT_IN_TM_LOG_M256:
   12744          773 :         return ".cR ";
   12745              : 
   12746       520612 :       case BUILT_IN_INDEX:
   12747       520612 :       case BUILT_IN_RINDEX:
   12748       520612 :       case BUILT_IN_STRCHR:
   12749       520612 :       case BUILT_IN_STRLEN:
   12750       520612 :       case BUILT_IN_STRRCHR:
   12751       520612 :         return ".cR ";
   12752        56735 :       case BUILT_IN_STRNLEN:
   12753        56735 :         return ".cR2";
   12754              : 
   12755              :       /* These read memory pointed to by the first argument.
   12756              :          Allocating memory does not have any side-effects apart from
   12757              :          being the definition point for the pointer.
   12758              :          Unix98 specifies that errno is set on allocation failure.  */
   12759        18233 :       case BUILT_IN_STRDUP:
   12760        18233 :         return "mCR ";
   12761        13308 :       case BUILT_IN_STRNDUP:
   12762        13308 :         return "mCR2";
   12763              :       /* Allocating memory does not have any side-effects apart from
   12764              :          being the definition point for the pointer.  */
   12765     11275359 :       case BUILT_IN_MALLOC:
   12766     11275359 :       case BUILT_IN_ALIGNED_ALLOC:
   12767     11275359 :       case BUILT_IN_CALLOC:
   12768     11275359 :       case BUILT_IN_GOMP_ALLOC:
   12769     11275359 :         return "mC";
   12770       845937 :       CASE_BUILT_IN_ALLOCA:
   12771       845937 :         return "mc";
   12772              :       /* These read memory pointed to by the first argument with size
   12773              :          in the third argument.  */
   12774       726691 :       case BUILT_IN_MEMCHR:
   12775       726691 :         return ".cR3";
   12776              :       /* These read memory pointed to by the first and second arguments.  */
   12777     11556405 :       case BUILT_IN_STRSTR:
   12778     11556405 :       case BUILT_IN_STRPBRK:
   12779     11556405 :       case BUILT_IN_STRCASECMP:
   12780     11556405 :       case BUILT_IN_STRCSPN:
   12781     11556405 :       case BUILT_IN_STRSPN:
   12782     11556405 :       case BUILT_IN_STRCMP:
   12783     11556405 :       case BUILT_IN_STRCMP_EQ:
   12784     11556405 :         return ".cR R ";
   12785              :       /* Freeing memory kills the pointed-to memory.  More importantly
   12786              :          the call has to serve as a barrier for moving loads and stores
   12787              :          across it.  */
   12788      6531054 :       case BUILT_IN_STACK_RESTORE:
   12789      6531054 :       case BUILT_IN_FREE:
   12790      6531054 :       case BUILT_IN_GOMP_FREE:
   12791      6531054 :         return ".co ";
   12792       108417 :       case BUILT_IN_VA_END:
   12793       108417 :         return ".cO ";
   12794              :       /* Realloc serves both as allocation point and deallocation point.  */
   12795      1079369 :       case BUILT_IN_REALLOC:
   12796      1079369 :       case BUILT_IN_GOMP_REALLOC:
   12797      1079369 :         return ".Cw ";
   12798        15732 :       case BUILT_IN_GAMMA_R:
   12799        15732 :       case BUILT_IN_GAMMAF_R:
   12800        15732 :       case BUILT_IN_GAMMAL_R:
   12801        15732 :       case BUILT_IN_LGAMMA_R:
   12802        15732 :       case BUILT_IN_LGAMMAF_R:
   12803        15732 :       case BUILT_IN_LGAMMAL_R:
   12804        15732 :         return ".C. Ot";
   12805        43890 :       case BUILT_IN_FREXP:
   12806        43890 :       case BUILT_IN_FREXPF:
   12807        43890 :       case BUILT_IN_FREXPL:
   12808        43890 :       case BUILT_IN_MODF:
   12809        43890 :       case BUILT_IN_MODFF:
   12810        43890 :       case BUILT_IN_MODFL:
   12811        43890 :         return ".c. Ot";
   12812         7586 :       case BUILT_IN_REMQUO:
   12813         7586 :       case BUILT_IN_REMQUOF:
   12814         7586 :       case BUILT_IN_REMQUOL:
   12815         7586 :         return ".c. . Ot";
   12816          164 :       case BUILT_IN_SINCOS:
   12817          164 :       case BUILT_IN_SINCOSF:
   12818          164 :       case BUILT_IN_SINCOSL:
   12819          164 :         return ".c. OtOt";
   12820      4364374 :       case BUILT_IN_MEMSET:
   12821      4364374 :       case BUILT_IN_MEMSET_CHK:
   12822      4364374 :       case BUILT_IN_TM_MEMSET:
   12823      4364374 :         return "1cO3";
   12824          366 :       CASE_BUILT_IN_TM_STORE (1):
   12825          366 :       CASE_BUILT_IN_TM_STORE (2):
   12826          366 :       CASE_BUILT_IN_TM_STORE (4):
   12827          366 :       CASE_BUILT_IN_TM_STORE (8):
   12828          366 :       CASE_BUILT_IN_TM_STORE (FLOAT):
   12829          366 :       CASE_BUILT_IN_TM_STORE (DOUBLE):
   12830          366 :       CASE_BUILT_IN_TM_STORE (LDOUBLE):
   12831          366 :       CASE_BUILT_IN_TM_STORE (M64):
   12832          366 :       CASE_BUILT_IN_TM_STORE (M128):
   12833          366 :       CASE_BUILT_IN_TM_STORE (M256):
   12834          366 :         return ".cO ";
   12835      2443470 :       case BUILT_IN_STACK_SAVE:
   12836      2443470 :       case BUILT_IN_RETURN:
   12837      2443470 :       case BUILT_IN_EH_POINTER:
   12838      2443470 :       case BUILT_IN_EH_FILTER:
   12839      2443470 :       case BUILT_IN_UNWIND_RESUME:
   12840      2443470 :       case BUILT_IN_CXA_END_CLEANUP:
   12841      2443470 :       case BUILT_IN_EH_COPY_VALUES:
   12842      2443470 :       case BUILT_IN_FRAME_ADDRESS:
   12843      2443470 :       case BUILT_IN_APPLY_ARGS:
   12844      2443470 :       case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT:
   12845      2443470 :       case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT:
   12846      2443470 :       case BUILT_IN_PREFETCH:
   12847      2443470 :       case BUILT_IN_DWARF_CFA:
   12848      2443470 :       case BUILT_IN_RETURN_ADDRESS:
   12849      2443470 :         return ".c";
   12850      2193592 :       case BUILT_IN_ASSUME_ALIGNED:
   12851      2193592 :       case BUILT_IN_EXPECT:
   12852      2193592 :       case BUILT_IN_EXPECT_WITH_PROBABILITY:
   12853      2193592 :         return "1cX ";
   12854              :       /* But posix_memalign stores a pointer into the memory pointed to
   12855              :          by its first argument.  */
   12856         5776 :       case BUILT_IN_POSIX_MEMALIGN:
   12857         5776 :         return ".cOt";
   12858         4438 :       case BUILT_IN_OMP_GET_MAPPED_PTR:
   12859         4438 :         return ". R ";
   12860              : 
   12861     42283072 :       default:
   12862     42283072 :         return "";
   12863              :     }
   12864              : }
        

Generated by: LCOV version 2.4-beta

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